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