1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Copyright(c) 2018 Intel Corporation.
4  *
5  */
6 #include "iowait.h"
7 #include "trace_iowait.h"
8 
9 void iowait_set_flag(struct iowait *wait, u32 flag)
10 {
11 	trace_hfi1_iowait_set(wait, flag);
12 	set_bit(flag, &wait->flags);
13 }
14 
15 bool iowait_flag_set(struct iowait *wait, u32 flag)
16 {
17 	return test_bit(flag, &wait->flags);
18 }
19 
20 inline void iowait_clear_flag(struct iowait *wait, u32 flag)
21 {
22 	trace_hfi1_iowait_clear(wait, flag);
23 	clear_bit(flag, &wait->flags);
24 }
25 
26 /**
27  * iowait_init() - initialize wait structure
28  * @wait: wait struct to initialize
29  * @tx_limit: limit for overflow queuing
30  * @func: restart function for workqueue
31  * @sleep: sleep function for no space
32  * @resume: wakeup function for no space
33  *
34  * This function initializes the iowait
35  * structure embedded in the QP or PQ.
36  *
37  */
38 void iowait_init(struct iowait *wait, u32 tx_limit,
39 		 void (*func)(struct work_struct *work),
40 		 void (*tidfunc)(struct work_struct *work),
41 		 int (*sleep)(struct sdma_engine *sde,
42 			      struct iowait_work *wait,
43 			      struct sdma_txreq *tx,
44 			      uint seq,
45 			      bool pkts_sent),
46 		 void (*wakeup)(struct iowait *wait, int reason),
47 		 void (*sdma_drained)(struct iowait *wait))
48 {
49 	int i;
50 
51 	wait->count = 0;
52 	INIT_LIST_HEAD(&wait->list);
53 	init_waitqueue_head(&wait->wait_dma);
54 	init_waitqueue_head(&wait->wait_pio);
55 	atomic_set(&wait->sdma_busy, 0);
56 	atomic_set(&wait->pio_busy, 0);
57 	wait->tx_limit = tx_limit;
58 	wait->sleep = sleep;
59 	wait->wakeup = wakeup;
60 	wait->sdma_drained = sdma_drained;
61 	wait->flags = 0;
62 	for (i = 0; i < IOWAIT_SES; i++) {
63 		wait->wait[i].iow = wait;
64 		INIT_LIST_HEAD(&wait->wait[i].tx_head);
65 		if (i == IOWAIT_IB_SE)
66 			INIT_WORK(&wait->wait[i].iowork, func);
67 		else
68 			INIT_WORK(&wait->wait[i].iowork, tidfunc);
69 	}
70 }
71 
72 /**
73  * iowait_cancel_work - cancel all work in iowait
74  * @w: the iowait struct
75  */
76 void iowait_cancel_work(struct iowait *w)
77 {
78 	cancel_work_sync(&iowait_get_ib_work(w)->iowork);
79 	cancel_work_sync(&iowait_get_tid_work(w)->iowork);
80 }
81 
82 /**
83  * iowait_set_work_flag - set work flag based on leg
84  * @w - the iowait work struct
85  */
86 int iowait_set_work_flag(struct iowait_work *w)
87 {
88 	if (w == &w->iow->wait[IOWAIT_IB_SE]) {
89 		iowait_set_flag(w->iow, IOWAIT_PENDING_IB);
90 		return IOWAIT_IB_SE;
91 	}
92 	iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
93 	return IOWAIT_TID_SE;
94 }
95