Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / vfio / pci / vfio_pci_zdev.c
blob0990fdb146b7826c02b214b3a383077a40dbaf0b
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * VFIO ZPCI devices support
5 * Copyright (C) IBM Corp. 2020. All rights reserved.
6 * Author(s): Pierre Morel <pmorel@linux.ibm.com>
7 * Matthew Rosato <mjrosato@linux.ibm.com>
8 */
9 #include <linux/io.h>
10 #include <linux/pci.h>
11 #include <linux/uaccess.h>
12 #include <linux/vfio.h>
13 #include <linux/vfio_zdev.h>
14 #include <linux/kvm_host.h>
15 #include <asm/pci_clp.h>
16 #include <asm/pci_io.h>
18 #include "vfio_pci_priv.h"
21 * Add the Base PCI Function information to the device info region.
23 static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
25 struct vfio_device_info_cap_zpci_base cap = {
26 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
27 .header.version = 2,
28 .start_dma = zdev->start_dma,
29 .end_dma = zdev->end_dma,
30 .pchid = zdev->pchid,
31 .vfn = zdev->vfn,
32 .fmb_length = zdev->fmb_length,
33 .pft = zdev->pft,
34 .gid = zdev->pfgid,
35 .fh = zdev->fh
38 return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
42 * Add the Base PCI Function Group information to the device info region.
44 static int zpci_group_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
46 struct vfio_device_info_cap_zpci_group cap = {
47 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_GROUP,
48 .header.version = 2,
49 .dasm = zdev->dma_mask,
50 .msi_addr = zdev->msi_addr,
51 .flags = VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH,
52 .mui = zdev->fmb_update,
53 .noi = zdev->max_msi,
54 .maxstbl = ZPCI_MAX_WRITE_SIZE,
55 .version = zdev->version,
56 .reserved = 0,
57 .imaxstbl = zdev->maxstbl
60 return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
64 * Add the device utility string to the device info region.
66 static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
68 struct vfio_device_info_cap_zpci_util *cap;
69 int cap_size = sizeof(*cap) + CLP_UTIL_STR_LEN;
70 int ret;
72 cap = kmalloc(cap_size, GFP_KERNEL);
73 if (!cap)
74 return -ENOMEM;
76 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL;
77 cap->header.version = 1;
78 cap->size = CLP_UTIL_STR_LEN;
79 memcpy(cap->util_str, zdev->util_str, cap->size);
81 ret = vfio_info_add_capability(caps, &cap->header, cap_size);
83 kfree(cap);
85 return ret;
89 * Add the function path string to the device info region.
91 static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
93 struct vfio_device_info_cap_zpci_pfip *cap;
94 int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS;
95 int ret;
97 cap = kmalloc(cap_size, GFP_KERNEL);
98 if (!cap)
99 return -ENOMEM;
101 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP;
102 cap->header.version = 1;
103 cap->size = CLP_PFIP_NR_SEGMENTS;
104 memcpy(cap->pfip, zdev->pfip, cap->size);
106 ret = vfio_info_add_capability(caps, &cap->header, cap_size);
108 kfree(cap);
110 return ret;
114 * Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain.
116 int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
117 struct vfio_info_cap *caps)
119 struct zpci_dev *zdev = to_zpci(vdev->pdev);
120 int ret;
122 if (!zdev)
123 return -ENODEV;
125 ret = zpci_base_cap(zdev, caps);
126 if (ret)
127 return ret;
129 ret = zpci_group_cap(zdev, caps);
130 if (ret)
131 return ret;
133 if (zdev->util_str_avail) {
134 ret = zpci_util_cap(zdev, caps);
135 if (ret)
136 return ret;
139 ret = zpci_pfip_cap(zdev, caps);
141 return ret;
144 int vfio_pci_zdev_open_device(struct vfio_pci_core_device *vdev)
146 struct zpci_dev *zdev = to_zpci(vdev->pdev);
148 if (!zdev)
149 return -ENODEV;
151 if (!vdev->vdev.kvm)
152 return 0;
154 if (zpci_kvm_hook.kvm_register)
155 return zpci_kvm_hook.kvm_register(zdev, vdev->vdev.kvm);
157 return -ENOENT;
160 void vfio_pci_zdev_close_device(struct vfio_pci_core_device *vdev)
162 struct zpci_dev *zdev = to_zpci(vdev->pdev);
164 if (!zdev || !vdev->vdev.kvm)
165 return;
167 if (zpci_kvm_hook.kvm_unregister)
168 zpci_kvm_hook.kvm_unregister(zdev);