xref: /openbmc/linux/drivers/infiniband/hw/hfi1/iowait.c (revision 15b796bc3d5cc8f776f5cb0770f9f3e8b282e4d1)
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"
7*15b796bcSKaike Wan #include "trace_iowait.h"
85da0fc9dSDennis Dalessandro 
95da0fc9dSDennis Dalessandro void iowait_set_flag(struct iowait *wait, u32 flag)
105da0fc9dSDennis Dalessandro {
11*15b796bcSKaike Wan 	trace_hfi1_iowait_set(wait, flag);
125da0fc9dSDennis Dalessandro 	set_bit(flag, &wait->flags);
135da0fc9dSDennis Dalessandro }
145da0fc9dSDennis Dalessandro 
155da0fc9dSDennis Dalessandro bool iowait_flag_set(struct iowait *wait, u32 flag)
165da0fc9dSDennis Dalessandro {
175da0fc9dSDennis Dalessandro 	return test_bit(flag, &wait->flags);
185da0fc9dSDennis Dalessandro }
195da0fc9dSDennis Dalessandro 
205da0fc9dSDennis Dalessandro inline void iowait_clear_flag(struct iowait *wait, u32 flag)
215da0fc9dSDennis Dalessandro {
22*15b796bcSKaike Wan 	trace_hfi1_iowait_clear(wait, flag);
235da0fc9dSDennis Dalessandro 	clear_bit(flag, &wait->flags);
245da0fc9dSDennis Dalessandro }
255da0fc9dSDennis Dalessandro 
265da0fc9dSDennis Dalessandro /**
275da0fc9dSDennis Dalessandro  * iowait_init() - initialize wait structure
285da0fc9dSDennis Dalessandro  * @wait: wait struct to initialize
295da0fc9dSDennis Dalessandro  * @tx_limit: limit for overflow queuing
305da0fc9dSDennis Dalessandro  * @func: restart function for workqueue
315da0fc9dSDennis Dalessandro  * @sleep: sleep function for no space
325da0fc9dSDennis Dalessandro  * @resume: wakeup function for no space
335da0fc9dSDennis Dalessandro  *
345da0fc9dSDennis Dalessandro  * This function initializes the iowait
355da0fc9dSDennis Dalessandro  * structure embedded in the QP or PQ.
365da0fc9dSDennis Dalessandro  *
375da0fc9dSDennis Dalessandro  */
385da0fc9dSDennis Dalessandro void iowait_init(struct iowait *wait, u32 tx_limit,
395da0fc9dSDennis Dalessandro 		 void (*func)(struct work_struct *work),
405da0fc9dSDennis Dalessandro 		 void (*tidfunc)(struct work_struct *work),
415da0fc9dSDennis Dalessandro 		 int (*sleep)(struct sdma_engine *sde,
425da0fc9dSDennis Dalessandro 			      struct iowait_work *wait,
435da0fc9dSDennis Dalessandro 			      struct sdma_txreq *tx,
445da0fc9dSDennis Dalessandro 			      uint seq,
455da0fc9dSDennis Dalessandro 			      bool pkts_sent),
465da0fc9dSDennis Dalessandro 		 void (*wakeup)(struct iowait *wait, int reason),
475da0fc9dSDennis Dalessandro 		 void (*sdma_drained)(struct iowait *wait))
485da0fc9dSDennis Dalessandro {
495da0fc9dSDennis Dalessandro 	int i;
505da0fc9dSDennis Dalessandro 
515da0fc9dSDennis Dalessandro 	wait->count = 0;
525da0fc9dSDennis Dalessandro 	INIT_LIST_HEAD(&wait->list);
535da0fc9dSDennis Dalessandro 	init_waitqueue_head(&wait->wait_dma);
545da0fc9dSDennis Dalessandro 	init_waitqueue_head(&wait->wait_pio);
555da0fc9dSDennis Dalessandro 	atomic_set(&wait->sdma_busy, 0);
565da0fc9dSDennis Dalessandro 	atomic_set(&wait->pio_busy, 0);
575da0fc9dSDennis Dalessandro 	wait->tx_limit = tx_limit;
585da0fc9dSDennis Dalessandro 	wait->sleep = sleep;
595da0fc9dSDennis Dalessandro 	wait->wakeup = wakeup;
605da0fc9dSDennis Dalessandro 	wait->sdma_drained = sdma_drained;
615da0fc9dSDennis Dalessandro 	wait->flags = 0;
625da0fc9dSDennis Dalessandro 	for (i = 0; i < IOWAIT_SES; i++) {
635da0fc9dSDennis Dalessandro 		wait->wait[i].iow = wait;
645da0fc9dSDennis Dalessandro 		INIT_LIST_HEAD(&wait->wait[i].tx_head);
655da0fc9dSDennis Dalessandro 		if (i == IOWAIT_IB_SE)
665da0fc9dSDennis Dalessandro 			INIT_WORK(&wait->wait[i].iowork, func);
675da0fc9dSDennis Dalessandro 		else
685da0fc9dSDennis Dalessandro 			INIT_WORK(&wait->wait[i].iowork, tidfunc);
695da0fc9dSDennis Dalessandro 	}
705da0fc9dSDennis Dalessandro }
715da0fc9dSDennis Dalessandro 
725da0fc9dSDennis Dalessandro /**
735da0fc9dSDennis Dalessandro  * iowait_cancel_work - cancel all work in iowait
745da0fc9dSDennis Dalessandro  * @w: the iowait struct
755da0fc9dSDennis Dalessandro  */
765da0fc9dSDennis Dalessandro void iowait_cancel_work(struct iowait *w)
775da0fc9dSDennis Dalessandro {
785da0fc9dSDennis Dalessandro 	cancel_work_sync(&iowait_get_ib_work(w)->iowork);
795da0fc9dSDennis Dalessandro 	cancel_work_sync(&iowait_get_tid_work(w)->iowork);
805da0fc9dSDennis Dalessandro }
815da0fc9dSDennis Dalessandro 
825da0fc9dSDennis Dalessandro /**
835da0fc9dSDennis Dalessandro  * iowait_set_work_flag - set work flag based on leg
845da0fc9dSDennis Dalessandro  * @w - the iowait work struct
855da0fc9dSDennis Dalessandro  */
865da0fc9dSDennis Dalessandro int iowait_set_work_flag(struct iowait_work *w)
875da0fc9dSDennis Dalessandro {
885da0fc9dSDennis Dalessandro 	if (w == &w->iow->wait[IOWAIT_IB_SE]) {
895da0fc9dSDennis Dalessandro 		iowait_set_flag(w->iow, IOWAIT_PENDING_IB);
905da0fc9dSDennis Dalessandro 		return IOWAIT_IB_SE;
915da0fc9dSDennis Dalessandro 	}
925da0fc9dSDennis Dalessandro 	iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
935da0fc9dSDennis Dalessandro 	return IOWAIT_TID_SE;
945da0fc9dSDennis Dalessandro }
95