Merge remote-tracking branch 'torvalds/master' into perf/core
[sfrench/cifs-2.6.git] / drivers / vfio / pci / vfio_pci_zdev.c
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_info_cap *caps)
28 {
29         struct vfio_device_info_cap_zpci_base cap = {
30                 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
31                 .header.version = 1,
32                 .start_dma = zdev->start_dma,
33                 .end_dma = zdev->end_dma,
34                 .pchid = zdev->pchid,
35                 .vfn = zdev->vfn,
36                 .fmb_length = zdev->fmb_length,
37                 .pft = zdev->pft,
38                 .gid = zdev->pfgid
39         };
40
41         return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
42 }
43
44 /*
45  * Add the Base PCI Function Group information to the device info region.
46  */
47 static int zpci_group_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
48 {
49         struct vfio_device_info_cap_zpci_group cap = {
50                 .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_GROUP,
51                 .header.version = 1,
52                 .dasm = zdev->dma_mask,
53                 .msi_addr = zdev->msi_addr,
54                 .flags = VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH,
55                 .mui = zdev->fmb_update,
56                 .noi = zdev->max_msi,
57                 .maxstbl = ZPCI_MAX_WRITE_SIZE,
58                 .version = zdev->version
59         };
60
61         return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
62 }
63
64 /*
65  * Add the device utility string to the device info region.
66  */
67 static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
68 {
69         struct vfio_device_info_cap_zpci_util *cap;
70         int cap_size = sizeof(*cap) + CLP_UTIL_STR_LEN;
71         int ret;
72
73         cap = kmalloc(cap_size, GFP_KERNEL);
74         if (!cap)
75                 return -ENOMEM;
76
77         cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL;
78         cap->header.version = 1;
79         cap->size = CLP_UTIL_STR_LEN;
80         memcpy(cap->util_str, zdev->util_str, cap->size);
81
82         ret = vfio_info_add_capability(caps, &cap->header, cap_size);
83
84         kfree(cap);
85
86         return ret;
87 }
88
89 /*
90  * Add the function path string to the device info region.
91  */
92 static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
93 {
94         struct vfio_device_info_cap_zpci_pfip *cap;
95         int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS;
96         int ret;
97
98         cap = kmalloc(cap_size, GFP_KERNEL);
99         if (!cap)
100                 return -ENOMEM;
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, caps);
127         if (ret)
128                 return ret;
129
130         ret = zpci_group_cap(zdev, caps);
131         if (ret)
132                 return ret;
133
134         if (zdev->util_str_avail) {
135                 ret = zpci_util_cap(zdev, caps);
136                 if (ret)
137                         return ret;
138         }
139
140         ret = zpci_pfip_cap(zdev, caps);
141
142         return ret;
143 }