diff options
Diffstat (limited to 'Documentation/driver-api')
-rw-r--r-- | Documentation/driver-api/basics.rst | 27 | ||||
-rw-r--r-- | Documentation/driver-api/infrastructure.rst | 18 | ||||
-rw-r--r-- | Documentation/driver-api/interconnect.rst | 25 | ||||
-rw-r--r-- | Documentation/driver-api/media/cec-core.rst | 44 | ||||
-rw-r--r-- | Documentation/driver-api/media/dtv-common.rst | 9 | ||||
-rw-r--r-- | Documentation/driver-api/media/v4l2-cci.rst | 5 | ||||
-rw-r--r-- | Documentation/driver-api/media/v4l2-core.rst | 1 | ||||
-rw-r--r-- | Documentation/driver-api/media/v4l2-subdev.rst | 110 | ||||
-rw-r--r-- | Documentation/driver-api/s390-drivers.rst | 4 | ||||
-rw-r--r-- | Documentation/driver-api/tty/tty_buffer.rst | 7 | ||||
-rw-r--r-- | Documentation/driver-api/usb/usb.rst | 9 | ||||
-rw-r--r-- | Documentation/driver-api/vfio.rst | 147 |
12 files changed, 329 insertions, 77 deletions
diff --git a/Documentation/driver-api/basics.rst b/Documentation/driver-api/basics.rst index 7671b531ba1a..d78b7c328ff7 100644 --- a/Documentation/driver-api/basics.rst +++ b/Documentation/driver-api/basics.rst @@ -15,8 +15,8 @@ Driver device table :no-identifiers: pci_device_id -Delaying, scheduling, and timer routines ----------------------------------------- +Delaying and scheduling routines +-------------------------------- .. kernel-doc:: include/linux/sched.h :internal: @@ -33,16 +33,16 @@ Delaying, scheduling, and timer routines .. kernel-doc:: include/linux/completion.h :internal: -.. kernel-doc:: kernel/time/timer.c - :export: - -Wait queues and Wake events ---------------------------- +Time and timer routines +----------------------- -.. kernel-doc:: include/linux/wait.h +.. kernel-doc:: include/linux/jiffies.h :internal: -.. kernel-doc:: kernel/sched/wait.c +.. kernel-doc:: kernel/time/time.c + :export: + +.. kernel-doc:: kernel/time/timer.c :export: High-resolution timers @@ -57,6 +57,15 @@ High-resolution timers .. kernel-doc:: kernel/time/hrtimer.c :export: +Wait queues and Wake events +--------------------------- + +.. kernel-doc:: include/linux/wait.h + :internal: + +.. kernel-doc:: kernel/sched/wait.c + :export: + Internal Functions ------------------ diff --git a/Documentation/driver-api/infrastructure.rst b/Documentation/driver-api/infrastructure.rst index 683bd460e222..3d52dfdfa9fd 100644 --- a/Documentation/driver-api/infrastructure.rst +++ b/Documentation/driver-api/infrastructure.rst @@ -8,12 +8,24 @@ The Basic Device Driver-Model Structures :internal: :no-identifiers: device_link_state +.. kernel-doc:: include/linux/device/bus.h + :identifiers: bus_type bus_notifier_event + +.. kernel-doc:: include/linux/device/class.h + :identifiers: class + +.. kernel-doc:: include/linux/device/driver.h + :identifiers: probe_type device_driver + Device Drivers Base ------------------- .. kernel-doc:: drivers/base/init.c :internal: +.. kernel-doc:: include/linux/device/driver.h + :no-identifiers: probe_type device_driver + .. kernel-doc:: drivers/base/driver.c :export: @@ -23,6 +35,9 @@ Device Drivers Base .. kernel-doc:: drivers/base/syscore.c :export: +.. kernel-doc:: include/linux/device/class.h + :no-identifiers: class + .. kernel-doc:: drivers/base/class.c :export: @@ -41,6 +56,9 @@ Device Drivers Base .. kernel-doc:: drivers/base/platform.c :export: +.. kernel-doc:: include/linux/device/bus.h + :no-identifiers: bus_type bus_notifier_event + .. kernel-doc:: drivers/base/bus.c :export: diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst index 5ed4f57a6bac..a92d0f277a1f 100644 --- a/Documentation/driver-api/interconnect.rst +++ b/Documentation/driver-api/interconnect.rst @@ -113,3 +113,28 @@ through dot to generate diagrams in many graphical formats:: $ cat /sys/kernel/debug/interconnect/interconnect_graph | \ dot -Tsvg > interconnect_graph.svg + +The ``test-client`` directory provides interfaces for issuing BW requests to +any arbitrary path. Note that for safety reasons, this feature is disabled by +default without a Kconfig to enable it. Enabling it requires code changes to +``#define INTERCONNECT_ALLOW_WRITE_DEBUGFS``. Example usage:: + + cd /sys/kernel/debug/interconnect/test-client/ + + # Configure node endpoints for the path from CPU to DDR on + # qcom/sm8550. + echo chm_apps > src_node + echo ebi > dst_node + + # Get path between src_node and dst_node. This is only + # necessary after updating the node endpoints. + echo 1 > get + + # Set desired BW to 1GBps avg and 2GBps peak. + echo 1000000 > avg_bw + echo 2000000 > peak_bw + + # Vote for avg_bw and peak_bw on the latest path from "get". + # Voting for multiple paths is possible by repeating this + # process for different nodes endpoints. + echo 1 > commit diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst index ae0d20798edc..f1ffdec388f3 100644 --- a/Documentation/driver-api/media/cec-core.rst +++ b/Documentation/driver-api/media/cec-core.rst @@ -109,9 +109,11 @@ your driver: int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable); int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable); int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr); - void (*adap_configured)(struct cec_adapter *adap, bool configured); + void (*adap_unconfigured)(struct cec_adapter *adap); int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg); + void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, + const struct cec_msg *msg); void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); void (*adap_free)(struct cec_adapter *adap); @@ -122,8 +124,8 @@ your driver: ... }; -The seven low-level ops deal with various aspects of controlling the CEC adapter -hardware: +These low-level ops deal with various aspects of controlling the CEC adapter +hardware. They are all called with the mutex adap->lock held. To enable/disable the hardware:: @@ -179,14 +181,12 @@ can receive directed messages to that address. Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID. -Called when the adapter is fully configured or unconfigured:: +Called when the adapter is unconfigured:: - void (*adap_configured)(struct cec_adapter *adap, bool configured); + void (*adap_unconfigured)(struct cec_adapter *adap); -If configured == true, then the adapter is fully configured, i.e. all logical -addresses have been successfully claimed. If configured == false, then the -adapter is unconfigured. If the driver has to take specific actions after -(un)configuration, then that can be done through this optional callback. +The adapter is unconfigured. If the driver has to take specific actions after +unconfiguration, then that can be done through this optional callback. To transmit a new message:: @@ -207,6 +207,19 @@ The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to microseconds (one data bit period is 2.4 ms). +To pass on the result of a canceled non-blocking transmit:: + + void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, + const struct cec_msg *msg); + +This optional callback can be used to obtain the result of a canceled +non-blocking transmit with sequence number msg->sequence. This is +called if the transmit was aborted, the transmit timed out (i.e. the +hardware never signaled that the transmit finished), or the transmit +was successful, but the wait for the expected reply was either aborted +or it timed out. + + To log the current CEC hardware status:: void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); @@ -372,7 +385,8 @@ Implementing the High-Level CEC Adapter --------------------------------------- The low-level operations drive the hardware, the high-level operations are -CEC protocol driven. The following high-level callbacks are available: +CEC protocol driven. The high-level callbacks are called without the adap->lock +mutex being held. The following high-level callbacks are available: .. code-block:: none @@ -384,9 +398,19 @@ CEC protocol driven. The following high-level callbacks are available: ... /* High-level CEC message callback */ + void (*configured)(struct cec_adapter *adap); int (*received)(struct cec_adapter *adap, struct cec_msg *msg); }; +Called when the adapter is configured:: + + void (*configured)(struct cec_adapter *adap); + +The adapter is fully configured, i.e. all logical addresses have been +successfully claimed. If the driver has to take specific actions after +configuration, then that can be done through this optional callback. + + The received() callback allows the driver to optionally handle a newly received CEC message:: diff --git a/Documentation/driver-api/media/dtv-common.rst b/Documentation/driver-api/media/dtv-common.rst index f8b2c4dc8170..207a22bcaf4a 100644 --- a/Documentation/driver-api/media/dtv-common.rst +++ b/Documentation/driver-api/media/dtv-common.rst @@ -3,15 +3,6 @@ Digital TV Common functions --------------------------- -Math functions -~~~~~~~~~~~~~~ - -Provide some commonly-used math functions, usually required in order to -estimate signal strength and signal to noise measurements in dB. - -.. kernel-doc:: include/media/dvb_math.h - - DVB devices ~~~~~~~~~~~ diff --git a/Documentation/driver-api/media/v4l2-cci.rst b/Documentation/driver-api/media/v4l2-cci.rst new file mode 100644 index 000000000000..dd297a40ed20 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-cci.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 CCI kAPI +^^^^^^^^^^^^^ +.. kernel-doc:: include/media/v4l2-cci.h diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst index 1a8c4a5f256b..239045ecc8f4 100644 --- a/Documentation/driver-api/media/v4l2-core.rst +++ b/Documentation/driver-api/media/v4l2-core.rst @@ -22,6 +22,7 @@ Video4Linux devices v4l2-mem2mem v4l2-async v4l2-fwnode + v4l2-cci v4l2-rect v4l2-tuner v4l2-common diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst index 602dadaa81d8..e56b50b3f203 100644 --- a/Documentation/driver-api/media/v4l2-subdev.rst +++ b/Documentation/driver-api/media/v4l2-subdev.rst @@ -157,6 +157,9 @@ below. Using one or the other registration method only affects the probing process, the run-time bridge-subdevice interaction is in both cases the same. +Registering synchronous sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + In the **synchronous** case a device (bridge) driver needs to register the :c:type:`v4l2_subdev` with the v4l2_device: @@ -175,10 +178,12 @@ You can unregister a sub-device using: :c:func:`v4l2_device_unregister_subdev <v4l2_device_unregister_subdev>` (:c:type:`sd <v4l2_subdev>`). - Afterwards the subdev module can be unloaded and :c:type:`sd <v4l2_subdev>`->dev == ``NULL``. +Registering asynchronous sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + In the **asynchronous** case subdevice probing can be invoked independently of the bridge driver availability. The subdevice driver then has to verify whether all the requirements for a successful probing are satisfied. This can include a @@ -190,64 +195,89 @@ performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices registered this way are stored in a global list of subdevices, ready to be picked up by bridge drivers. -Bridge drivers in turn have to register a notifier object. This is -performed using the :c:func:`v4l2_async_nf_register` call. To -unregister the notifier the driver has to call -:c:func:`v4l2_async_nf_unregister`. The former of the two functions -takes two arguments: a pointer to struct :c:type:`v4l2_device` and a -pointer to struct :c:type:`v4l2_async_notifier`. +Asynchronous sub-device notifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Bridge drivers in turn have to register a notifier object. This is performed +using the :c:func:`v4l2_async_nf_register` call. To unregister the notifier the +driver has to call :c:func:`v4l2_async_nf_unregister`. Before releasing memory +of an unregister notifier, it must be cleaned up by calling +:c:func:`v4l2_async_nf_cleanup`. Before registering the notifier, bridge drivers must do two things: first, the -notifier must be initialized using the :c:func:`v4l2_async_nf_init`. -Second, bridge drivers can then begin to form a list of subdevice descriptors -that the bridge device needs for its operation. Several functions are available -to add subdevice descriptors to a notifier, depending on the type of device and -the needs of the driver. - -:c:func:`v4l2_async_nf_add_fwnode_remote` and -:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for -registering their async sub-devices with the notifier. - -:c:func:`v4l2_async_register_subdev_sensor` is a helper function for -sensor drivers registering their own async sub-device, but it also registers a -notifier and further registers async sub-devices for lens and flash devices -found in firmware. The notifier for the sub-device is unregistered with the -async sub-device. - -These functions allocate an async sub-device descriptor which is of type struct -:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct -:c:type:`v4l2_async_subdev` shall be the first member of this struct: +notifier must be initialized using the :c:func:`v4l2_async_nf_init`. Second, +bridge drivers can then begin to form a list of async connection descriptors +that the bridge device needs for its +operation. :c:func:`v4l2_async_nf_add_fwnode`, +:c:func:`v4l2_async_nf_add_fwnode_remote` and :c:func:`v4l2_async_nf_add_i2c` + +Async connection descriptors describe connections to external sub-devices the +drivers for which are not yet probed. Based on an async connection, a media data +or ancillary link may be created when the related sub-device becomes +available. There may be one or more async connections to a given sub-device but +this is not known at the time of adding the connections to the notifier. Async +connections are bound as matching async sub-devices are found, one by one. + +Asynchronous sub-device notifier for sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A driver that registers an asynchronous sub-device may also register an +asynchronous notifier. This is called an asynchronous sub-device notifier andthe +process is similar to that of a bridge driver apart from that the notifier is +initialised using :c:func:`v4l2_async_subdev_nf_init` instead. A sub-device +notifier may complete only after the V4L2 device becomes available, i.e. there's +a path via async sub-devices and notifiers to a notifier that is not an +asynchronous sub-device notifier. + +Asynchronous sub-device registration helper for camera sensor drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:c:func:`v4l2_async_register_subdev_sensor` is a helper function for sensor +drivers registering their own async connection, but it also registers a notifier +and further registers async connections for lens and flash devices found in +firmware. The notifier for the sub-device is unregistered and cleaned up with +the async sub-device, using :c:func:`v4l2_async_unregister_subdev`. + +Asynchronous sub-device notifier example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These functions allocate an async connection descriptor which is of type struct +:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct +:c:type:`v4l2_async_connection` shall be the first member of this struct: .. code-block:: c - struct my_async_subdev { - struct v4l2_async_subdev asd; + struct my_async_connection { + struct v4l2_async_connection asc; ... }; - struct my_async_subdev *my_asd; + struct my_async_connection *my_asc; struct fwnode_handle *ep; ... - my_asd = v4l2_async_nf_add_fwnode_remote(¬ifier, ep, - struct my_async_subdev); + my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep, + struct my_async_connection); fwnode_handle_put(ep); - if (IS_ERR(asd)) - return PTR_ERR(asd); + if (IS_ERR(my_asc)) + return PTR_ERR(my_asc); + +Asynchronous sub-device notifier callbacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The V4L2 core will then use these descriptors to match asynchronously -registered subdevices to them. If a match is detected the ``.bound()`` -notifier callback is called. After all subdevices have been located the -.complete() callback is called. When a subdevice is removed from the -system the .unbind() method is called. All three callbacks are optional. +The V4L2 core will then use these connection descriptors to match asynchronously +registered subdevices to them. If a match is detected the ``.bound()`` notifier +callback is called. After all connections have been bound the .complete() +callback is called. When a connection is removed from the system the +``.unbind()`` method is called. All three callbacks are optional. Drivers can store any type of custom data in their driver-specific -:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special +:c:type:`v4l2_async_connection` wrapper. If any of that data requires special handling when the structure is freed, drivers must implement the ``.destroy()`` notifier callback. The framework will call it right before freeing the -:c:type:`v4l2_async_subdev`. +:c:type:`v4l2_async_connection`. Calling subdev operations ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/driver-api/s390-drivers.rst b/Documentation/driver-api/s390-drivers.rst index 5158577bc29b..8c0845c4eee7 100644 --- a/Documentation/driver-api/s390-drivers.rst +++ b/Documentation/driver-api/s390-drivers.rst @@ -27,7 +27,7 @@ not strictly considered I/O devices. They are considered here as well, although they are not the focus of this document. Some additional information can also be found in the kernel source under -Documentation/s390/driver-model.rst. +Documentation/arch/s390/driver-model.rst. The css bus =========== @@ -38,7 +38,7 @@ into several categories: * Standard I/O subchannels, for use by the system. They have a child device on the ccw bus and are described below. * I/O subchannels bound to the vfio-ccw driver. See - Documentation/s390/vfio-ccw.rst. + Documentation/arch/s390/vfio-ccw.rst. * Message subchannels. No Linux driver currently exists. * CHSC subchannels (at most one). The chsc subchannel driver can be used to send asynchronous chsc commands. diff --git a/Documentation/driver-api/tty/tty_buffer.rst b/Documentation/driver-api/tty/tty_buffer.rst index a39d4781e0d2..4b5ca1776d4f 100644 --- a/Documentation/driver-api/tty/tty_buffer.rst +++ b/Documentation/driver-api/tty/tty_buffer.rst @@ -15,10 +15,13 @@ Flip Buffer Management ====================== .. kernel-doc:: drivers/tty/tty_buffer.c - :identifiers: tty_prepare_flip_string tty_insert_flip_string_fixed_flag - tty_insert_flip_string_flags __tty_insert_flip_char + :identifiers: tty_prepare_flip_string tty_flip_buffer_push tty_ldisc_receive_buf +.. kernel-doc:: include/linux/tty_flip.h + :identifiers: tty_insert_flip_string_fixed_flag tty_insert_flip_string_flags + tty_insert_flip_char + ---- Other Functions diff --git a/Documentation/driver-api/usb/usb.rst b/Documentation/driver-api/usb/usb.rst index 2c94ff2f4385..fb41768696ec 100644 --- a/Documentation/driver-api/usb/usb.rst +++ b/Documentation/driver-api/usb/usb.rst @@ -420,6 +420,12 @@ USBDEVFS_CONNECTINFO know the devnum value already, it's the DDD value of the device file name. +USBDEVFS_GET_SPEED + Returns the speed of the device. The speed is returned as a + nummerical value in accordance with enum usb_device_speed + + File modification time is not updated by this request. + USBDEVFS_GETDRIVER Returns the name of the kernel driver bound to a given interface (a string). Parameter is a pointer to this structure, which is @@ -771,8 +777,7 @@ Speed may be: ======= ====================================================== 1.5 Mbit/s for low speed USB 12 Mbit/s for full speed USB - 480 Mbit/s for high speed USB (added for USB 2.0); - also used for Wireless USB, which has no fixed speed + 480 Mbit/s for high speed USB (added for USB 2.0) 5000 Mbit/s for SuperSpeed USB (added for USB 3.0) ======= ====================================================== diff --git a/Documentation/driver-api/vfio.rst b/Documentation/driver-api/vfio.rst index 68abc089d6dd..633d11c7fa71 100644 --- a/Documentation/driver-api/vfio.rst +++ b/Documentation/driver-api/vfio.rst @@ -239,6 +239,137 @@ group and can access them as follows:: /* Gratuitous device reset and go... */ ioctl(device, VFIO_DEVICE_RESET); +IOMMUFD and vfio_iommu_type1 +---------------------------- + +IOMMUFD is the new user API to manage I/O page tables from userspace. +It intends to be the portal of delivering advanced userspace DMA +features (nested translation [5]_, PASID [6]_, etc.) while also providing +a backwards compatibility interface for existing VFIO_TYPE1v2_IOMMU use +cases. Eventually the vfio_iommu_type1 driver, as well as the legacy +vfio container and group model is intended to be deprecated. + +The IOMMUFD backwards compatibility interface can be enabled two ways. +In the first method, the kernel can be configured with +CONFIG_IOMMUFD_VFIO_CONTAINER, in which case the IOMMUFD subsystem +transparently provides the entire infrastructure for the VFIO +container and IOMMU backend interfaces. The compatibility mode can +also be accessed if the VFIO container interface, ie. /dev/vfio/vfio is +simply symlink'd to /dev/iommu. Note that at the time of writing, the +compatibility mode is not entirely feature complete relative to +VFIO_TYPE1v2_IOMMU (ex. DMA mapping MMIO) and does not attempt to +provide compatibility to the VFIO_SPAPR_TCE_IOMMU interface. Therefore +it is not generally advisable at this time to switch from native VFIO +implementations to the IOMMUFD compatibility interfaces. + +Long term, VFIO users should migrate to device access through the cdev +interface described below, and native access through the IOMMUFD +provided interfaces. + +VFIO Device cdev +---------------- + +Traditionally user acquires a device fd via VFIO_GROUP_GET_DEVICE_FD +in a VFIO group. + +With CONFIG_VFIO_DEVICE_CDEV=y the user can now acquire a device fd +by directly opening a character device /dev/vfio/devices/vfioX where +"X" is the number allocated uniquely by VFIO for registered devices. +cdev interface does not support noiommu devices, so user should use +the legacy group interface if noiommu is wanted. + +The cdev only works with IOMMUFD. Both VFIO drivers and applications +must adapt to the new cdev security model which requires using +VFIO_DEVICE_BIND_IOMMUFD to claim DMA ownership before starting to +actually use the device. Once BIND succeeds then a VFIO device can +be fully accessed by the user. + +VFIO device cdev doesn't rely on VFIO group/container/iommu drivers. +Hence those modules can be fully compiled out in an environment +where no legacy VFIO application exists. + +So far SPAPR does not support IOMMUFD yet. So it cannot support device +cdev either. + +vfio device cdev access is still bound by IOMMU group semantics, ie. there +can be only one DMA owner for the group. Devices belonging to the same +group can not be bound to multiple iommufd_ctx or shared between native +kernel and vfio bus driver or other driver supporting the driver_managed_dma +flag. A violation of this ownership requirement will fail at the +VFIO_DEVICE_BIND_IOMMUFD ioctl, which gates full device access. + +Device cdev Example +------------------- + +Assume user wants to access PCI device 0000:6a:01.0:: + + $ ls /sys/bus/pci/devices/0000:6a:01.0/vfio-dev/ + vfio0 + +This device is therefore represented as vfio0. The user can verify +its existence:: + + $ ls -l /dev/vfio/devices/vfio0 + crw------- 1 root root 511, 0 Feb 16 01:22 /dev/vfio/devices/vfio0 + $ cat /sys/bus/pci/devices/0000:6a:01.0/vfio-dev/vfio0/dev + 511:0 + $ ls -l /dev/char/511\:0 + lrwxrwxrwx 1 root root 21 Feb 16 01:22 /dev/char/511:0 -> ../vfio/devices/vfio0 + +Then provide the user with access to the device if unprivileged +operation is desired:: + + $ chown user:user /dev/vfio/devices/vfio0 + +Finally the user could get cdev fd by:: + + cdev_fd = open("/dev/vfio/devices/vfio0", O_RDWR); + +An opened cdev_fd doesn't give the user any permission of accessing +the device except binding the cdev_fd to an iommufd. After that point +then the device is fully accessible including attaching it to an +IOMMUFD IOAS/HWPT to enable userspace DMA:: + + struct vfio_device_bind_iommufd bind = { + .argsz = sizeof(bind), + .flags = 0, + }; + struct iommu_ioas_alloc alloc_data = { + .size = sizeof(alloc_data), + .flags = 0, + }; + struct vfio_device_attach_iommufd_pt attach_data = { + .argsz = sizeof(attach_data), + .flags = 0, + }; + struct iommu_ioas_map map = { + .size = sizeof(map), + .flags = IOMMU_IOAS_MAP_READABLE | + IOMMU_IOAS_MAP_WRITEABLE | + IOMMU_IOAS_MAP_FIXED_IOVA, + .__reserved = 0, + }; + + iommufd = open("/dev/iommu", O_RDWR); + + bind.iommufd = iommufd; + ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind); + + ioctl(iommufd, IOMMU_IOAS_ALLOC, &alloc_data); + attach_data.pt_id = alloc_data.out_ioas_id; + ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data); + + /* Allocate some space and setup a DMA mapping */ + map.user_va = (int64_t)mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + map.iova = 0; /* 1MB starting at 0x0 from device view */ + map.length = 1024 * 1024; + map.ioas_id = alloc_data.out_ioas_id;; + + ioctl(iommufd, IOMMU_IOAS_MAP, &map); + + /* Other device operations as stated in "VFIO Usage Example" */ + VFIO User API ------------------------------------------------------------------------------- @@ -279,6 +410,7 @@ similar to a file operations structure:: struct iommufd_ctx *ictx, u32 *out_device_id); void (*unbind_iommufd)(struct vfio_device *vdev); int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id); + void (*detach_ioas)(struct vfio_device *vdev); int (*open_device)(struct vfio_device *vdev); void (*close_device)(struct vfio_device *vdev); ssize_t (*read)(struct vfio_device *vdev, char __user *buf, @@ -315,9 +447,10 @@ container_of(). - The [un]bind_iommufd callbacks are issued when the device is bound to and unbound from iommufd. - - The attach_ioas callback is issued when the device is attached to an - IOAS managed by the bound iommufd. The attached IOAS is automatically - detached when the device is unbound from iommufd. + - The [de]attach_ioas callback is issued when the device is attached to + and detached from an IOAS managed by the bound iommufd. However, the + attached IOAS can also be automatically detached when the device is + unbound from iommufd. - The read/write/mmap callbacks implement the device region access defined by the device's own VFIO_DEVICE_GET_REGION_INFO ioctl. @@ -564,3 +697,11 @@ This implementation has some specifics: \-0d.1 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 90) + +.. [5] Nested translation is an IOMMU feature which supports two stage + address translations. This improves the address translation efficiency + in IOMMU virtualization. + +.. [6] PASID stands for Process Address Space ID, introduced by PCI + Express. It is a prerequisite for Shared Virtual Addressing (SVA) + and Scalable I/O Virtualization (Scalable IOV). |