11b197032SDavid Matlack // SPDX-License-Identifier: GPL-2.0-only 21b197032SDavid Matlack #include <stdio.h> 31b197032SDavid Matlack 41b197032SDavid Matlack #include "../../../kselftest.h" 51b197032SDavid Matlack #include <vfio_util.h> 61b197032SDavid Matlack 72223587dSDavid Matlack #ifdef __x86_64__ 8*35b05bd9SDavid Matlack extern struct vfio_pci_driver_ops dsa_ops; 92223587dSDavid Matlack extern struct vfio_pci_driver_ops ioat_ops; 102223587dSDavid Matlack #endif 112223587dSDavid Matlack 122223587dSDavid Matlack static struct vfio_pci_driver_ops *driver_ops[] = { 132223587dSDavid Matlack #ifdef __x86_64__ 14*35b05bd9SDavid Matlack &dsa_ops, 152223587dSDavid Matlack &ioat_ops, 162223587dSDavid Matlack #endif 172223587dSDavid Matlack }; 181b197032SDavid Matlack 191b197032SDavid Matlack void vfio_pci_driver_probe(struct vfio_pci_device *device) 201b197032SDavid Matlack { 211b197032SDavid Matlack struct vfio_pci_driver_ops *ops; 221b197032SDavid Matlack int i; 231b197032SDavid Matlack 241b197032SDavid Matlack VFIO_ASSERT_NULL(device->driver.ops); 251b197032SDavid Matlack 261b197032SDavid Matlack for (i = 0; i < ARRAY_SIZE(driver_ops); i++) { 271b197032SDavid Matlack ops = driver_ops[i]; 281b197032SDavid Matlack 291b197032SDavid Matlack if (ops->probe(device)) 301b197032SDavid Matlack continue; 311b197032SDavid Matlack 321b197032SDavid Matlack printf("Driver found: %s\n", ops->name); 331b197032SDavid Matlack device->driver.ops = ops; 341b197032SDavid Matlack } 351b197032SDavid Matlack } 361b197032SDavid Matlack 371b197032SDavid Matlack static void vfio_check_driver_op(struct vfio_pci_driver *driver, void *op, 381b197032SDavid Matlack const char *op_name) 391b197032SDavid Matlack { 401b197032SDavid Matlack VFIO_ASSERT_NOT_NULL(driver->ops); 411b197032SDavid Matlack VFIO_ASSERT_NOT_NULL(op, "Driver has no %s()\n", op_name); 421b197032SDavid Matlack VFIO_ASSERT_EQ(driver->initialized, op != driver->ops->init); 431b197032SDavid Matlack VFIO_ASSERT_EQ(driver->memcpy_in_progress, op == driver->ops->memcpy_wait); 441b197032SDavid Matlack } 451b197032SDavid Matlack 461b197032SDavid Matlack #define VFIO_CHECK_DRIVER_OP(_driver, _op) do { \ 471b197032SDavid Matlack struct vfio_pci_driver *__driver = (_driver); \ 481b197032SDavid Matlack vfio_check_driver_op(__driver, __driver->ops->_op, #_op); \ 491b197032SDavid Matlack } while (0) 501b197032SDavid Matlack 511b197032SDavid Matlack void vfio_pci_driver_init(struct vfio_pci_device *device) 521b197032SDavid Matlack { 531b197032SDavid Matlack struct vfio_pci_driver *driver = &device->driver; 541b197032SDavid Matlack 551b197032SDavid Matlack VFIO_ASSERT_NOT_NULL(driver->region.vaddr); 561b197032SDavid Matlack VFIO_CHECK_DRIVER_OP(driver, init); 571b197032SDavid Matlack 581b197032SDavid Matlack driver->ops->init(device); 591b197032SDavid Matlack 601b197032SDavid Matlack driver->initialized = true; 611b197032SDavid Matlack 621b197032SDavid Matlack printf("%s: region: vaddr %p, iova 0x%lx, size 0x%lx\n", 631b197032SDavid Matlack driver->ops->name, 641b197032SDavid Matlack driver->region.vaddr, 651b197032SDavid Matlack driver->region.iova, 661b197032SDavid Matlack driver->region.size); 671b197032SDavid Matlack 681b197032SDavid Matlack printf("%s: max_memcpy_size 0x%lx, max_memcpy_count 0x%lx\n", 691b197032SDavid Matlack driver->ops->name, 701b197032SDavid Matlack driver->max_memcpy_size, 711b197032SDavid Matlack driver->max_memcpy_count); 721b197032SDavid Matlack } 731b197032SDavid Matlack 741b197032SDavid Matlack void vfio_pci_driver_remove(struct vfio_pci_device *device) 751b197032SDavid Matlack { 761b197032SDavid Matlack struct vfio_pci_driver *driver = &device->driver; 771b197032SDavid Matlack 781b197032SDavid Matlack VFIO_CHECK_DRIVER_OP(driver, remove); 791b197032SDavid Matlack 801b197032SDavid Matlack driver->ops->remove(device); 811b197032SDavid Matlack driver->initialized = false; 821b197032SDavid Matlack } 831b197032SDavid Matlack 841b197032SDavid Matlack void vfio_pci_driver_send_msi(struct vfio_pci_device *device) 851b197032SDavid Matlack { 861b197032SDavid Matlack struct vfio_pci_driver *driver = &device->driver; 871b197032SDavid Matlack 881b197032SDavid Matlack VFIO_CHECK_DRIVER_OP(driver, send_msi); 891b197032SDavid Matlack 901b197032SDavid Matlack driver->ops->send_msi(device); 911b197032SDavid Matlack } 921b197032SDavid Matlack 931b197032SDavid Matlack void vfio_pci_driver_memcpy_start(struct vfio_pci_device *device, 941b197032SDavid Matlack iova_t src, iova_t dst, u64 size, 951b197032SDavid Matlack u64 count) 961b197032SDavid Matlack { 971b197032SDavid Matlack struct vfio_pci_driver *driver = &device->driver; 981b197032SDavid Matlack 991b197032SDavid Matlack VFIO_ASSERT_LE(size, driver->max_memcpy_size); 1001b197032SDavid Matlack VFIO_ASSERT_LE(count, driver->max_memcpy_count); 1011b197032SDavid Matlack VFIO_CHECK_DRIVER_OP(driver, memcpy_start); 1021b197032SDavid Matlack 1031b197032SDavid Matlack driver->ops->memcpy_start(device, src, dst, size, count); 1041b197032SDavid Matlack driver->memcpy_in_progress = true; 1051b197032SDavid Matlack } 1061b197032SDavid Matlack 1071b197032SDavid Matlack int vfio_pci_driver_memcpy_wait(struct vfio_pci_device *device) 1081b197032SDavid Matlack { 1091b197032SDavid Matlack struct vfio_pci_driver *driver = &device->driver; 1101b197032SDavid Matlack int r; 1111b197032SDavid Matlack 1121b197032SDavid Matlack VFIO_CHECK_DRIVER_OP(driver, memcpy_wait); 1131b197032SDavid Matlack 1141b197032SDavid Matlack r = driver->ops->memcpy_wait(device); 1151b197032SDavid Matlack driver->memcpy_in_progress = false; 1161b197032SDavid Matlack 1171b197032SDavid Matlack return r; 1181b197032SDavid Matlack } 1191b197032SDavid Matlack 1201b197032SDavid Matlack int vfio_pci_driver_memcpy(struct vfio_pci_device *device, 1211b197032SDavid Matlack iova_t src, iova_t dst, u64 size) 1221b197032SDavid Matlack { 1231b197032SDavid Matlack vfio_pci_driver_memcpy_start(device, src, dst, size, 1); 1241b197032SDavid Matlack 1251b197032SDavid Matlack return vfio_pci_driver_memcpy_wait(device); 1261b197032SDavid Matlack } 127