nouveau_usif.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright 2014 Red Hat Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Authors: Ben Skeggs <[email protected]>
  23. */
  24. #include "nouveau_drv.h"
  25. #include "nouveau_usif.h"
  26. #include "nouveau_abi16.h"
  27. #include <nvif/unpack.h>
  28. #include <nvif/client.h>
  29. #include <nvif/ioctl.h>
  30. #include <nvif/class.h>
  31. #include <nvif/cl0080.h>
  32. struct usif_object {
  33. struct list_head head;
  34. u8 route;
  35. u64 token;
  36. };
  37. static void
  38. usif_object_dtor(struct usif_object *object)
  39. {
  40. list_del(&object->head);
  41. kfree(object);
  42. }
  43. static int
  44. usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16)
  45. {
  46. struct nouveau_cli *cli = nouveau_cli(f);
  47. struct nvif_client *client = &cli->base;
  48. union {
  49. struct nvif_ioctl_new_v0 v0;
  50. } *args = data;
  51. struct usif_object *object;
  52. int ret = -ENOSYS;
  53. if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true)))
  54. return ret;
  55. switch (args->v0.oclass) {
  56. case NV_DMA_FROM_MEMORY:
  57. case NV_DMA_TO_MEMORY:
  58. case NV_DMA_IN_MEMORY:
  59. return -EINVAL;
  60. case NV_DEVICE: {
  61. union {
  62. struct nv_device_v0 v0;
  63. } *args = data;
  64. if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)))
  65. return ret;
  66. args->v0.priv = false;
  67. break;
  68. }
  69. default:
  70. if (!parent_abi16)
  71. return -EINVAL;
  72. break;
  73. }
  74. if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
  75. return -ENOMEM;
  76. list_add(&object->head, &cli->objects);
  77. object->route = args->v0.route;
  78. object->token = args->v0.token;
  79. args->v0.route = NVDRM_OBJECT_USIF;
  80. args->v0.token = (unsigned long)(void *)object;
  81. ret = nvif_client_ioctl(client, argv, argc);
  82. if (ret) {
  83. usif_object_dtor(object);
  84. return ret;
  85. }
  86. args->v0.token = object->token;
  87. args->v0.route = object->route;
  88. return 0;
  89. }
  90. int
  91. usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
  92. {
  93. struct nouveau_cli *cli = nouveau_cli(filp);
  94. struct nvif_client *client = &cli->base;
  95. void *data = kmalloc(argc, GFP_KERNEL);
  96. u32 size = argc;
  97. union {
  98. struct nvif_ioctl_v0 v0;
  99. } *argv = data;
  100. struct usif_object *object;
  101. bool abi16 = false;
  102. u8 owner;
  103. int ret;
  104. if (ret = -ENOMEM, !argv)
  105. goto done;
  106. if (ret = -EFAULT, copy_from_user(argv, user, size))
  107. goto done;
  108. if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
  109. /* block access to objects not created via this interface */
  110. owner = argv->v0.owner;
  111. if (argv->v0.object == 0ULL &&
  112. argv->v0.type != NVIF_IOCTL_V0_DEL)
  113. argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
  114. else
  115. argv->v0.owner = NVDRM_OBJECT_USIF;
  116. } else
  117. goto done;
  118. /* USIF slightly abuses some return-only ioctl members in order
  119. * to provide interoperability with the older ABI16 objects
  120. */
  121. mutex_lock(&cli->mutex);
  122. if (argv->v0.route) {
  123. if (ret = -EINVAL, argv->v0.route == 0xff)
  124. ret = nouveau_abi16_usif(filp, argv, argc);
  125. if (ret) {
  126. mutex_unlock(&cli->mutex);
  127. goto done;
  128. }
  129. abi16 = true;
  130. }
  131. switch (argv->v0.type) {
  132. case NVIF_IOCTL_V0_NEW:
  133. ret = usif_object_new(filp, data, size, argv, argc, abi16);
  134. break;
  135. case NVIF_IOCTL_V0_NTFY_NEW:
  136. case NVIF_IOCTL_V0_NTFY_DEL:
  137. case NVIF_IOCTL_V0_NTFY_GET:
  138. case NVIF_IOCTL_V0_NTFY_PUT:
  139. ret = -ENOSYS;
  140. break;
  141. default:
  142. ret = nvif_client_ioctl(client, argv, argc);
  143. break;
  144. }
  145. if (argv->v0.route == NVDRM_OBJECT_USIF) {
  146. object = (void *)(unsigned long)argv->v0.token;
  147. argv->v0.route = object->route;
  148. argv->v0.token = object->token;
  149. if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) {
  150. list_del(&object->head);
  151. kfree(object);
  152. }
  153. } else {
  154. argv->v0.route = NVIF_IOCTL_V0_ROUTE_HIDDEN;
  155. argv->v0.token = 0;
  156. }
  157. argv->v0.owner = owner;
  158. mutex_unlock(&cli->mutex);
  159. if (copy_to_user(user, argv, argc))
  160. ret = -EFAULT;
  161. done:
  162. kfree(argv);
  163. return ret;
  164. }
  165. void
  166. usif_client_fini(struct nouveau_cli *cli)
  167. {
  168. struct usif_object *object, *otemp;
  169. list_for_each_entry_safe(object, otemp, &cli->objects, head) {
  170. usif_object_dtor(object);
  171. }
  172. }
  173. void
  174. usif_client_init(struct nouveau_cli *cli)
  175. {
  176. INIT_LIST_HEAD(&cli->objects);
  177. }