iowait.c 3.3 KB

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