162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2018 Intel Corporation. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "iowait.h" 762306a36Sopenharmony_ci#include "trace_iowait.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1 priority == 16 starve_cnt */ 1062306a36Sopenharmony_ci#define IOWAIT_PRIORITY_STARVE_SHIFT 4 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_civoid iowait_set_flag(struct iowait *wait, u32 flag) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci trace_hfi1_iowait_set(wait, flag); 1562306a36Sopenharmony_ci set_bit(flag, &wait->flags); 1662306a36Sopenharmony_ci} 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cibool iowait_flag_set(struct iowait *wait, u32 flag) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci return test_bit(flag, &wait->flags); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciinline void iowait_clear_flag(struct iowait *wait, u32 flag) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci trace_hfi1_iowait_clear(wait, flag); 2662306a36Sopenharmony_ci clear_bit(flag, &wait->flags); 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * iowait_init() - initialize wait structure 3162306a36Sopenharmony_ci * @wait: wait struct to initialize 3262306a36Sopenharmony_ci * @tx_limit: limit for overflow queuing 3362306a36Sopenharmony_ci * @func: restart function for workqueue 3462306a36Sopenharmony_ci * @sleep: sleep function for no space 3562306a36Sopenharmony_ci * @resume: wakeup function for no space 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * This function initializes the iowait 3862306a36Sopenharmony_ci * structure embedded in the QP or PQ. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_civoid iowait_init(struct iowait *wait, u32 tx_limit, 4262306a36Sopenharmony_ci void (*func)(struct work_struct *work), 4362306a36Sopenharmony_ci void (*tidfunc)(struct work_struct *work), 4462306a36Sopenharmony_ci int (*sleep)(struct sdma_engine *sde, 4562306a36Sopenharmony_ci struct iowait_work *wait, 4662306a36Sopenharmony_ci struct sdma_txreq *tx, 4762306a36Sopenharmony_ci uint seq, 4862306a36Sopenharmony_ci bool pkts_sent), 4962306a36Sopenharmony_ci void (*wakeup)(struct iowait *wait, int reason), 5062306a36Sopenharmony_ci void (*sdma_drained)(struct iowait *wait), 5162306a36Sopenharmony_ci void (*init_priority)(struct iowait *wait)) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci int i; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci wait->count = 0; 5662306a36Sopenharmony_ci INIT_LIST_HEAD(&wait->list); 5762306a36Sopenharmony_ci init_waitqueue_head(&wait->wait_dma); 5862306a36Sopenharmony_ci init_waitqueue_head(&wait->wait_pio); 5962306a36Sopenharmony_ci atomic_set(&wait->sdma_busy, 0); 6062306a36Sopenharmony_ci atomic_set(&wait->pio_busy, 0); 6162306a36Sopenharmony_ci wait->tx_limit = tx_limit; 6262306a36Sopenharmony_ci wait->sleep = sleep; 6362306a36Sopenharmony_ci wait->wakeup = wakeup; 6462306a36Sopenharmony_ci wait->sdma_drained = sdma_drained; 6562306a36Sopenharmony_ci wait->init_priority = init_priority; 6662306a36Sopenharmony_ci wait->flags = 0; 6762306a36Sopenharmony_ci for (i = 0; i < IOWAIT_SES; i++) { 6862306a36Sopenharmony_ci wait->wait[i].iow = wait; 6962306a36Sopenharmony_ci INIT_LIST_HEAD(&wait->wait[i].tx_head); 7062306a36Sopenharmony_ci if (i == IOWAIT_IB_SE) 7162306a36Sopenharmony_ci INIT_WORK(&wait->wait[i].iowork, func); 7262306a36Sopenharmony_ci else 7362306a36Sopenharmony_ci INIT_WORK(&wait->wait[i].iowork, tidfunc); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/** 7862306a36Sopenharmony_ci * iowait_cancel_work - cancel all work in iowait 7962306a36Sopenharmony_ci * @w: the iowait struct 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_civoid iowait_cancel_work(struct iowait *w) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci cancel_work_sync(&iowait_get_ib_work(w)->iowork); 8462306a36Sopenharmony_ci /* Make sure that the iowork for TID RDMA is used */ 8562306a36Sopenharmony_ci if (iowait_get_tid_work(w)->iowork.func) 8662306a36Sopenharmony_ci cancel_work_sync(&iowait_get_tid_work(w)->iowork); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/** 9062306a36Sopenharmony_ci * iowait_set_work_flag - set work flag based on leg 9162306a36Sopenharmony_ci * @w: the iowait work struct 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ciint iowait_set_work_flag(struct iowait_work *w) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci if (w == &w->iow->wait[IOWAIT_IB_SE]) { 9662306a36Sopenharmony_ci iowait_set_flag(w->iow, IOWAIT_PENDING_IB); 9762306a36Sopenharmony_ci return IOWAIT_IB_SE; 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci iowait_set_flag(w->iow, IOWAIT_PENDING_TID); 10062306a36Sopenharmony_ci return IOWAIT_TID_SE; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/** 10462306a36Sopenharmony_ci * iowait_priority_update_top - update the top priority entry 10562306a36Sopenharmony_ci * @w: the iowait struct 10662306a36Sopenharmony_ci * @top: a pointer to the top priority entry 10762306a36Sopenharmony_ci * @idx: the index of the current iowait in an array 10862306a36Sopenharmony_ci * @top_idx: the array index for the iowait entry that has the top priority 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * This function is called to compare the priority of a given 11162306a36Sopenharmony_ci * iowait with the given top priority entry. The top index will 11262306a36Sopenharmony_ci * be returned. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ciuint iowait_priority_update_top(struct iowait *w, 11562306a36Sopenharmony_ci struct iowait *top, 11662306a36Sopenharmony_ci uint idx, uint top_idx) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci u8 cnt, tcnt; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Convert priority into starve_cnt and compare the total.*/ 12162306a36Sopenharmony_ci cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt; 12262306a36Sopenharmony_ci tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + 12362306a36Sopenharmony_ci top->starved_cnt; 12462306a36Sopenharmony_ci if (cnt > tcnt) 12562306a36Sopenharmony_ci return idx; 12662306a36Sopenharmony_ci else 12762306a36Sopenharmony_ci return top_idx; 12862306a36Sopenharmony_ci} 129