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 } 144