123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include "hab.h"
- #include "hab_ghs.h"
- #define GIPC_VM_SET_CNT 22
- /* same vmid assignment for all the vms. it should matches dt_gipc_path_name */
- static int mmid_order[GIPC_VM_SET_CNT] = {
- MM_AUD_1,
- MM_AUD_2,
- MM_AUD_3,
- MM_AUD_4,
- MM_CAM_1,
- MM_CAM_2,
- MM_DISP_1,
- MM_DISP_2,
- MM_DISP_3,
- MM_DISP_4,
- MM_DISP_5,
- MM_GFX,
- MM_VID,
- MM_MISC,
- MM_QCPE_VM1,
- MM_VID_2, /* newly recycled */
- 0,
- 0,
- MM_CLK_VM1,
- MM_CLK_VM2,
- MM_FDE_1,
- MM_BUFFERQ_1,
- };
- struct ghs_vmm_plugin_info_s ghs_vmm_plugin_info = {
- dt_gipc_path_name,
- mmid_order,
- 0,
- 0,
- };
- int get_dt_name_idx(int vmid_base, int mmid,
- struct ghs_vmm_plugin_info_s *plugin_info)
- {
- int idx = -1;
- int i;
- if (vmid_base < 0 || vmid_base > plugin_info->probe_cnt /
- GIPC_VM_SET_CNT) {
- pr_err("vmid %d overflow expected max %d\n", vmid_base,
- plugin_info->probe_cnt / GIPC_VM_SET_CNT);
- return idx;
- }
- for (i = 0; i < GIPC_VM_SET_CNT; i++) {
- if (mmid == plugin_info->mmid_dt_mapping[i]) {
- idx = vmid_base * GIPC_VM_SET_CNT + i;
- if (idx > plugin_info->probe_cnt) {
- pr_err("dt name idx %d overflow max %d\n",
- idx, plugin_info->probe_cnt);
- idx = -1;
- }
- break;
- }
- }
- return idx;
- }
- /* static struct physical_channel *habhyp_commdev_alloc(int id) */
- int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
- struct hab_device *mmid_device)
- {
- struct ghs_vdev *dev = NULL;
- struct ghs_vdev_os *dev_os = NULL;
- struct physical_channel *pchan = NULL;
- struct physical_channel **ppchan = (struct physical_channel **)commdev;
- int ret = 0;
- if (ghs_vmm_plugin_info.curr > ghs_vmm_plugin_info.probe_cnt) {
- pr_err("too many commdev alloc %d, supported is %d\n",
- ghs_vmm_plugin_info.curr,
- ghs_vmm_plugin_info.probe_cnt);
- ret = -ENOENT;
- goto err;
- }
- /* common part for hyp_data */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- pr_err("allocate struct ghs_vdev failed %zu bytes on pchan %s\n",
- sizeof(*dev), name);
- goto err;
- }
- memset(dev, 0, sizeof(*dev));
- /* os specific part for hyp_data */
- dev_os = kzalloc(sizeof(*dev_os), GFP_KERNEL);
- if (!dev_os) {
- ret = -ENOMEM;
- pr_err("allocate ghs_vdev_os failed %zu bytes on pchan %s\n",
- sizeof(*dev_os), name);
- goto err;
- }
- dev->os_data = dev_os;
- spin_lock_init(&dev->io_lock);
- /*
- * TODO: ExtractEndpoint is in ghs_comm.c because it blocks.
- * Extrace and Request should be in roughly the same spot
- */
- ret = hab_gipc_ep_attach(is_be, name, vmid_remote, mmid_device, dev);
- if (ret)
- goto err;
- /* add pchan into the mmid_device list */
- pchan = hab_pchan_alloc(mmid_device, vmid_remote);
- if (!pchan) {
- pr_err("hab_pchan_alloc failed for %s, cnt %d\n",
- mmid_device->name, mmid_device->pchan_cnt);
- ret = -ENOMEM;
- goto err;
- }
- pchan->closed = 0;
- pchan->hyp_data = (void *)dev;
- pchan->is_be = is_be;
- strscpy(dev->name, name, sizeof(dev->name));
- strscpy(pchan->name, name, sizeof(pchan->name));
- *ppchan = pchan;
- dev->read_data = kmalloc(GIPC_RECV_BUFF_SIZE_BYTES, GFP_KERNEL);
- if (!dev->read_data) {
- ret = -ENOMEM;
- goto err;
- }
- ret = habhyp_commdev_create_dispatcher(pchan);
- if (ret)
- goto err;
- /* this value could be more than devp total */
- ghs_vmm_plugin_info.curr++;
- return 0;
- err:
- hab_pchan_put(pchan);
- kfree(dev);
- kfree(dev_os);
- return ret;
- }
- int habhyp_commdev_dealloc(void *commdev)
- {
- struct physical_channel *pchan = (struct physical_channel *)commdev;
- struct ghs_vdev *dev = pchan->hyp_data;
- /* os specific deallocation for this commdev */
- habhyp_commdev_dealloc_os(commdev);
- kfree(dev->read_data);
- kfree(dev->os_data);
- kfree(dev);
- pchan->closed = 1;
- pchan->hyp_data = NULL;
- if (get_refcnt(pchan->refcount) > 1) {
- pr_warn("potential leak pchan %s vchans %d refcnt %d\n",
- pchan->name, pchan->vcnt, get_refcnt(pchan->refcount));
- }
- hab_pchan_put(pchan);
- return 0;
- }
- void hab_hypervisor_unregister(void)
- {
- pr_debug("total %d\n", hab_driver.ndevices);
- hab_hypervisor_unregister_common();
- ghs_vmm_plugin_info.curr = 0;
- }
- int hab_hypervisor_register(void)
- {
- int ret = 0;
- /* os-specific registration work */
- ret = hab_hypervisor_register_os();
- return ret;
- }
- int hab_hypervisor_register_post(void) { return 0; }
|