1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * VFIO based AP device driver 4 * 5 * Copyright IBM Corp. 2018 6 * 7 * Author(s): Tony Krowiak <akrowiak@linux.ibm.com> 8 * Pierre Morel <pmorel@linux.ibm.com> 9 */ 10 11 #include <linux/module.h> 12 #include <linux/mod_devicetable.h> 13 #include <linux/slab.h> 14 #include <linux/string.h> 15 #include <asm/facility.h> 16 #include "vfio_ap_private.h" 17 18 #define VFIO_AP_ROOT_NAME "vfio_ap" 19 #define VFIO_AP_DEV_NAME "matrix" 20 #define AP_QUEUE_ASSIGNED "assigned" 21 #define AP_QUEUE_UNASSIGNED "unassigned" 22 #define AP_QUEUE_IN_USE "in use" 23 24 MODULE_AUTHOR("IBM Corporation"); 25 MODULE_DESCRIPTION("VFIO AP device driver, Copyright IBM Corp. 2018"); 26 MODULE_LICENSE("GPL v2"); 27 28 struct ap_matrix_dev *matrix_dev; 29 30 /* Only type 10 adapters (CEX4 and later) are supported 31 * by the AP matrix device driver 32 */ 33 static struct ap_device_id ap_queue_ids[] = { 34 { .dev_type = AP_DEVICE_TYPE_CEX4, 35 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 36 { .dev_type = AP_DEVICE_TYPE_CEX5, 37 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 38 { .dev_type = AP_DEVICE_TYPE_CEX6, 39 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 40 { .dev_type = AP_DEVICE_TYPE_CEX7, 41 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, 42 { /* end of sibling */ }, 43 }; 44 45 MODULE_DEVICE_TABLE(vfio_ap, ap_queue_ids); 46 47 static struct ap_matrix_mdev *vfio_ap_mdev_for_queue(struct vfio_ap_queue *q) 48 { 49 struct ap_matrix_mdev *matrix_mdev; 50 unsigned long apid = AP_QID_CARD(q->apqn); 51 unsigned long apqi = AP_QID_QUEUE(q->apqn); 52 53 list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) { 54 if (test_bit_inv(apid, matrix_mdev->matrix.apm) && 55 test_bit_inv(apqi, matrix_mdev->matrix.aqm)) 56 return matrix_mdev; 57 } 58 59 return NULL; 60 } 61 62 static ssize_t status_show(struct device *dev, 63 struct device_attribute *attr, 64 char *buf) 65 { 66 ssize_t nchars = 0; 67 struct vfio_ap_queue *q; 68 struct ap_matrix_mdev *matrix_mdev; 69 struct ap_device *apdev = to_ap_dev(dev); 70 71 mutex_lock(&matrix_dev->lock); 72 q = dev_get_drvdata(&apdev->device); 73 matrix_mdev = vfio_ap_mdev_for_queue(q); 74 75 if (matrix_mdev) { 76 if (matrix_mdev->kvm) 77 nchars = scnprintf(buf, PAGE_SIZE, "%s\n", 78 AP_QUEUE_IN_USE); 79 else 80 nchars = scnprintf(buf, PAGE_SIZE, "%s\n", 81 AP_QUEUE_ASSIGNED); 82 } else { 83 nchars = scnprintf(buf, PAGE_SIZE, "%s\n", 84 AP_QUEUE_UNASSIGNED); 85 } 86 87 mutex_unlock(&matrix_dev->lock); 88 89 return nchars; 90 } 91 92 static DEVICE_ATTR_RO(status); 93 94 static struct attribute *vfio_queue_attrs[] = { 95 &dev_attr_status.attr, 96 NULL, 97 }; 98 99 static const struct attribute_group vfio_queue_attr_group = { 100 .attrs = vfio_queue_attrs, 101 }; 102 103 /** 104 * vfio_ap_queue_dev_probe: Allocate a vfio_ap_queue structure and associate it 105 * with the device as driver_data. 106 * 107 * @apdev: the AP device being probed 108 * 109 * Return: returns 0 if the probe succeeded; otherwise, returns an error if 110 * storage could not be allocated for a vfio_ap_queue object or the 111 * sysfs 'status' attribute could not be created for the queue device. 112 */ 113 static int vfio_ap_queue_dev_probe(struct ap_device *apdev) 114 { 115 int ret; 116 struct vfio_ap_queue *q; 117 118 q = kzalloc(sizeof(*q), GFP_KERNEL); 119 if (!q) 120 return -ENOMEM; 121 122 mutex_lock(&matrix_dev->lock); 123 dev_set_drvdata(&apdev->device, q); 124 q->apqn = to_ap_queue(&apdev->device)->qid; 125 q->saved_isc = VFIO_AP_ISC_INVALID; 126 127 ret = sysfs_create_group(&apdev->device.kobj, &vfio_queue_attr_group); 128 if (ret) { 129 dev_set_drvdata(&apdev->device, NULL); 130 kfree(q); 131 } 132 133 mutex_unlock(&matrix_dev->lock); 134 135 return ret; 136 } 137 138 /** 139 * vfio_ap_queue_dev_remove: Free the associated vfio_ap_queue structure. 140 * 141 * @apdev: the AP device being removed 142 * 143 * Takes the matrix lock to avoid actions on this device while doing the remove. 144 */ 145 static void vfio_ap_queue_dev_remove(struct ap_device *apdev) 146 { 147 struct vfio_ap_queue *q; 148 149 mutex_lock(&matrix_dev->lock); 150 sysfs_remove_group(&apdev->device.kobj, &vfio_queue_attr_group); 151 q = dev_get_drvdata(&apdev->device); 152 vfio_ap_mdev_reset_queue(q, 1); 153 dev_set_drvdata(&apdev->device, NULL); 154 kfree(q); 155 mutex_unlock(&matrix_dev->lock); 156 } 157 158 static struct ap_driver vfio_ap_drv = { 159 .probe = vfio_ap_queue_dev_probe, 160 .remove = vfio_ap_queue_dev_remove, 161 .ids = ap_queue_ids, 162 }; 163 164 static void vfio_ap_matrix_dev_release(struct device *dev) 165 { 166 struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev); 167 168 kfree(matrix_dev); 169 } 170 171 static int matrix_bus_match(struct device *dev, struct device_driver *drv) 172 { 173 return 1; 174 } 175 176 static struct bus_type matrix_bus = { 177 .name = "matrix", 178 .match = &matrix_bus_match, 179 }; 180 181 static struct device_driver matrix_driver = { 182 .name = "vfio_ap", 183 .bus = &matrix_bus, 184 .suppress_bind_attrs = true, 185 }; 186 187 static int vfio_ap_matrix_dev_create(void) 188 { 189 int ret; 190 struct device *root_device; 191 192 root_device = root_device_register(VFIO_AP_ROOT_NAME); 193 if (IS_ERR(root_device)) 194 return PTR_ERR(root_device); 195 196 ret = bus_register(&matrix_bus); 197 if (ret) 198 goto bus_register_err; 199 200 matrix_dev = kzalloc(sizeof(*matrix_dev), GFP_KERNEL); 201 if (!matrix_dev) { 202 ret = -ENOMEM; 203 goto matrix_alloc_err; 204 } 205 206 /* Fill in config info via PQAP(QCI), if available */ 207 if (test_facility(12)) { 208 ret = ap_qci(&matrix_dev->info); 209 if (ret) 210 goto matrix_alloc_err; 211 } 212 213 mutex_init(&matrix_dev->lock); 214 INIT_LIST_HEAD(&matrix_dev->mdev_list); 215 216 dev_set_name(&matrix_dev->device, "%s", VFIO_AP_DEV_NAME); 217 matrix_dev->device.parent = root_device; 218 matrix_dev->device.bus = &matrix_bus; 219 matrix_dev->device.release = vfio_ap_matrix_dev_release; 220 matrix_dev->vfio_ap_drv = &vfio_ap_drv; 221 222 ret = device_register(&matrix_dev->device); 223 if (ret) 224 goto matrix_reg_err; 225 226 ret = driver_register(&matrix_driver); 227 if (ret) 228 goto matrix_drv_err; 229 230 return 0; 231 232 matrix_drv_err: 233 device_unregister(&matrix_dev->device); 234 matrix_reg_err: 235 put_device(&matrix_dev->device); 236 matrix_alloc_err: 237 bus_unregister(&matrix_bus); 238 bus_register_err: 239 root_device_unregister(root_device); 240 return ret; 241 } 242 243 static void vfio_ap_matrix_dev_destroy(void) 244 { 245 struct device *root_device = matrix_dev->device.parent; 246 247 driver_unregister(&matrix_driver); 248 device_unregister(&matrix_dev->device); 249 bus_unregister(&matrix_bus); 250 root_device_unregister(root_device); 251 } 252 253 static int __init vfio_ap_init(void) 254 { 255 int ret; 256 257 /* If there are no AP instructions, there is nothing to pass through. */ 258 if (!ap_instructions_available()) 259 return -ENODEV; 260 261 ret = vfio_ap_matrix_dev_create(); 262 if (ret) 263 return ret; 264 265 ret = ap_driver_register(&vfio_ap_drv, THIS_MODULE, VFIO_AP_DRV_NAME); 266 if (ret) { 267 vfio_ap_matrix_dev_destroy(); 268 return ret; 269 } 270 271 ret = vfio_ap_mdev_register(); 272 if (ret) { 273 ap_driver_unregister(&vfio_ap_drv); 274 vfio_ap_matrix_dev_destroy(); 275 276 return ret; 277 } 278 279 return 0; 280 } 281 282 static void __exit vfio_ap_exit(void) 283 { 284 vfio_ap_mdev_unregister(); 285 ap_driver_unregister(&vfio_ap_drv); 286 vfio_ap_matrix_dev_destroy(); 287 } 288 289 module_init(vfio_ap_init); 290 module_exit(vfio_ap_exit); 291