0001
0002
0003
0004
0005
0006 #include "iowait.h"
0007 #include "trace_iowait.h"
0008
0009
0010 #define IOWAIT_PRIORITY_STARVE_SHIFT 4
0011
0012 void iowait_set_flag(struct iowait *wait, u32 flag)
0013 {
0014 trace_hfi1_iowait_set(wait, flag);
0015 set_bit(flag, &wait->flags);
0016 }
0017
0018 bool iowait_flag_set(struct iowait *wait, u32 flag)
0019 {
0020 return test_bit(flag, &wait->flags);
0021 }
0022
0023 inline void iowait_clear_flag(struct iowait *wait, u32 flag)
0024 {
0025 trace_hfi1_iowait_clear(wait, flag);
0026 clear_bit(flag, &wait->flags);
0027 }
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 void iowait_init(struct iowait *wait, u32 tx_limit,
0042 void (*func)(struct work_struct *work),
0043 void (*tidfunc)(struct work_struct *work),
0044 int (*sleep)(struct sdma_engine *sde,
0045 struct iowait_work *wait,
0046 struct sdma_txreq *tx,
0047 uint seq,
0048 bool pkts_sent),
0049 void (*wakeup)(struct iowait *wait, int reason),
0050 void (*sdma_drained)(struct iowait *wait),
0051 void (*init_priority)(struct iowait *wait))
0052 {
0053 int i;
0054
0055 wait->count = 0;
0056 INIT_LIST_HEAD(&wait->list);
0057 init_waitqueue_head(&wait->wait_dma);
0058 init_waitqueue_head(&wait->wait_pio);
0059 atomic_set(&wait->sdma_busy, 0);
0060 atomic_set(&wait->pio_busy, 0);
0061 wait->tx_limit = tx_limit;
0062 wait->sleep = sleep;
0063 wait->wakeup = wakeup;
0064 wait->sdma_drained = sdma_drained;
0065 wait->init_priority = init_priority;
0066 wait->flags = 0;
0067 for (i = 0; i < IOWAIT_SES; i++) {
0068 wait->wait[i].iow = wait;
0069 INIT_LIST_HEAD(&wait->wait[i].tx_head);
0070 if (i == IOWAIT_IB_SE)
0071 INIT_WORK(&wait->wait[i].iowork, func);
0072 else
0073 INIT_WORK(&wait->wait[i].iowork, tidfunc);
0074 }
0075 }
0076
0077
0078
0079
0080
0081 void iowait_cancel_work(struct iowait *w)
0082 {
0083 cancel_work_sync(&iowait_get_ib_work(w)->iowork);
0084
0085 if (iowait_get_tid_work(w)->iowork.func)
0086 cancel_work_sync(&iowait_get_tid_work(w)->iowork);
0087 }
0088
0089
0090
0091
0092
0093 int iowait_set_work_flag(struct iowait_work *w)
0094 {
0095 if (w == &w->iow->wait[IOWAIT_IB_SE]) {
0096 iowait_set_flag(w->iow, IOWAIT_PENDING_IB);
0097 return IOWAIT_IB_SE;
0098 }
0099 iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
0100 return IOWAIT_TID_SE;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 uint iowait_priority_update_top(struct iowait *w,
0115 struct iowait *top,
0116 uint idx, uint top_idx)
0117 {
0118 u8 cnt, tcnt;
0119
0120
0121 cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt;
0122 tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) +
0123 top->starved_cnt;
0124 if (cnt > tcnt)
0125 return idx;
0126 else
0127 return top_idx;
0128 }