xref: /openbmc/linux/drivers/vfio/pci/vfio_pci_zdev.c (revision be58f710)
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  */
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  */
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  */
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  */
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  */
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