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