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