15da0fc9dSDennis Dalessandro // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 25da0fc9dSDennis Dalessandro /* 35da0fc9dSDennis Dalessandro * Copyright(c) 2018 Intel Corporation. 45da0fc9dSDennis Dalessandro * 55da0fc9dSDennis Dalessandro */ 65da0fc9dSDennis Dalessandro #include "iowait.h" 7*15b796bcSKaike Wan #include "trace_iowait.h" 85da0fc9dSDennis Dalessandro 95da0fc9dSDennis Dalessandro void iowait_set_flag(struct iowait *wait, u32 flag) 105da0fc9dSDennis Dalessandro { 11*15b796bcSKaike Wan trace_hfi1_iowait_set(wait, flag); 125da0fc9dSDennis Dalessandro set_bit(flag, &wait->flags); 135da0fc9dSDennis Dalessandro } 145da0fc9dSDennis Dalessandro 155da0fc9dSDennis Dalessandro bool iowait_flag_set(struct iowait *wait, u32 flag) 165da0fc9dSDennis Dalessandro { 175da0fc9dSDennis Dalessandro return test_bit(flag, &wait->flags); 185da0fc9dSDennis Dalessandro } 195da0fc9dSDennis Dalessandro 205da0fc9dSDennis Dalessandro inline void iowait_clear_flag(struct iowait *wait, u32 flag) 215da0fc9dSDennis Dalessandro { 22*15b796bcSKaike Wan trace_hfi1_iowait_clear(wait, flag); 235da0fc9dSDennis Dalessandro clear_bit(flag, &wait->flags); 245da0fc9dSDennis Dalessandro } 255da0fc9dSDennis Dalessandro 265da0fc9dSDennis Dalessandro /** 275da0fc9dSDennis Dalessandro * iowait_init() - initialize wait structure 285da0fc9dSDennis Dalessandro * @wait: wait struct to initialize 295da0fc9dSDennis Dalessandro * @tx_limit: limit for overflow queuing 305da0fc9dSDennis Dalessandro * @func: restart function for workqueue 315da0fc9dSDennis Dalessandro * @sleep: sleep function for no space 325da0fc9dSDennis Dalessandro * @resume: wakeup function for no space 335da0fc9dSDennis Dalessandro * 345da0fc9dSDennis Dalessandro * This function initializes the iowait 355da0fc9dSDennis Dalessandro * structure embedded in the QP or PQ. 365da0fc9dSDennis Dalessandro * 375da0fc9dSDennis Dalessandro */ 385da0fc9dSDennis Dalessandro void iowait_init(struct iowait *wait, u32 tx_limit, 395da0fc9dSDennis Dalessandro void (*func)(struct work_struct *work), 405da0fc9dSDennis Dalessandro void (*tidfunc)(struct work_struct *work), 415da0fc9dSDennis Dalessandro int (*sleep)(struct sdma_engine *sde, 425da0fc9dSDennis Dalessandro struct iowait_work *wait, 435da0fc9dSDennis Dalessandro struct sdma_txreq *tx, 445da0fc9dSDennis Dalessandro uint seq, 455da0fc9dSDennis Dalessandro bool pkts_sent), 465da0fc9dSDennis Dalessandro void (*wakeup)(struct iowait *wait, int reason), 475da0fc9dSDennis Dalessandro void (*sdma_drained)(struct iowait *wait)) 485da0fc9dSDennis Dalessandro { 495da0fc9dSDennis Dalessandro int i; 505da0fc9dSDennis Dalessandro 515da0fc9dSDennis Dalessandro wait->count = 0; 525da0fc9dSDennis Dalessandro INIT_LIST_HEAD(&wait->list); 535da0fc9dSDennis Dalessandro init_waitqueue_head(&wait->wait_dma); 545da0fc9dSDennis Dalessandro init_waitqueue_head(&wait->wait_pio); 555da0fc9dSDennis Dalessandro atomic_set(&wait->sdma_busy, 0); 565da0fc9dSDennis Dalessandro atomic_set(&wait->pio_busy, 0); 575da0fc9dSDennis Dalessandro wait->tx_limit = tx_limit; 585da0fc9dSDennis Dalessandro wait->sleep = sleep; 595da0fc9dSDennis Dalessandro wait->wakeup = wakeup; 605da0fc9dSDennis Dalessandro wait->sdma_drained = sdma_drained; 615da0fc9dSDennis Dalessandro wait->flags = 0; 625da0fc9dSDennis Dalessandro for (i = 0; i < IOWAIT_SES; i++) { 635da0fc9dSDennis Dalessandro wait->wait[i].iow = wait; 645da0fc9dSDennis Dalessandro INIT_LIST_HEAD(&wait->wait[i].tx_head); 655da0fc9dSDennis Dalessandro if (i == IOWAIT_IB_SE) 665da0fc9dSDennis Dalessandro INIT_WORK(&wait->wait[i].iowork, func); 675da0fc9dSDennis Dalessandro else 685da0fc9dSDennis Dalessandro INIT_WORK(&wait->wait[i].iowork, tidfunc); 695da0fc9dSDennis Dalessandro } 705da0fc9dSDennis Dalessandro } 715da0fc9dSDennis Dalessandro 725da0fc9dSDennis Dalessandro /** 735da0fc9dSDennis Dalessandro * iowait_cancel_work - cancel all work in iowait 745da0fc9dSDennis Dalessandro * @w: the iowait struct 755da0fc9dSDennis Dalessandro */ 765da0fc9dSDennis Dalessandro void iowait_cancel_work(struct iowait *w) 775da0fc9dSDennis Dalessandro { 785da0fc9dSDennis Dalessandro cancel_work_sync(&iowait_get_ib_work(w)->iowork); 795da0fc9dSDennis Dalessandro cancel_work_sync(&iowait_get_tid_work(w)->iowork); 805da0fc9dSDennis Dalessandro } 815da0fc9dSDennis Dalessandro 825da0fc9dSDennis Dalessandro /** 835da0fc9dSDennis Dalessandro * iowait_set_work_flag - set work flag based on leg 845da0fc9dSDennis Dalessandro * @w - the iowait work struct 855da0fc9dSDennis Dalessandro */ 865da0fc9dSDennis Dalessandro int iowait_set_work_flag(struct iowait_work *w) 875da0fc9dSDennis Dalessandro { 885da0fc9dSDennis Dalessandro if (w == &w->iow->wait[IOWAIT_IB_SE]) { 895da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_IB); 905da0fc9dSDennis Dalessandro return IOWAIT_IB_SE; 915da0fc9dSDennis Dalessandro } 925da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_TID); 935da0fc9dSDennis Dalessandro return IOWAIT_TID_SE; 945da0fc9dSDennis Dalessandro } 95