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
iowait_set_flag(struct iowait * wait,u32 flag)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
iowait_flag_set(struct iowait * wait,u32 flag)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
iowait_clear_flag(struct iowait * wait,u32 flag)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 */
iowait_init(struct iowait * wait,u32 tx_limit,void (* func)(struct work_struct * work),void (* tidfunc)(struct work_struct * work),int (* sleep)(struct sdma_engine * sde,struct iowait_work * wait,struct sdma_txreq * tx,uint seq,bool pkts_sent),void (* wakeup)(struct iowait * wait,int reason),void (* sdma_drained)(struct iowait * wait),void (* init_priority)(struct iowait * wait))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 */
iowait_cancel_work(struct iowait * w)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 */
iowait_set_work_flag(struct iowait_work * w)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 */
iowait_priority_update_top(struct iowait * w,struct iowait * top,uint idx,uint top_idx)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