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