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" 715b796bcSKaike Wan #include "trace_iowait.h" 85da0fc9dSDennis Dalessandro 9*34025fb0SKaike Wan /* 1 priority == 16 starve_cnt */ 10*34025fb0SKaike Wan #define IOWAIT_PRIORITY_STARVE_SHIFT 4 11*34025fb0SKaike Wan 125da0fc9dSDennis Dalessandro void iowait_set_flag(struct iowait *wait, u32 flag) 135da0fc9dSDennis Dalessandro { 1415b796bcSKaike Wan trace_hfi1_iowait_set(wait, flag); 155da0fc9dSDennis Dalessandro set_bit(flag, &wait->flags); 165da0fc9dSDennis Dalessandro } 175da0fc9dSDennis Dalessandro 185da0fc9dSDennis Dalessandro bool iowait_flag_set(struct iowait *wait, u32 flag) 195da0fc9dSDennis Dalessandro { 205da0fc9dSDennis Dalessandro return test_bit(flag, &wait->flags); 215da0fc9dSDennis Dalessandro } 225da0fc9dSDennis Dalessandro 235da0fc9dSDennis Dalessandro inline void iowait_clear_flag(struct iowait *wait, u32 flag) 245da0fc9dSDennis Dalessandro { 2515b796bcSKaike Wan trace_hfi1_iowait_clear(wait, flag); 265da0fc9dSDennis Dalessandro clear_bit(flag, &wait->flags); 275da0fc9dSDennis Dalessandro } 285da0fc9dSDennis Dalessandro 295da0fc9dSDennis Dalessandro /** 305da0fc9dSDennis Dalessandro * iowait_init() - initialize wait structure 315da0fc9dSDennis Dalessandro * @wait: wait struct to initialize 325da0fc9dSDennis Dalessandro * @tx_limit: limit for overflow queuing 335da0fc9dSDennis Dalessandro * @func: restart function for workqueue 345da0fc9dSDennis Dalessandro * @sleep: sleep function for no space 355da0fc9dSDennis Dalessandro * @resume: wakeup function for no space 365da0fc9dSDennis Dalessandro * 375da0fc9dSDennis Dalessandro * This function initializes the iowait 385da0fc9dSDennis Dalessandro * structure embedded in the QP or PQ. 395da0fc9dSDennis Dalessandro * 405da0fc9dSDennis Dalessandro */ 415da0fc9dSDennis Dalessandro void iowait_init(struct iowait *wait, u32 tx_limit, 425da0fc9dSDennis Dalessandro void (*func)(struct work_struct *work), 435da0fc9dSDennis Dalessandro void (*tidfunc)(struct work_struct *work), 445da0fc9dSDennis Dalessandro int (*sleep)(struct sdma_engine *sde, 455da0fc9dSDennis Dalessandro struct iowait_work *wait, 465da0fc9dSDennis Dalessandro struct sdma_txreq *tx, 475da0fc9dSDennis Dalessandro uint seq, 485da0fc9dSDennis Dalessandro bool pkts_sent), 495da0fc9dSDennis Dalessandro void (*wakeup)(struct iowait *wait, int reason), 50*34025fb0SKaike Wan void (*sdma_drained)(struct iowait *wait), 51*34025fb0SKaike Wan void (*init_priority)(struct iowait *wait)) 525da0fc9dSDennis Dalessandro { 535da0fc9dSDennis Dalessandro int i; 545da0fc9dSDennis Dalessandro 555da0fc9dSDennis Dalessandro wait->count = 0; 565da0fc9dSDennis Dalessandro INIT_LIST_HEAD(&wait->list); 575da0fc9dSDennis Dalessandro init_waitqueue_head(&wait->wait_dma); 585da0fc9dSDennis Dalessandro init_waitqueue_head(&wait->wait_pio); 595da0fc9dSDennis Dalessandro atomic_set(&wait->sdma_busy, 0); 605da0fc9dSDennis Dalessandro atomic_set(&wait->pio_busy, 0); 615da0fc9dSDennis Dalessandro wait->tx_limit = tx_limit; 625da0fc9dSDennis Dalessandro wait->sleep = sleep; 635da0fc9dSDennis Dalessandro wait->wakeup = wakeup; 645da0fc9dSDennis Dalessandro wait->sdma_drained = sdma_drained; 65*34025fb0SKaike Wan wait->init_priority = init_priority; 665da0fc9dSDennis Dalessandro wait->flags = 0; 675da0fc9dSDennis Dalessandro for (i = 0; i < IOWAIT_SES; i++) { 685da0fc9dSDennis Dalessandro wait->wait[i].iow = wait; 695da0fc9dSDennis Dalessandro INIT_LIST_HEAD(&wait->wait[i].tx_head); 705da0fc9dSDennis Dalessandro if (i == IOWAIT_IB_SE) 715da0fc9dSDennis Dalessandro INIT_WORK(&wait->wait[i].iowork, func); 725da0fc9dSDennis Dalessandro else 735da0fc9dSDennis Dalessandro INIT_WORK(&wait->wait[i].iowork, tidfunc); 745da0fc9dSDennis Dalessandro } 755da0fc9dSDennis Dalessandro } 765da0fc9dSDennis Dalessandro 775da0fc9dSDennis Dalessandro /** 785da0fc9dSDennis Dalessandro * iowait_cancel_work - cancel all work in iowait 795da0fc9dSDennis Dalessandro * @w: the iowait struct 805da0fc9dSDennis Dalessandro */ 815da0fc9dSDennis Dalessandro void iowait_cancel_work(struct iowait *w) 825da0fc9dSDennis Dalessandro { 835da0fc9dSDennis Dalessandro cancel_work_sync(&iowait_get_ib_work(w)->iowork); 845da0fc9dSDennis Dalessandro cancel_work_sync(&iowait_get_tid_work(w)->iowork); 855da0fc9dSDennis Dalessandro } 865da0fc9dSDennis Dalessandro 875da0fc9dSDennis Dalessandro /** 885da0fc9dSDennis Dalessandro * iowait_set_work_flag - set work flag based on leg 895da0fc9dSDennis Dalessandro * @w - the iowait work struct 905da0fc9dSDennis Dalessandro */ 915da0fc9dSDennis Dalessandro int iowait_set_work_flag(struct iowait_work *w) 925da0fc9dSDennis Dalessandro { 935da0fc9dSDennis Dalessandro if (w == &w->iow->wait[IOWAIT_IB_SE]) { 945da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_IB); 955da0fc9dSDennis Dalessandro return IOWAIT_IB_SE; 965da0fc9dSDennis Dalessandro } 975da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_TID); 985da0fc9dSDennis Dalessandro return IOWAIT_TID_SE; 995da0fc9dSDennis Dalessandro } 100*34025fb0SKaike Wan 101*34025fb0SKaike Wan /** 102*34025fb0SKaike Wan * iowait_priority_update_top - update the top priority entry 103*34025fb0SKaike Wan * @w: the iowait struct 104*34025fb0SKaike Wan * @top: a pointer to the top priority entry 105*34025fb0SKaike Wan * @idx: the index of the current iowait in an array 106*34025fb0SKaike Wan * @top_idx: the array index for the iowait entry that has the top priority 107*34025fb0SKaike Wan * 108*34025fb0SKaike Wan * This function is called to compare the priority of a given 109*34025fb0SKaike Wan * iowait with the given top priority entry. The top index will 110*34025fb0SKaike Wan * be returned. 111*34025fb0SKaike Wan */ 112*34025fb0SKaike Wan uint iowait_priority_update_top(struct iowait *w, 113*34025fb0SKaike Wan struct iowait *top, 114*34025fb0SKaike Wan uint idx, uint top_idx) 115*34025fb0SKaike Wan { 116*34025fb0SKaike Wan u8 cnt, tcnt; 117*34025fb0SKaike Wan 118*34025fb0SKaike Wan /* Convert priority into starve_cnt and compare the total.*/ 119*34025fb0SKaike Wan cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt; 120*34025fb0SKaike Wan tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + 121*34025fb0SKaike Wan top->starved_cnt; 122*34025fb0SKaike Wan if (cnt > tcnt) 123*34025fb0SKaike Wan return idx; 124*34025fb0SKaike Wan else 125*34025fb0SKaike Wan return top_idx; 126*34025fb0SKaike Wan } 127