xref: /OK3568_Linux_fs/kernel/drivers/infiniband/hw/hfi1/iowait.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright(c) 2018 Intel Corporation.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include "iowait.h"
7*4882a593Smuzhiyun #include "trace_iowait.h"
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun /* 1 priority == 16 starve_cnt */
10*4882a593Smuzhiyun #define IOWAIT_PRIORITY_STARVE_SHIFT 4
11*4882a593Smuzhiyun 
iowait_set_flag(struct iowait * wait,u32 flag)12*4882a593Smuzhiyun void iowait_set_flag(struct iowait *wait, u32 flag)
13*4882a593Smuzhiyun {
14*4882a593Smuzhiyun 	trace_hfi1_iowait_set(wait, flag);
15*4882a593Smuzhiyun 	set_bit(flag, &wait->flags);
16*4882a593Smuzhiyun }
17*4882a593Smuzhiyun 
iowait_flag_set(struct iowait * wait,u32 flag)18*4882a593Smuzhiyun bool iowait_flag_set(struct iowait *wait, u32 flag)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun 	return test_bit(flag, &wait->flags);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun 
iowait_clear_flag(struct iowait * wait,u32 flag)23*4882a593Smuzhiyun inline void iowait_clear_flag(struct iowait *wait, u32 flag)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	trace_hfi1_iowait_clear(wait, flag);
26*4882a593Smuzhiyun 	clear_bit(flag, &wait->flags);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /**
30*4882a593Smuzhiyun  * iowait_init() - initialize wait structure
31*4882a593Smuzhiyun  * @wait: wait struct to initialize
32*4882a593Smuzhiyun  * @tx_limit: limit for overflow queuing
33*4882a593Smuzhiyun  * @func: restart function for workqueue
34*4882a593Smuzhiyun  * @sleep: sleep function for no space
35*4882a593Smuzhiyun  * @resume: wakeup function for no space
36*4882a593Smuzhiyun  *
37*4882a593Smuzhiyun  * This function initializes the iowait
38*4882a593Smuzhiyun  * structure embedded in the QP or PQ.
39*4882a593Smuzhiyun  *
40*4882a593Smuzhiyun  */
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),void (* init_priority)(struct iowait * wait))41*4882a593Smuzhiyun void iowait_init(struct iowait *wait, u32 tx_limit,
42*4882a593Smuzhiyun 		 void (*func)(struct work_struct *work),
43*4882a593Smuzhiyun 		 void (*tidfunc)(struct work_struct *work),
44*4882a593Smuzhiyun 		 int (*sleep)(struct sdma_engine *sde,
45*4882a593Smuzhiyun 			      struct iowait_work *wait,
46*4882a593Smuzhiyun 			      struct sdma_txreq *tx,
47*4882a593Smuzhiyun 			      uint seq,
48*4882a593Smuzhiyun 			      bool pkts_sent),
49*4882a593Smuzhiyun 		 void (*wakeup)(struct iowait *wait, int reason),
50*4882a593Smuzhiyun 		 void (*sdma_drained)(struct iowait *wait),
51*4882a593Smuzhiyun 		 void (*init_priority)(struct iowait *wait))
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	int i;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	wait->count = 0;
56*4882a593Smuzhiyun 	INIT_LIST_HEAD(&wait->list);
57*4882a593Smuzhiyun 	init_waitqueue_head(&wait->wait_dma);
58*4882a593Smuzhiyun 	init_waitqueue_head(&wait->wait_pio);
59*4882a593Smuzhiyun 	atomic_set(&wait->sdma_busy, 0);
60*4882a593Smuzhiyun 	atomic_set(&wait->pio_busy, 0);
61*4882a593Smuzhiyun 	wait->tx_limit = tx_limit;
62*4882a593Smuzhiyun 	wait->sleep = sleep;
63*4882a593Smuzhiyun 	wait->wakeup = wakeup;
64*4882a593Smuzhiyun 	wait->sdma_drained = sdma_drained;
65*4882a593Smuzhiyun 	wait->init_priority = init_priority;
66*4882a593Smuzhiyun 	wait->flags = 0;
67*4882a593Smuzhiyun 	for (i = 0; i < IOWAIT_SES; i++) {
68*4882a593Smuzhiyun 		wait->wait[i].iow = wait;
69*4882a593Smuzhiyun 		INIT_LIST_HEAD(&wait->wait[i].tx_head);
70*4882a593Smuzhiyun 		if (i == IOWAIT_IB_SE)
71*4882a593Smuzhiyun 			INIT_WORK(&wait->wait[i].iowork, func);
72*4882a593Smuzhiyun 		else
73*4882a593Smuzhiyun 			INIT_WORK(&wait->wait[i].iowork, tidfunc);
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /**
78*4882a593Smuzhiyun  * iowait_cancel_work - cancel all work in iowait
79*4882a593Smuzhiyun  * @w: the iowait struct
80*4882a593Smuzhiyun  */
iowait_cancel_work(struct iowait * w)81*4882a593Smuzhiyun void iowait_cancel_work(struct iowait *w)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	cancel_work_sync(&iowait_get_ib_work(w)->iowork);
84*4882a593Smuzhiyun 	/* Make sure that the iowork for TID RDMA is used */
85*4882a593Smuzhiyun 	if (iowait_get_tid_work(w)->iowork.func)
86*4882a593Smuzhiyun 		cancel_work_sync(&iowait_get_tid_work(w)->iowork);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /**
90*4882a593Smuzhiyun  * iowait_set_work_flag - set work flag based on leg
91*4882a593Smuzhiyun  * @w - the iowait work struct
92*4882a593Smuzhiyun  */
iowait_set_work_flag(struct iowait_work * w)93*4882a593Smuzhiyun int iowait_set_work_flag(struct iowait_work *w)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	if (w == &w->iow->wait[IOWAIT_IB_SE]) {
96*4882a593Smuzhiyun 		iowait_set_flag(w->iow, IOWAIT_PENDING_IB);
97*4882a593Smuzhiyun 		return IOWAIT_IB_SE;
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 	iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
100*4882a593Smuzhiyun 	return IOWAIT_TID_SE;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /**
104*4882a593Smuzhiyun  * iowait_priority_update_top - update the top priority entry
105*4882a593Smuzhiyun  * @w: the iowait struct
106*4882a593Smuzhiyun  * @top: a pointer to the top priority entry
107*4882a593Smuzhiyun  * @idx: the index of the current iowait in an array
108*4882a593Smuzhiyun  * @top_idx: the array index for the iowait entry that has the top priority
109*4882a593Smuzhiyun  *
110*4882a593Smuzhiyun  * This function is called to compare the priority of a given
111*4882a593Smuzhiyun  * iowait with the given top priority entry. The top index will
112*4882a593Smuzhiyun  * be returned.
113*4882a593Smuzhiyun  */
iowait_priority_update_top(struct iowait * w,struct iowait * top,uint idx,uint top_idx)114*4882a593Smuzhiyun uint iowait_priority_update_top(struct iowait *w,
115*4882a593Smuzhiyun 				struct iowait *top,
116*4882a593Smuzhiyun 				uint idx, uint top_idx)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	u8 cnt, tcnt;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	/* Convert priority into starve_cnt and compare the total.*/
121*4882a593Smuzhiyun 	cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt;
122*4882a593Smuzhiyun 	tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) +
123*4882a593Smuzhiyun 		top->starved_cnt;
124*4882a593Smuzhiyun 	if (cnt > tcnt)
125*4882a593Smuzhiyun 		return idx;
126*4882a593Smuzhiyun 	else
127*4882a593Smuzhiyun 		return top_idx;
128*4882a593Smuzhiyun }
129