ethosu_gem.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. // SPDX-License-Identifier: GPL-2.0-only or MIT
  2. /* Copyright 2025 Arm, Ltd. */
  3. #include <linux/err.h>
  4. #include <linux/slab.h>
  5. #include <drm/ethosu_accel.h>
  6. #include "ethosu_device.h"
  7. #include "ethosu_gem.h"
  8. static void ethosu_gem_free_object(struct drm_gem_object *obj)
  9. {
  10. struct ethosu_gem_object *bo = to_ethosu_bo(obj);
  11. kfree(bo->info);
  12. drm_gem_free_mmap_offset(&bo->base.base);
  13. drm_gem_dma_free(&bo->base);
  14. }
  15. static int ethosu_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
  16. {
  17. struct ethosu_gem_object *bo = to_ethosu_bo(obj);
  18. /* Don't allow mmap on objects that have the NO_MMAP flag set. */
  19. if (bo->flags & DRM_ETHOSU_BO_NO_MMAP)
  20. return -EINVAL;
  21. return drm_gem_dma_object_mmap(obj, vma);
  22. }
  23. static const struct drm_gem_object_funcs ethosu_gem_funcs = {
  24. .free = ethosu_gem_free_object,
  25. .print_info = drm_gem_dma_object_print_info,
  26. .get_sg_table = drm_gem_dma_object_get_sg_table,
  27. .vmap = drm_gem_dma_object_vmap,
  28. .mmap = ethosu_gem_mmap,
  29. .vm_ops = &drm_gem_dma_vm_ops,
  30. };
  31. /**
  32. * ethosu_gem_create_object - Implementation of driver->gem_create_object.
  33. * @ddev: DRM device
  34. * @size: Size in bytes of the memory the object will reference
  35. *
  36. * This lets the GEM helpers allocate object structs for us, and keep
  37. * our BO stats correct.
  38. */
  39. struct drm_gem_object *ethosu_gem_create_object(struct drm_device *ddev, size_t size)
  40. {
  41. struct ethosu_gem_object *obj;
  42. obj = kzalloc_obj(*obj);
  43. if (!obj)
  44. return ERR_PTR(-ENOMEM);
  45. obj->base.base.funcs = &ethosu_gem_funcs;
  46. return &obj->base.base;
  47. }
  48. /**
  49. * ethosu_gem_create_with_handle() - Create a GEM object and attach it to a handle.
  50. * @file: DRM file.
  51. * @ddev: DRM device.
  52. * @size: Size of the GEM object to allocate.
  53. * @flags: Combination of drm_ethosu_bo_flags flags.
  54. * @handle: Pointer holding the handle pointing to the new GEM object.
  55. *
  56. * Return: Zero on success
  57. */
  58. int ethosu_gem_create_with_handle(struct drm_file *file,
  59. struct drm_device *ddev,
  60. u64 *size, u32 flags, u32 *handle)
  61. {
  62. struct drm_gem_dma_object *mem;
  63. struct ethosu_gem_object *bo;
  64. int ret;
  65. mem = drm_gem_dma_create(ddev, *size);
  66. if (IS_ERR(mem))
  67. return PTR_ERR(mem);
  68. bo = to_ethosu_bo(&mem->base);
  69. bo->flags = flags;
  70. /*
  71. * Allocate an id of idr table where the obj is registered
  72. * and handle has the id what user can see.
  73. */
  74. ret = drm_gem_handle_create(file, &mem->base, handle);
  75. if (!ret)
  76. *size = bo->base.base.size;
  77. /* drop reference from allocate - handle holds it now. */
  78. drm_gem_object_put(&mem->base);
  79. return ret;
  80. }
  81. struct dma {
  82. s8 region;
  83. u64 len;
  84. u64 offset;
  85. s64 stride[2];
  86. };
  87. struct dma_state {
  88. u16 size0;
  89. u16 size1;
  90. s8 mode;
  91. struct dma src;
  92. struct dma dst;
  93. };
  94. struct buffer {
  95. u64 base;
  96. u32 length;
  97. s8 region;
  98. };
  99. struct feat_matrix {
  100. u64 base[4];
  101. s64 stride_x;
  102. s64 stride_y;
  103. s64 stride_c;
  104. s8 region;
  105. u8 broadcast;
  106. u16 stride_kernel;
  107. u16 precision;
  108. u16 depth;
  109. u16 width;
  110. u16 width0;
  111. u16 height[3];
  112. u8 pad_top;
  113. u8 pad_left;
  114. u8 pad_bottom;
  115. u8 pad_right;
  116. };
  117. struct cmd_state {
  118. struct dma_state dma;
  119. struct buffer scale[2];
  120. struct buffer weight[4];
  121. struct feat_matrix ofm;
  122. struct feat_matrix ifm;
  123. struct feat_matrix ifm2;
  124. };
  125. static void cmd_state_init(struct cmd_state *st)
  126. {
  127. /* Initialize to all 1s to detect missing setup */
  128. memset(st, 0xff, sizeof(*st));
  129. }
  130. static u64 cmd_to_addr(u32 *cmd)
  131. {
  132. return (((u64)cmd[0] & 0xff0000) << 16) | cmd[1];
  133. }
  134. static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
  135. struct dma_state *dma_st, struct dma *dma)
  136. {
  137. s8 mode = dma_st->mode;
  138. u64 len = dma->len;
  139. if (mode >= 1) {
  140. len += dma->stride[0];
  141. len *= dma_st->size0;
  142. }
  143. if (mode == 2) {
  144. len += dma->stride[1];
  145. len *= dma_st->size1;
  146. }
  147. if (dma->region >= 0)
  148. info->region_size[dma->region] = max(info->region_size[dma->region],
  149. len + dma->offset);
  150. return len;
  151. }
  152. static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
  153. struct feat_matrix *fm,
  154. u32 x, u32 y, u32 c)
  155. {
  156. u32 element_size, storage = fm->precision >> 14;
  157. int tile = 0;
  158. u64 addr;
  159. if (fm->region < 0)
  160. return U64_MAX;
  161. switch (storage) {
  162. case 0:
  163. if (x >= fm->width0 + 1) {
  164. x -= fm->width0 + 1;
  165. tile += 1;
  166. }
  167. if (y >= fm->height[tile] + 1) {
  168. y -= fm->height[tile] + 1;
  169. tile += 2;
  170. }
  171. break;
  172. case 1:
  173. if (y >= fm->height[1] + 1) {
  174. y -= fm->height[1] + 1;
  175. tile = 2;
  176. } else if (y >= fm->height[0] + 1) {
  177. y -= fm->height[0] + 1;
  178. tile = 1;
  179. }
  180. break;
  181. }
  182. if (fm->base[tile] == U64_MAX)
  183. return U64_MAX;
  184. addr = fm->base[tile] + y * fm->stride_y;
  185. switch ((fm->precision >> 6) & 0x3) { // format
  186. case 0: //nhwc:
  187. addr += x * fm->stride_x + c;
  188. break;
  189. case 1: //nhcwb16:
  190. element_size = BIT((fm->precision >> 1) & 0x3);
  191. addr += (c / 16) * fm->stride_c + (16 * x + (c & 0xf)) * element_size;
  192. break;
  193. }
  194. info->region_size[fm->region] = max(info->region_size[fm->region], addr + 1);
  195. return addr;
  196. }
  197. static int calc_sizes(struct drm_device *ddev,
  198. struct ethosu_validated_cmdstream_info *info,
  199. u16 op, struct cmd_state *st,
  200. bool ifm, bool ifm2, bool weight, bool scale)
  201. {
  202. u64 len;
  203. if (ifm) {
  204. if (st->ifm.stride_kernel == U16_MAX)
  205. return -EINVAL;
  206. u32 stride_y = ((st->ifm.stride_kernel >> 8) & 0x2) +
  207. ((st->ifm.stride_kernel >> 1) & 0x1) + 1;
  208. u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) +
  209. (st->ifm.stride_kernel & 0x1) + 1;
  210. s32 ifm_height = st->ofm.height[2] * stride_y +
  211. st->ifm.height[2] - (st->ifm.pad_top + st->ifm.pad_bottom);
  212. s32 ifm_width = st->ofm.width * stride_x +
  213. st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right);
  214. if (ifm_height < 0 || ifm_width < 0)
  215. return -EINVAL;
  216. len = feat_matrix_length(info, &st->ifm, ifm_width,
  217. ifm_height, st->ifm.depth);
  218. dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
  219. op, st->ifm.region, st->ifm.base[0], len);
  220. if (len == U64_MAX)
  221. return -EINVAL;
  222. }
  223. if (ifm2) {
  224. len = feat_matrix_length(info, &st->ifm2, st->ifm.depth,
  225. 0, st->ofm.depth);
  226. dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
  227. op, st->ifm2.region, st->ifm2.base[0], len);
  228. if (len == U64_MAX)
  229. return -EINVAL;
  230. }
  231. if (weight) {
  232. dev_dbg(ddev->dev, "op %d: W:%d:0x%llx-0x%llx\n",
  233. op, st->weight[0].region, st->weight[0].base,
  234. st->weight[0].base + st->weight[0].length - 1);
  235. if (st->weight[0].region < 0 || st->weight[0].base == U64_MAX ||
  236. st->weight[0].length == U32_MAX)
  237. return -EINVAL;
  238. info->region_size[st->weight[0].region] =
  239. max(info->region_size[st->weight[0].region],
  240. st->weight[0].base + st->weight[0].length);
  241. }
  242. if (scale) {
  243. dev_dbg(ddev->dev, "op %d: S:%d:0x%llx-0x%llx\n",
  244. op, st->scale[0].region, st->scale[0].base,
  245. st->scale[0].base + st->scale[0].length - 1);
  246. if (st->scale[0].region < 0 || st->scale[0].base == U64_MAX ||
  247. st->scale[0].length == U32_MAX)
  248. return -EINVAL;
  249. info->region_size[st->scale[0].region] =
  250. max(info->region_size[st->scale[0].region],
  251. st->scale[0].base + st->scale[0].length);
  252. }
  253. len = feat_matrix_length(info, &st->ofm, st->ofm.width,
  254. st->ofm.height[2], st->ofm.depth);
  255. dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
  256. op, st->ofm.region, st->ofm.base[0], len);
  257. if (len == U64_MAX)
  258. return -EINVAL;
  259. info->output_region[st->ofm.region] = true;
  260. return 0;
  261. }
  262. static int calc_sizes_elemwise(struct drm_device *ddev,
  263. struct ethosu_validated_cmdstream_info *info,
  264. u16 op, struct cmd_state *st,
  265. bool ifm, bool ifm2)
  266. {
  267. u32 height, width, depth;
  268. u64 len;
  269. if (ifm) {
  270. height = st->ifm.broadcast & 0x1 ? 0 : st->ofm.height[2];
  271. width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width;
  272. depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth;
  273. len = feat_matrix_length(info, &st->ifm, width,
  274. height, depth);
  275. dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
  276. op, st->ifm.region, st->ifm.base[0], len);
  277. if (len == U64_MAX)
  278. return -EINVAL;
  279. }
  280. if (ifm2) {
  281. height = st->ifm2.broadcast & 0x1 ? 0 : st->ofm.height[2];
  282. width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width;
  283. depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth;
  284. len = feat_matrix_length(info, &st->ifm2, width,
  285. height, depth);
  286. dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
  287. op, st->ifm2.region, st->ifm2.base[0], len);
  288. if (len == U64_MAX)
  289. return -EINVAL;
  290. }
  291. len = feat_matrix_length(info, &st->ofm, st->ofm.width,
  292. st->ofm.height[2], st->ofm.depth);
  293. dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
  294. op, st->ofm.region, st->ofm.base[0], len);
  295. if (len == U64_MAX)
  296. return -EINVAL;
  297. info->output_region[st->ofm.region] = true;
  298. return 0;
  299. }
  300. static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
  301. u32 __user *ucmds,
  302. struct ethosu_gem_object *bo,
  303. u32 size)
  304. {
  305. struct ethosu_validated_cmdstream_info __free(kfree) *info = kzalloc_obj(*info);
  306. struct ethosu_device *edev = to_ethosu_device(ddev);
  307. u32 *bocmds = bo->base.vaddr;
  308. struct cmd_state st;
  309. int i, ret;
  310. if (!info)
  311. return -ENOMEM;
  312. info->cmd_size = size;
  313. cmd_state_init(&st);
  314. for (i = 0; i < size / 4; i++) {
  315. bool use_ifm, use_ifm2, use_scale;
  316. u64 dstlen, srclen;
  317. u16 cmd, param;
  318. u32 cmds[2];
  319. u64 addr;
  320. if (get_user(cmds[0], ucmds++))
  321. return -EFAULT;
  322. bocmds[i] = cmds[0];
  323. cmd = cmds[0];
  324. param = cmds[0] >> 16;
  325. if (cmd & 0x4000) {
  326. if (get_user(cmds[1], ucmds++))
  327. return -EFAULT;
  328. i++;
  329. bocmds[i] = cmds[1];
  330. addr = cmd_to_addr(cmds);
  331. }
  332. switch (cmd) {
  333. case NPU_OP_DMA_START:
  334. srclen = dma_length(info, &st.dma, &st.dma.src);
  335. dstlen = dma_length(info, &st.dma, &st.dma.dst);
  336. if (st.dma.dst.region >= 0)
  337. info->output_region[st.dma.dst.region] = true;
  338. dev_dbg(ddev->dev, "cmd: DMA SRC:%d:0x%llx+0x%llx DST:%d:0x%llx+0x%llx\n",
  339. st.dma.src.region, st.dma.src.offset, srclen,
  340. st.dma.dst.region, st.dma.dst.offset, dstlen);
  341. break;
  342. case NPU_OP_CONV:
  343. case NPU_OP_DEPTHWISE:
  344. use_ifm2 = param & 0x1; // weights_ifm2
  345. use_scale = !(st.ofm.precision & 0x100);
  346. ret = calc_sizes(ddev, info, cmd, &st, true, use_ifm2,
  347. !use_ifm2, use_scale);
  348. if (ret)
  349. return ret;
  350. break;
  351. case NPU_OP_POOL:
  352. use_ifm = param != 0x4; // pooling mode
  353. use_scale = !(st.ofm.precision & 0x100);
  354. ret = calc_sizes(ddev, info, cmd, &st, use_ifm, false,
  355. false, use_scale);
  356. if (ret)
  357. return ret;
  358. break;
  359. case NPU_OP_ELEMENTWISE:
  360. use_scale = ethosu_is_u65(edev) ?
  361. (st.ifm2.broadcast & 0x80) :
  362. (st.ifm2.broadcast == 8);
  363. use_ifm2 = !(use_scale || (param == 5) ||
  364. (param == 6) || (param == 7) || (param == 0x24));
  365. use_ifm = st.ifm.broadcast != 8;
  366. ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2);
  367. if (ret)
  368. return ret;
  369. break;
  370. case NPU_OP_RESIZE: // U85 only
  371. WARN_ON(1); // TODO
  372. break;
  373. case NPU_SET_KERNEL_WIDTH_M1:
  374. st.ifm.width = param;
  375. break;
  376. case NPU_SET_KERNEL_HEIGHT_M1:
  377. st.ifm.height[2] = param;
  378. break;
  379. case NPU_SET_KERNEL_STRIDE:
  380. st.ifm.stride_kernel = param;
  381. break;
  382. case NPU_SET_IFM_PAD_TOP:
  383. st.ifm.pad_top = param & 0x7f;
  384. break;
  385. case NPU_SET_IFM_PAD_LEFT:
  386. st.ifm.pad_left = param & 0x7f;
  387. break;
  388. case NPU_SET_IFM_PAD_RIGHT:
  389. st.ifm.pad_right = param & 0xff;
  390. break;
  391. case NPU_SET_IFM_PAD_BOTTOM:
  392. st.ifm.pad_bottom = param & 0xff;
  393. break;
  394. case NPU_SET_IFM_DEPTH_M1:
  395. st.ifm.depth = param;
  396. break;
  397. case NPU_SET_IFM_PRECISION:
  398. st.ifm.precision = param;
  399. break;
  400. case NPU_SET_IFM_BROADCAST:
  401. st.ifm.broadcast = param;
  402. break;
  403. case NPU_SET_IFM_REGION:
  404. st.ifm.region = param & 0x7f;
  405. break;
  406. case NPU_SET_IFM_WIDTH0_M1:
  407. st.ifm.width0 = param;
  408. break;
  409. case NPU_SET_IFM_HEIGHT0_M1:
  410. st.ifm.height[0] = param;
  411. break;
  412. case NPU_SET_IFM_HEIGHT1_M1:
  413. st.ifm.height[1] = param;
  414. break;
  415. case NPU_SET_IFM_BASE0:
  416. case NPU_SET_IFM_BASE1:
  417. case NPU_SET_IFM_BASE2:
  418. case NPU_SET_IFM_BASE3:
  419. st.ifm.base[cmd & 0x3] = addr;
  420. break;
  421. case NPU_SET_IFM_STRIDE_X:
  422. st.ifm.stride_x = addr;
  423. break;
  424. case NPU_SET_IFM_STRIDE_Y:
  425. st.ifm.stride_y = addr;
  426. break;
  427. case NPU_SET_IFM_STRIDE_C:
  428. st.ifm.stride_c = addr;
  429. break;
  430. case NPU_SET_OFM_WIDTH_M1:
  431. st.ofm.width = param;
  432. break;
  433. case NPU_SET_OFM_HEIGHT_M1:
  434. st.ofm.height[2] = param;
  435. break;
  436. case NPU_SET_OFM_DEPTH_M1:
  437. st.ofm.depth = param;
  438. break;
  439. case NPU_SET_OFM_PRECISION:
  440. st.ofm.precision = param;
  441. break;
  442. case NPU_SET_OFM_REGION:
  443. st.ofm.region = param & 0x7;
  444. break;
  445. case NPU_SET_OFM_WIDTH0_M1:
  446. st.ofm.width0 = param;
  447. break;
  448. case NPU_SET_OFM_HEIGHT0_M1:
  449. st.ofm.height[0] = param;
  450. break;
  451. case NPU_SET_OFM_HEIGHT1_M1:
  452. st.ofm.height[1] = param;
  453. break;
  454. case NPU_SET_OFM_BASE0:
  455. case NPU_SET_OFM_BASE1:
  456. case NPU_SET_OFM_BASE2:
  457. case NPU_SET_OFM_BASE3:
  458. st.ofm.base[cmd & 0x3] = addr;
  459. break;
  460. case NPU_SET_OFM_STRIDE_X:
  461. st.ofm.stride_x = addr;
  462. break;
  463. case NPU_SET_OFM_STRIDE_Y:
  464. st.ofm.stride_y = addr;
  465. break;
  466. case NPU_SET_OFM_STRIDE_C:
  467. st.ofm.stride_c = addr;
  468. break;
  469. case NPU_SET_IFM2_BROADCAST:
  470. st.ifm2.broadcast = param;
  471. break;
  472. case NPU_SET_IFM2_PRECISION:
  473. st.ifm2.precision = param;
  474. break;
  475. case NPU_SET_IFM2_REGION:
  476. st.ifm2.region = param & 0x7;
  477. break;
  478. case NPU_SET_IFM2_WIDTH0_M1:
  479. st.ifm2.width0 = param;
  480. break;
  481. case NPU_SET_IFM2_HEIGHT0_M1:
  482. st.ifm2.height[0] = param;
  483. break;
  484. case NPU_SET_IFM2_HEIGHT1_M1:
  485. st.ifm2.height[1] = param;
  486. break;
  487. case NPU_SET_IFM2_BASE0:
  488. case NPU_SET_IFM2_BASE1:
  489. case NPU_SET_IFM2_BASE2:
  490. case NPU_SET_IFM2_BASE3:
  491. st.ifm2.base[cmd & 0x3] = addr;
  492. break;
  493. case NPU_SET_IFM2_STRIDE_X:
  494. st.ifm2.stride_x = addr;
  495. break;
  496. case NPU_SET_IFM2_STRIDE_Y:
  497. st.ifm2.stride_y = addr;
  498. break;
  499. case NPU_SET_IFM2_STRIDE_C:
  500. st.ifm2.stride_c = addr;
  501. break;
  502. case NPU_SET_WEIGHT_REGION:
  503. st.weight[0].region = param & 0x7;
  504. break;
  505. case NPU_SET_SCALE_REGION:
  506. st.scale[0].region = param & 0x7;
  507. break;
  508. case NPU_SET_WEIGHT_BASE:
  509. st.weight[0].base = addr;
  510. break;
  511. case NPU_SET_WEIGHT_LENGTH:
  512. st.weight[0].length = cmds[1];
  513. break;
  514. case NPU_SET_SCALE_BASE:
  515. st.scale[0].base = addr;
  516. break;
  517. case NPU_SET_SCALE_LENGTH:
  518. st.scale[0].length = cmds[1];
  519. break;
  520. case NPU_SET_WEIGHT1_BASE:
  521. st.weight[1].base = addr;
  522. break;
  523. case NPU_SET_WEIGHT1_LENGTH:
  524. st.weight[1].length = cmds[1];
  525. break;
  526. case NPU_SET_SCALE1_BASE: // NPU_SET_WEIGHT2_BASE (U85)
  527. if (ethosu_is_u65(edev))
  528. st.scale[1].base = addr;
  529. else
  530. st.weight[2].base = addr;
  531. break;
  532. case NPU_SET_SCALE1_LENGTH: // NPU_SET_WEIGHT2_LENGTH (U85)
  533. if (ethosu_is_u65(edev))
  534. st.scale[1].length = cmds[1];
  535. else
  536. st.weight[1].length = cmds[1];
  537. break;
  538. case NPU_SET_WEIGHT3_BASE:
  539. st.weight[3].base = addr;
  540. break;
  541. case NPU_SET_WEIGHT3_LENGTH:
  542. st.weight[3].length = cmds[1];
  543. break;
  544. case NPU_SET_DMA0_SRC_REGION:
  545. if (param & 0x100)
  546. st.dma.src.region = -1;
  547. else
  548. st.dma.src.region = param & 0x7;
  549. st.dma.mode = (param >> 9) & 0x3;
  550. break;
  551. case NPU_SET_DMA0_DST_REGION:
  552. if (param & 0x100)
  553. st.dma.dst.region = -1;
  554. else
  555. st.dma.dst.region = param & 0x7;
  556. break;
  557. case NPU_SET_DMA0_SIZE0:
  558. st.dma.size0 = param;
  559. break;
  560. case NPU_SET_DMA0_SIZE1:
  561. st.dma.size1 = param;
  562. break;
  563. case NPU_SET_DMA0_SRC_STRIDE0:
  564. st.dma.src.stride[0] = ((s64)addr << 24) >> 24;
  565. break;
  566. case NPU_SET_DMA0_SRC_STRIDE1:
  567. st.dma.src.stride[1] = ((s64)addr << 24) >> 24;
  568. break;
  569. case NPU_SET_DMA0_DST_STRIDE0:
  570. st.dma.dst.stride[0] = ((s64)addr << 24) >> 24;
  571. break;
  572. case NPU_SET_DMA0_DST_STRIDE1:
  573. st.dma.dst.stride[1] = ((s64)addr << 24) >> 24;
  574. break;
  575. case NPU_SET_DMA0_SRC:
  576. st.dma.src.offset = addr;
  577. break;
  578. case NPU_SET_DMA0_DST:
  579. st.dma.dst.offset = addr;
  580. break;
  581. case NPU_SET_DMA0_LEN:
  582. st.dma.src.len = st.dma.dst.len = addr;
  583. break;
  584. default:
  585. break;
  586. }
  587. }
  588. for (i = 0; i < NPU_BASEP_REGION_MAX; i++) {
  589. if (!info->region_size[i])
  590. continue;
  591. dev_dbg(ddev->dev, "region %d max size: 0x%llx\n",
  592. i, info->region_size[i]);
  593. }
  594. bo->info = no_free_ptr(info);
  595. return 0;
  596. }
  597. /**
  598. * ethosu_gem_cmdstream_create() - Create a GEM object and attach it to a handle.
  599. * @file: DRM file.
  600. * @ddev: DRM device.
  601. * @exclusive_vm: Exclusive VM. Not NULL if the GEM object can't be shared.
  602. * @size: Size of the GEM object to allocate.
  603. * @flags: Combination of drm_ethosu_bo_flags flags.
  604. * @handle: Pointer holding the handle pointing to the new GEM object.
  605. *
  606. * Return: Zero on success
  607. */
  608. int ethosu_gem_cmdstream_create(struct drm_file *file,
  609. struct drm_device *ddev,
  610. u32 size, u64 data, u32 flags, u32 *handle)
  611. {
  612. int ret;
  613. struct drm_gem_dma_object *mem;
  614. struct ethosu_gem_object *bo;
  615. mem = drm_gem_dma_create(ddev, size);
  616. if (IS_ERR(mem))
  617. return PTR_ERR(mem);
  618. bo = to_ethosu_bo(&mem->base);
  619. bo->flags = flags;
  620. ret = ethosu_gem_cmdstream_copy_and_validate(ddev,
  621. (void __user *)(uintptr_t)data,
  622. bo, size);
  623. if (ret)
  624. goto fail;
  625. /*
  626. * Allocate an id of idr table where the obj is registered
  627. * and handle has the id what user can see.
  628. */
  629. ret = drm_gem_handle_create(file, &mem->base, handle);
  630. fail:
  631. /* drop reference from allocate - handle holds it now. */
  632. drm_gem_object_put(&mem->base);
  633. return ret;
  634. }