18c2ecf20Sopenharmony_ci#ifndef _HFI1_IOWAIT_H 28c2ecf20Sopenharmony_ci#define _HFI1_IOWAIT_H 38c2ecf20Sopenharmony_ci/* 48c2ecf20Sopenharmony_ci * Copyright(c) 2015 - 2018 Intel Corporation. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 78c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 128c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 138c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 168c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 178c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 188c2ecf20Sopenharmony_ci * General Public License for more details. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * BSD LICENSE 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 238c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 248c2ecf20Sopenharmony_ci * are met: 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above copyright 278c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 288c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright 298c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 308c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 318c2ecf20Sopenharmony_ci * distribution. 328c2ecf20Sopenharmony_ci * - Neither the name of Intel Corporation nor the names of its 338c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 348c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 378c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 388c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 398c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 408c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 418c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 428c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 438c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 448c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 458c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 468c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#include <linux/list.h> 518c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 528c2ecf20Sopenharmony_ci#include <linux/wait.h> 538c2ecf20Sopenharmony_ci#include <linux/sched.h> 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#include "sdma_txreq.h" 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * typedef (*restart_t)() - restart callback 598c2ecf20Sopenharmony_ci * @work: pointer to work structure 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_citypedef void (*restart_t)(struct work_struct *work); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define IOWAIT_PENDING_IB 0x0 648c2ecf20Sopenharmony_ci#define IOWAIT_PENDING_TID 0x1 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* 678c2ecf20Sopenharmony_ci * A QP can have multiple Send Engines (SEs). 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * The current use case is for supporting a TID RDMA 708c2ecf20Sopenharmony_ci * packet build/xmit mechanism independent from verbs. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci#define IOWAIT_SES 2 738c2ecf20Sopenharmony_ci#define IOWAIT_IB_SE 0 748c2ecf20Sopenharmony_ci#define IOWAIT_TID_SE 1 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct sdma_txreq; 778c2ecf20Sopenharmony_cistruct sdma_engine; 788c2ecf20Sopenharmony_ci/** 798c2ecf20Sopenharmony_ci * @iowork: the work struct 808c2ecf20Sopenharmony_ci * @tx_head: list of prebuilt packets 818c2ecf20Sopenharmony_ci * @iow: the parent iowait structure 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * This structure is the work item (process) specific 848c2ecf20Sopenharmony_ci * details associated with the each of the two SEs of the 858c2ecf20Sopenharmony_ci * QP. 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * The workstruct and the queued TXs are unique to each 888c2ecf20Sopenharmony_ci * SE. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_cistruct iowait; 918c2ecf20Sopenharmony_cistruct iowait_work { 928c2ecf20Sopenharmony_ci struct work_struct iowork; 938c2ecf20Sopenharmony_ci struct list_head tx_head; 948c2ecf20Sopenharmony_ci struct iowait *iow; 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/** 988c2ecf20Sopenharmony_ci * @list: used to add/insert into QP/PQ wait lists 998c2ecf20Sopenharmony_ci * @tx_head: overflow list of sdma_txreq's 1008c2ecf20Sopenharmony_ci * @sleep: no space callback 1018c2ecf20Sopenharmony_ci * @wakeup: space callback wakeup 1028c2ecf20Sopenharmony_ci * @sdma_drained: sdma count drained 1038c2ecf20Sopenharmony_ci * @init_priority: callback to manipulate priority 1048c2ecf20Sopenharmony_ci * @lock: lock protected head of wait queue 1058c2ecf20Sopenharmony_ci * @iowork: workqueue overhead 1068c2ecf20Sopenharmony_ci * @wait_dma: wait for sdma_busy == 0 1078c2ecf20Sopenharmony_ci * @wait_pio: wait for pio_busy == 0 1088c2ecf20Sopenharmony_ci * @sdma_busy: # of packets in flight 1098c2ecf20Sopenharmony_ci * @count: total number of descriptors in tx_head'ed list 1108c2ecf20Sopenharmony_ci * @tx_limit: limit for overflow queuing 1118c2ecf20Sopenharmony_ci * @tx_count: number of tx entry's in tx_head'ed list 1128c2ecf20Sopenharmony_ci * @flags: wait flags (one per QP) 1138c2ecf20Sopenharmony_ci * @wait: SE array for multiple legs 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * This is to be embedded in user's state structure 1168c2ecf20Sopenharmony_ci * (QP or PQ). 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * The sleep and wakeup members are a 1198c2ecf20Sopenharmony_ci * bit misnamed. They do not strictly 1208c2ecf20Sopenharmony_ci * speaking sleep or wake up, but they 1218c2ecf20Sopenharmony_ci * are callbacks for the ULP to implement 1228c2ecf20Sopenharmony_ci * what ever queuing/dequeuing of 1238c2ecf20Sopenharmony_ci * the embedded iowait and its containing struct 1248c2ecf20Sopenharmony_ci * when a resource shortage like SDMA ring space 1258c2ecf20Sopenharmony_ci * or PIO credit space is seen. 1268c2ecf20Sopenharmony_ci * 1278c2ecf20Sopenharmony_ci * Both potentially have locks help 1288c2ecf20Sopenharmony_ci * so sleeping is not allowed and it is not 1298c2ecf20Sopenharmony_ci * supported to submit txreqs from the wakeup 1308c2ecf20Sopenharmony_ci * call directly because of lock conflicts. 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * The wait_dma member along with the iow 1338c2ecf20Sopenharmony_ci * 1348c2ecf20Sopenharmony_ci * The lock field is used by waiters to record 1358c2ecf20Sopenharmony_ci * the seqlock_t that guards the list head. 1368c2ecf20Sopenharmony_ci * Waiters explicity know that, but the destroy 1378c2ecf20Sopenharmony_ci * code that unwaits QPs does not. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_cistruct iowait { 1408c2ecf20Sopenharmony_ci struct list_head list; 1418c2ecf20Sopenharmony_ci int (*sleep)( 1428c2ecf20Sopenharmony_ci struct sdma_engine *sde, 1438c2ecf20Sopenharmony_ci struct iowait_work *wait, 1448c2ecf20Sopenharmony_ci struct sdma_txreq *tx, 1458c2ecf20Sopenharmony_ci uint seq, 1468c2ecf20Sopenharmony_ci bool pkts_sent 1478c2ecf20Sopenharmony_ci ); 1488c2ecf20Sopenharmony_ci void (*wakeup)(struct iowait *wait, int reason); 1498c2ecf20Sopenharmony_ci void (*sdma_drained)(struct iowait *wait); 1508c2ecf20Sopenharmony_ci void (*init_priority)(struct iowait *wait); 1518c2ecf20Sopenharmony_ci seqlock_t *lock; 1528c2ecf20Sopenharmony_ci wait_queue_head_t wait_dma; 1538c2ecf20Sopenharmony_ci wait_queue_head_t wait_pio; 1548c2ecf20Sopenharmony_ci atomic_t sdma_busy; 1558c2ecf20Sopenharmony_ci atomic_t pio_busy; 1568c2ecf20Sopenharmony_ci u32 count; 1578c2ecf20Sopenharmony_ci u32 tx_limit; 1588c2ecf20Sopenharmony_ci u32 tx_count; 1598c2ecf20Sopenharmony_ci u8 starved_cnt; 1608c2ecf20Sopenharmony_ci u8 priority; 1618c2ecf20Sopenharmony_ci unsigned long flags; 1628c2ecf20Sopenharmony_ci struct iowait_work wait[IOWAIT_SES]; 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci#define SDMA_AVAIL_REASON 0 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_civoid iowait_set_flag(struct iowait *wait, u32 flag); 1688c2ecf20Sopenharmony_cibool iowait_flag_set(struct iowait *wait, u32 flag); 1698c2ecf20Sopenharmony_civoid iowait_clear_flag(struct iowait *wait, u32 flag); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_civoid iowait_init(struct iowait *wait, u32 tx_limit, 1728c2ecf20Sopenharmony_ci void (*func)(struct work_struct *work), 1738c2ecf20Sopenharmony_ci void (*tidfunc)(struct work_struct *work), 1748c2ecf20Sopenharmony_ci int (*sleep)(struct sdma_engine *sde, 1758c2ecf20Sopenharmony_ci struct iowait_work *wait, 1768c2ecf20Sopenharmony_ci struct sdma_txreq *tx, 1778c2ecf20Sopenharmony_ci uint seq, 1788c2ecf20Sopenharmony_ci bool pkts_sent), 1798c2ecf20Sopenharmony_ci void (*wakeup)(struct iowait *wait, int reason), 1808c2ecf20Sopenharmony_ci void (*sdma_drained)(struct iowait *wait), 1818c2ecf20Sopenharmony_ci void (*init_priority)(struct iowait *wait)); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/** 1848c2ecf20Sopenharmony_ci * iowait_schedule() - schedule the default send engine work 1858c2ecf20Sopenharmony_ci * @wait: wait struct to schedule 1868c2ecf20Sopenharmony_ci * @wq: workqueue for schedule 1878c2ecf20Sopenharmony_ci * @cpu: cpu 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_cistatic inline bool iowait_schedule(struct iowait *wait, 1908c2ecf20Sopenharmony_ci struct workqueue_struct *wq, int cpu) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci return !!queue_work_on(cpu, wq, &wait->wait[IOWAIT_IB_SE].iowork); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/** 1968c2ecf20Sopenharmony_ci * iowait_tid_schedule - schedule the tid SE 1978c2ecf20Sopenharmony_ci * @wait: the iowait structure 1988c2ecf20Sopenharmony_ci * @wq: the work queue 1998c2ecf20Sopenharmony_ci * @cpu: the cpu 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_cistatic inline bool iowait_tid_schedule(struct iowait *wait, 2028c2ecf20Sopenharmony_ci struct workqueue_struct *wq, int cpu) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci return !!queue_work_on(cpu, wq, &wait->wait[IOWAIT_TID_SE].iowork); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/** 2088c2ecf20Sopenharmony_ci * iowait_sdma_drain() - wait for DMAs to drain 2098c2ecf20Sopenharmony_ci * 2108c2ecf20Sopenharmony_ci * @wait: iowait structure 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * This will delay until the iowait sdmas have 2138c2ecf20Sopenharmony_ci * completed. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_cistatic inline void iowait_sdma_drain(struct iowait *wait) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci wait_event(wait->wait_dma, !atomic_read(&wait->sdma_busy)); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/** 2218c2ecf20Sopenharmony_ci * iowait_sdma_pending() - return sdma pending count 2228c2ecf20Sopenharmony_ci * 2238c2ecf20Sopenharmony_ci * @wait: iowait structure 2248c2ecf20Sopenharmony_ci * 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_cistatic inline int iowait_sdma_pending(struct iowait *wait) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci return atomic_read(&wait->sdma_busy); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci/** 2328c2ecf20Sopenharmony_ci * iowait_sdma_inc - note sdma io pending 2338c2ecf20Sopenharmony_ci * @wait: iowait structure 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_cistatic inline void iowait_sdma_inc(struct iowait *wait) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci atomic_inc(&wait->sdma_busy); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/** 2418c2ecf20Sopenharmony_ci * iowait_sdma_add - add count to pending 2428c2ecf20Sopenharmony_ci * @wait: iowait structure 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cistatic inline void iowait_sdma_add(struct iowait *wait, int count) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci atomic_add(count, &wait->sdma_busy); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/** 2508c2ecf20Sopenharmony_ci * iowait_sdma_dec - note sdma complete 2518c2ecf20Sopenharmony_ci * @wait: iowait structure 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_cistatic inline int iowait_sdma_dec(struct iowait *wait) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci if (!wait) 2568c2ecf20Sopenharmony_ci return 0; 2578c2ecf20Sopenharmony_ci return atomic_dec_and_test(&wait->sdma_busy); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * iowait_pio_drain() - wait for pios to drain 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * @wait: iowait structure 2648c2ecf20Sopenharmony_ci * 2658c2ecf20Sopenharmony_ci * This will delay until the iowait pios have 2668c2ecf20Sopenharmony_ci * completed. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_cistatic inline void iowait_pio_drain(struct iowait *wait) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci wait_event_timeout(wait->wait_pio, 2718c2ecf20Sopenharmony_ci !atomic_read(&wait->pio_busy), 2728c2ecf20Sopenharmony_ci HZ); 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * iowait_pio_pending() - return pio pending count 2778c2ecf20Sopenharmony_ci * 2788c2ecf20Sopenharmony_ci * @wait: iowait structure 2798c2ecf20Sopenharmony_ci * 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_cistatic inline int iowait_pio_pending(struct iowait *wait) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci return atomic_read(&wait->pio_busy); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci/** 2878c2ecf20Sopenharmony_ci * iowait_pio_inc - note pio pending 2888c2ecf20Sopenharmony_ci * @wait: iowait structure 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_cistatic inline void iowait_pio_inc(struct iowait *wait) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci atomic_inc(&wait->pio_busy); 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci/** 2968c2ecf20Sopenharmony_ci * iowait_pio_dec - note pio complete 2978c2ecf20Sopenharmony_ci * @wait: iowait structure 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_cistatic inline int iowait_pio_dec(struct iowait *wait) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci if (!wait) 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci return atomic_dec_and_test(&wait->pio_busy); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci/** 3078c2ecf20Sopenharmony_ci * iowait_drain_wakeup() - trigger iowait_drain() waiter 3088c2ecf20Sopenharmony_ci * 3098c2ecf20Sopenharmony_ci * @wait: iowait structure 3108c2ecf20Sopenharmony_ci * 3118c2ecf20Sopenharmony_ci * This will trigger any waiters. 3128c2ecf20Sopenharmony_ci */ 3138c2ecf20Sopenharmony_cistatic inline void iowait_drain_wakeup(struct iowait *wait) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci wake_up(&wait->wait_dma); 3168c2ecf20Sopenharmony_ci wake_up(&wait->wait_pio); 3178c2ecf20Sopenharmony_ci if (wait->sdma_drained) 3188c2ecf20Sopenharmony_ci wait->sdma_drained(wait); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci/** 3228c2ecf20Sopenharmony_ci * iowait_get_txhead() - get packet off of iowait list 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * @wait iowait_work struture 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_cistatic inline struct sdma_txreq *iowait_get_txhead(struct iowait_work *wait) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct sdma_txreq *tx = NULL; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (!list_empty(&wait->tx_head)) { 3318c2ecf20Sopenharmony_ci tx = list_first_entry( 3328c2ecf20Sopenharmony_ci &wait->tx_head, 3338c2ecf20Sopenharmony_ci struct sdma_txreq, 3348c2ecf20Sopenharmony_ci list); 3358c2ecf20Sopenharmony_ci list_del_init(&tx->list); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci return tx; 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic inline u16 iowait_get_desc(struct iowait_work *w) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci u16 num_desc = 0; 3438c2ecf20Sopenharmony_ci struct sdma_txreq *tx = NULL; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (!list_empty(&w->tx_head)) { 3468c2ecf20Sopenharmony_ci tx = list_first_entry(&w->tx_head, struct sdma_txreq, 3478c2ecf20Sopenharmony_ci list); 3488c2ecf20Sopenharmony_ci num_desc = tx->num_desc; 3498c2ecf20Sopenharmony_ci if (tx->flags & SDMA_TXREQ_F_VIP) 3508c2ecf20Sopenharmony_ci w->iow->priority++; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci return num_desc; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic inline u32 iowait_get_all_desc(struct iowait *w) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci u32 num_desc = 0; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci num_desc = iowait_get_desc(&w->wait[IOWAIT_IB_SE]); 3608c2ecf20Sopenharmony_ci num_desc += iowait_get_desc(&w->wait[IOWAIT_TID_SE]); 3618c2ecf20Sopenharmony_ci return num_desc; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic inline void iowait_update_priority(struct iowait_work *w) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct sdma_txreq *tx = NULL; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (!list_empty(&w->tx_head)) { 3698c2ecf20Sopenharmony_ci tx = list_first_entry(&w->tx_head, struct sdma_txreq, 3708c2ecf20Sopenharmony_ci list); 3718c2ecf20Sopenharmony_ci if (tx->flags & SDMA_TXREQ_F_VIP) 3728c2ecf20Sopenharmony_ci w->iow->priority++; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic inline void iowait_update_all_priority(struct iowait *w) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci iowait_update_priority(&w->wait[IOWAIT_IB_SE]); 3798c2ecf20Sopenharmony_ci iowait_update_priority(&w->wait[IOWAIT_TID_SE]); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic inline void iowait_init_priority(struct iowait *w) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci w->priority = 0; 3858c2ecf20Sopenharmony_ci if (w->init_priority) 3868c2ecf20Sopenharmony_ci w->init_priority(w); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic inline void iowait_get_priority(struct iowait *w) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci iowait_init_priority(w); 3928c2ecf20Sopenharmony_ci iowait_update_all_priority(w); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/** 3968c2ecf20Sopenharmony_ci * iowait_queue - Put the iowait on a wait queue 3978c2ecf20Sopenharmony_ci * @pkts_sent: have some packets been sent before queuing? 3988c2ecf20Sopenharmony_ci * @w: the iowait struct 3998c2ecf20Sopenharmony_ci * @wait_head: the wait queue 4008c2ecf20Sopenharmony_ci * 4018c2ecf20Sopenharmony_ci * This function is called to insert an iowait struct into a 4028c2ecf20Sopenharmony_ci * wait queue after a resource (eg, sdma descriptor or pio 4038c2ecf20Sopenharmony_ci * buffer) is run out. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_cistatic inline void iowait_queue(bool pkts_sent, struct iowait *w, 4068c2ecf20Sopenharmony_ci struct list_head *wait_head) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci /* 4098c2ecf20Sopenharmony_ci * To play fair, insert the iowait at the tail of the wait queue if it 4108c2ecf20Sopenharmony_ci * has already sent some packets; Otherwise, put it at the head. 4118c2ecf20Sopenharmony_ci * However, if it has priority packets to send, also put it at the 4128c2ecf20Sopenharmony_ci * head. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci if (pkts_sent) 4158c2ecf20Sopenharmony_ci w->starved_cnt = 0; 4168c2ecf20Sopenharmony_ci else 4178c2ecf20Sopenharmony_ci w->starved_cnt++; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci if (w->priority > 0 || !pkts_sent) 4208c2ecf20Sopenharmony_ci list_add(&w->list, wait_head); 4218c2ecf20Sopenharmony_ci else 4228c2ecf20Sopenharmony_ci list_add_tail(&w->list, wait_head); 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci/** 4268c2ecf20Sopenharmony_ci * iowait_starve_clear - clear the wait queue's starve count 4278c2ecf20Sopenharmony_ci * @pkts_sent: have some packets been sent? 4288c2ecf20Sopenharmony_ci * @w: the iowait struct 4298c2ecf20Sopenharmony_ci * 4308c2ecf20Sopenharmony_ci * This function is called to clear the starve count. If no 4318c2ecf20Sopenharmony_ci * packets have been sent, the starve count will not be cleared. 4328c2ecf20Sopenharmony_ci */ 4338c2ecf20Sopenharmony_cistatic inline void iowait_starve_clear(bool pkts_sent, struct iowait *w) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci if (pkts_sent) 4368c2ecf20Sopenharmony_ci w->starved_cnt = 0; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* Update the top priority index */ 4408c2ecf20Sopenharmony_ciuint iowait_priority_update_top(struct iowait *w, 4418c2ecf20Sopenharmony_ci struct iowait *top, 4428c2ecf20Sopenharmony_ci uint idx, uint top_idx); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci/** 4458c2ecf20Sopenharmony_ci * iowait_packet_queued() - determine if a packet is queued 4468c2ecf20Sopenharmony_ci * @wait: the iowait_work structure 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_cistatic inline bool iowait_packet_queued(struct iowait_work *wait) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci return !list_empty(&wait->tx_head); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci/** 4548c2ecf20Sopenharmony_ci * inc_wait_count - increment wait counts 4558c2ecf20Sopenharmony_ci * @w: the log work struct 4568c2ecf20Sopenharmony_ci * @n: the count 4578c2ecf20Sopenharmony_ci */ 4588c2ecf20Sopenharmony_cistatic inline void iowait_inc_wait_count(struct iowait_work *w, u16 n) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci if (!w) 4618c2ecf20Sopenharmony_ci return; 4628c2ecf20Sopenharmony_ci w->iow->tx_count++; 4638c2ecf20Sopenharmony_ci w->iow->count += n; 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci/** 4678c2ecf20Sopenharmony_ci * iowait_get_tid_work - return iowait_work for tid SE 4688c2ecf20Sopenharmony_ci * @w: the iowait struct 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_cistatic inline struct iowait_work *iowait_get_tid_work(struct iowait *w) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci return &w->wait[IOWAIT_TID_SE]; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci/** 4768c2ecf20Sopenharmony_ci * iowait_get_ib_work - return iowait_work for ib SE 4778c2ecf20Sopenharmony_ci * @w: the iowait struct 4788c2ecf20Sopenharmony_ci */ 4798c2ecf20Sopenharmony_cistatic inline struct iowait_work *iowait_get_ib_work(struct iowait *w) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci return &w->wait[IOWAIT_IB_SE]; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci/** 4858c2ecf20Sopenharmony_ci * iowait_ioww_to_iow - return iowait given iowait_work 4868c2ecf20Sopenharmony_ci * @w: the iowait_work struct 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_cistatic inline struct iowait *iowait_ioww_to_iow(struct iowait_work *w) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci if (likely(w)) 4918c2ecf20Sopenharmony_ci return w->iow; 4928c2ecf20Sopenharmony_ci return NULL; 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_civoid iowait_cancel_work(struct iowait *w); 4968c2ecf20Sopenharmony_ciint iowait_set_work_flag(struct iowait_work *w); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci#endif 499