aie2_solver.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2022-2024, Advanced Micro Devices, Inc.
  4. */
  5. #include <drm/drm_device.h>
  6. #include <drm/drm_managed.h>
  7. #include <drm/drm_print.h>
  8. #include <linux/bitops.h>
  9. #include <linux/bitmap.h>
  10. #include <linux/slab.h>
  11. #include "aie2_solver.h"
  12. struct partition_node {
  13. struct list_head list;
  14. u32 nshared; /* # shared requests */
  15. u32 start_col; /* start column */
  16. u32 ncols; /* # columns */
  17. bool exclusive; /* can not be shared if set */
  18. };
  19. struct solver_node {
  20. struct list_head list;
  21. u64 rid; /* Request ID from consumer */
  22. struct partition_node *pt_node;
  23. void *cb_arg;
  24. u32 dpm_level;
  25. u32 cols_len;
  26. u32 start_cols[] __counted_by(cols_len);
  27. };
  28. struct solver_rgroup {
  29. u32 rgid;
  30. u32 nnode;
  31. u32 npartition_node;
  32. DECLARE_BITMAP(resbit, XRS_MAX_COL);
  33. struct list_head node_list;
  34. struct list_head pt_node_list;
  35. };
  36. struct solver_state {
  37. struct solver_rgroup rgp;
  38. struct init_config cfg;
  39. struct xrs_action_ops *actions;
  40. };
  41. static u32 calculate_gops(struct aie_qos *rqos)
  42. {
  43. u32 service_rate = 0;
  44. if (rqos->latency)
  45. service_rate = (1000 / rqos->latency);
  46. if (rqos->fps > service_rate)
  47. return rqos->fps * rqos->gops;
  48. return service_rate * rqos->gops;
  49. }
  50. /*
  51. * qos_meet() - Check the QOS request can be met.
  52. */
  53. static int qos_meet(struct solver_state *xrs, struct aie_qos *rqos, u32 cgops)
  54. {
  55. u32 request_gops = calculate_gops(rqos) * xrs->cfg.sys_eff_factor;
  56. if (request_gops <= cgops)
  57. return 0;
  58. return -EINVAL;
  59. }
  60. /*
  61. * sanity_check() - Do a basic sanity check on allocation request.
  62. */
  63. static int sanity_check(struct solver_state *xrs, struct alloc_requests *req)
  64. {
  65. struct cdo_parts *cdop = &req->cdo;
  66. struct aie_qos *rqos = &req->rqos;
  67. u32 cu_clk_freq;
  68. if (cdop->ncols > xrs->cfg.total_col)
  69. return -EINVAL;
  70. /*
  71. * We can find at least one CDOs groups that meet the
  72. * GOPs requirement.
  73. */
  74. cu_clk_freq = xrs->cfg.clk_list.cu_clk_list[xrs->cfg.clk_list.num_levels - 1];
  75. if (qos_meet(xrs, rqos, cdop->qos_cap.opc * cu_clk_freq / 1000))
  76. return -EINVAL;
  77. return 0;
  78. }
  79. static bool is_valid_qos_dpm_params(struct aie_qos *rqos)
  80. {
  81. /*
  82. * gops is retrieved from the xmodel, so it's always set
  83. * fps and latency are the configurable params from the application
  84. */
  85. if (rqos->gops > 0 && (rqos->fps > 0 || rqos->latency > 0))
  86. return true;
  87. return false;
  88. }
  89. static int set_dpm_level(struct solver_state *xrs, struct alloc_requests *req, u32 *dpm_level)
  90. {
  91. struct solver_rgroup *rgp = &xrs->rgp;
  92. struct cdo_parts *cdop = &req->cdo;
  93. struct aie_qos *rqos = &req->rqos;
  94. u32 freq, max_dpm_level, level;
  95. struct solver_node *node;
  96. max_dpm_level = xrs->cfg.clk_list.num_levels - 1;
  97. /* If no QoS parameters are passed, set it to the max DPM level */
  98. if (!is_valid_qos_dpm_params(rqos)) {
  99. level = max_dpm_level;
  100. goto set_dpm;
  101. }
  102. /* Find one CDO group that meet the GOPs requirement. */
  103. for (level = 0; level < max_dpm_level; level++) {
  104. freq = xrs->cfg.clk_list.cu_clk_list[level];
  105. if (!qos_meet(xrs, rqos, cdop->qos_cap.opc * freq / 1000))
  106. break;
  107. }
  108. /* set the dpm level which fits all the sessions */
  109. list_for_each_entry(node, &rgp->node_list, list) {
  110. if (node->dpm_level > level)
  111. level = node->dpm_level;
  112. }
  113. set_dpm:
  114. *dpm_level = level;
  115. return xrs->cfg.actions->set_dft_dpm_level(xrs->cfg.ddev, level);
  116. }
  117. static struct solver_node *rg_search_node(struct solver_rgroup *rgp, u64 rid)
  118. {
  119. struct solver_node *node;
  120. list_for_each_entry(node, &rgp->node_list, list) {
  121. if (node->rid == rid)
  122. return node;
  123. }
  124. return NULL;
  125. }
  126. static void remove_partition_node(struct solver_rgroup *rgp,
  127. struct partition_node *pt_node)
  128. {
  129. pt_node->nshared--;
  130. if (pt_node->nshared > 0)
  131. return;
  132. list_del(&pt_node->list);
  133. rgp->npartition_node--;
  134. bitmap_clear(rgp->resbit, pt_node->start_col, pt_node->ncols);
  135. kfree(pt_node);
  136. }
  137. static void remove_solver_node(struct solver_rgroup *rgp,
  138. struct solver_node *node)
  139. {
  140. list_del(&node->list);
  141. rgp->nnode--;
  142. if (node->pt_node)
  143. remove_partition_node(rgp, node->pt_node);
  144. kfree(node);
  145. }
  146. static int get_free_partition(struct solver_state *xrs,
  147. struct solver_node *snode,
  148. struct alloc_requests *req)
  149. {
  150. struct partition_node *pt_node;
  151. u32 ncols = req->cdo.ncols;
  152. u32 col, i;
  153. for (i = 0; i < snode->cols_len; i++) {
  154. col = snode->start_cols[i];
  155. if (find_next_bit(xrs->rgp.resbit, XRS_MAX_COL, col) >= col + ncols)
  156. break;
  157. }
  158. if (i == snode->cols_len)
  159. return -ENODEV;
  160. pt_node = kzalloc_obj(*pt_node);
  161. if (!pt_node)
  162. return -ENOMEM;
  163. pt_node->nshared = 1;
  164. pt_node->start_col = col;
  165. pt_node->ncols = ncols;
  166. /*
  167. * Always set exclusive to false for now.
  168. */
  169. pt_node->exclusive = false;
  170. list_add_tail(&pt_node->list, &xrs->rgp.pt_node_list);
  171. xrs->rgp.npartition_node++;
  172. bitmap_set(xrs->rgp.resbit, pt_node->start_col, pt_node->ncols);
  173. snode->pt_node = pt_node;
  174. return 0;
  175. }
  176. static int allocate_partition(struct solver_state *xrs,
  177. struct solver_node *snode,
  178. struct alloc_requests *req)
  179. {
  180. struct partition_node *pt_node, *rpt_node = NULL;
  181. int idx, ret;
  182. ret = get_free_partition(xrs, snode, req);
  183. if (!ret)
  184. return ret;
  185. /* try to get a share-able partition */
  186. list_for_each_entry(pt_node, &xrs->rgp.pt_node_list, list) {
  187. if (pt_node->exclusive)
  188. continue;
  189. if (rpt_node && pt_node->nshared >= rpt_node->nshared)
  190. continue;
  191. for (idx = 0; idx < snode->cols_len; idx++) {
  192. if (snode->start_cols[idx] != pt_node->start_col)
  193. continue;
  194. if (req->cdo.ncols != pt_node->ncols)
  195. continue;
  196. rpt_node = pt_node;
  197. break;
  198. }
  199. }
  200. if (!rpt_node)
  201. return -ENODEV;
  202. rpt_node->nshared++;
  203. snode->pt_node = rpt_node;
  204. return 0;
  205. }
  206. static struct solver_node *create_solver_node(struct solver_state *xrs,
  207. struct alloc_requests *req)
  208. {
  209. struct cdo_parts *cdop = &req->cdo;
  210. struct solver_node *node;
  211. int ret;
  212. node = kzalloc_flex(*node, start_cols, cdop->cols_len);
  213. if (!node)
  214. return ERR_PTR(-ENOMEM);
  215. node->rid = req->rid;
  216. node->cols_len = cdop->cols_len;
  217. memcpy(node->start_cols, cdop->start_cols, cdop->cols_len * sizeof(u32));
  218. ret = allocate_partition(xrs, node, req);
  219. if (ret)
  220. goto free_node;
  221. list_add_tail(&node->list, &xrs->rgp.node_list);
  222. xrs->rgp.nnode++;
  223. return node;
  224. free_node:
  225. kfree(node);
  226. return ERR_PTR(ret);
  227. }
  228. static void fill_load_action(struct solver_state *xrs,
  229. struct solver_node *snode,
  230. struct xrs_action_load *action)
  231. {
  232. action->rid = snode->rid;
  233. action->part.start_col = snode->pt_node->start_col;
  234. action->part.ncols = snode->pt_node->ncols;
  235. }
  236. int xrs_allocate_resource(void *hdl, struct alloc_requests *req, void *cb_arg)
  237. {
  238. struct xrs_action_load load_act;
  239. struct solver_node *snode;
  240. struct solver_state *xrs;
  241. u32 dpm_level;
  242. int ret;
  243. xrs = (struct solver_state *)hdl;
  244. ret = sanity_check(xrs, req);
  245. if (ret) {
  246. drm_err(xrs->cfg.ddev, "invalid request");
  247. return ret;
  248. }
  249. if (rg_search_node(&xrs->rgp, req->rid)) {
  250. drm_err(xrs->cfg.ddev, "rid %lld is in-use", req->rid);
  251. return -EEXIST;
  252. }
  253. snode = create_solver_node(xrs, req);
  254. if (IS_ERR(snode))
  255. return PTR_ERR(snode);
  256. fill_load_action(xrs, snode, &load_act);
  257. ret = xrs->cfg.actions->load(cb_arg, &load_act);
  258. if (ret)
  259. goto free_node;
  260. ret = set_dpm_level(xrs, req, &dpm_level);
  261. if (ret)
  262. goto free_node;
  263. snode->dpm_level = dpm_level;
  264. snode->cb_arg = cb_arg;
  265. drm_dbg(xrs->cfg.ddev, "start col %d ncols %d\n",
  266. snode->pt_node->start_col, snode->pt_node->ncols);
  267. return 0;
  268. free_node:
  269. remove_solver_node(&xrs->rgp, snode);
  270. return ret;
  271. }
  272. int xrs_release_resource(void *hdl, u64 rid)
  273. {
  274. struct solver_state *xrs = hdl;
  275. struct solver_node *node;
  276. node = rg_search_node(&xrs->rgp, rid);
  277. if (!node) {
  278. drm_err(xrs->cfg.ddev, "node not exist");
  279. return -ENODEV;
  280. }
  281. xrs->cfg.actions->unload(node->cb_arg);
  282. remove_solver_node(&xrs->rgp, node);
  283. return 0;
  284. }
  285. void *xrsm_init(struct init_config *cfg)
  286. {
  287. struct solver_rgroup *rgp;
  288. struct solver_state *xrs;
  289. xrs = drmm_kzalloc(cfg->ddev, sizeof(*xrs), GFP_KERNEL);
  290. if (!xrs)
  291. return NULL;
  292. memcpy(&xrs->cfg, cfg, sizeof(*cfg));
  293. rgp = &xrs->rgp;
  294. INIT_LIST_HEAD(&rgp->node_list);
  295. INIT_LIST_HEAD(&rgp->pt_node_list);
  296. return xrs;
  297. }