linux-next/drivers/vfio/iommufd.c
Peter Zijlstra cdd30ebb1b module: Convert symbol namespace to string literal
Clean up the existing export namespace code along the same lines of
commit 33def8498f ("treewide: Convert macro and uses of __section(foo)
to __section("foo")") and for the same reason, it is not desired for the
namespace argument to be a macro expansion itself.

Scripted using

  git grep -l -e MODULE_IMPORT_NS -e EXPORT_SYMBOL_NS | while read file;
  do
    awk -i inplace '
      /^#define EXPORT_SYMBOL_NS/ {
        gsub(/__stringify\(ns\)/, "ns");
        print;
        next;
      }
      /^#define MODULE_IMPORT_NS/ {
        gsub(/__stringify\(ns\)/, "ns");
        print;
        next;
      }
      /MODULE_IMPORT_NS/ {
        $0 = gensub(/MODULE_IMPORT_NS\(([^)]*)\)/, "MODULE_IMPORT_NS(\"\\1\")", "g");
      }
      /EXPORT_SYMBOL_NS/ {
        if ($0 ~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+),/) {
  	if ($0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/ &&
  	    $0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(\)/ &&
  	    $0 !~ /^my/) {
  	  getline line;
  	  gsub(/[[:space:]]*\\$/, "");
  	  gsub(/[[:space:]]/, "", line);
  	  $0 = $0 " " line;
  	}

  	$0 = gensub(/(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/,
  		    "\\1(\\2, \"\\3\")", "g");
        }
      }
      { print }' $file;
  done

Requested-by: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://mail.google.com/mail/u/2/#inbox/FMfcgzQXKWgMmjdFwwdsfgxzKpVHWPlc
Acked-by: Greg KH <gregkh@linuxfoundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2024-12-02 11:34:44 -08:00

248 lines
6.0 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
*/
#include <linux/vfio.h>
#include <linux/iommufd.h>
#include "vfio.h"
MODULE_IMPORT_NS("IOMMUFD");
MODULE_IMPORT_NS("IOMMUFD_VFIO");
bool vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev,
struct iommufd_ctx *ictx)
{
u32 ioas_id;
return !iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id);
}
int vfio_df_iommufd_bind(struct vfio_device_file *df)
{
struct vfio_device *vdev = df->device;
struct iommufd_ctx *ictx = df->iommufd;
lockdep_assert_held(&vdev->dev_set->lock);
return vdev->ops->bind_iommufd(vdev, ictx, &df->devid);
}
int vfio_iommufd_compat_attach_ioas(struct vfio_device *vdev,
struct iommufd_ctx *ictx)
{
u32 ioas_id;
int ret;
lockdep_assert_held(&vdev->dev_set->lock);
/* compat noiommu does not need to do ioas attach */
if (vfio_device_is_noiommu(vdev))
return 0;
ret = iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id);
if (ret)
return ret;
/* The legacy path has no way to return the selected pt_id */
return vdev->ops->attach_ioas(vdev, &ioas_id);
}
void vfio_df_iommufd_unbind(struct vfio_device_file *df)
{
struct vfio_device *vdev = df->device;
lockdep_assert_held(&vdev->dev_set->lock);
if (vfio_device_is_noiommu(vdev))
return;
if (vdev->ops->unbind_iommufd)
vdev->ops->unbind_iommufd(vdev);
}
struct iommufd_ctx *vfio_iommufd_device_ictx(struct vfio_device *vdev)
{
if (vdev->iommufd_device)
return iommufd_device_to_ictx(vdev->iommufd_device);
return NULL;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_device_ictx);
static int vfio_iommufd_device_id(struct vfio_device *vdev)
{
if (vdev->iommufd_device)
return iommufd_device_to_id(vdev->iommufd_device);
return -EINVAL;
}
/*
* Return devid for a device.
* valid ID for the device that is owned by the ictx
* -ENOENT = device is owned but there is no ID
* -ENODEV or other error = device is not owned
*/
int vfio_iommufd_get_dev_id(struct vfio_device *vdev, struct iommufd_ctx *ictx)
{
struct iommu_group *group;
int devid;
if (vfio_iommufd_device_ictx(vdev) == ictx)
return vfio_iommufd_device_id(vdev);
group = iommu_group_get(vdev->dev);
if (!group)
return -ENODEV;
if (iommufd_ctx_has_group(ictx, group))
devid = -ENOENT;
else
devid = -ENODEV;
iommu_group_put(group);
return devid;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_get_dev_id);
/*
* The physical standard ops mean that the iommufd_device is bound to the
* physical device vdev->dev that was provided to vfio_init_group_dev(). Drivers
* using this ops set should call vfio_register_group_dev()
*/
int vfio_iommufd_physical_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id)
{
struct iommufd_device *idev;
idev = iommufd_device_bind(ictx, vdev->dev, out_device_id);
if (IS_ERR(idev))
return PTR_ERR(idev);
vdev->iommufd_device = idev;
return 0;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_bind);
void vfio_iommufd_physical_unbind(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
if (vdev->iommufd_attached) {
iommufd_device_detach(vdev->iommufd_device);
vdev->iommufd_attached = false;
}
iommufd_device_unbind(vdev->iommufd_device);
vdev->iommufd_device = NULL;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_unbind);
int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
{
int rc;
lockdep_assert_held(&vdev->dev_set->lock);
if (WARN_ON(!vdev->iommufd_device))
return -EINVAL;
if (vdev->iommufd_attached)
rc = iommufd_device_replace(vdev->iommufd_device, pt_id);
else
rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
if (rc)
return rc;
vdev->iommufd_attached = true;
return 0;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
if (WARN_ON(!vdev->iommufd_device) || !vdev->iommufd_attached)
return;
iommufd_device_detach(vdev->iommufd_device);
vdev->iommufd_attached = false;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);
/*
* The emulated standard ops mean that vfio_device is going to use the
* "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
* ops set should call vfio_register_emulated_iommu_dev(). Drivers that do
* not call vfio_pin_pages()/vfio_dma_rw() have no need to provide dma_unmap.
*/
static void vfio_emulated_unmap(void *data, unsigned long iova,
unsigned long length)
{
struct vfio_device *vdev = data;
if (vdev->ops->dma_unmap)
vdev->ops->dma_unmap(vdev, iova, length);
}
static const struct iommufd_access_ops vfio_user_ops = {
.needs_pin_pages = 1,
.unmap = vfio_emulated_unmap,
};
int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id)
{
struct iommufd_access *user;
lockdep_assert_held(&vdev->dev_set->lock);
user = iommufd_access_create(ictx, &vfio_user_ops, vdev, out_device_id);
if (IS_ERR(user))
return PTR_ERR(user);
vdev->iommufd_access = user;
return 0;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
if (vdev->iommufd_access) {
iommufd_access_destroy(vdev->iommufd_access);
vdev->iommufd_attached = false;
vdev->iommufd_access = NULL;
}
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
{
int rc;
lockdep_assert_held(&vdev->dev_set->lock);
if (vdev->iommufd_attached)
rc = iommufd_access_replace(vdev->iommufd_access, *pt_id);
else
rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
if (rc)
return rc;
vdev->iommufd_attached = true;
return 0;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);
void vfio_iommufd_emulated_detach_ioas(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
if (WARN_ON(!vdev->iommufd_access) ||
!vdev->iommufd_attached)
return;
iommufd_access_detach(vdev->iommufd_access);
vdev->iommufd_attached = false;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_detach_ioas);