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 934025fb0SKaike Wan /* 1 priority == 16 starve_cnt */ 1034025fb0SKaike Wan #define IOWAIT_PRIORITY_STARVE_SHIFT 4 1134025fb0SKaike 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 29*36da5370SLee Jones /* 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), 5034025fb0SKaike Wan void (*sdma_drained)(struct iowait *wait), 5134025fb0SKaike 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; 6534025fb0SKaike 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); 84ca9033baSKaike Wan /* Make sure that the iowork for TID RDMA is used */ 85ca9033baSKaike Wan if (iowait_get_tid_work(w)->iowork.func) 865da0fc9dSDennis Dalessandro cancel_work_sync(&iowait_get_tid_work(w)->iowork); 875da0fc9dSDennis Dalessandro } 885da0fc9dSDennis Dalessandro 895da0fc9dSDennis Dalessandro /** 905da0fc9dSDennis Dalessandro * iowait_set_work_flag - set work flag based on leg 91*36da5370SLee Jones * @w: the iowait work struct 925da0fc9dSDennis Dalessandro */ 935da0fc9dSDennis Dalessandro int iowait_set_work_flag(struct iowait_work *w) 945da0fc9dSDennis Dalessandro { 955da0fc9dSDennis Dalessandro if (w == &w->iow->wait[IOWAIT_IB_SE]) { 965da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_IB); 975da0fc9dSDennis Dalessandro return IOWAIT_IB_SE; 985da0fc9dSDennis Dalessandro } 995da0fc9dSDennis Dalessandro iowait_set_flag(w->iow, IOWAIT_PENDING_TID); 1005da0fc9dSDennis Dalessandro return IOWAIT_TID_SE; 1015da0fc9dSDennis Dalessandro } 10234025fb0SKaike Wan 10334025fb0SKaike Wan /** 10434025fb0SKaike Wan * iowait_priority_update_top - update the top priority entry 10534025fb0SKaike Wan * @w: the iowait struct 10634025fb0SKaike Wan * @top: a pointer to the top priority entry 10734025fb0SKaike Wan * @idx: the index of the current iowait in an array 10834025fb0SKaike Wan * @top_idx: the array index for the iowait entry that has the top priority 10934025fb0SKaike Wan * 11034025fb0SKaike Wan * This function is called to compare the priority of a given 11134025fb0SKaike Wan * iowait with the given top priority entry. The top index will 11234025fb0SKaike Wan * be returned. 11334025fb0SKaike Wan */ 11434025fb0SKaike Wan uint iowait_priority_update_top(struct iowait *w, 11534025fb0SKaike Wan struct iowait *top, 11634025fb0SKaike Wan uint idx, uint top_idx) 11734025fb0SKaike Wan { 11834025fb0SKaike Wan u8 cnt, tcnt; 11934025fb0SKaike Wan 12034025fb0SKaike Wan /* Convert priority into starve_cnt and compare the total.*/ 12134025fb0SKaike Wan cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt; 12234025fb0SKaike Wan tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + 12334025fb0SKaike Wan top->starved_cnt; 12434025fb0SKaike Wan if (cnt > tcnt) 12534025fb0SKaike Wan return idx; 12634025fb0SKaike Wan else 12734025fb0SKaike Wan return top_idx; 12834025fb0SKaike Wan } 129