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