^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright(c) 2018 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "iowait.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "trace_iowait.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /* 1 priority == 16 starve_cnt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define IOWAIT_PRIORITY_STARVE_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) void iowait_set_flag(struct iowait *wait, u32 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) trace_hfi1_iowait_set(wait, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) set_bit(flag, &wait->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) bool iowait_flag_set(struct iowait *wait, u32 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) return test_bit(flag, &wait->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) inline void iowait_clear_flag(struct iowait *wait, u32 flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) trace_hfi1_iowait_clear(wait, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) clear_bit(flag, &wait->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * iowait_init() - initialize wait structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @wait: wait struct to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @tx_limit: limit for overflow queuing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @func: restart function for workqueue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @sleep: sleep function for no space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @resume: wakeup function for no space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * This function initializes the iowait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * structure embedded in the QP or PQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) void iowait_init(struct iowait *wait, u32 tx_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void (*func)(struct work_struct *work),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void (*tidfunc)(struct work_struct *work),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int (*sleep)(struct sdma_engine *sde,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct iowait_work *wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct sdma_txreq *tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) uint seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) bool pkts_sent),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) void (*wakeup)(struct iowait *wait, int reason),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) void (*sdma_drained)(struct iowait *wait),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) void (*init_priority)(struct iowait *wait))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) wait->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) INIT_LIST_HEAD(&wait->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) init_waitqueue_head(&wait->wait_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) init_waitqueue_head(&wait->wait_pio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) atomic_set(&wait->sdma_busy, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) atomic_set(&wait->pio_busy, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) wait->tx_limit = tx_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) wait->sleep = sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) wait->wakeup = wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) wait->sdma_drained = sdma_drained;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) wait->init_priority = init_priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) wait->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) for (i = 0; i < IOWAIT_SES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) wait->wait[i].iow = wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) INIT_LIST_HEAD(&wait->wait[i].tx_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (i == IOWAIT_IB_SE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) INIT_WORK(&wait->wait[i].iowork, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) INIT_WORK(&wait->wait[i].iowork, tidfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * iowait_cancel_work - cancel all work in iowait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @w: the iowait struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) void iowait_cancel_work(struct iowait *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) cancel_work_sync(&iowait_get_ib_work(w)->iowork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Make sure that the iowork for TID RDMA is used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (iowait_get_tid_work(w)->iowork.func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) cancel_work_sync(&iowait_get_tid_work(w)->iowork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * iowait_set_work_flag - set work flag based on leg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @w - the iowait work struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int iowait_set_work_flag(struct iowait_work *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (w == &w->iow->wait[IOWAIT_IB_SE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) iowait_set_flag(w->iow, IOWAIT_PENDING_IB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return IOWAIT_IB_SE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) iowait_set_flag(w->iow, IOWAIT_PENDING_TID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return IOWAIT_TID_SE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * iowait_priority_update_top - update the top priority entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @w: the iowait struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @top: a pointer to the top priority entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @idx: the index of the current iowait in an array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @top_idx: the array index for the iowait entry that has the top priority
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * This function is called to compare the priority of a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * iowait with the given top priority entry. The top index will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) uint iowait_priority_update_top(struct iowait *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct iowait *top,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) uint idx, uint top_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 cnt, tcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Convert priority into starve_cnt and compare the total.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) cnt = (w->priority << IOWAIT_PRIORITY_STARVE_SHIFT) + w->starved_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) tcnt = (top->priority << IOWAIT_PRIORITY_STARVE_SHIFT) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) top->starved_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (cnt > tcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return top_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }