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 */ 27static 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 */ 48static 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 */ 69static 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 if (!cap) 78 return -ENOMEM; 79 80 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL; 81 cap->header.version = 1; 82 cap->size = CLP_UTIL_STR_LEN; 83 memcpy(cap->util_str, zdev->util_str, cap->size); 84 85 ret = vfio_info_add_capability(caps, &cap->header, cap_size); 86 87 kfree(cap); 88 89 return ret; 90} 91 92/* 93 * Add the function path string to the device info region. 94 */ 95static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_pci_device *vdev, 96 struct vfio_info_cap *caps) 97{ 98 struct vfio_device_info_cap_zpci_pfip *cap; 99 int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS; 100 int ret; 101 102 cap = kmalloc(cap_size, GFP_KERNEL); 103 if (!cap) 104 return -ENOMEM; 105 106 cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP; 107 cap->header.version = 1; 108 cap->size = CLP_PFIP_NR_SEGMENTS; 109 memcpy(cap->pfip, zdev->pfip, cap->size); 110 111 ret = vfio_info_add_capability(caps, &cap->header, cap_size); 112 113 kfree(cap); 114 115 return ret; 116} 117 118/* 119 * Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain. 120 */ 121int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev, 122 struct vfio_info_cap *caps) 123{ 124 struct zpci_dev *zdev = to_zpci(vdev->pdev); 125 int ret; 126 127 if (!zdev) 128 return -ENODEV; 129 130 ret = zpci_base_cap(zdev, vdev, caps); 131 if (ret) 132 return ret; 133 134 ret = zpci_group_cap(zdev, vdev, caps); 135 if (ret) 136 return ret; 137 138 if (zdev->util_str_avail) { 139 ret = zpci_util_cap(zdev, vdev, caps); 140 if (ret) 141 return ret; 142 } 143 144 ret = zpci_pfip_cap(zdev, vdev, caps); 145 146 return ret; 147} 148