0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "nouveau_drv.h"
0026 #include "nouveau_usif.h"
0027 #include "nouveau_abi16.h"
0028
0029 #include <nvif/unpack.h>
0030 #include <nvif/client.h>
0031 #include <nvif/ioctl.h>
0032
0033 #include <nvif/class.h>
0034 #include <nvif/cl0080.h>
0035
0036 struct usif_object {
0037 struct list_head head;
0038 u8 route;
0039 u64 token;
0040 };
0041
0042 static void
0043 usif_object_dtor(struct usif_object *object)
0044 {
0045 list_del(&object->head);
0046 kfree(object);
0047 }
0048
0049 static int
0050 usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16)
0051 {
0052 struct nouveau_cli *cli = nouveau_cli(f);
0053 struct nvif_client *client = &cli->base;
0054 union {
0055 struct nvif_ioctl_new_v0 v0;
0056 } *args = data;
0057 struct usif_object *object;
0058 int ret = -ENOSYS;
0059
0060 if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true)))
0061 return ret;
0062
0063 switch (args->v0.oclass) {
0064 case NV_DMA_FROM_MEMORY:
0065 case NV_DMA_TO_MEMORY:
0066 case NV_DMA_IN_MEMORY:
0067 return -EINVAL;
0068 case NV_DEVICE: {
0069 union {
0070 struct nv_device_v0 v0;
0071 } *args = data;
0072
0073 if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)))
0074 return ret;
0075
0076 args->v0.priv = false;
0077 break;
0078 }
0079 default:
0080 if (!parent_abi16)
0081 return -EINVAL;
0082 break;
0083 }
0084
0085 if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
0086 return -ENOMEM;
0087 list_add(&object->head, &cli->objects);
0088
0089 object->route = args->v0.route;
0090 object->token = args->v0.token;
0091 args->v0.route = NVDRM_OBJECT_USIF;
0092 args->v0.token = (unsigned long)(void *)object;
0093 ret = nvif_client_ioctl(client, argv, argc);
0094 if (ret) {
0095 usif_object_dtor(object);
0096 return ret;
0097 }
0098
0099 args->v0.token = object->token;
0100 args->v0.route = object->route;
0101 return 0;
0102 }
0103
0104 int
0105 usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
0106 {
0107 struct nouveau_cli *cli = nouveau_cli(filp);
0108 struct nvif_client *client = &cli->base;
0109 void *data = kmalloc(argc, GFP_KERNEL);
0110 u32 size = argc;
0111 union {
0112 struct nvif_ioctl_v0 v0;
0113 } *argv = data;
0114 struct usif_object *object;
0115 bool abi16 = false;
0116 u8 owner;
0117 int ret;
0118
0119 if (ret = -ENOMEM, !argv)
0120 goto done;
0121 if (ret = -EFAULT, copy_from_user(argv, user, size))
0122 goto done;
0123
0124 if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
0125
0126 owner = argv->v0.owner;
0127 if (argv->v0.object == 0ULL &&
0128 argv->v0.type != NVIF_IOCTL_V0_DEL)
0129 argv->v0.owner = NVDRM_OBJECT_ANY;
0130 else
0131 argv->v0.owner = NVDRM_OBJECT_USIF;
0132 } else
0133 goto done;
0134
0135
0136
0137
0138 mutex_lock(&cli->mutex);
0139 if (argv->v0.route) {
0140 if (ret = -EINVAL, argv->v0.route == 0xff)
0141 ret = nouveau_abi16_usif(filp, argv, argc);
0142 if (ret) {
0143 mutex_unlock(&cli->mutex);
0144 goto done;
0145 }
0146
0147 abi16 = true;
0148 }
0149
0150 switch (argv->v0.type) {
0151 case NVIF_IOCTL_V0_NEW:
0152 ret = usif_object_new(filp, data, size, argv, argc, abi16);
0153 break;
0154 case NVIF_IOCTL_V0_NTFY_NEW:
0155 case NVIF_IOCTL_V0_NTFY_DEL:
0156 case NVIF_IOCTL_V0_NTFY_GET:
0157 case NVIF_IOCTL_V0_NTFY_PUT:
0158 ret = -ENOSYS;
0159 break;
0160 default:
0161 ret = nvif_client_ioctl(client, argv, argc);
0162 break;
0163 }
0164 if (argv->v0.route == NVDRM_OBJECT_USIF) {
0165 object = (void *)(unsigned long)argv->v0.token;
0166 argv->v0.route = object->route;
0167 argv->v0.token = object->token;
0168 if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) {
0169 list_del(&object->head);
0170 kfree(object);
0171 }
0172 } else {
0173 argv->v0.route = NVIF_IOCTL_V0_ROUTE_HIDDEN;
0174 argv->v0.token = 0;
0175 }
0176 argv->v0.owner = owner;
0177 mutex_unlock(&cli->mutex);
0178
0179 if (copy_to_user(user, argv, argc))
0180 ret = -EFAULT;
0181 done:
0182 kfree(argv);
0183 return ret;
0184 }
0185
0186 void
0187 usif_client_fini(struct nouveau_cli *cli)
0188 {
0189 struct usif_object *object, *otemp;
0190
0191 list_for_each_entry_safe(object, otemp, &cli->objects, head) {
0192 usif_object_dtor(object);
0193 }
0194 }
0195
0196 void
0197 usif_client_init(struct nouveau_cli *cli)
0198 {
0199 INIT_LIST_HEAD(&cli->objects);
0200 }