1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * VFIO ZPCI devices support
4 *
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 <asm/pci_clp.h>
15 #include <asm/pci_io.h>
16
17 #include <linux/vfio_pci_core.h>
18
19 /*
20 * Add the Base PCI Function information to the device info region.
21 */
zpci_base_cap(struct zpci_dev * zdev,struct vfio_info_cap * caps)22 static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
23 {
24 struct vfio_device_info_cap_zpci_base cap = {
25 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
26 .header.version = 1,
27 .start_dma = zdev->start_dma,
28 .end_dma = zdev->end_dma,
29 .pchid = zdev->pchid,
30 .vfn = zdev->vfn,
31 .fmb_length = zdev->fmb_length,
32 .pft = zdev->pft,
33 .gid = zdev->pfgid
34 };
35
36 return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
37 }
38
39 /*
40 * Add the Base PCI Function Group information to the device info region.
41 */
zpci_group_cap(struct zpci_dev * zdev,struct vfio_info_cap * caps)42 static int zpci_group_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
43 {
44 struct vfio_device_info_cap_zpci_group cap = {
45 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_GROUP,
46 .header.version = 1,
47 .dasm = zdev->dma_mask,
48 .msi_addr = zdev->msi_addr,
49 .flags = VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH,
50 .mui = zdev->fmb_update,
51 .noi = zdev->max_msi,
52 .maxstbl = ZPCI_MAX_WRITE_SIZE,
53 .version = zdev->version
54 };
55
56 return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
57 }
58
59 /*
60 * Add the device utility string to the device info region.
61 */
zpci_util_cap(struct zpci_dev * zdev,struct vfio_info_cap * caps)62 static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
63 {
64 struct vfio_device_info_cap_zpci_util *cap;
65 int cap_size = sizeof(*cap) + CLP_UTIL_STR_LEN;
66 int ret;
67
68 cap = kmalloc(cap_size, GFP_KERNEL);
69 if (!cap)
70 return -ENOMEM;
71
72 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL;
73 cap->header.version = 1;
74 cap->size = CLP_UTIL_STR_LEN;
75 memcpy(cap->util_str, zdev->util_str, cap->size);
76
77 ret = vfio_info_add_capability(caps, &cap->header, cap_size);
78
79 kfree(cap);
80
81 return ret;
82 }
83
84 /*
85 * Add the function path string to the device info region.
86 */
zpci_pfip_cap(struct zpci_dev * zdev,struct vfio_info_cap * caps)87 static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
88 {
89 struct vfio_device_info_cap_zpci_pfip *cap;
90 int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS;
91 int ret;
92
93 cap = kmalloc(cap_size, GFP_KERNEL);
94 if (!cap)
95 return -ENOMEM;
96
97 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP;
98 cap->header.version = 1;
99 cap->size = CLP_PFIP_NR_SEGMENTS;
100 memcpy(cap->pfip, zdev->pfip, cap->size);
101
102 ret = vfio_info_add_capability(caps, &cap->header, cap_size);
103
104 kfree(cap);
105
106 return ret;
107 }
108
109 /*
110 * Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain.
111 */
vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device * vdev,struct vfio_info_cap * caps)112 int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
113 struct vfio_info_cap *caps)
114 {
115 struct zpci_dev *zdev = to_zpci(vdev->pdev);
116 int ret;
117
118 if (!zdev)
119 return -ENODEV;
120
121 ret = zpci_base_cap(zdev, caps);
122 if (ret)
123 return ret;
124
125 ret = zpci_group_cap(zdev, caps);
126 if (ret)
127 return ret;
128
129 if (zdev->util_str_avail) {
130 ret = zpci_util_cap(zdev, caps);
131 if (ret)
132 return ret;
133 }
134
135 ret = zpci_pfip_cap(zdev, caps);
136
137 return ret;
138 }
139