xrp_linux.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. * Copyright (c) 2016 - 2018 Cadence Design Systems Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <fcntl.h>
  24. #include <stdint.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/stat.h>
  30. #include <sys/types.h>
  31. #include <signal.h>
  32. #include <unistd.h>
  33. #include "xrp_types.h"
  34. #include "xrp_host_common.h"
  35. #include "xrp_host_impl.h"
  36. #include "xrp_kernel_defs.h"
  37. #include "xrp_report.h"
  38. #include "dsp_common.h"
  39. struct xrp_request {
  40. struct xrp_queue_item q;
  41. void *in_data;
  42. void *out_data;
  43. size_t in_data_size;
  44. size_t out_data_size;
  45. struct xrp_buffer_group *buffer_group;
  46. struct xrp_event *event;
  47. };
  48. /* Device API. */
  49. struct xrp_device *xrp_open_device(int idx, enum xrp_status *status)
  50. {
  51. struct xrp_device *device;
  52. char name[sizeof("/dev/xvp") + sizeof(int) * 4];
  53. int fd;
  54. sprintf(name, "/dev/xvp%u", idx);
  55. fd = open(name, O_RDWR);
  56. if (fd == -1) {
  57. set_status(status, XRP_STATUS_FAILURE);
  58. return NULL;
  59. }
  60. device = alloc_refcounted(sizeof(*device));
  61. if (!device) {
  62. set_status(status, XRP_STATUS_FAILURE);
  63. return NULL;
  64. }
  65. device->impl.fd = fd;
  66. set_status(status, XRP_STATUS_SUCCESS);
  67. return device;
  68. }
  69. void xrp_impl_release_device(struct xrp_device *device)
  70. {
  71. close(device->impl.fd);
  72. }
  73. /* Buffer API. */
  74. void xrp_impl_create_device_buffer(struct xrp_device *device,
  75. struct xrp_buffer *buffer,
  76. size_t size,
  77. enum xrp_status *status)
  78. {
  79. struct xrp_ioctl_alloc ioctl_alloc = {
  80. .size = size,
  81. };
  82. int ret;
  83. xrp_retain_device(device);
  84. buffer->device = device;
  85. ret = ioctl(buffer->device->impl.fd, XRP_IOCTL_ALLOC, &ioctl_alloc);
  86. if (ret < 0) {
  87. xrp_release_device(buffer->device);
  88. set_status(status, XRP_STATUS_FAILURE);
  89. return;
  90. }
  91. buffer->ptr = (void *)(uintptr_t)ioctl_alloc.addr;
  92. buffer->size = size;
  93. buffer->phy_addr = ioctl_alloc.paddr;
  94. set_status(status, XRP_STATUS_SUCCESS);
  95. }
  96. void xrp_impl_release_device_buffer(struct xrp_buffer *buffer)
  97. {
  98. struct xrp_ioctl_alloc ioctl_alloc = {
  99. .addr = (uintptr_t)buffer->ptr,
  100. };
  101. ioctl(buffer->device->impl.fd,
  102. XRP_IOCTL_FREE, &ioctl_alloc);
  103. xrp_release_device(buffer->device);
  104. }
  105. /* Queue API. */
  106. static void _xrp_run_command(struct xrp_queue *queue,
  107. const void *in_data, size_t in_data_size,
  108. void *out_data, size_t out_data_size,
  109. struct xrp_buffer_group *buffer_group,
  110. enum xrp_status *status)
  111. {
  112. int ret;
  113. if (buffer_group)
  114. xrp_mutex_lock(&buffer_group->mutex);
  115. {
  116. size_t n_buffers = buffer_group ? buffer_group->n_buffers : 0;
  117. struct xrp_ioctl_buffer ioctl_buffer[n_buffers];/* TODO */
  118. struct xrp_ioctl_queue ioctl_queue = {
  119. .flags = (queue->use_nsid ? XRP_QUEUE_FLAG_NSID : 0) |
  120. ((queue->priority << XRP_QUEUE_FLAG_PRIO_SHIFT) &
  121. XRP_QUEUE_FLAG_PRIO),
  122. .in_data_size = in_data_size,
  123. .out_data_size = out_data_size,
  124. .buffer_size = n_buffers *
  125. sizeof(struct xrp_ioctl_buffer),
  126. .in_data_addr = (uintptr_t)in_data,
  127. .out_data_addr = (uintptr_t)out_data,
  128. .buffer_addr = (uintptr_t)ioctl_buffer,
  129. .nsid_addr = (uintptr_t)queue->nsid,
  130. };
  131. size_t i;
  132. for (i = 0; i < n_buffers; ++i) {
  133. ioctl_buffer[i] = (struct xrp_ioctl_buffer){
  134. .flags = buffer_group->buffer[i].access_flags,
  135. .size = buffer_group->buffer[i].buffer->size,
  136. .addr = (uintptr_t)buffer_group->buffer[i].buffer->ptr,
  137. };
  138. }
  139. if (buffer_group)
  140. xrp_mutex_unlock(&buffer_group->mutex);
  141. ret = ioctl(queue->device->impl.fd,
  142. XRP_IOCTL_QUEUE, &ioctl_queue);
  143. }
  144. // printf("%s, user out data\n",__func__);
  145. if (ret < 0)
  146. set_status(status, XRP_STATUS_FAILURE);
  147. else
  148. set_status(status, XRP_STATUS_SUCCESS);
  149. }
  150. static void xrp_request_process(struct xrp_queue_item *q,
  151. void *context)
  152. {
  153. enum xrp_status status;
  154. struct xrp_request *rq = (struct xrp_request *)q;
  155. _xrp_run_command(context,
  156. rq->in_data, rq->in_data_size,
  157. rq->out_data, rq->out_data_size,
  158. rq->buffer_group,
  159. &status);
  160. if (rq->buffer_group)
  161. xrp_release_buffer_group(rq->buffer_group);
  162. if (rq->event) {
  163. xrp_impl_broadcast_event(rq->event, status);
  164. xrp_release_event(rq->event);
  165. }
  166. // printf("%s,get resp with event %p!\n",__func__,rq->event);
  167. free(rq->in_data);
  168. free(rq);
  169. }
  170. void xrp_impl_create_queue(struct xrp_queue *queue,
  171. enum xrp_status *status)
  172. {
  173. xrp_queue_init(&queue->impl.queue, queue->priority,
  174. queue, xrp_request_process);
  175. set_status(status, XRP_STATUS_SUCCESS);
  176. }
  177. void xrp_impl_release_queue(struct xrp_queue *queue)
  178. {
  179. xrp_queue_destroy(&queue->impl.queue);
  180. }
  181. /* Communication API */
  182. void xrp_enqueue_command(struct xrp_queue *queue,
  183. const void *in_data, size_t in_data_size,
  184. void *out_data, size_t out_data_size,
  185. struct xrp_buffer_group *buffer_group,
  186. struct xrp_event **evt,
  187. enum xrp_status *status)
  188. {
  189. struct xrp_request *rq;
  190. void *in_data_copy;
  191. rq = malloc(sizeof(*rq));
  192. in_data_copy = malloc(in_data_size);
  193. if (!rq || (in_data_size && !in_data_copy)) {
  194. free(in_data_copy);
  195. free(rq);
  196. set_status(status, XRP_STATUS_FAILURE);
  197. return;
  198. }
  199. memcpy(in_data_copy, in_data, in_data_size);
  200. rq->in_data = in_data_copy;
  201. rq->in_data_size = in_data_size;
  202. rq->out_data = out_data;
  203. rq->out_data_size = out_data_size;
  204. if (evt) {
  205. struct xrp_event *event = xrp_event_create();
  206. if (!event) {
  207. free(rq->in_data);
  208. free(rq);
  209. set_status(status, XRP_STATUS_FAILURE);
  210. return;
  211. }
  212. xrp_retain_queue(queue);
  213. event->queue = queue;
  214. *evt = event;
  215. xrp_retain_event(event);
  216. rq->event = event;
  217. } else {
  218. rq->event = NULL;
  219. }
  220. if (buffer_group)
  221. xrp_retain_buffer_group(buffer_group);
  222. rq->buffer_group = buffer_group;
  223. set_status(status, XRP_STATUS_SUCCESS);
  224. xrp_queue_push(&queue->impl.queue, &rq->q);
  225. }
  226. static struct xrp_report *reporter;
  227. void xrp_reporter_sig_handler()
  228. {
  229. // printf("%s\n",__func__);
  230. struct xrp_report_buffer *report_buffer;
  231. if(!reporter || !reporter->report_buf)
  232. {
  233. return;
  234. }
  235. report_buffer = (struct xrp_report_buffer *)reporter->report_buf;
  236. // printf("buffer:%lx,id:%d,data:%x,%x,%x,%x\n",report_buffer,report_buffer->report_id,report_buffer->data[0],report_buffer->data[1],report_buffer->data[2],report_buffer->data[3]);
  237. xrp_process_report(&reporter->list,report_buffer->data,report_buffer->report_id);
  238. }
  239. int xrp_add_report_item_with_id(struct xrp_report *report,
  240. int (*cb)(void*context,void*data),
  241. int report_id,
  242. void* context,
  243. size_t data_size)
  244. {
  245. // int id;
  246. // // set_status(status, XRP_STATUS_SUCCESS);
  247. // id =xrp_alloc_report_id(&report->list);
  248. if(report_id<0 || !report)
  249. {
  250. // set_status(status, XRP_STATUS_FAILURE);
  251. return -1;
  252. }
  253. if(data_size>report->buf_size)
  254. {
  255. //realloc()
  256. DSP_PRINT(WARNING,"report instance size %d is exceed limit %d\n",data_size,report->buf_size);
  257. // set_status(status, XRP_STATUS_FAILURE);
  258. return -1;
  259. }
  260. char *report_buf = malloc(data_size);
  261. if(!report_buf)
  262. {
  263. // set_status(status, XRP_STATUS_FAILURE);
  264. return -1;
  265. }
  266. struct xrp_report_item new_item={
  267. .report_id = report_id,
  268. .buf = report_buf,
  269. .size = data_size,
  270. .context = context,
  271. .fn = cb,
  272. };
  273. DSP_PRINT(DEBUG,"add report id:%d\n", report_id);
  274. if(xrp_add_report(&report->list,&new_item))
  275. {
  276. free(report_buf);
  277. return -1;
  278. }
  279. DSP_PRINT(INFO,"the report item: %d is added sucessfully\n",report_id);
  280. return report_id;
  281. }
  282. int xrp_add_report_item(struct xrp_report *report,
  283. int (*cb)(void*context,void*data),
  284. void* context,
  285. size_t data_size)
  286. {
  287. int id;
  288. id =xrp_alloc_report_id(&report->list);
  289. if(id<0)
  290. {
  291. return -1;
  292. }
  293. return xrp_add_report_item_with_id(report,cb,id,context,data_size);
  294. }
  295. void xrp_remove_report_item(struct xrp_report *report,int report_id)
  296. {
  297. int id;
  298. struct xrp_report_item* item=xrp_get_report_entry(&report->list,report_id);
  299. free(item->buf);
  300. xrp_remove_report(&report->list,report_id);
  301. }
  302. void xrp_impl_create_report(struct xrp_device *device,
  303. struct xrp_report *report,
  304. size_t size,
  305. enum xrp_status *status)
  306. {
  307. // char *report_buf = malloc(size+4);
  308. // if(!report_buf)
  309. // {
  310. // set_status(status, XRP_STATUS_FAILURE);
  311. // return;
  312. // }
  313. struct xrp_ioctl_alloc ioctl_alloc = {
  314. .addr = (uintptr_t)NULL,
  315. .size = size,
  316. };
  317. int ret;
  318. xrp_retain_device(device);
  319. report->device = device;
  320. ret = ioctl(report->device->impl.fd, XRP_IOCTL_REPORT_CREATE, &ioctl_alloc);
  321. if (ret < 0) {
  322. // free(report_buf);
  323. set_status(status, XRP_STATUS_FAILURE);
  324. return;
  325. }
  326. if(ioctl_alloc.addr ==NULL)
  327. {
  328. DSP_PRINT(INFO,"alloc report buffer fail\n");
  329. set_status(status, XRP_STATUS_FAILURE);
  330. return ;
  331. }
  332. report->report_buf = (void *)(uintptr_t)ioctl_alloc.addr;
  333. // printf("buf:%lx,report:x\n",ioctl_alloc.addr,report);
  334. report->buf_size = size;
  335. report->list.queue.head=NULL;
  336. reporter=report;
  337. signal(SIGIO, xrp_reporter_sig_handler); /* sigaction() is better */
  338. fcntl(report->device->impl.fd, F_SETOWN, getpid());
  339. int oflags = fcntl(report->device->impl.fd, F_GETFL);
  340. fcntl(report->device->impl.fd, F_SETFL, oflags | FASYNC);
  341. set_status(status, XRP_STATUS_SUCCESS);
  342. DSP_PRINT(INFO,"buf:%lx,user space report create\n",ioctl_alloc.addr);
  343. }
  344. void xrp_impl_release_report(struct xrp_device *device,
  345. struct xrp_report *report,enum xrp_status *status)
  346. {
  347. struct xrp_ioctl_alloc ioctl_alloc = {
  348. .addr = (uintptr_t)report->report_buf,
  349. .size = report->buf_size,
  350. };
  351. int ret = ioctl(report->device->impl.fd, XRP_IOCTL_REPORT_RELEASE, &ioctl_alloc);
  352. if (ret < 0) {
  353. // free(report_buf);
  354. set_status(status, XRP_STATUS_FAILURE);
  355. return;
  356. }
  357. report->report_buf=NULL;
  358. xrp_release_device(device);
  359. set_status(status, XRP_STATUS_SUCCESS);
  360. return;
  361. }
  362. void xrp_import_dma_buf(struct xrp_device *device, int fd,enum xrp_access_flags flag,uint64_t *phy_addr,
  363. uint64_t *user_addr,size_t* size,enum xrp_status *status)
  364. {
  365. struct xrp_dma_buf dma_buf;
  366. if(fd < 0 || !(flag&XRP_FLAG_READ_WRITE))
  367. {
  368. set_status(status, XRP_STATUS_FAILURE);
  369. DSP_PRINT(DEBUG,"param check fail\n");
  370. return;
  371. }
  372. dma_buf.fd = fd;
  373. dma_buf.flags = flag;
  374. int ret = ioctl(device->impl.fd, XRP_IOCTL_DMABUF_IMPORT,&dma_buf);
  375. if (ret < 0) {
  376. DSP_PRINT(DEBUG,"_DMABUF_IMPORT fail\n");
  377. set_status(status, XRP_STATUS_FAILURE);
  378. }
  379. else
  380. {
  381. *phy_addr = dma_buf.paddr;
  382. *user_addr = dma_buf.addr;
  383. *size = dma_buf.size;
  384. set_status(status, XRP_STATUS_SUCCESS);
  385. }
  386. return;
  387. }
  388. void xrp_release_dma_buf(struct xrp_device *device, int fd,enum xrp_status *status)
  389. {
  390. if(fd < 0)
  391. {
  392. set_status(status, XRP_STATUS_FAILURE);
  393. return;
  394. }
  395. int ret = ioctl(device->impl.fd, XRP_IOCTL_DMABUF_RELEASE,&fd);
  396. if (ret < 0) {
  397. set_status(status, XRP_STATUS_FAILURE);
  398. }
  399. else
  400. {
  401. set_status(status, XRP_STATUS_SUCCESS);
  402. }
  403. return ;
  404. }
  405. void xrp_flush_dma_buf(struct xrp_device *device, int fd,enum xrp_access_flags flag,enum xrp_status *status)
  406. {
  407. struct xrp_dma_buf dma_buf;
  408. dma_buf.fd = fd;
  409. dma_buf.flags = flag;
  410. if(fd < 0)
  411. {
  412. set_status(status, XRP_STATUS_FAILURE);
  413. return;
  414. }
  415. int ret = ioctl(device->impl.fd, XRP_IOCTL_DMABUF_SYNC,&dma_buf);
  416. if (ret < 0) {
  417. set_status(status, XRP_STATUS_FAILURE);
  418. }
  419. else
  420. {
  421. set_status(status, XRP_STATUS_SUCCESS);
  422. }
  423. }