1 /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
15 #define HAB_DEVICE_CNSTR(__name__, __id__, __num__) { \
18 .pchannels = LIST_HEAD_INIT(hab_devices[__num__].pchannels),\
19 .pchan_lock = __MUTEX_INITIALIZER(hab_devices[__num__].pchan_lock),\
20 .openq_list = LIST_HEAD_INIT(hab_devices[__num__].openq_list),\
21 .openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\
25 * The following has to match habmm definitions, order does not matter if
26 * hab config does not care either. When hab config is not present, the default
27 * is as guest VM all pchans are pchan opener (FE)
29 static struct hab_device hab_devices[] = {
30 HAB_DEVICE_CNSTR(DEVICE_AUD1_NAME, MM_AUD_1, 0),
31 HAB_DEVICE_CNSTR(DEVICE_AUD2_NAME, MM_AUD_2, 1),
32 HAB_DEVICE_CNSTR(DEVICE_AUD3_NAME, MM_AUD_3, 2),
33 HAB_DEVICE_CNSTR(DEVICE_AUD4_NAME, MM_AUD_4, 3),
34 HAB_DEVICE_CNSTR(DEVICE_CAM1_NAME, MM_CAM_1, 4),
35 HAB_DEVICE_CNSTR(DEVICE_CAM2_NAME, MM_CAM_2, 5),
36 HAB_DEVICE_CNSTR(DEVICE_DISP1_NAME, MM_DISP_1, 6),
37 HAB_DEVICE_CNSTR(DEVICE_DISP2_NAME, MM_DISP_2, 7),
38 HAB_DEVICE_CNSTR(DEVICE_DISP3_NAME, MM_DISP_3, 8),
39 HAB_DEVICE_CNSTR(DEVICE_DISP4_NAME, MM_DISP_4, 9),
40 HAB_DEVICE_CNSTR(DEVICE_DISP5_NAME, MM_DISP_5, 10),
41 HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11),
42 HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12),
43 HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 13),
44 HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 14),
45 HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 15),
46 HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 16),
47 HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17),
48 HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18),
49 HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19),
52 struct hab_driver hab_driver = {
53 .ndevices = ARRAY_SIZE(hab_devices),
57 struct uhab_context *hab_ctx_alloc(int kernel)
59 struct uhab_context *ctx;
61 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
66 INIT_LIST_HEAD(&ctx->vchannels);
67 INIT_LIST_HEAD(&ctx->exp_whse);
68 INIT_LIST_HEAD(&ctx->imp_whse);
70 INIT_LIST_HEAD(&ctx->exp_rxq);
71 init_waitqueue_head(&ctx->exp_wq);
72 spin_lock_init(&ctx->expq_lock);
74 spin_lock_init(&ctx->imp_lock);
75 rwlock_init(&ctx->exp_lock);
76 rwlock_init(&ctx->ctx_lock);
78 kref_init(&ctx->refcount);
79 ctx->import_ctx = habmem_imp_hyp_open();
80 if (!ctx->import_ctx) {
81 pr_err("habmem_imp_hyp_open failed\n");
90 void hab_ctx_free(struct kref *ref)
92 struct uhab_context *ctx =
93 container_of(ref, struct uhab_context, refcount);
94 struct hab_export_ack_recvd *ack_recvd, *tmp;
96 habmem_imp_hyp_close(ctx->import_ctx, ctx->kernel);
98 list_for_each_entry_safe(ack_recvd, tmp, &ctx->exp_rxq, node) {
99 list_del(&ack_recvd->node);
106 struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
107 struct uhab_context *ctx)
109 struct virtual_channel *vchan;
111 read_lock(&ctx->ctx_lock);
112 list_for_each_entry(vchan, &ctx->vchannels, node) {
113 if (vcid == vchan->id) {
114 kref_get(&vchan->refcount);
115 read_unlock(&ctx->ctx_lock);
119 read_unlock(&ctx->ctx_lock);
123 static struct hab_device *find_hab_device(unsigned int mm_id)
127 for (i = 0; i < hab_driver.ndevices; i++) {
128 if (hab_driver.devp[i].id == HAB_MMID_GET_MAJOR(mm_id))
129 return &hab_driver.devp[i];
132 pr_err("find_hab_device failed: id=%d\n", mm_id);
136 * open handshake in FE and BE
139 * send(INIT) wait(INIT)
140 * wait(INIT_ACK) send(INIT_ACK)
141 * send(ACK) wait(ACK)
144 struct virtual_channel *frontend_open(struct uhab_context *ctx,
148 int ret, open_id = 0;
149 struct physical_channel *pchan = NULL;
150 struct hab_device *dev;
151 struct virtual_channel *vchan = NULL;
152 static atomic_t open_id_counter = ATOMIC_INIT(0);
153 struct hab_open_request request;
154 struct hab_open_request *recv_request;
155 int sub_id = HAB_MMID_GET_MINOR(mm_id);
157 dev = find_hab_device(mm_id);
159 pr_err("HAB device %d is not initialized\n", mm_id);
164 pchan = hab_pchan_find_domid(dev, dom_id);
166 pr_err("hab_pchan_find_domid failed: dom_id=%d\n", dom_id);
171 vchan = hab_vchan_alloc(ctx, pchan);
173 pr_err("vchan alloc failed\n");
178 /* Send Init sequence */
179 open_id = atomic_inc_return(&open_id_counter);
180 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT, pchan,
181 vchan->id, sub_id, open_id);
182 ret = hab_open_request_send(&request);
184 pr_err("hab_open_request_send failed: %d\n", ret);
188 /* Wait for Init-Ack sequence */
189 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT_ACK, pchan,
191 ret = hab_open_listen(ctx, dev, &request, &recv_request, 0);
192 if (ret || !recv_request) {
193 pr_err("hab_open_listen failed: %d\n", ret);
197 vchan->otherend_id = recv_request->vchan_id;
198 hab_open_request_free(recv_request);
200 vchan->session_id = open_id;
201 pr_debug("vchan->session_id:%d\n", vchan->session_id);
203 /* Send Ack sequence */
204 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_ACK, pchan,
206 ret = hab_open_request_send(&request);
210 hab_pchan_put(pchan);
215 hab_vchan_put(vchan);
217 hab_pchan_put(pchan);
222 struct virtual_channel *backend_listen(struct uhab_context *ctx,
227 int sub_id = HAB_MMID_GET_MINOR(mm_id);
228 struct physical_channel *pchan = NULL;
229 struct hab_device *dev;
230 struct virtual_channel *vchan = NULL;
231 struct hab_open_request request;
232 struct hab_open_request *recv_request;
233 uint32_t otherend_vchan_id;
235 dev = find_hab_device(mm_id);
237 pr_err("failed to find dev based on id %d\n", mm_id);
243 /* Wait for Init sequence */
244 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT,
246 ret = hab_open_listen(ctx, dev, &request, &recv_request, 0);
247 if (ret || !recv_request) {
248 pr_err("hab_open_listen failed: %d\n", ret);
252 otherend_vchan_id = recv_request->vchan_id;
253 open_id = recv_request->open_id;
254 pchan = recv_request->pchan;
255 hab_pchan_get(pchan);
256 hab_open_request_free(recv_request);
258 vchan = hab_vchan_alloc(ctx, pchan);
264 vchan->otherend_id = otherend_vchan_id;
266 vchan->session_id = open_id;
267 pr_debug("vchan->session_id:%d\n", vchan->session_id);
269 /* Send Init-Ack sequence */
270 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT_ACK,
271 pchan, vchan->id, sub_id, open_id);
272 ret = hab_open_request_send(&request);
276 /* Wait for Ack sequence */
277 hab_open_request_init(&request, HAB_PAYLOAD_TYPE_ACK,
278 pchan, 0, sub_id, open_id);
279 ret = hab_open_listen(ctx, dev, &request, &recv_request, 0);
284 hab_vchan_put(vchan);
286 hab_pchan_put(pchan);
290 if (ret || !recv_request) {
291 pr_err("backend_listen failed: %d\n", ret);
296 hab_open_request_free(recv_request);
297 hab_pchan_put(pchan);
300 pr_err("listen on mmid %d failed\n", mm_id);
302 hab_vchan_put(vchan);
304 hab_pchan_put(pchan);
308 long hab_vchan_send(struct uhab_context *ctx,
314 struct virtual_channel *vchan;
316 struct hab_header header = HAB_HEADER_INITIALIZER;
317 int nonblocking_flag = flags & HABMM_SOCKET_SEND_FLAGS_NON_BLOCKING;
319 if (sizebytes > HAB_MAX_MSG_SIZEBYTES) {
320 pr_err("Message too large, %lu bytes\n", sizebytes);
324 vchan = hab_get_vchan_fromvcid(vcid, ctx);
325 if (!vchan || vchan->otherend_closed) {
330 HAB_HEADER_SET_SIZE(header, sizebytes);
331 if (flags & HABMM_SOCKET_SEND_FLAGS_XING_VM_STAT)
332 HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_PROFILE);
334 HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_MSG);
336 HAB_HEADER_SET_ID(header, vchan->otherend_id);
337 HAB_HEADER_SET_SESSION_ID(header, vchan->session_id);
340 ret = physical_channel_send(vchan->pchan, &header, data);
342 if (vchan->otherend_closed || nonblocking_flag ||
352 hab_vchan_put(vchan);
357 struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
361 struct virtual_channel *vchan;
362 struct hab_message *message;
364 int nonblocking_flag = flags & HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING;
366 vchan = hab_get_vchan_fromvcid(vcid, ctx);
368 return ERR_PTR(-ENODEV);
370 if (nonblocking_flag) {
372 * Try to pull data from the ring in this context instead of
373 * IRQ handler. Any available messages will be copied and queued
374 * internally, then fetched by hab_msg_dequeue()
376 physical_channel_rx_dispatch((unsigned long) vchan->pchan);
379 message = hab_msg_dequeue(vchan, !nonblocking_flag);
381 if (nonblocking_flag)
383 else if (vchan->otherend_closed)
389 hab_vchan_put(vchan);
390 return ret ? ERR_PTR(ret) : message;
393 bool hab_is_loopback(void)
395 return hab_driver.b_loopback;
398 int hab_vchan_open(struct uhab_context *ctx,
403 struct virtual_channel *vchan = NULL;
404 struct hab_device *dev;
406 pr_debug("Open mmid=%d, loopback mode=%d, loopback num=%d\n",
407 mmid, hab_driver.b_loopback, hab_driver.loopback_num);
412 if (hab_is_loopback()) {
413 if (!hab_driver.loopback_num) {
414 hab_driver.loopback_num = 1;
415 vchan = backend_listen(ctx, mmid);
417 hab_driver.loopback_num = 0;
418 vchan = frontend_open(ctx, mmid, LOOPBACK_DOM);
421 dev = find_hab_device(mmid);
424 struct physical_channel *pchan =
425 hab_pchan_find_domid(dev, HABCFG_VMID_DONT_CARE);
428 vchan = backend_listen(ctx, mmid);
430 vchan = frontend_open(ctx, mmid,
431 HABCFG_VMID_DONT_CARE);
433 pr_err("failed to find device, mmid %d\n", mmid);
438 pr_err("vchan open failed over mmid=%d\n", mmid);
439 return PTR_ERR(vchan);
442 pr_debug("vchan id %x, remote id %x\n",
443 vchan->id, vchan->otherend_id);
445 write_lock(&ctx->ctx_lock);
446 list_add_tail(&vchan->node, &ctx->vchannels);
447 write_unlock(&ctx->ctx_lock);
454 void hab_send_close_msg(struct virtual_channel *vchan)
456 struct hab_header header = {0};
458 if (vchan && !vchan->otherend_closed) {
459 HAB_HEADER_SET_SIZE(header, 0);
460 HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_CLOSE);
461 HAB_HEADER_SET_ID(header, vchan->otherend_id);
462 HAB_HEADER_SET_SESSION_ID(header, vchan->session_id);
463 physical_channel_send(vchan->pchan, &header, NULL);
467 static void hab_vchan_close_impl(struct kref *ref)
469 struct virtual_channel *vchan =
470 container_of(ref, struct virtual_channel, usagecnt);
472 list_del(&vchan->node);
473 hab_vchan_stop_notify(vchan);
474 hab_vchan_put(vchan);
478 void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
480 struct virtual_channel *vchan, *tmp;
485 write_lock(&ctx->ctx_lock);
486 list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
487 if (vchan->id == vcid) {
488 kref_put(&vchan->usagecnt, hab_vchan_close_impl);
493 write_unlock(&ctx->ctx_lock);
497 * To name the pchan - the pchan has two ends, either FE or BE locally.
498 * if is_be is true, then this is listener for BE. pchane name use remote
499 * FF's vmid from the table.
500 * if is_be is false, then local is FE as opener. pchan name use local FE's
503 static int hab_initialize_pchan_entry(struct hab_device *mmid_device,
504 int vmid_local, int vmid_remote, int is_be)
506 char pchan_name[MAX_VMID_NAME_SIZE];
507 struct physical_channel *pchan = NULL;
509 int vmid = is_be ? vmid_remote : vmid_local;
512 pr_err("habdev %pK, vmid local %d, remote %d, is be %d\n",
513 mmid_device, vmid_local, vmid_remote, is_be);
517 snprintf(pchan_name, MAX_VMID_NAME_SIZE, "vm%d-", vmid);
518 strlcat(pchan_name, mmid_device->name, MAX_VMID_NAME_SIZE);
520 ret = habhyp_commdev_alloc((void **)&pchan, is_be, pchan_name,
521 vmid_remote, mmid_device);
523 pr_debug("pchan %s added, vmid local %d, remote %d, is_be %d, total %d\n",
524 pchan_name, vmid_local, vmid_remote, is_be,
525 mmid_device->pchan_cnt);
527 pr_err("failed %d to allocate pchan %s, vmid local %d, remote %d, is_be %d, total %d\n",
528 ret, pchan_name, vmid_local, vmid_remote,
529 is_be, mmid_device->pchan_cnt);
535 static void hab_generate_pchan(struct local_vmid *settings, int i, int j)
539 pr_debug("%d as mmid %d in vmid %d\n",
540 HABCFG_GET_MMID(settings, i, j), j, i);
542 switch (HABCFG_GET_MMID(settings, i, j)) {
543 case MM_AUD_START/100:
544 for (k = MM_AUD_START + 1; k < MM_AUD_END; k++) {
546 * if this local pchan end is BE, then use
547 * remote FE's vmid. If local end is FE, then
550 ret += hab_initialize_pchan_entry(
553 HABCFG_GET_VMID(settings, i),
554 HABCFG_GET_BE(settings, i, j));
558 case MM_CAM_START/100:
559 for (k = MM_CAM_START + 1; k < MM_CAM_END; k++) {
560 ret += hab_initialize_pchan_entry(
563 HABCFG_GET_VMID(settings, i),
564 HABCFG_GET_BE(settings, i, j));
568 case MM_DISP_START/100:
569 for (k = MM_DISP_START + 1; k < MM_DISP_END; k++) {
570 ret += hab_initialize_pchan_entry(
573 HABCFG_GET_VMID(settings, i),
574 HABCFG_GET_BE(settings, i, j));
578 case MM_GFX_START/100:
579 for (k = MM_GFX_START + 1; k < MM_GFX_END; k++) {
580 ret += hab_initialize_pchan_entry(
583 HABCFG_GET_VMID(settings, i),
584 HABCFG_GET_BE(settings, i, j));
588 case MM_VID_START/100:
589 for (k = MM_VID_START + 1; k < MM_VID_END; k++) {
590 ret += hab_initialize_pchan_entry(
593 HABCFG_GET_VMID(settings, i),
594 HABCFG_GET_BE(settings, i, j));
598 case MM_MISC_START/100:
599 for (k = MM_MISC_START + 1; k < MM_MISC_END; k++) {
600 ret += hab_initialize_pchan_entry(
603 HABCFG_GET_VMID(settings, i),
604 HABCFG_GET_BE(settings, i, j));
608 case MM_QCPE_START/100:
609 for (k = MM_QCPE_START + 1; k < MM_QCPE_END; k++) {
610 ret += hab_initialize_pchan_entry(
613 HABCFG_GET_VMID(settings, i),
614 HABCFG_GET_BE(settings, i, j));
618 case MM_CLK_START/100:
619 for (k = MM_CLK_START + 1; k < MM_CLK_END; k++) {
620 ret += hab_initialize_pchan_entry(
623 HABCFG_GET_VMID(settings, i),
624 HABCFG_GET_BE(settings, i, j));
629 pr_err("failed to find mmid %d, i %d, j %d\n",
630 HABCFG_GET_MMID(settings, i, j), i, j);
637 * generate pchan list based on hab settings table.
638 * return status 0: success, otherwise failure
640 static int hab_generate_pchan_list(struct local_vmid *settings)
644 /* scan by valid VMs, then mmid */
645 pr_debug("self vmid is %d\n", settings->self);
646 for (i = 0; i < HABCFG_VMID_MAX; i++) {
647 if (HABCFG_GET_VMID(settings, i) != HABCFG_VMID_INVALID &&
648 HABCFG_GET_VMID(settings, i) != settings->self) {
649 pr_debug("create pchans for vm %d\n", i);
651 for (j = 1; j <= HABCFG_MMID_AREA_MAX; j++) {
652 if (HABCFG_GET_MMID(settings, i, j)
653 != HABCFG_VMID_INVALID)
654 hab_generate_pchan(settings, i, j);
663 * This function checks hypervisor plug-in readiness, read in hab configs,
664 * and configure pchans
666 int do_hab_parse(void)
670 struct hab_device *device;
673 /* first check if hypervisor plug-in is ready */
674 result = hab_hypervisor_register();
676 pr_err("register HYP plug-in failed, ret %d\n", result);
680 /* Initialize open Q before first pchan starts */
681 for (i = 0; i < hab_driver.ndevices; i++) {
682 device = &hab_driver.devp[i];
683 init_waitqueue_head(&device->openq);
686 /* read in hab config and create pchans*/
687 memset(&hab_driver.settings, HABCFG_VMID_INVALID,
688 sizeof(hab_driver.settings));
690 result = hab_parse(&hab_driver.settings);
692 pr_warn("hab_parse failed and use the default settings\n");
693 fill_default_gvm_settings(&hab_driver.settings, 2,
694 MM_AUD_START, MM_ID_MAX);
697 /* now generate hab pchan list */
698 result = hab_generate_pchan_list(&hab_driver.settings);
700 pr_err("generate pchan list failed, ret %d\n", result);
702 for (i = 0; i < hab_driver.ndevices; i++) {
703 device = &hab_driver.devp[i];
704 pchan_total += device->pchan_cnt;
706 pr_debug("ret %d, total %d pchans added, ndevices %d\n",
707 result, pchan_total, hab_driver.ndevices);
713 static int hab_open(struct inode *inodep, struct file *filep)
716 struct uhab_context *ctx;
718 ctx = hab_ctx_alloc(0);
721 pr_err("hab_ctx_alloc failed\n");
722 filep->private_data = NULL;
726 filep->private_data = ctx;
731 static int hab_release(struct inode *inodep, struct file *filep)
733 struct uhab_context *ctx = filep->private_data;
734 struct virtual_channel *vchan, *tmp;
739 pr_debug("inode %pK, filep %pK\n", inodep, filep);
741 write_lock(&ctx->ctx_lock);
743 list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
744 list_del(&vchan->node);
745 hab_vchan_stop_notify(vchan);
746 hab_vchan_put(vchan);
749 write_unlock(&ctx->ctx_lock);
752 filep->private_data = NULL;
757 static long hab_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
759 struct uhab_context *ctx = (struct uhab_context *)filep->private_data;
760 struct hab_open *open_param;
761 struct hab_close *close_param;
762 struct hab_recv *recv_param;
763 struct hab_send *send_param;
764 struct hab_message *msg;
766 unsigned char data[256] = { 0 };
769 if (_IOC_SIZE(cmd) && (cmd & IOC_IN)) {
770 if (_IOC_SIZE(cmd) > sizeof(data))
773 if (copy_from_user(data, (void __user *)arg, _IOC_SIZE(cmd))) {
774 pr_err("copy_from_user failed cmd=%x size=%d\n",
775 cmd, _IOC_SIZE(cmd));
781 case IOCTL_HAB_VC_OPEN:
782 open_param = (struct hab_open *)data;
783 ret = hab_vchan_open(ctx, open_param->mmid,
784 &open_param->vcid, open_param->flags);
786 case IOCTL_HAB_VC_CLOSE:
787 close_param = (struct hab_close *)data;
788 hab_vchan_close(ctx, close_param->vcid);
791 send_param = (struct hab_send *)data;
792 if (send_param->sizebytes > HAB_MAX_MSG_SIZEBYTES) {
797 send_data = kzalloc(send_param->sizebytes, GFP_TEMPORARY);
803 if (copy_from_user(send_data, (void __user *)send_param->data,
804 send_param->sizebytes)) {
807 ret = hab_vchan_send(ctx, send_param->vcid,
808 send_param->sizebytes,
815 recv_param = (struct hab_recv *)data;
816 if (!recv_param->data) {
821 msg = hab_vchan_recv(ctx, recv_param->vcid, recv_param->flags);
824 recv_param->sizebytes = 0;
829 if (recv_param->sizebytes < msg->sizebytes) {
830 recv_param->sizebytes = 0;
832 } else if (copy_to_user((void __user *)recv_param->data,
835 pr_err("copy_to_user failed: vc=%x size=%d\n",
836 recv_param->vcid, (int)msg->sizebytes);
837 recv_param->sizebytes = 0;
840 recv_param->sizebytes = msg->sizebytes;
845 case IOCTL_HAB_VC_EXPORT:
846 ret = hab_mem_export(ctx, (struct hab_export *)data, 0);
848 case IOCTL_HAB_VC_IMPORT:
849 ret = hab_mem_import(ctx, (struct hab_import *)data, 0);
851 case IOCTL_HAB_VC_UNEXPORT:
852 ret = hab_mem_unexport(ctx, (struct hab_unexport *)data, 0);
854 case IOCTL_HAB_VC_UNIMPORT:
855 ret = hab_mem_unimport(ctx, (struct hab_unimport *)data, 0);
861 if (ret == 0 && _IOC_SIZE(cmd) && (cmd & IOC_OUT))
862 if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd))) {
863 pr_err("copy_to_user failed: cmd=%x\n", cmd);
870 static const struct file_operations hab_fops = {
871 .owner = THIS_MODULE,
873 .release = hab_release,
874 .mmap = habmem_imp_hyp_mmap,
875 .unlocked_ioctl = hab_ioctl
879 * These map sg functions are pass through because the memory backing the
880 * sg list is already accessible to the kernel as they come from a the
881 * dedicated shared vm pool
884 static int hab_map_sg(struct device *dev, struct scatterlist *sgl,
885 int nelems, enum dma_data_direction dir,
886 struct dma_attrs *attrs)
888 /* return nelems directly */
892 static void hab_unmap_sg(struct device *dev,
893 struct scatterlist *sgl, int nelems,
894 enum dma_data_direction dir,
895 struct dma_attrs *attrs)
900 static const struct dma_map_ops hab_dma_ops = {
901 .map_sg = hab_map_sg,
902 .unmap_sg = hab_unmap_sg,
905 static int __init hab_init(void)
910 result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab");
913 pr_err("alloc_chrdev_region failed: %d\n", result);
917 cdev_init(&hab_driver.cdev, &hab_fops);
918 hab_driver.cdev.owner = THIS_MODULE;
919 hab_driver.cdev.ops = &hab_fops;
920 dev = MKDEV(MAJOR(hab_driver.major), 0);
922 result = cdev_add(&hab_driver.cdev, dev, 1);
925 unregister_chrdev_region(dev, 1);
926 pr_err("cdev_add failed: %d\n", result);
930 hab_driver.class = class_create(THIS_MODULE, "hab");
932 if (IS_ERR(hab_driver.class)) {
933 result = PTR_ERR(hab_driver.class);
934 pr_err("class_create failed: %d\n", result);
938 hab_driver.dev = device_create(hab_driver.class, NULL,
939 dev, &hab_driver, "hab");
941 if (IS_ERR(hab_driver.dev)) {
942 result = PTR_ERR(hab_driver.dev);
943 pr_err("device_create failed: %d\n", result);
947 /* read in hab config, then configure pchans */
948 result = do_hab_parse();
951 hab_driver.kctx = hab_ctx_alloc(1);
952 if (!hab_driver.kctx) {
953 pr_err("hab_ctx_alloc failed");
955 hab_hypervisor_unregister();
959 set_dma_ops(hab_driver.dev, &hab_dma_ops);
965 if (!IS_ERR_OR_NULL(hab_driver.dev))
966 device_destroy(hab_driver.class, dev);
967 if (!IS_ERR_OR_NULL(hab_driver.class))
968 class_destroy(hab_driver.class);
969 cdev_del(&hab_driver.cdev);
970 unregister_chrdev_region(dev, 1);
972 pr_err("Error in hab init, result %d\n", result);
976 static void __exit hab_exit(void)
980 hab_hypervisor_unregister();
981 hab_ctx_put(hab_driver.kctx);
982 dev = MKDEV(MAJOR(hab_driver.major), 0);
983 device_destroy(hab_driver.class, dev);
984 class_destroy(hab_driver.class);
985 cdev_del(&hab_driver.cdev);
986 unregister_chrdev_region(dev, 1);
989 subsys_initcall(hab_init);
990 module_exit(hab_exit);
992 MODULE_DESCRIPTION("Hypervisor abstraction layer");
993 MODULE_LICENSE("GPL v2");