Xilinx Alveo/XRT patch overview
Subsystems (2)
cover Xilinx Alveo/XRT patch overview
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards, https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.
The patch depends on the "PATCH Xilinx Alveo libfdt prep" which was posted before.
ALVEO PLATFORM ARCHITECTURE
Alveo PCIe FPGA based platforms have a static *shell* partition and a partial re-configurable *user* partition. The shell partition is automatically loaded from flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be changed till the next cold reboot. The shell exposes two PCIe physical functions:
1. management physical function
2. user physical function
The patch series includes Documentation/xrt.rst which describes Alveo platform, xmgmt driver architecture and deployment model in more more detail.
Users compile their high level design in C/C++/OpenCL or RTL into FPGA image using Vitis https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The image is packaged as xclbin and contains partial bitstream for the user partition and necessary metadata. Users can dynamically swap the image running on the user partition in order to switch between different workloads.
ALVEO DRIVERS
Alveo Linux kernel driver *xmgmt* binds to management physical function of Alveo platform. The modular driver framework is organized into several platform drivers which primarily handle the following functionality:
1. Loading firmware container also called xsabin at driver attach time 2. Loading of user compiled xclbin with FPGA Manager integration 3. Clock scaling of image running on user partition 4. In-band sensors: temp, voltage, power, etc. 5. Device reset and rescan 6. Flashing static *shell* partition
The platform drivers are packaged into *xrt-lib* helper module with a well defined interfaces the details of which can be found in Documentation/xrt.rst.
xmgmt driver is second generation Alveo management driver and evolution of the first generation (out of tree) Alveo management driver, xclmgmt. The sources of the first generation drivers were posted on LKML last year--
https://lore.kernel.org/lkml/[email protected]/
Changes since the first generation driver include the following: the driver has been re-architected as data driven modular driver; the driver has been split into xmgmt and xrt-lib; user physical function driver has been removed from the patch series.
Alveo/XRT security and platform architecture is documented on the following GitHub pages:
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.html
User physical function driver is not included in this patch series.
TESTING AND VALIDATION
xmgmt driver can be tested with full XRT open source stack which includes user space libraries, board utilities and (out of tree) first generation user physical function driver xocl. XRT open source runtime stack is available at https://github.com/Xilinx/XRT. This patch series has been validated on Alveo U50 platform.
Complete documentation for XRT open source stack can be found here--
https://xilinx.github.io/XRT/master/html/index.html
Thanks,
-Sonal
Sonal Santan (8):
Documentation: fpga: Add a document describing Alveo XRT drivers
fpga: xrt: Add UAPI header files
fpga: xrt: infrastructure support for xmgmt driver
fpga: xrt: core infrastructure for xrt-lib module
fpga: xrt: platform drivers for subsystems in shell partition
fpga: xrt: header file for platform and parent drivers
fpga: xrt: Alveo management physical function driver
fpga: xrt: Kconfig and Makefile updates for XRT drivers
Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588 +++++ drivers/fpga/Kconfig | 2 + drivers/fpga/Makefile | 3 + drivers/fpga/alveo/Kconfig | 7 + drivers/fpga/alveo/common/xrt-metadata.c | 590 +++++ drivers/fpga/alveo/common/xrt-root.c | 744 +++++++ drivers/fpga/alveo/common/xrt-root.h | 24 + drivers/fpga/alveo/common/xrt-xclbin.c | 387 ++++ drivers/fpga/alveo/common/xrt-xclbin.h | 46 + drivers/fpga/alveo/include/xmgmt-main.h | 34 + drivers/fpga/alveo/include/xrt-axigate.h | 31 + drivers/fpga/alveo/include/xrt-calib.h | 28 + drivers/fpga/alveo/include/xrt-clkfreq.h | 21 + drivers/fpga/alveo/include/xrt-clock.h | 29 + drivers/fpga/alveo/include/xrt-cmc.h | 23 + drivers/fpga/alveo/include/xrt-ddr-srsr.h | 29 + drivers/fpga/alveo/include/xrt-flash.h | 28 + drivers/fpga/alveo/include/xrt-gpio.h | 41 + drivers/fpga/alveo/include/xrt-icap.h | 27 + drivers/fpga/alveo/include/xrt-mailbox.h | 44 + drivers/fpga/alveo/include/xrt-metadata.h | 184 ++ drivers/fpga/alveo/include/xrt-parent.h | 103 + drivers/fpga/alveo/include/xrt-partition.h | 33 + drivers/fpga/alveo/include/xrt-subdev.h | 333 +++ drivers/fpga/alveo/include/xrt-ucs.h | 22 + drivers/fpga/alveo/lib/Kconfig | 11 + drivers/fpga/alveo/lib/Makefile | 42 + drivers/fpga/alveo/lib/subdevs/xrt-axigate.c | 298 +++ drivers/fpga/alveo/lib/subdevs/xrt-calib.c | 291 +++ drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c | 214 ++ drivers/fpga/alveo/lib/subdevs/xrt-clock.c | 638 ++++++ .../fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c | 343 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h | 135 ++ .../fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c | 320 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c | 361 ++++ .../fpga/alveo/lib/subdevs/xrt-cmc-sensors.c | 445 ++++ drivers/fpga/alveo/lib/subdevs/xrt-cmc.c | 239 +++ drivers/fpga/alveo/lib/subdevs/xrt-gpio.c | 198 ++ drivers/fpga/alveo/lib/subdevs/xrt-icap.c | 306 +++ drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c | 1905 +++++++++++++++++ .../fpga/alveo/lib/subdevs/xrt-partition.c | 261 +++ drivers/fpga/alveo/lib/subdevs/xrt-qspi.c | 1347 ++++++++++++ drivers/fpga/alveo/lib/subdevs/xrt-srsr.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-test.c | 274 +++ drivers/fpga/alveo/lib/subdevs/xrt-ucs.c | 238 ++ .../fpga/alveo/lib/subdevs/xrt-vsec-golden.c | 238 ++ drivers/fpga/alveo/lib/subdevs/xrt-vsec.c | 337 +++ drivers/fpga/alveo/lib/xrt-cdev.c | 234 ++ drivers/fpga/alveo/lib/xrt-main.c | 275 +++ drivers/fpga/alveo/lib/xrt-main.h | 46 + drivers/fpga/alveo/lib/xrt-subdev.c | 1007 +++++++++ drivers/fpga/alveo/mgmt/Kconfig | 11 + drivers/fpga/alveo/mgmt/Makefile | 28 + drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++ include/uapi/linux/xrt/flash_xrt_data.h | 67 + include/uapi/linux/xrt/mailbox_proto.h | 394 ++++ include/uapi/linux/xrt/mailbox_transport.h | 74 + include/uapi/linux/xrt/xclbin.h | 418 ++++ include/uapi/linux/xrt/xmgmt-ioctl.h | 72 + 67 files changed, 17710 insertions(+) create mode 100644 Documentation/fpga/xrt.rst create mode 100644 drivers/fpga/alveo/Kconfig create mode 100644 drivers/fpga/alveo/common/xrt-metadata.c create mode 100644 drivers/fpga/alveo/common/xrt-root.c create mode 100644 drivers/fpga/alveo/common/xrt-root.h create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.c create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.h create mode 100644 drivers/fpga/alveo/include/xmgmt-main.h create mode 100644 drivers/fpga/alveo/include/xrt-axigate.h create mode 100644 drivers/fpga/alveo/include/xrt-calib.h create mode 100644 drivers/fpga/alveo/include/xrt-clkfreq.h create mode 100644 drivers/fpga/alveo/include/xrt-clock.h create mode 100644 drivers/fpga/alveo/include/xrt-cmc.h create mode 100644 drivers/fpga/alveo/include/xrt-ddr-srsr.h create mode 100644 drivers/fpga/alveo/include/xrt-flash.h create mode 100644 drivers/fpga/alveo/include/xrt-gpio.h create mode 100644 drivers/fpga/alveo/include/xrt-icap.h create mode 100644 drivers/fpga/alveo/include/xrt-mailbox.h create mode 100644 drivers/fpga/alveo/include/xrt-metadata.h create mode 100644 drivers/fpga/alveo/include/xrt-parent.h create mode 100644 drivers/fpga/alveo/include/xrt-partition.h create mode 100644 drivers/fpga/alveo/include/xrt-subdev.h create mode 100644 drivers/fpga/alveo/include/xrt-ucs.h create mode 100644 drivers/fpga/alveo/lib/Kconfig create mode 100644 drivers/fpga/alveo/lib/Makefile create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-axigate.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-calib.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clock.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sensors.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-gpio.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-icap.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-partition.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-qspi.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-srsr.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-test.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-ucs.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec-golden.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec.c create mode 100644 drivers/fpga/alveo/lib/xrt-cdev.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.h create mode 100644 drivers/fpga/alveo/lib/xrt-subdev.c create mode 100644 drivers/fpga/alveo/mgmt/Kconfig create mode 100644 drivers/fpga/alveo/mgmt/Makefile create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.c create mode 100644 include/uapi/linux/xrt/flash_xrt_data.h create mode 100644 include/uapi/linux/xrt/mailbox_proto.h create mode 100644 include/uapi/linux/xrt/mailbox_transport.h create mode 100644 include/uapi/linux/xrt/xclbin.h create mode 100644 include/uapi/linux/xrt/xmgmt-ioctl.h
--
2.17.1
PATCH 1/8 Documentation: fpga: Add a document describing Alveo XRT drivers
From: Sonal Santan <[email protected]>
Describe Alveo XRT driver architecture and provide basic overview of Xilinx Alveo platform.
--- Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588 +++++++++++++++++++++++++++++++++++ 2 files changed, 589 insertions(+) create mode 100644 Documentation/fpga/xrt.rst
Documentation/fpga/index.rst +1 -0
@@ -8,6 +8,7 @@ fpga :maxdepth: 1 dfl + xrt .. only:: subproject and html
Documentation/fpga/xrt.rst new file +588 -1
589 lines not on this page · raw message
2.17.1
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Quoted 33 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Describe Alveo XRT driver architecture and provide basic overview of Xilinx Alveo platform.
Signed-off-by Sonal Santan <[email protected]>--- Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588 +++++++++++++++++++++++++++++++++++ 2 files changed, 589 insertions(+) create mode 100644 Documentation/fpga/xrt.rstDocumentation/fpga/index.rst +1
-0@@ -8,6 +8,7 @@ fpga :maxdepth: 1 dfl + xrt .. only:: subproject and htmlDocumentation/fpga/xrt.rst new file +3
-0@@ -0,1 +1,588 @@ +================================== +XRTV2 Linux Kernel Driver Overview +==================================
Documentation/fpga/xrt.rst line 13
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +XRTV2 drivers are second generation `XRT <https://github.com/Xilinx/XRT>`_ drivers which +support `Alveo <https://www.xilinx.com/products/boards-and-kits/alveo.html>`_ PCIe platforms +from Xilinx. + +XRTV2 drivers support *subsystem* style data driven platforms where driver's configuration +and behavior is determined by meta data provided by platform (in *device tree* format). +Primary management physical function (MPF) driver is called **xmgmt**. Primary user physical +function (UPF) driver is called **xuser** and HW subsystem drivers are packaged into a library +module called **xrt-lib**, which is shared by **xmgmt** and **xuser** (WIP).
WIP?
Documentation/fpga/xrt.rst line 18
Quoted 5 lines
Documentation/fpga/xrt.rst new file +5
-0+ +Alveo Platform Overview +======================= + +Alveo platforms are architected as two physical FPGA partitions: *Shell* and *User*. Shell
Nit: The Shell provides ...
Quoted 31 lines
Documentation/fpga/xrt.rst new file +31
-0+provides basic infrastructure for the Alveo platform like PCIe connectivity, board management, +Dynamic Function Exchange (DFX), sensors, clocking, reset, and security. User partition contains +user compiled binary which is loaded by a process called DFX also known as partial reconfiguration. + +Physical partitions require strict HW compatibility with each other for DFX to work properly. +Every physical partition has two interface UUIDs: *parent* UUID and *child* UUID. For simple +single stage platforms Shell → User forms parent child relationship. For complex two stage +platforms Base → Shell → User forms the parent child relationship chain. + +.. note:: + Partition compatibility matching is key design component of Alveo platforms and XRT. Partitions + have child and parent relationship. A loaded partition exposes child partition UUID to advertise + its compatibility requirement for child partition. When loading a child partition the xmgmt + management driver matches parent UUID of the child partition against child UUID exported by the + parent. Parent and child partition UUIDs are stored in the *xclbin* (for user) or *xsabin* (for + base and shell). Except for root UUID, VSEC, hardware itself does not know about UUIDs. UUIDs are + stored in xsabin and xclbin. + + +The physical partitions and their loading is illustrated below:: + + SHELL USER + +-----------+ +-------------------+ + | | | | + | VSEC UUID | CHILD PARENT | LOGIC UUID | + | o------->|<--------o | + | | UUID UUID | | + +-----+-----+ +--------+----------+ + | | + . . + | |
Documentation/fpga/xrt.rst line 59
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +---+---+ +------+--------+ + | POR | | USER COMPILED | + | FLASH | | XCLBIN | + +-------+ +---------------+ + + +Loading Sequence +---------------- + +Shell partition is loaded from flash at system boot time. It establishes the PCIe link and exposes
Nit: The Shell
Documentation/fpga/xrt.rst line 64
Quoted 5 lines
Documentation/fpga/xrt.rst new file +5
-0+two physical functions to the BIOS. After OS boot, xmgmt driver attaches to PCIe physical function +0 exposed by the Shell and then looks for VSEC in PCIe extended configuration space. Using VSEC it +determines the logic UUID of Shell and uses the UUID to load matching *xsabin* file from Linux +firmware directory. The xsabin file contains metadata to discover peripherals that are part of Shell +and firmware(s) for any embedded soft processors in Shell.
Neat.
Documentation/fpga/xrt.rst line 66
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+ +Shell exports child interface UUID which is used for compatibility check when loading user compiled
Nit: The Shell
Documentation/fpga/xrt.rst line 78
Quoted 12 lines
Documentation/fpga/xrt.rst new file +12
-0+xclbin over the User partition as part of DFX. When a user requests loading of a specific xclbin the +xmgmt management driver reads the parent interface UUID specified in the xclbin and matches it with +child interface UUID exported by Shell to determine if xclbin is compatible with the Shell. If match +fails loading of xclbin is denied. + +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctl command. When loading xclbin xmgmt driver +performs the following operations: + +1. Sanity check the xclbin contents +2. Isolate the User partition +3. Download the bitstream using the FPGA config engine (ICAP) +4. De-isolate the User partition
Is this modelled as bridges and regions?
Quoted 74 lines
Documentation/fpga/xrt.rst new file +74
-0+5. Program the clocks (ClockWiz) driving the User partition +6. Wait for memory controller (MIG) calibration + +`Platform Loading Overview <https://xilinx.github.io/XRT/master/html/platforms_partitions.html>`_ +provides more detailed information on platform loading. + +xsabin +------ + +Each Alveo platform comes packaged with its own xsabin. The xsabin is trusted component of the +platform. For format details refer to :ref:`xsabin/xclbin Container Format`. xsabin contains +basic information like UUIDs, platform name and metadata in the form of device tree. See +:ref:`Device Tree Usage` for details and example. + +xclbin +------ + +xclbin is compiled by end user using +`Vitis <https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html>`_ tool set from +Xilinx. The xclbin contains sections describing user compiled acceleration engines/kernels, memory +subsystems, clocking information etc. It also contains bitstream for the user partition, UUIDs, +platform name, etc. xclbin uses the same container format as xsabin which is described below. + + +xsabin/xclbin Container Format +------------------------------ + +xclbin/xsabin is ELF-like binary container format. It is structured as series of sections. +There is a file header followed by several section headers which is followed by sections. +A section header points to an actual section. There is an optional signature at the end. +The format is defined by header file ``xclbin.h``. The following figure illustrates a +typical xclbin:: + + + +---------------------+ + | | + | HEADER | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | SIGNATURE | + | (OPTIONAL) | + +---------------------+ + + +xclbin/xsabin files can be packaged, un-packaged and inspected using XRT utility called +**xclbinutil**. xclbinutil is part of XRT open source software stack. The source code for +xclbinutil can be found at https://github.com/Xilinx/XRT/tree/master/src/runtime_src/tools/xclbinutil + +For example to enumerate the contents of a xclbin/xsabin use the *--info* switch as shown +below:: + + xclbinutil --info --input /opt/xilinx/firmware/u50/gen3x16-xdma/blp/test/bandwidth.xclbin + xclbinutil --info --input /lib/firmware/xilinx/862c7020a250293e32036f19956669e5/partition.xsabin + + +Device Tree Usage +-----------------
Documentation/fpga/xrt.rst line 162
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +As mentioned previously xsabin stores metadata which advertise HW subsystems present in a partition. +The metadata is stored in device tree format with well defined schema. Subsystem instantiations are +captured as children of ``addressable_endpoints`` node. Subsystem nodes have standard attributes like +``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes: +``pcie_physical_function`` and ``pcie_bar_mapping``. These identify which PCIe physical function and +which BAR space in that physical function the subsystem resides. XRT management driver uses this +information to bind *platform drivers* to the subsystem instantiations. The platform drivers are +found in **xrt-lib.ko** kernel module defined later. Below is an example of device tree for Alveo U50 +platform::
I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
What are the regs relative to?
Quoted 309 lines
Documentation/fpga/xrt.rst new file +309
-0+ + /dts-v1/; + + /{ + logic_uuid = "f465b0a3ae8c64f619bc150384ace69b"; + + schema_version { + major = <0x01>; + minor = <0x00>; + }; + + interfaces { + + @0 { + interface_uuid = "862c7020a250293e32036f19956669e5"; + }; + }; + + addressable_endpoints { + + ep_blp_rom_00 { + reg = <0x00 0x1f04000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + }; + + ep_card_flash_program_00 { + reg = <0x00 0x1f06000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_quad_spi-1.0\0axi_quad_spi"; + interrupts = <0x03 0x03>; + }; + + ep_cmc_firmware_mem_00 { + reg = <0x00 0x1e20000 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "cmc"; + firmware_branch_name = "u50"; + firmware_version_major = <0x01>; + firmware_version_minor = <0x00>; + }; + }; + + ep_cmc_intc_00 { + reg = <0x00 0x1e03000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x04 0x04>; + }; + + ep_cmc_mutex_00 { + reg = <0x00 0x1e02000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_cmc_regmap_00 { + reg = <0x00 0x1e08000 0x00 0x2000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "sc-fw"; + firmware_branch_name = "u50"; + firmware_version_major = <0x05>; + }; + }; + + ep_cmc_reset_00 { + reg = <0x00 0x1e01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ddr_mem_calib_00 { + reg = <0x00 0x63000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_debug_bscan_mgmt_00 { + reg = <0x00 0x1e90000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-debug_bridge-1.0\0debug_bridge"; + }; + + ep_ert_base_address_00 { + reg = <0x00 0x21000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_command_queue_mgmt_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue"; + }; + + ep_ert_command_queue_user_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue"; + }; + + ep_ert_firmware_mem_00 { + reg = <0x00 0x30000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "ert"; + firmware_branch_name = "v20"; + firmware_version_major = <0x01>; + }; + }; + + ep_ert_intc_00 { + reg = <0x00 0x23000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x05 0x05>; + }; + + ep_ert_reset_00 { + reg = <0x00 0x22000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_sched_00 { + reg = <0x00 0x50000 0x00 0x1000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_sched-1.0\0ert_sched"; + interrupts = <0x09 0x0c>; + }; + + ep_fpga_configuration_00 { + reg = <0x00 0x1e88000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_hwicap-1.0\0axi_hwicap"; + interrupts = <0x02 0x02>; + }; + + ep_icap_reset_00 { + reg = <0x00 0x1f07000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_mailbox_mgmt_00 { + reg = <0x00 0x1f10000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x00 0x00>; + }; + + ep_mailbox_user_00 { + reg = <0x00 0x1f00000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x08 0x08>; + }; + + ep_msix_00 { + reg = <0x00 0x00 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-msix-1.0\0msix"; + pcie_bar_mapping = <0x02>; + }; + + ep_pcie_link_mon_00 { + reg = <0x00 0x1f05000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_pr_isolate_plp_00 { + reg = <0x00 0x1f01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_pr_isolate_ulp_00 { + reg = <0x00 0x1000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_uuid_rom_00 { + reg = <0x00 0x64000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + }; + + ep_xdma_00 { + reg = <0x00 0x00 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-xdma-1.0\0xdma"; + pcie_bar_mapping = <0x02>; + }; + }; + + } + + + +Deployment Models +================= + +Baremetal +--------- + +In bare-metal deployments both MPF and UPF are visible and accessible. xmgmt driver binds to +MPF. xmgmt driver operations are privileged and available to system administrator. The full +stack is illustrated below:: + + + HOST + + [XMGMT] [XUSER] + | | + | | + +-----+ +-----+ + | MPF | | UPF | + | | | | + | PF0 | | PF1 | + +--+--+ +--+--+ + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | | + | | + +------------------------+ + + + +Virtualized +----------- + +In virtualized deployments privileged MPF is assigned to host but unprivileged UPF +is assigned to guest VM via PCIe pass-through. xmgmt driver in host binds to MPF. +xmgmt driver operations are privileged and only accessible by hosting service provider. +The full stack is illustrated below:: + + + ............. + HOST . VM . + . . + [XMGMT] . [XUSER] . + | . | . + | . | . + +-----+ . +-----+ . + | MPF | . | UPF | . + | | . | | . + | PF0 | . | PF1 | . + +--+--+ . +--+--+ . + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | | + | | + +------------------------+ + + + +Driver Modules +============== + +xrt-lib.ko +---------- + +Repository of all subsystem drivers and pure software modules that can potentially +be shared between xmgmt and xuser. All these drivers are structured as Linux +*platform driver* and are instantiated by xmgmt (or xuser in future) based on meta +data associated with hardware. The metadata is in the form of device tree as +explained before. + +xmgmt.ko +-------- + +The xmgmt driver is a PCIe device driver driving MPF found on Xilinx's Alveo +PCIE device. It consists of one *root* driver, one or more *partition* drivers +and one or more *leaf* drivers. The root and MPF specific leaf drivers are in +xmgmt.ko. The partition driver and other leaf drivers are in xrt-lib.ko. + +The instantiation of specific partition driver or leaf driver is completely data +driven based on meta data (mostly in device tree format) found through VSEC +capability and inside firmware files, such as xsabin or xclbin file. The root +driver manages life cycle of multiple partition drivers, which, in turn, manages +multiple leaf drivers. This allows a single set of driver code to support all
Documentation/fpga/xrt.rst line 481
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+kinds of subsystems exposed by different shells. The difference among all +these subsystems will be handled in leaf drivers with root and partition drivers +being part of the infrastructure and provide common services for all leaves found +on all platforms. + + +xmgmt-root +^^^^^^^^^^ + +The xmgmt-root driver is a PCIe device driver attaches to MPF. It's part of the
Nit: s/attaches/attached ?
Quoted 90 lines
Documentation/fpga/xrt.rst new file +90
-0+infrastructure of the MPF driver and resides in xmgmt.ko. This driver + +* manages one or more partition drivers +* provides access to functionalities that requires pci_dev, such as PCIE config + space access, to other leaf drivers through parent calls +* together with partition driver, facilities event callbacks for other leaf drivers +* together with partition driver, facilities inter-leaf driver calls for other leaf + drivers + +When root driver starts, it will explicitly create an initial partition instance, +which contains leaf drivers that will trigger the creation of other partition +instances. The root driver will wait for all partitions and leaves to be created +before it returns from it's probe routine and claim success of the initialization +of the entire xmgmt driver. + +partition +^^^^^^^^^ + +The partition driver is a platform device driver whose life cycle is managed by +root and does not have real IO mem or IRQ resources. It's part of the +infrastructure of the MPF driver and resides in xrt-lib.ko. This driver + +* manages one or more leaf drivers so that multiple leaves can be managed as a group +* provides access to root from leaves, so that parent calls, event notifications + and inter-leaf calls can happen + +In xmgmt, an initial partition driver instance will be created by root, which +contains leaves that will trigger partition instances to be created to manage +groups of leaves found on different partitions on hardware, such as VSEC, Shell, +and User. + +leaves +^^^^^^ + +The leaf driver is a platform device driver whose life cycle is managed by +a partition driver and may or may not have real IO mem or IRQ resources. They +are the real meat of xmgmt and contains platform specific code to Shell and User +found on a MPF. + +A leaf driver may not have real hardware resources when it merely acts as a driver +that manages certain in-memory states for xmgmt. These in-memory states could be +shared by multiple other leaves. + +Leaf drivers assigned to specific hardware resources drive specific subsystem in +the device. To manipulate the subsystem or carry out a task, a leaf driver may ask +help from root via parent calls and/or from other leaves via inter-leaf calls. + +A leaf can also broadcast events through infrastructure code for other leaves +to process. It can also receive event notification from infrastructure about certain +events, such as post-creation or pre-exit of a particular leaf. + + +Driver Interfaces +================= + +xmgmt Driver Ioctls +------------------- + +Ioctls exposed by xmgmt driver to user space are enumerated in the following table: + +== ===================== ============================= =========================== +# Functionality ioctl request code data format +== ===================== ============================= =========================== +1 FPGA image download XMGMT_IOCICAPDOWNLOAD_AXLF xmgmt_ioc_bitstream_axlf +2 CL frequency scaling XMGMT_IOCFREQSCALE xmgmt_ioc_freqscaling +== ===================== ============================= =========================== + +xmgmt Driver Sysfs +------------------ + +xmgmt driver exposes a rich set of sysfs interfaces. Subsystem platform drivers +export sysfs node for every platform instance. + +Every partition also exports its UUIDs. See below for examples:: + + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/interface_uuids + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/logic_uuids + + +hwmon +----- + +xmgmt driver exposes standard hwmon interface to report voltage, current, temperature, +power, etc. These can easily be viewed using *sensors* command line utility. + + +mailbox +------- + +xmgmt communicates with user physical function driver via HW mailbox. Mailbox opcodes
Documentation/fpga/xrt.rst line 581
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+are defined in ``mailbox_proto.h``. `Mailbox Inter-domain Communication Protocol +<https://xilinx.github.io/XRT/master/html/mailbox.proto.html>`_ defines the full +specification. xmgmt implements subset of the specification. It provides the following +services to the UPF driver: + +1. Responding to *are you there* request including determining if the two drivers are + running in the same OS domain +2. Provide sensor readings, loaded xclbin UUID, clock frequency, shell information, etc. +3. Perform PCIe hot reset +4. Download user compiled xclbin
Is this gonna use the mailbox framework?
Quoted 9 lines
Documentation/fpga/xrt.rst new file +7
-1+ + +Platform Security Considerations +================================ + +`Security of Alveo Platform <https://xilinx.github.io/XRT/master/html/security.html>`_ +discusses the deployment options and security implications in great detail. --2.17.1
That's a lot of text, I'll have to read it again most likely,
- Moritz
RE: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Hi Moritz,
Thanks for your feedback. Please see my reply inline.
Thanks,
-Max
Quoted 56 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Monday, November 30, 2020 20:55
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT driversQuoted 9 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Describe Alveo XRT driver architecture and provide basic overview of Xilinx Alveo platform.
Signed-off-by Sonal Santan <[email protected]>--- Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588+++++++++++++++++++++++++++++++++++
Quoted 5 lines
2 files changed, 589 insertions(+) create mode 100644 Documentation/fpga/xrt.rst(quoted diff) +0
-0
b/Documentation/fpga/index.rstindexf80f95667ca2..30134357b70d100644
Quoted 15 lines
Documentation/fpga/index.rst +1
-0@@ -8,6 +8,7 @@ fpga :maxdepth: 1 dfl + xrt .. only:: subproject and htmlDocumentation/fpga/xrt.rst new file +0
-0Documentation/fpga/xrt.rst line 7
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0@@ -0,1 +1,588 @@ +================================== +XRTV2 Linux Kernel Driver Overview +================================== + +XRTV2 drivers are second generation `XRT +<https://github.com/Xilinx/XRT>`_ drivers which support `Alveo +<https://www.xilinx.com/products/boards-and-kits/alveo.html>`_ PCIeplatforms from Xilinx.
Documentation/fpga/xrt.rst line 10
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +XRTV2 drivers support *subsystem* style data driven platforms where +driver's configuration and behavior is determined by meta data providedby platform (in *device tree* format).
Quoted 5 lines
Documentation/fpga/xrt.rst line 13
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+Primary management physical function (MPF) driver is called +**xmgmt**. Primary user physical function (UPF) driver is called +**xuser** and HW subsystem drivers are packaged into a library modulecalled **xrt-lib**, which is shared by **xmgmt** and **xuser** (WIP). WIP?
Working in progress. I'll expand it in the doc.
Quoted 7 lines
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ +Alveo Platform Overview +======================= + +Alveo platforms are architected as two physical FPGA partitions: +*Shell* and *User*. ShellNit: The Shell provides ...
Sure. Will fix.
Quoted 45 lines
Documentation/fpga/xrt.rst line 22
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+provides basic infrastructure for the Alveo platform like PCIe +connectivity, board management, Dynamic Function Exchange (DFX), +sensors, clocking, reset, and security. User partition contains usercompiled binary which is loaded by a process called DFX also known as partial reconfiguration.
Documentation/fpga/xrt.rst line 24
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+ +Physical partitions require strict HW compatibility with each other for DFXto work properly.
Documentation/fpga/xrt.rst line 27
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+Every physical partition has two interface UUIDs: *parent* UUID and +*child* UUID. For simple single stage platforms Shell → User forms +parent child relationship. For complex two stage platforms Base → Shell→ User forms the parent child relationship chain.
Documentation/fpga/xrt.rst
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +.. note:: + Partition compatibility matching is key design component of Alveoplatforms and XRT. Partitions
Documentation/fpga/xrt.rst line 31
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ have child and parent relationship. A loaded partition exposes childpartition UUID to advertise
Documentation/fpga/xrt.rst line 32
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ its compatibility requirement for child partition. When loading a childpartition the xmgmt
Documentation/fpga/xrt.rst line 33
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ management driver matches parent UUID of the child partition againstchild UUID exported by the
Documentation/fpga/xrt.rst line 34
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ parent. Parent and child partition UUIDs are stored in the *xclbin* (foruser) or *xsabin* (for
Documentation/fpga/xrt.rst line 35
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ base and shell). Except for root UUID, VSEC, hardware itself does notknow about UUIDs. UUIDs are
Quoted 19 lines
Documentation/fpga/xrt.rst new file +19
-0+ stored in xsabin and xclbin. + + +The physical partitions and their loading is illustrated below:: + + SHELL USER + +-----------+ +-------------------+ + | | | | + | VSEC UUID | CHILD PARENT | LOGIC UUID | + | o------->|<--------o | + | | UUID UUID | | + +-----+-----+ +--------+----------+ + | | + . . + | | + +---+---+ +------+--------+ + | POR | | USER COMPILED | + | FLASH | | XCLBIN | + +-------+ +---------------+
Quoted 8 lines
Documentation/fpga/xrt.rst
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+ + +Loading Sequence +---------------- + +Shell partition is loaded from flash at system boot time. It +establishes the PCIe link and exposesNit: The Shell
Will fix.
Quoted 9 lines
Documentation/fpga/xrt.rst line 67
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+two physical functions to the BIOS. After OS boot, xmgmt driver +attaches to PCIe physical function +0 exposed by the Shell and then looks for VSEC in PCIe extended +configuration space. Using VSEC it determines the logic UUID of Shell +and uses the UUID to load matching *xsabin* file from Linux firmware +directory. The xsabin file contains metadata to discover peripherals thatare part of Shell and firmware(s) for any embedded soft processors in Shell.
Neat.
Thanks :-).
Quoted 4 lines
Documentation/fpga/xrt.rst line 70
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +Shell exports child interface UUID which is used for compatibility +check when loading user compiledNit: The Shell
Sure.
Quoted 5 lines
Documentation/fpga/xrt.rst line 74
Quoted 4 lines
Documentation/fpga/xrt.rst new file +4
-0+xclbin over the User partition as part of DFX. When a user requests +loading of a specific xclbin the xmgmt management driver reads the +parent interface UUID specified in the xclbin and matches it with +child interface UUID exported by Shell to determine if xclbin is compatiblewith the Shell. If match fails loading of xclbin is denied.
Quoted 9 lines
Documentation/fpga/xrt.rst
Quoted 8 lines
Documentation/fpga/xrt.rst new file +8
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctl command. +When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents +2. Isolate the User partition +3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Alveo drivers as written today do not use fpga bridge and region framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
Or maybe we have missed some points about the use case for this framework?
Quoted 97 lines
Quoted 5 lines
Documentation/fpga/xrt.rst new file +4
-0+5. Program the clocks (ClockWiz) driving the User partition 6. Wait +for memory controller (MIG) calibration + +`Platform Loading OverviewDocumentation/fpga/xrt.rst line 96
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+<https://xilinx.github.io/XRT/master/html/platforms_partitions.html>` +_ provides more detailed information on platform loading. + +xsabin +------ + +Each Alveo platform comes packaged with its own xsabin. The xsabin is +trusted component of the platform. For format details refer to +:ref:`xsabin/xclbin Container Format`. xsabin contains basic +information like UUIDs, platform name and metadata in the form ofdevice tree. See :ref:
Device Tree Usagefor details and example.Documentation/fpga/xrt.rst
Quoted 9 lines
Documentation/fpga/xrt.rst new file +9
-0+ +xclbin +------ + +xclbin is compiled by end user using +`Vitis +<https://www.xilinx.com/products/design-tools/vitis/vitis-platform.ht +ml>`_ tool set from Xilinx. The xclbin contains sections describing +user compiled acceleration engines/kernels, memory subsystems,clocking information etc. It also contains bitstream for the user partition, UUIDs, platform name, etc. xclbin uses the same container format as xsabin which is described below.
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ + +xsabin/xclbin Container Format +------------------------------ + +xclbin/xsabin is ELF-like binary container format. It is structured as seriesof sections.
Documentation/fpga/xrt.rst line 112
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+There is a file header followed by several section headers which isfollowed by sections.
Documentation/fpga/xrt.rst line 113
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+A section header points to an actual section. There is an optional signatureat the end.
Quoted 42 lines
Documentation/fpga/xrt.rst new file +42
-0+The format is defined by header file ``xclbin.h``. The following +figure illustrates a typical xclbin:: + + + +---------------------+ + | | + | HEADER | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | SIGNATURE | + | (OPTIONAL) | + +---------------------+ + + +xclbin/xsabin files can be packaged, un-packaged and inspected using +XRT utility called **xclbinutil**. xclbinutil is part of XRT open +source software stack. The source code for xclbinutil can be found at +https://github.com/Xilinx/XRT/tree/master/src/runtime_src/tools/xclbi +nutil + +For example to enumerate the contents of a xclbin/xsabin use the +*--info* switch as shown +below:: + + xclbinutil --info --inputDocumentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ /opt/xilinx/firmware/u50/gen3x16-xdma/blp/test/bandwidth.xclbin + xclbinutil --info --input + /lib/firmware/xilinx/862c7020a250293e32036f19956669e5/partition.xsab + in + + +Device Tree Usage +----------------- + +As mentioned previously xsabin stores metadata which advertise HWsubsystems present in a partition.
Documentation/fpga/xrt.rst line 168
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+The metadata is stored in device tree format with well defined +schema. Subsystem instantiations are captured as children of +``addressable_endpoints`` node. Subsystem nodes have standardattributes like ``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes:
Quoted 12 lines
Documentation/fpga/xrt.rst line 176
Quoted 8 lines
Documentation/fpga/xrt.rst new file +8
-0+``pcie_physical_function`` and ``pcie_bar_mapping``. These identify +which PCIe physical function and which BAR space in that physical +function the subsystem resides. XRT management driver uses this +information to bind *platform drivers* to the subsystem +instantiations. The platform drivers are found in **xrt-lib.ko** +kernel module defined later. Below is an example of device tree for +Alveo U50 +platform::I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
Alveo driver does not generate the metadata. The metadata is formatted and generated by HW tools when the Alveo HW platform is built.
Quoted 2 lines
What are the regs relative to?
Regs indicates offset of the register on the PCIE BAR of the Alveo device.
Quoted 327 lines
Quoted 14 lines
Documentation/fpga/xrt.rst new file +14
-0+ + /dts-v1/; + + /{ + logic_uuid = "f465b0a3ae8c64f619bc150384ace69b"; + + schema_version { + major = <0x01>; + minor = <0x00>; + }; + + interfaces { + + @0 {Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ interface_uuid = "862c7020a250293e32036f19956669e5"; + }; + }; + + addressable_endpoints { + + ep_blp_rom_00 { + reg = <0x00 0x1f04000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl";
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ }; + + ep_card_flash_program_00 { + reg = <0x00 0x1f06000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_quad_spi-1.0\0axi_quad_spi";
Quoted 49 lines
Documentation/fpga/xrt.rst new file +49
-0+ interrupts = <0x03 0x03>; + }; + + ep_cmc_firmware_mem_00 { + reg = <0x00 0x1e20000 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "cmc"; + firmware_branch_name = "u50"; + firmware_version_major = <0x01>; + firmware_version_minor = <0x00>; + }; + }; + + ep_cmc_intc_00 { + reg = <0x00 0x1e03000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x04 0x04>; + }; + + ep_cmc_mutex_00 { + reg = <0x00 0x1e02000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_cmc_regmap_00 { + reg = <0x00 0x1e08000 0x00 0x2000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "sc-fw"; + firmware_branch_name = "u50"; + firmware_version_major = <0x05>; + }; + }; + + ep_cmc_reset_00 { + reg = <0x00 0x1e01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ ep_ddr_mem_calib_00 { + reg = <0x00 0x63000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_debug_bscan_mgmt_00 { + reg = <0x00 0x1e90000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-debug_bridge-1.0\0debug_bridge";
Documentation/fpga/xrt.rst
Quoted 12 lines
Documentation/fpga/xrt.rst new file +12
-0+ }; + + ep_ert_base_address_00 { + reg = <0x00 0x21000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_command_queue_mgmt_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue";
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ }; + + ep_ert_command_queue_user_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue";
Quoted 81 lines
Documentation/fpga/xrt.rst new file +81
-0+ }; + + ep_ert_firmware_mem_00 { + reg = <0x00 0x30000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "ert"; + firmware_branch_name = "v20"; + firmware_version_major = <0x01>; + }; + }; + + ep_ert_intc_00 { + reg = <0x00 0x23000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x05 0x05>; + }; + + ep_ert_reset_00 { + reg = <0x00 0x22000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_sched_00 { + reg = <0x00 0x50000 0x00 0x1000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_sched-1.0\0ert_sched"; + interrupts = <0x09 0x0c>; + }; + + ep_fpga_configuration_00 { + reg = <0x00 0x1e88000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_hwicap-1.0\0axi_hwicap"; + interrupts = <0x02 0x02>; + }; + + ep_icap_reset_00 { + reg = <0x00 0x1f07000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_mailbox_mgmt_00 { + reg = <0x00 0x1f10000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x00 0x00>; + }; + + ep_mailbox_user_00 { + reg = <0x00 0x1f00000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x08 0x08>; + }; + + ep_msix_00 { + reg = <0x00 0x00 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-msix-1.0\0msix"; + pcie_bar_mapping = <0x02>; + }; + + ep_pcie_link_mon_00 { + reg = <0x00 0x1f05000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_pr_isolate_plp_00 { + reg = <0x00 0x1f01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ ep_pr_isolate_ulp_00 { + reg = <0x00 0x1000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_uuid_rom_00 { + reg = <0x00 0x64000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl";
Quoted 13 lines
Documentation/fpga/xrt.rst new file +13
-0+ }; + + ep_xdma_00 { + reg = <0x00 0x00 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-xdma-1.0\0xdma"; + pcie_bar_mapping = <0x02>; + }; + }; + + } + +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +Deployment Models +================= + +Baremetal +--------- + +In bare-metal deployments both MPF and UPF are visible and +accessible. xmgmt driver binds to MPF. xmgmt driver operations are +privileged and available to system administrator. The full stack isillustrated below::
Quoted 24 lines
Documentation/fpga/xrt.rst new file +24
-0+ + + HOST + + [XMGMT] [XUSER] + | | + | | + +-----+ +-----+ + | MPF | | UPF | + | | | | + | PF0 | | PF1 | + +--+--+ +--+--+ + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | |Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ | | + +------------------------+ + + + +Virtualized +----------- + +In virtualized deployments privileged MPF is assigned to host but +unprivileged UPF is assigned to guest VM via PCIe pass-through. xmgmtdriver in host binds to MPF.
Documentation/fpga/xrt.rst line 432
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+xmgmt driver operations are privileged and only accessible by hostingservice provider.
Quoted 40 lines
Documentation/fpga/xrt.rst new file +40
-0+The full stack is illustrated below:: + + + ............. + HOST . VM . + . . + [XMGMT] . [XUSER] . + | . | . + | . | . + +-----+ . +-----+ . + | MPF | . | UPF | . + | | . | | . + | PF0 | . | PF1 | . + +--+--+ . +--+--+ . + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | | + | | + +------------------------+ + + + +Driver Modules +============== + +xrt-lib.ko +---------- + +Repository of all subsystem drivers and pure software modules that +can potentially be shared between xmgmt and xuser. All these drivers +are structured as Linux *platform driver* and are instantiated byDocumentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+xmgmt (or xuser in future) based on meta data associated with +hardware. The metadata is in the form of device tree as explained before. + +xmgmt.ko +-------- + +The xmgmt driver is a PCIe device driver driving MPF found on +Xilinx's Alveo PCIE device. It consists of one *root* driver, one or +more *partition* drivers and one or more *leaf* drivers. The root and +MPF specific leaf drivers are in xmgmt.ko. The partition driver and otherleaf drivers are in xrt-lib.ko.
Documentation/fpga/xrt.rst line 492
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +The instantiation of specific partition driver or leaf driver is +completely data driven based on meta data (mostly in device tree +format) found through VSEC capability and inside firmware files, such +as xsabin or xclbin file. The root driver manages life cycle of +multiple partition drivers, which, in turn, manages multiple leaf +drivers. This allows a single set of driver code to support all kinds +of subsystems exposed by different shells. The difference among all +these subsystems will be handled in leaf drivers with root and +partition drivers being part of the infrastructure and provide commonservices for all leaves found on all platforms.
Quoted 8 lines
Documentation/fpga/xrt.rst
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+ + +xmgmt-root +^^^^^^^^^^ + +The xmgmt-root driver is a PCIe device driver attaches to MPF. It's +part of theNit: s/attaches/attached ?
Yes, sure.
Quoted 113 lines
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+infrastructure of the MPF driver and resides in xmgmt.ko. This driver + +* manages one or more partition drivers +* provides access to functionalities that requires pci_dev, such as +PCIE config + space access, to other leaf drivers through parent calls +* together with partition driver, facilities event callbacks forDocumentation/fpga/xrt.rst line 516
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+other leaf drivers +* together with partition driver, facilities inter-leaf driver calls +for other leaf + drivers + +When root driver starts, it will explicitly create an initial +partition instance, which contains leaf drivers that will trigger the +creation of other partition instances. The root driver will wait for +all partitions and leaves to be created before it returns from it's +probe routine and claim success of the initialization of the entire xmgmtdriver.
Quoted 25 lines
Documentation/fpga/xrt.rst new file +25
-0+ +partition +^^^^^^^^^ + +The partition driver is a platform device driver whose life cycle is +managed by root and does not have real IO mem or IRQ resources. It's +part of the infrastructure of the MPF driver and resides in +xrt-lib.ko. This driver + +* manages one or more leaf drivers so that multiple leaves can be +managed as a group +* provides access to root from leaves, so that parent calls, event +notifications + and inter-leaf calls can happen + +In xmgmt, an initial partition driver instance will be created by +root, which contains leaves that will trigger partition instances to +be created to manage groups of leaves found on different partitions +on hardware, such as VSEC, Shell, and User. + +leaves +^^^^^^ + +The leaf driver is a platform device driver whose life cycle is +managed by a partition driver and may or may not have real IO mem orDocumentation/fpga/xrt.rst line 551
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+IRQ resources. They are the real meat of xmgmt and contains platform +specific code to Shell and User found on a MPF. + +A leaf driver may not have real hardware resources when it merely +acts as a driver that manages certain in-memory states for xmgmt. +These in-memory states could be shared by multiple other leaves. + +Leaf drivers assigned to specific hardware resources drive specific +subsystem in the device. To manipulate the subsystem or carry out a +task, a leaf driver may ask help from root via parent calls and/or fromother leaves via inter-leaf calls.
Documentation/fpga/xrt.rst line 555
Quoted 4 lines
Documentation/fpga/xrt.rst new file +4
-0+ +A leaf can also broadcast events through infrastructure code for +other leaves to process. It can also receive event notification from +infrastructure about certain events, such as post-creation or pre-exit of aparticular leaf.
Documentation/fpga/xrt.rst
Quoted 9 lines
Documentation/fpga/xrt.rst new file +9
-0+ + +Driver Interfaces +================= + +xmgmt Driver Ioctls +------------------- + +Ioctls exposed by xmgmt driver to user space are enumerated in thefollowing table:
Documentation/fpga/xrt.rst line 566
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+ +== ===================== ========================================================
Documentation/fpga/xrt.rst line 568
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+# Functionality ioctl request code data format +== ===================== ========================================================
Documentation/fpga/xrt.rst line 569
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+1 FPGA image download XMGMT_IOCICAPDOWNLOAD_AXLF
xmgmt_ioc_bitstream_axlfDocumentation/fpga/xrt.rst line 570
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+2 CL frequency scaling XMGMT_IOCFREQSCALE
xmgmt_ioc_freqscalingQuoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+== ===================== ============================= +=========================== + +xmgmt Driver Sysfs +------------------ + +xmgmt driver exposes a rich set of sysfs interfaces. Subsystem +platform drivers export sysfs node for every platform instance. + +Every partition also exports its UUIDs. See below for examples::Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/interface_uuids + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/logic_uuids + + +hwmon +----- + +xmgmt driver exposes standard hwmon interface to report voltage, +current, temperature, power, etc. These can easily be viewed using*sensors* command line utility.
Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ + +mailbox +------- + +xmgmt communicates with user physical function driver via HW mailbox. +Mailbox opcodes are defined in ``mailbox_proto.h``. `Mailbox +Inter-domain Communication Protocol +<https://xilinx.github.io/XRT/master/html/mailbox.proto.html>`_ +defines the full specification. xmgmt implements subset of thespecification. It provides the following services to the UPF driver:
Quoted 2 lines
+
+1. Responding to *are you there* request including determining if the
Quoted 8 lines
two drivers are
Quoted 2 lines
+ running in the same OS domain
+2. Provide sensor readings, loaded xclbin UUID, clock frequency, shellinformation, etc.
Quoted 2 lines
+3. Perform PCIe hot reset
+4. Download user compiled xclbinIs this gonna use the mailbox framework?
The xclbin can be downloaded via IOCTL interface of xmgmt driver. Or the download request can come from user pf driver via mailbox, yes.
Thanks,
Max
Quoted 15 lines
Quoted 11 lines
Documentation/fpga/xrt.rst new file +8
-1+ + +Platform Security Considerations +================================ + +`Security of Alveo Platform +<https://xilinx.github.io/XRT/master/html/security.html>`_ +discusses the deployment options and security implications in great detail. --2.17.1
That's a lot of text, I'll have to read it again most likely,
- Moritz
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Hi Max,
Quoted 171 lines · Max Zhen
Hi Moritz,
Thanks for your feedback. Please see my reply inline.
Thanks,
-MaxQuoted 56 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Monday, November 30, 2020 20:55
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT driversQuoted 9 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Describe Alveo XRT driver architecture and provide basic overview of Xilinx Alveo platform.
Signed-off-by Sonal Santan <[email protected]>--- Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588+++++++++++++++++++++++++++++++++++
Quoted 5 lines
2 files changed, 589 insertions(+) create mode 100644 Documentation/fpga/xrt.rst(quoted diff) +0
-0
b/Documentation/fpga/index.rstindexf80f95667ca2..30134357b70d100644
Quoted 15 lines
Documentation/fpga/index.rst +1
-0@@ -8,6 +8,7 @@ fpga :maxdepth: 1 dfl + xrt .. only:: subproject and htmlDocumentation/fpga/xrt.rst new file +0
-0Documentation/fpga/xrt.rst line 7
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0@@ -0,1 +1,588 @@ +================================== +XRTV2 Linux Kernel Driver Overview +================================== + +XRTV2 drivers are second generation `XRT +<https://github.com/Xilinx/XRT>`_ drivers which support `Alveo +<https://www.xilinx.com/products/boards-and-kits/alveo.html>`_ PCIeplatforms from Xilinx.
Documentation/fpga/xrt.rst line 10
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +XRTV2 drivers support *subsystem* style data driven platforms where +driver's configuration and behavior is determined by meta data providedby platform (in *device tree* format).
Quoted 5 lines
Documentation/fpga/xrt.rst line 13
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+Primary management physical function (MPF) driver is called +**xmgmt**. Primary user physical function (UPF) driver is called +**xuser** and HW subsystem drivers are packaged into a library modulecalled **xrt-lib**, which is shared by **xmgmt** and **xuser** (WIP). WIP?
Working in progress. I'll expand it in the doc.
Quoted 7 lines
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ +Alveo Platform Overview +======================= + +Alveo platforms are architected as two physical FPGA partitions: +*Shell* and *User*. ShellNit: The Shell provides ...
Sure. Will fix.
Quoted 45 lines
Documentation/fpga/xrt.rst line 22
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+provides basic infrastructure for the Alveo platform like PCIe +connectivity, board management, Dynamic Function Exchange (DFX), +sensors, clocking, reset, and security. User partition contains usercompiled binary which is loaded by a process called DFX also known as partial reconfiguration.
Documentation/fpga/xrt.rst line 24
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+ +Physical partitions require strict HW compatibility with each other for DFXto work properly.
Documentation/fpga/xrt.rst line 27
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+Every physical partition has two interface UUIDs: *parent* UUID and +*child* UUID. For simple single stage platforms Shell → User forms +parent child relationship. For complex two stage platforms Base → Shell→ User forms the parent child relationship chain.
Documentation/fpga/xrt.rst
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +.. note:: + Partition compatibility matching is key design component of Alveoplatforms and XRT. Partitions
Documentation/fpga/xrt.rst line 31
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ have child and parent relationship. A loaded partition exposes childpartition UUID to advertise
Documentation/fpga/xrt.rst line 32
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ its compatibility requirement for child partition. When loading a childpartition the xmgmt
Documentation/fpga/xrt.rst line 33
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ management driver matches parent UUID of the child partition againstchild UUID exported by the
Documentation/fpga/xrt.rst line 34
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ parent. Parent and child partition UUIDs are stored in the *xclbin* (foruser) or *xsabin* (for
Documentation/fpga/xrt.rst line 35
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+ base and shell). Except for root UUID, VSEC, hardware itself does notknow about UUIDs. UUIDs are
Quoted 19 lines
Documentation/fpga/xrt.rst new file +19
-0+ stored in xsabin and xclbin. + + +The physical partitions and their loading is illustrated below:: + + SHELL USER + +-----------+ +-------------------+ + | | | | + | VSEC UUID | CHILD PARENT | LOGIC UUID | + | o------->|<--------o | + | | UUID UUID | | + +-----+-----+ +--------+----------+ + | | + . . + | | + +---+---+ +------+--------+ + | POR | | USER COMPILED | + | FLASH | | XCLBIN | + +-------+ +---------------+Quoted 8 lines
Documentation/fpga/xrt.rst
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+ + +Loading Sequence +---------------- + +Shell partition is loaded from flash at system boot time. It +establishes the PCIe link and exposesNit: The Shell
Will fix.
Quoted 9 lines
Documentation/fpga/xrt.rst line 67
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+two physical functions to the BIOS. After OS boot, xmgmt driver +attaches to PCIe physical function +0 exposed by the Shell and then looks for VSEC in PCIe extended +configuration space. Using VSEC it determines the logic UUID of Shell +and uses the UUID to load matching *xsabin* file from Linux firmware +directory. The xsabin file contains metadata to discover peripherals thatare part of Shell and firmware(s) for any embedded soft processors in Shell.
Neat.
Thanks :-).
Quoted 4 lines
Documentation/fpga/xrt.rst line 70
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+ +Shell exports child interface UUID which is used for compatibility +check when loading user compiledNit: The Shell
Sure.
Quoted 5 lines
Documentation/fpga/xrt.rst line 74
Quoted 4 lines
Documentation/fpga/xrt.rst new file +4
-0+xclbin over the User partition as part of DFX. When a user requests +loading of a specific xclbin the xmgmt management driver reads the +parent interface UUID specified in the xclbin and matches it with +child interface UUID exported by Shell to determine if xclbin is compatiblewith the Shell. If match fails loading of xclbin is denied.
Quoted 9 lines
Documentation/fpga/xrt.rst
Quoted 8 lines
Documentation/fpga/xrt.rst new file +8
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctl command. +When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents +2. Isolate the User partition +3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Quoted 1 line
Alveo drivers as written today do not use fpga bridge and region framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
I'm not 100% sure I understand the concern here, let me reply to what I think I understand:
You're worried that if you use FPGA region as interface to accept PR requests something else could attempt to reconfigure the region from within the kernel using the FPGA Region API?
Assuming I got this right, I don't think this is a big deal. When you create the regions you control who gets the references to it.
From what I've seen so far Regions seem to be roughly equivalent to Partitions, hence my surprise to see a new structure bypassing them.
Quoted 113 lines
Or maybe we have missed some points about the use case for this framework?
Quoted 97 lines
Quoted 5 lines
Documentation/fpga/xrt.rst new file +4
-0+5. Program the clocks (ClockWiz) driving the User partition 6. Wait +for memory controller (MIG) calibration + +`Platform Loading OverviewDocumentation/fpga/xrt.rst line 96
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+<https://xilinx.github.io/XRT/master/html/platforms_partitions.html>` +_ provides more detailed information on platform loading. + +xsabin +------ + +Each Alveo platform comes packaged with its own xsabin. The xsabin is +trusted component of the platform. For format details refer to +:ref:`xsabin/xclbin Container Format`. xsabin contains basic +information like UUIDs, platform name and metadata in the form ofdevice tree. See :ref:
Device Tree Usagefor details and example.Documentation/fpga/xrt.rst
Quoted 9 lines
Documentation/fpga/xrt.rst new file +9
-0+ +xclbin +------ + +xclbin is compiled by end user using +`Vitis +<https://www.xilinx.com/products/design-tools/vitis/vitis-platform.ht +ml>`_ tool set from Xilinx. The xclbin contains sections describing +user compiled acceleration engines/kernels, memory subsystems,clocking information etc. It also contains bitstream for the user partition, UUIDs, platform name, etc. xclbin uses the same container format as xsabin which is described below.
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ + +xsabin/xclbin Container Format +------------------------------ + +xclbin/xsabin is ELF-like binary container format. It is structured as seriesof sections.
Documentation/fpga/xrt.rst line 112
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+There is a file header followed by several section headers which isfollowed by sections.
Documentation/fpga/xrt.rst line 113
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+A section header points to an actual section. There is an optional signatureat the end.
Quoted 42 lines
Documentation/fpga/xrt.rst new file +42
-0+The format is defined by header file ``xclbin.h``. The following +figure illustrates a typical xclbin:: + + + +---------------------+ + | | + | HEADER | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION HEADER | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | ... | + | | + +---------------------+ + | SECTION | + | | + +---------------------+ + | SIGNATURE | + | (OPTIONAL) | + +---------------------+ + + +xclbin/xsabin files can be packaged, un-packaged and inspected using +XRT utility called **xclbinutil**. xclbinutil is part of XRT open +source software stack. The source code for xclbinutil can be found at +https://github.com/Xilinx/XRT/tree/master/src/runtime_src/tools/xclbi +nutil + +For example to enumerate the contents of a xclbin/xsabin use the +*--info* switch as shown +below:: + + xclbinutil --info --inputDocumentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ /opt/xilinx/firmware/u50/gen3x16-xdma/blp/test/bandwidth.xclbin + xclbinutil --info --input + /lib/firmware/xilinx/862c7020a250293e32036f19956669e5/partition.xsab + in + + +Device Tree Usage +----------------- + +As mentioned previously xsabin stores metadata which advertise HWsubsystems present in a partition.
Documentation/fpga/xrt.rst line 168
Quoted 3 lines
Documentation/fpga/xrt.rst new file +3
-0+The metadata is stored in device tree format with well defined +schema. Subsystem instantiations are captured as children of +``addressable_endpoints`` node. Subsystem nodes have standardattributes like ``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes:
Quoted 12 lines
Documentation/fpga/xrt.rst line 176
Quoted 8 lines
Documentation/fpga/xrt.rst new file +8
-0+``pcie_physical_function`` and ``pcie_bar_mapping``. These identify +which PCIe physical function and which BAR space in that physical +function the subsystem resides. XRT management driver uses this +information to bind *platform drivers* to the subsystem +instantiations. The platform drivers are found in **xrt-lib.ko** +kernel module defined later. Below is an example of device tree for +Alveo U50 +platform::I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
Quoted 1 line
Alveo driver does not generate the metadata. The metadata is formatted and generated by HW tools when the Alveo HW platform is built.
Sure, but you control the tools that generate the metadata :) Your userland can structure / process it however it wants / needs?
Quoted 464 lines
Quoted 3 lines
What are the regs relative to?
Regs indicates offset of the register on the PCIE BAR of the Alveo device.
Quoted 327 lines
Quoted 14 lines
Documentation/fpga/xrt.rst new file +14
-0+ + /dts-v1/; + + /{ + logic_uuid = "f465b0a3ae8c64f619bc150384ace69b"; + + schema_version { + major = <0x01>; + minor = <0x00>; + }; + + interfaces { + + @0 {Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ interface_uuid = "862c7020a250293e32036f19956669e5"; + }; + }; + + addressable_endpoints { + + ep_blp_rom_00 { + reg = <0x00 0x1f04000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl";
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ }; + + ep_card_flash_program_00 { + reg = <0x00 0x1f06000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_quad_spi-1.0\0axi_quad_spi";
Quoted 49 lines
Documentation/fpga/xrt.rst new file +49
-0+ interrupts = <0x03 0x03>; + }; + + ep_cmc_firmware_mem_00 { + reg = <0x00 0x1e20000 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "cmc"; + firmware_branch_name = "u50"; + firmware_version_major = <0x01>; + firmware_version_minor = <0x00>; + }; + }; + + ep_cmc_intc_00 { + reg = <0x00 0x1e03000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x04 0x04>; + }; + + ep_cmc_mutex_00 { + reg = <0x00 0x1e02000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_cmc_regmap_00 { + reg = <0x00 0x1e08000 0x00 0x2000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "sc-fw"; + firmware_branch_name = "u50"; + firmware_version_major = <0x05>; + }; + }; + + ep_cmc_reset_00 { + reg = <0x00 0x1e01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ ep_ddr_mem_calib_00 { + reg = <0x00 0x63000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_debug_bscan_mgmt_00 { + reg = <0x00 0x1e90000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-debug_bridge-1.0\0debug_bridge";
Documentation/fpga/xrt.rst
Quoted 12 lines
Documentation/fpga/xrt.rst new file +12
-0+ }; + + ep_ert_base_address_00 { + reg = <0x00 0x21000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_command_queue_mgmt_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue";
Documentation/fpga/xrt.rst
Quoted 6 lines
Documentation/fpga/xrt.rst new file +6
-0+ }; + + ep_ert_command_queue_user_00 { + reg = <0x00 0x40000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_command_queue-1.0\0ert_command_queue";
Quoted 81 lines
Documentation/fpga/xrt.rst new file +81
-0+ }; + + ep_ert_firmware_mem_00 { + reg = <0x00 0x30000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = + "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl"; + + firmware { + firmware_product_name = "ert"; + firmware_branch_name = "v20"; + firmware_version_major = <0x01>; + }; + }; + + ep_ert_intc_00 { + reg = <0x00 0x23000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_intc-1.0\0axi_intc"; + interrupts = <0x05 0x05>; + }; + + ep_ert_reset_00 { + reg = <0x00 0x22000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_ert_sched_00 { + reg = <0x00 0x50000 0x00 0x1000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-ert_sched-1.0\0ert_sched"; + interrupts = <0x09 0x0c>; + }; + + ep_fpga_configuration_00 { + reg = <0x00 0x1e88000 0x00 0x8000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_hwicap-1.0\0axi_hwicap"; + interrupts = <0x02 0x02>; + }; + + ep_icap_reset_00 { + reg = <0x00 0x1f07000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_mailbox_mgmt_00 { + reg = <0x00 0x1f10000 0x00 0x10000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x00 0x00>; + }; + + ep_mailbox_user_00 { + reg = <0x00 0x1f00000 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-mailbox-1.0\0mailbox"; + interrupts = <0x08 0x08>; + }; + + ep_msix_00 { + reg = <0x00 0x00 0x00 0x20000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-msix-1.0\0msix"; + pcie_bar_mapping = <0x02>; + }; + + ep_pcie_link_mon_00 { + reg = <0x00 0x1f05000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_pr_isolate_plp_00 { + reg = <0x00 0x1f01000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ ep_pr_isolate_ulp_00 { + reg = <0x00 0x1000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_gpio-1.0\0axi_gpio"; + }; + + ep_uuid_rom_00 { + reg = <0x00 0x64000 0x00 0x1000>; + pcie_physical_function = <0x00>; + compatible = "xilinx.com,reg_abs-axi_bram_ctrl-1.0\0axi_bram_ctrl";
Quoted 13 lines
Documentation/fpga/xrt.rst new file +13
-0+ }; + + ep_xdma_00 { + reg = <0x00 0x00 0x00 0x10000>; + pcie_physical_function = <0x01>; + compatible = "xilinx.com,reg_abs-xdma-1.0\0xdma"; + pcie_bar_mapping = <0x02>; + }; + }; + + } + +Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +Deployment Models +================= + +Baremetal +--------- + +In bare-metal deployments both MPF and UPF are visible and +accessible. xmgmt driver binds to MPF. xmgmt driver operations are +privileged and available to system administrator. The full stack isillustrated below::
Quoted 24 lines
Documentation/fpga/xrt.rst new file +24
-0+ + + HOST + + [XMGMT] [XUSER] + | | + | | + +-----+ +-----+ + | MPF | | UPF | + | | | | + | PF0 | | PF1 | + +--+--+ +--+--+ + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | |Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ | | + +------------------------+ + + + +Virtualized +----------- + +In virtualized deployments privileged MPF is assigned to host but +unprivileged UPF is assigned to guest VM via PCIe pass-through. xmgmtdriver in host binds to MPF.
Documentation/fpga/xrt.rst line 432
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+xmgmt driver operations are privileged and only accessible by hostingservice provider.
Quoted 40 lines
Documentation/fpga/xrt.rst new file +40
-0+The full stack is illustrated below:: + + + ............. + HOST . VM . + . . + [XMGMT] . [XUSER] . + | . | . + | . | . + +-----+ . +-----+ . + | MPF | . | UPF | . + | | . | | . + | PF0 | . | PF1 | . + +--+--+ . +--+--+ . + ......... ^................. ^.......... + | | + | PCIe DEVICE | + | | + +--+------------------+--+ + | SHELL | + | | + +------------------------+ + | USER | + | | + | | + | | + | | + +------------------------+ + + + +Driver Modules +============== + +xrt-lib.ko +---------- + +Repository of all subsystem drivers and pure software modules that +can potentially be shared between xmgmt and xuser. All these drivers +are structured as Linux *platform driver* and are instantiated byDocumentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+xmgmt (or xuser in future) based on meta data associated with +hardware. The metadata is in the form of device tree as explained before. + +xmgmt.ko +-------- + +The xmgmt driver is a PCIe device driver driving MPF found on +Xilinx's Alveo PCIE device. It consists of one *root* driver, one or +more *partition* drivers and one or more *leaf* drivers. The root and +MPF specific leaf drivers are in xmgmt.ko. The partition driver and otherleaf drivers are in xrt-lib.ko.
Documentation/fpga/xrt.rst line 492
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ +The instantiation of specific partition driver or leaf driver is +completely data driven based on meta data (mostly in device tree +format) found through VSEC capability and inside firmware files, such +as xsabin or xclbin file. The root driver manages life cycle of +multiple partition drivers, which, in turn, manages multiple leaf +drivers. This allows a single set of driver code to support all kinds +of subsystems exposed by different shells. The difference among all +these subsystems will be handled in leaf drivers with root and +partition drivers being part of the infrastructure and provide commonservices for all leaves found on all platforms.
Quoted 8 lines
Documentation/fpga/xrt.rst
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+ + +xmgmt-root +^^^^^^^^^^ + +The xmgmt-root driver is a PCIe device driver attaches to MPF. It's +part of theNit: s/attaches/attached ?
Yes, sure.
Quoted 120 lines
Quoted 7 lines
Documentation/fpga/xrt.rst new file +7
-0+infrastructure of the MPF driver and resides in xmgmt.ko. This driver + +* manages one or more partition drivers +* provides access to functionalities that requires pci_dev, such as +PCIE config + space access, to other leaf drivers through parent calls +* together with partition driver, facilities event callbacks forDocumentation/fpga/xrt.rst line 516
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+other leaf drivers +* together with partition driver, facilities inter-leaf driver calls +for other leaf + drivers + +When root driver starts, it will explicitly create an initial +partition instance, which contains leaf drivers that will trigger the +creation of other partition instances. The root driver will wait for +all partitions and leaves to be created before it returns from it's +probe routine and claim success of the initialization of the entire xmgmtdriver.
Quoted 25 lines
Documentation/fpga/xrt.rst new file +25
-0+ +partition +^^^^^^^^^ + +The partition driver is a platform device driver whose life cycle is +managed by root and does not have real IO mem or IRQ resources. It's +part of the infrastructure of the MPF driver and resides in +xrt-lib.ko. This driver + +* manages one or more leaf drivers so that multiple leaves can be +managed as a group +* provides access to root from leaves, so that parent calls, event +notifications + and inter-leaf calls can happen + +In xmgmt, an initial partition driver instance will be created by +root, which contains leaves that will trigger partition instances to +be created to manage groups of leaves found on different partitions +on hardware, such as VSEC, Shell, and User. + +leaves +^^^^^^ + +The leaf driver is a platform device driver whose life cycle is +managed by a partition driver and may or may not have real IO mem orDocumentation/fpga/xrt.rst line 551
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+IRQ resources. They are the real meat of xmgmt and contains platform +specific code to Shell and User found on a MPF. + +A leaf driver may not have real hardware resources when it merely +acts as a driver that manages certain in-memory states for xmgmt. +These in-memory states could be shared by multiple other leaves. + +Leaf drivers assigned to specific hardware resources drive specific +subsystem in the device. To manipulate the subsystem or carry out a +task, a leaf driver may ask help from root via parent calls and/or fromother leaves via inter-leaf calls.
Documentation/fpga/xrt.rst line 555
Quoted 4 lines
Documentation/fpga/xrt.rst new file +4
-0+ +A leaf can also broadcast events through infrastructure code for +other leaves to process. It can also receive event notification from +infrastructure about certain events, such as post-creation or pre-exit of aparticular leaf.
Documentation/fpga/xrt.rst
Quoted 9 lines
Documentation/fpga/xrt.rst new file +9
-0+ + +Driver Interfaces +================= + +xmgmt Driver Ioctls +------------------- + +Ioctls exposed by xmgmt driver to user space are enumerated in thefollowing table:
Documentation/fpga/xrt.rst line 566
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+ +== ===================== ========================================================
Documentation/fpga/xrt.rst line 568
Quoted 2 lines
Documentation/fpga/xrt.rst new file +2
-0+# Functionality ioctl request code data format +== ===================== ========================================================
Documentation/fpga/xrt.rst line 569
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+1 FPGA image download XMGMT_IOCICAPDOWNLOAD_AXLF
xmgmt_ioc_bitstream_axlfDocumentation/fpga/xrt.rst line 570
Quoted 1 line
Documentation/fpga/xrt.rst new file +1
-0+2 CL frequency scaling XMGMT_IOCFREQSCALE
xmgmt_ioc_freqscalingQuoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+== ===================== ============================= +=========================== + +xmgmt Driver Sysfs +------------------ + +xmgmt driver exposes a rich set of sysfs interfaces. Subsystem +platform drivers export sysfs node for every platform instance. + +Every partition also exports its UUIDs. See below for examples::Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/interface_uuids + /sys/bus/pci/devices/0000:06:00.0/xmgmt_main.0/logic_uuids + + +hwmon +----- + +xmgmt driver exposes standard hwmon interface to report voltage, +current, temperature, power, etc. These can easily be viewed using*sensors* command line utility.
Documentation/fpga/xrt.rst
Quoted 10 lines
Documentation/fpga/xrt.rst new file +10
-0+ + +mailbox +------- + +xmgmt communicates with user physical function driver via HW mailbox. +Mailbox opcodes are defined in ``mailbox_proto.h``. `Mailbox +Inter-domain Communication Protocol +<https://xilinx.github.io/XRT/master/html/mailbox.proto.html>`_ +defines the full specification. xmgmt implements subset of thespecification. It provides the following services to the UPF driver:
Quoted 2 lines
+
+1. Responding to *are you there* request including determining if thetwo drivers are
Quoted 2 lines
+ running in the same OS domain
+2. Provide sensor readings, loaded xclbin UUID, clock frequency, shellinformation, etc.
Quoted 2 lines
+3. Perform PCIe hot reset
+4. Download user compiled xclbin
Quoted 23 lines
Quoted 1 line
Is this gonna use the mailbox framework?
The xclbin can be downloaded via IOCTL interface of xmgmt driver. Or the download request can come from user pf driver via mailbox, yes.
Thanks,
MaxQuoted 15 lines
Quoted 11 lines
Documentation/fpga/xrt.rst new file +8
-1+ + +Platform Security Considerations +================================ + +`Security of Alveo Platform +<https://xilinx.github.io/XRT/master/html/security.html>`_ +discusses the deployment options and security implications in great detail. --2.17.1
That's a lot of text, I'll have to read it again most likely,
- Moritz
Thanks,
Moritz
RE: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Hi Moritz,
Please see my reply below.
Thanks,
-Max
Quoted 48 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Wednesday, December 2, 2020 15:10
To: Max Zhen <[email protected]>
Cc: Moritz Fischer <[email protected]>; Sonal Santan <[email protected]>; [email protected]; [email protected]; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT driversHi Max,
Quoted 33 lines · Max Zhen
Hi Moritz,
Thanks for your feedback. Please see my reply inline.
Thanks,
-MaxQuoted 26 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Monday, November 30, 2020 20:55
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT driversQuoted 9 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Describe Alveo XRT driver architecture and provide basic overview of Xilinx Alveo platform.
Signed-off-by Sonal Santan <[email protected]>--- Documentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588+++++++++++++++++++++++++++++++++++
Quoted 3 lines
2 files changed, 589 insertions(+) create mode 100644
Documentation/fpga/xrt.rst
[...cut...]
Quoted 25 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+xclbin over the User partition as part of DFX. When a user +requests loading of a specific xclbin the xmgmt management +driver reads the parent interface UUID specified in the xclbin +and matches it with child interface UUID exported by Shell to +determine if xclbin is compatiblewith the Shell. If match fails loading of xclbin is denied.
Review
Quoted 2 lines
(quoted diff) +2
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctlcommand.
Quoted 8 lines
Quoted 6 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents 2. Isolate the User +partition 3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Alveo drivers as written today do not use fpga bridge and region
framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
I'm not 100% sure I understand the concern here, let me reply to what I think I understand:
Quoted 6 lines
You're worried that if you use FPGA region as interface to accept PR requests something else could attempt to reconfigure the region from within the kernel using the FPGA Region API?
Assuming I got this right, I don't think this is a big deal. When you create the regions you control who gets the references to it.
Thanks for explaining. Yes, I think you got my point :-).
Quoted 3 lines
From what I've seen so far Regions seem to be roughly equivalent to Partitions, hence my surprise to see a new structure bypassing them.
I see where the gap is.
Regions in Linux is very different than "partitions" we have defined in xmgmt. Regions seem to be a software data structure representing an area on the FPGA that can be reprogrammed. This area is protected by the concept of "bridge" which can be disabled before program and reenabled after it. And you go through region when you need to reprogram this area.
The "partition" is part of the main infrastructure of xmgmt driver, which represents a group of subdev drivers for each individual IP (HW subcomponents). Basically, xmgmt root driver is parent of several partitions who is, in turn, the parent of several subdev drivers. The parent manages the life cycle of its children here.
We do have a partition to represent the group of subdevs/IPs in the reprogrammable area. And we also have partitions representing other areas which cannot be reprogrammed. So, it is difficult to use "Region" to implement "partition".
From what you have explained, it seems that even if I use region / bridge in xmgmt, we can still keep it private to xmgmt instead of exposing the interface to outside world, which we can't support anyway? This means that region will be used as an internal data structure for xmgmt. Since we can't simply replace partition with region, we might as well just use partition throughout the driver, instead of introducing two data structures and use them both in different places.
However, if using region/bridge can bring in other benefits, please let us know and we could see if we can also add this to xmgmt.
Quoted 4 lines
Quoted 2 lines
Or maybe we have missed some points about the use case for this
framework?
Quoted 1 line
[...cut...]
Quoted 23 lines
Quoted 23 lines
Quoted 22 lines
Review
Quoted 4 lines
+-----------------
(quoted diff) +3
-0+ +As mentioned previously xsabin stores metadata which advertise +HWsubsystems present in a partition.
Review
Quoted 3 lines
(quoted diff) +3
-0+The metadata is stored in device tree format with well defined +schema. Subsystem instantiations are captured as children of +``addressable_endpoints`` node. Subsystem nodes have standardattributes like ``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes:
Review
Quoted 8 lines
+``pcie_physical_function`` and ``pcie_bar_mapping``. These
(quoted diff) +7
-0+identify which PCIe physical function and which BAR space in +that physical function the subsystem resides. XRT management +driver uses this information to bind *platform drivers* to the +subsystem instantiations. The platform drivers are found in +**xrt-lib.ko** kernel module defined later. Below is an example +of device tree for Alveo U50 +platform::I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
Quoted 6 lines
Quoted 2 lines
Alveo driver does not generate the metadata. The metadata is formatted
and generated by HW tools when the Alveo HW platform is built.
Sure, but you control the tools that generate the metadata :) Your userland can structure / process it however it wants / needs?
XRT is a runtime software stack, it is not responsible for generating HW metadata. It is one of the consumers of these data. The shell design is generated by a sophisticated tool framework which is difficult to change.
However, we will take this as a feedback for future revision of the tool.
Thanks,
Max
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Max,
Quoted 27 lines · Max Zhen
[...cut...]
Quoted 25 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+xclbin over the User partition as part of DFX. When a user +requests loading of a specific xclbin the xmgmt management +driver reads the parent interface UUID specified in the xclbin +and matches it with child interface UUID exported by Shell to +determine if xclbin is compatiblewith the Shell. If match fails loading of xclbin is denied.
Review
Quoted 2 lines
(quoted diff) +2
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctlcommand.
Quoted 8 lines
Quoted 6 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents 2. Isolate the User +partition 3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Alveo drivers as written today do not use fpga bridge and region
framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
I'm not 100% sure I understand the concern here, let me reply to what I think I understand:
Quoted 8 lines
Quoted 6 lines
You're worried that if you use FPGA region as interface to accept PR requests something else could attempt to reconfigure the region from within the kernel using the FPGA Region API?
Assuming I got this right, I don't think this is a big deal. When you create the regions you control who gets the references to it.
Thanks for explaining. Yes, I think you got my point :-).
We can add code to make a region 'static' or 'one-time' or 'fixed'.
Quoted 8 lines
Quoted 4 lines
From what I've seen so far Regions seem to be roughly equivalent to Partitions, hence my surprise to see a new structure bypassing them.
I see where the gap is.
Regions in Linux is very different than "partitions" we have defined in xmgmt. Regions seem to be a software data structure representing an area on the FPGA that can be reprogrammed. This area is protected by the concept of "bridge" which can be disabled before program and reenabled after it. And you go through region when you need to reprogram this area.
Your central management driver can create / destroy regions at will. It can keep them in a list, array or tree.
Regions can but don't have to have bridges.
If you need to go through the central driver to reprogram a region, you can use that to figure out which region to program.
Quoted 2 lines
The "partition" is part of the main infrastructure of xmgmt driver, which represents a group of subdev drivers for each individual IP (HW subcomponents). Basically, xmgmt root driver is parent of several partitions who is, in turn, the parent of several subdev drivers. The parent manages the life cycle of its children here.
I don't see how this is conceptually different from what DFL does, and they managed to use Regions and Bridges.
If things are missing in the framework, please add them instead of rewriting an entire parallel framework.
Quoted 2 lines
We do have a partition to represent the group of subdevs/IPs in the reprogrammable area. And we also have partitions representing other areas which cannot be reprogrammed. So, it is difficult to use "Region" to implement "partition".
You implement your regions callbacks, you can return -EINVAL / -ENOTTY if you want to fail a reprogramming request to a static partion / region.
Quoted 1 line
From what you have explained, it seems that even if I use region / bridge in xmgmt, we can still keep it private to xmgmt instead of exposing the interface to outside world, which we can't support anyway? This means that region will be used as an internal data structure for xmgmt. Since we can't simply replace partition with region, we might as well just use partition throughout the driver, instead of introducing two data structures and use them both in different places.
Think about your partition as an extension to a region that implements what you need to do for your case of enumerating and reprogramming that particular piece of your chip.
Quoted 1 line
However, if using region/bridge can bring in other benefits, please let us know and we could see if we can also add this to xmgmt.
As maintainer I can say it brings the benefit of looking like existing infrastructure we have. We can add features to the framework as needed but blanket replacing the entire thing is always a hard sell.
Quoted 31 lines
Quoted 5 lines
Quoted 3 lines
Or maybe we have missed some points about the use case for this
framework?
Quoted 1 line
[...cut...]
Quoted 23 lines
Quoted 23 lines
Quoted 22 lines
Review
Quoted 4 lines
+-----------------
(quoted diff) +3
-0+ +As mentioned previously xsabin stores metadata which advertise +HWsubsystems present in a partition.
Review
Quoted 3 lines
(quoted diff) +3
-0+The metadata is stored in device tree format with well defined +schema. Subsystem instantiations are captured as children of +``addressable_endpoints`` node. Subsystem nodes have standardattributes like ``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes:
Review
Quoted 8 lines
+``pcie_physical_function`` and ``pcie_bar_mapping``. These
(quoted diff) +7
-0+identify which PCIe physical function and which BAR space in +that physical function the subsystem resides. XRT management +driver uses this information to bind *platform drivers* to the +subsystem instantiations. The platform drivers are found in +**xrt-lib.ko** kernel module defined later. Below is an example +of device tree for Alveo U50 +platform::I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Alveo driver does not generate the metadata. The metadata is formatted
and generated by HW tools when the Alveo HW platform is built.
Sure, but you control the tools that generate the metadata :) Your userland can structure / process it however it wants / needs?
XRT is a runtime software stack, it is not responsible for generating HW metadata. It is one of the consumers of these data. The shell design is generated by a sophisticated tool framework which is difficult to change.
The Kernel userspace ABI is not going to change once it is merged, which is why we need to get it right. You can change your userspace code long time after it is merged into the kernel. The otherway round does not work.
If you're going to do device-tree you'll need device-tree maintainers to be ok with your bindings.
Quoted 4 lines
However, we will take this as a feedback for future revision of the tool.
Thanks,
Max
Btw: Can you fix your line-breaks :)
- Moritz
RE: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Hi Moritz,
I manually fixed some line breaks. Not sure why outlook is not doing it properly. Let me know if it still looks bad to you.
Please see my reply below.
Quoted 51 lines
Max,
Quoted 25 lines · Max Zhen
[...cut...]
Quoted 23 lines
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+xclbin over the User partition as part of DFX. When a user +requests loading of a specific xclbin the xmgmt management +driver reads the parent interface UUID specified in the xclbin +and matches it with child interface UUID exported by Shell to +determine if xclbin is compatible with the Shell. If match fails loading of xclbin is denied.Quoted 8 lines
Review
Quoted 7 lines
(quoted diff) +7
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctl command. +When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents 2. Isolate the User +partition 3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Quoted 5 lines
Alveo drivers as written today do not use fpga bridge and region framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
I'm not 100% sure I understand the concern here, let me reply to what I think I understand:
Quoted 8 lines
Quoted 6 lines
You're worried that if you use FPGA region as interface to accept PR requests something else could attempt to reconfigure the region from within the kernel using the FPGA Region API?
Assuming I got this right, I don't think this is a big deal. When you create the regions you control who gets the references to it.
Thanks for explaining. Yes, I think you got my point :-).
We can add code to make a region 'static' or 'one-time' or 'fixed'.
Quoted 10 lines
Quoted 4 lines
From what I've seen so far Regions seem to be roughly equivalent to Partitions, hence my surprise to see a new structure bypassing them.
I see where the gap is.
Regions in Linux is very different than "partitions" we have defined in xmgmt. Regions seem to be a software data structure representing an area on the FPGA that can be reprogrammed. This area is protected by the concept of "bridge" which can be disabled before program and reenabled after it. And you go through region when you need to reprogram this area.
Quoted 7 lines
Your central management driver can create / destroy regions at will. It can keep them in a list, array or tree.
Regions can but don't have to have bridges.
If you need to go through the central driver to reprogram a region, you can use that to figure out which region to program.
That sounds fine. I can create a region and call into it from xmgmt for PR programing. The region will, then, call the xmgmt's fpga manager to program it.
Quoted 19 lines
Quoted 4 lines
The "partition" is part of the main infrastructure of xmgmt driver, which represents a group of subdev drivers for each individual IP (HW subcomponents). Basically, xmgmt root driver is parent of several partitions who is, in turn, the parent of several subdev drivers. The parent manages the life cycle of its children here.
I don't see how this is conceptually different from what DFL does, and they managed to use Regions and Bridges.
If things are missing in the framework, please add them instead of rewriting an entire parallel framework.
Quoted 3 lines
We do have a partition to represent the group of subdevs/IPs in the reprogrammable area. And we also have partitions representing other areas which cannot be reprogrammed. So, it is difficult to use "Region" to implement "partition".
You implement your regions callbacks, you can return
-EINVAL/-ENOTTYif you want to fail a reprogramming request to a static partion / region.
Quoted 8 lines
Quoted 4 lines
From what you have explained, it seems that even if I use region / bridge in xmgmt, we can still keep it private to xmgmt instead of exposing the interface to outside world, which we can't support anyway? This means that region will be used as an internal data structure for xmgmt. Since we can't simply replace partition with region, we might as well just use partition throughout the driver, instead of introducing two data structures and use them both in different places.
Think about your partition as an extension to a region that implements what you need to do for your case of enumerating and reprogramming that particular piece of your chip.
Yes, we can add region / bridges to represent the PR area and use it in our code path for reprogramming the PR area. I think what we will do is to instantiate a region instance for the PR area and associate it with the FPGA manager in xmgmt for reprogramming it. We can also instantiate bridges and map the "ULP gate" subdev driver to it in xmgmt. Thus, we could incorporate region and bridge data structures in xmgmt for PR reprogramming.
This will be a non-trivial change for us. I'd like to confirm that this is what you are looking for before we start working on the change. Let us know :-).
Quoted 47 lines
Quoted 2 lines
However, if using region/bridge can bring in other benefits, please let us know and we could see if we can also add this to xmgmt.
As maintainer I can say it brings the benefit of looking like existing infrastructure we have. We can add features to the framework as needed but blanket replacing the entire thing is always a hard sell.
Quoted 35 lines
Quoted 5 lines
Quoted 5 lines
Or maybe we have missed some points about the use case for this framework?
[...cut...]
Quoted 27 lines
Quoted 26 lines
Quoted 14 lines
Quoted 14 lines
+-----------------
(quoted diff) +3
-0+ +As mentioned previously xsabin stores metadata which advertise +HWsubsystems present in a partition.
(quoted diff) +3
-0+The metadata is stored in device tree format with well defined +schema. Subsystem instantiations are captured as children of +``addressable_endpoints`` node. Subsystem nodes have standardattributes like ``reg``, ``interrupts`` etc. Additionally the nodes also have PCIe specific attributes:
+``pcie_physical_function`` and ``pcie_bar_mapping``. These(quoted diff) +3
-0+identify which PCIe physical function and which BAR space in +that physical function the subsystem resides. XRT management +driver uses this information to bind *platform drivers* to theQuoted 8 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+subsystem instantiations. The platform drivers are found in +**xrt-lib.ko** kernel module defined later. Below is an example +of device tree for Alveo U50 +platform::I might be missing something, but couldn't you structure the addressable endpoints in a way that encode the physical function as a parent / child relation?
Alveo driver does not generate the metadata. The metadata is formatted
and generated by HW tools when the Alveo HW platform is built.Quoted 5 lines
Quoted 2 lines
Sure, but you control the tools that generate the metadata :) Your userland can structure / process it however it wants / needs?
XRT is a runtime software stack, it is not responsible for generating HW metadata. It is one of the consumers of these data. The shell design is generated by a sophisticated tool framework which is difficult to change.
Quoted 8 lines
The Kernel userspace ABI is not going to change once it is merged, which is why we need to get it right. You can change your userspace code long time after it is merged into the kernel. The otherway round does not work.
If you're going to do device-tree you'll need device-tree maintainers to be ok with your bindings.
Yes, we'll wait for the device-tree maintainers to chime in here :-).
Thanks,
Max
Quoted 8 lines
Quoted 4 lines
However, we will take this as a feedback for future revision of the tool.
Thanks,
MaxBtw: Can you fix your line-breaks :)
- Moritz
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 1/8] Documentation: fpga: Add a document describing Alveo XRT drivers
Quoted 4 lines · Max Zhen
Hi Moritz,
I manually fixed some line breaks. Not sure why outlook is not doing it properly. Let me know if it still looks bad to you.
That might just be outlook :)
Quoted 57 lines
Please see my reply below.
Quoted 54 lines
Max,
Quoted 25 lines · Max Zhen
[...cut...]
Quoted 23 lines
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+xclbin over the User partition as part of DFX. When a user +requests loading of a specific xclbin the xmgmt management +driver reads the parent interface UUID specified in the xclbin +and matches it with child interface UUID exported by Shell to +determine if xclbin is compatible with the Shell. If match fails loading of xclbin is denied.Quoted 8 lines
Review
Quoted 7 lines
(quoted diff) +7
-0+ +xclbin loading is requested using ICAP_DOWNLOAD_AXLF ioctl command. +When loading xclbin xmgmt driver performs the following operations: + +1. Sanity check the xclbin contents 2. Isolate the User +partition 3. Download the bitstream using the FPGA config engine (ICAP) 4. +De-isolate the User partitionIs this modelled as bridges and regions?
Quoted 5 lines
Alveo drivers as written today do not use fpga bridge and region framework. It seems that if we add support for that framework, it’s possible to receive PR program request from kernel outside of xmgmt driver? Currently, we can’t support this and PR program can only be initiated using XRT’s runtime API in user space.
I'm not 100% sure I understand the concern here, let me reply to what I think I understand:
Quoted 8 lines
Quoted 6 lines
You're worried that if you use FPGA region as interface to accept PR requests something else could attempt to reconfigure the region from within the kernel using the FPGA Region API?
Assuming I got this right, I don't think this is a big deal. When you create the regions you control who gets the references to it.
Thanks for explaining. Yes, I think you got my point :-).
We can add code to make a region 'static' or 'one-time' or 'fixed'.
Quoted 10 lines
Quoted 4 lines
From what I've seen so far Regions seem to be roughly equivalent to Partitions, hence my surprise to see a new structure bypassing them.
I see where the gap is.
Regions in Linux is very different than "partitions" we have defined in xmgmt. Regions seem to be a software data structure representing an area on the FPGA that can be reprogrammed. This area is protected by the concept of "bridge" which can be disabled before program and reenabled after it. And you go through region when you need to reprogram this area.
Your central management driver can create / destroy regions at will. It can keep them in a list, array or tree.
Quoted 8 lines
Quoted 4 lines
Regions can but don't have to have bridges.
If you need to go through the central driver to reprogram a region, you can use that to figure out which region to program.
That sounds fine. I can create a region and call into it from xmgmt for PR programing. The region will, then, call the xmgmt's fpga manager to program it.
It sounds closer than what I'd expect.
Quoted 29 lines
Quoted 20 lines
Quoted 5 lines
The "partition" is part of the main infrastructure of xmgmt driver, which represents a group of subdev drivers for each individual IP (HW subcomponents). Basically, xmgmt root driver is parent of several partitions who is, in turn, the parent of several subdev drivers. The parent manages the life cycle of its children here.
I don't see how this is conceptually different from what DFL does, and they managed to use Regions and Bridges.
If things are missing in the framework, please add them instead of rewriting an entire parallel framework.
Quoted 3 lines
We do have a partition to represent the group of subdevs/IPs in the reprogrammable area. And we also have partitions representing other areas which cannot be reprogrammed. So, it is difficult to use "Region" to implement "partition".
You implement your regions callbacks, you can return
-EINVAL/-ENOTTYif you want to fail a reprogramming request to a static partion / region.Quoted 8 lines
Quoted 4 lines
From what you have explained, it seems that even if I use region / bridge in xmgmt, we can still keep it private to xmgmt instead of exposing the interface to outside world, which we can't support anyway? This means that region will be used as an internal data structure for xmgmt. Since we can't simply replace partition with region, we might as well just use partition throughout the driver, instead of introducing two data structures and use them both in different places.
Think about your partition as an extension to a region that implements what you need to do for your case of enumerating and reprogramming that particular piece of your chip.
Quoted 7 lines
Yes, we can add region / bridges to represent the PR area and use it in our code path for reprogramming the PR area. I think what we will do is to instantiate a region instance for the PR area and associate it with the FPGA manager in xmgmt for reprogramming it. We can also instantiate bridges and map the "ULP gate" subdev driver to it in xmgmt. Thus, we could incorporate region and bridge data structures in xmgmt for PR reprogramming.
I'd need to take another look, but the ULP gate sounds like a bridge (or close to it).
Quoted 2 lines
This will be a non-trivial change for us. I'd like to confirm that this is what you are looking for before we start working on the change. Let us know :-).
I understand. It looks like the right direction. Let's discuss code when we have code to look at.
It may take a couple of iterations to get it all sorted.
That's normal when you show show up with that much code all at once :)
Cheers,
Moritz
PATCH 2/8 fpga: xrt: Add UAPI header files
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add XRT UAPI header files which describe flash layout, XRT mailbox protocol, xclBin/axlf FPGA image container format and XRT management physical function driver ioctl interfaces.
flash_xrt_data.h:
Layout used by XRT to store private data on flash.
mailbox_proto.h:
Mailbox opcodes and high level data structures representing various kinds of information like sensors, clock, etc.
mailbox_transport.h:
Transport protocol used by mailbox.
xclbin.h:
Container format used to store compiled FPGA image which includes bitstream and metadata.
xmgmt-ioctl.h:
Ioctls defined by management physical function driver:
* XMGMT_IOCICAPDOWNLOAD_AXLF
xclbin download which programs the user partition
* XMGMT_IOCFREQSCALE
Program the clocks driving user partition
--- include/uapi/linux/xrt/flash_xrt_data.h | 67 ++++ include/uapi/linux/xrt/mailbox_proto.h | 394 +++++++++++++++++++ include/uapi/linux/xrt/mailbox_transport.h | 74 ++++ include/uapi/linux/xrt/xclbin.h | 418 +++++++++++++++++++++ include/uapi/linux/xrt/xmgmt-ioctl.h | 72 ++++ 5 files changed, 1025 insertions(+) create mode 100644 include/uapi/linux/xrt/flash_xrt_data.h create mode 100644 include/uapi/linux/xrt/mailbox_proto.h create mode 100644 include/uapi/linux/xrt/mailbox_transport.h create mode 100644 include/uapi/linux/xrt/xclbin.h create mode 100644 include/uapi/linux/xrt/xmgmt-ioctl.h
include/uapi/linux/xrt/flash_xrt_data.h new file +67 -0
@@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _FLASH_XRT_DATA_H_ +#define _FLASH_XRT_DATA_H_ + +#define XRT_DATA_MAGIC "XRTDATA" + +/* +* This header file contains data structure for xrt meta data on flash. This +* file is included in user space utilities and kernel drivers. The data +* structure is used to describe on-flash xrt data which is written by utility +* and read by driver. Any change of the data structure should either be +* backward compatible or cause version to be bumped up. +*/ + +struct flash_data_ident { +char fdi_magic[7 ]; +char fdi_version; +}; + +/* +* On-flash meta data describing XRT data on flash. Either fdh_id_begin or +* fdh_id_end should be at well-known location on flash so that the reader +* can easily pick up fdi_version from flash before it tries to interpret +* the whole data structure. +* E.g., you align header in the end of the flash so that fdh_id_end is at well +* known location or align header at the beginning of the flash so that +* fdh_id_begin is at well known location. +*/ +struct flash_data_header { +struct flash_data_ident fdh_id_begin; +uint32_t fdh_data_offset; +uint32_t fdh_data_len; +uint32_t fdh_data_parity; +uint8_t fdh_reserved[16 ]; +struct flash_data_ident fdh_id_end; +}; + +static inline uint32_t flash_xrt_data_get_parity32 (unsigned char *buf,size_t n) +{ +char *p; +size_t i; +size_t len; +uint32_t parity =0 ; + +for (len =0 ; len < n; len +=4 ) { +uint32_t tmp =0 ; +size_t thislen = n - len; + +/* One word at a time. */ +if (thislen >4 ) + thislen =4 ; + +for (i =0 , p = (char *)&tmp; i < thislen; i++) + p[i] = buf[len + i]; + parity ^= tmp; + } +return parity; +} + +#endif
include/uapi/linux/xrt/mailbox_proto.h new file +394 -0
394 lines not on this page · raw message
include/uapi/linux/xrt/mailbox_transport.h new file +74 -0
74 lines not on this page · raw message
include/uapi/linux/xrt/xclbin.h new file +418 -0
418 lines not on this page · raw message
include/uapi/linux/xrt/xmgmt-ioctl.h new file +72 -0
72 lines not on this page · raw message
Signature · 1 line
2.17.1
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 2/8] fpga: xrt: Add UAPI header files
Hi Sonal,
Quoted 13 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Add XRT UAPI header files which describe flash layout, XRT mailbox protocol, xclBin/axlf FPGA image container format and XRT management physical function driver ioctl interfaces.
flash_xrt_data.h:
Layout used by XRT to store private data on flash.
mailbox_proto.h:
Mailbox opcodes and high level data structures representing various kinds of information like sensors, clock, etc.
Quoted 6 lines
mailbox_transport.h:
Transport protocol used by mailbox.
xclbin.h:
Container format used to store compiled FPGA image which includes bitstream and metadata.
Can these headers be introduced together with the code that uses them as logical change?
I haven't looked too closely, but it helps reviewing if you can break it into smaller pieces that can stand by themselves.
Thanks,
Moritz
RE: [PATCH Xilinx Alveo 2/8] fpga: xrt: Add UAPI header files
Hi Moritz,
Quoted 33 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Monday, November 30, 2020 8:27 PM
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 2/8] fpga: xrt: Add UAPI header filesHi Sonal,
Quoted 13 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Add XRT UAPI header files which describe flash layout, XRT mailbox protocol, xclBin/axlf FPGA image container format and XRT management physical function driver ioctl interfaces.
flash_xrt_data.h:
Layout used by XRT to store private data on flash.
mailbox_proto.h:
Mailbox opcodes and high level data structures representing various kinds of information like sensors, clock, etc.Quoted 6 lines
mailbox_transport.h:
Transport protocol used by mailbox.
xclbin.h:
Container format used to store compiled FPGA image which includes bitstream and metadata.
Quoted 6 lines
Can these headers be introduced together with the code that uses them as logical change?
I haven't looked too closely, but it helps reviewing if you can break it into smaller pieces that can stand by themselves.
These UAPI header files are used by multiple source files hence I wanted to get these reviewed separately. However if this is getting in the way, in the next version of the patch series I would look into arranging the files differently.
You can browse the changes here as well--
https://github.com/Xilinx/linux-xoclv2/tree/xrtv2-A
Thanks,
-Sonal
Quoted 2 lines
Thanks,
Moritz
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 2/8] fpga: xrt: Add UAPI header files
Hi Sonal,
Quoted 42 lines · Sonal Santan
Hi Moritz,
Quoted 33 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Monday, November 30, 2020 8:27 PM
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 2/8] fpga: xrt: Add UAPI header filesHi Sonal,
Quoted 13 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Add XRT UAPI header files which describe flash layout, XRT mailbox protocol, xclBin/axlf FPGA image container format and XRT management physical function driver ioctl interfaces.
flash_xrt_data.h:
Layout used by XRT to store private data on flash.
mailbox_proto.h:
Mailbox opcodes and high level data structures representing various kinds of information like sensors, clock, etc.Quoted 6 lines
mailbox_transport.h:
Transport protocol used by mailbox.
xclbin.h:
Container format used to store compiled FPGA image which includes bitstream and metadata.Quoted 6 lines
Can these headers be introduced together with the code that uses them as logical change?
I haven't looked too closely, but it helps reviewing if you can break it into smaller pieces that can stand by themselves.
Quoted 6 lines
These UAPI header files are used by multiple source files hence I wanted to get these reviewed separately. However if this is getting in the way, in the next version of the patch series I would look into arranging the files differently.
You can browse the changes here as well--
https://github.com/Xilinx/linux-xoclv2/tree/xrtv2-A
Please submit the code in the form you want the patches to be applied, in this case submit the headers with the code that uses them, and split it up in smaller chunks please.
Submitting them as a series in the correct order should provide the proper context for reviewers.
Cheers,
Moritz
PATCH 3/8 fpga: xrt: infrastructure support for xmgmt driver
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add infrastructure code for XRT management physical function driver. This provides support for enumerating and extracting sections from xclbin files, interacting with device tree nodes found in xclbin and working with Alveo partitions.
--- drivers/fpga/alveo/common/xrt-metadata.c | 590 ++++++++++++++++++ drivers/fpga/alveo/common/xrt-root.c | 744 +++++++++++++++++++++++ drivers/fpga/alveo/common/xrt-root.h | 24 + drivers/fpga/alveo/common/xrt-xclbin.c | 387 ++++++++++++ drivers/fpga/alveo/common/xrt-xclbin.h | 46 ++ 5 files changed, 1791 insertions(+) create mode 100644 drivers/fpga/alveo/common/xrt-metadata.c create mode 100644 drivers/fpga/alveo/common/xrt-root.c create mode 100644 drivers/fpga/alveo/common/xrt-root.h create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.c create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.h
drivers/fpga/alveo/common/xrt-metadata.c new file +590 -0
@@ -0,0 +1,590 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA Metadata parse APIs +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#include <linux/libfdt_env.h> +#include "libfdt.h" +#include "xrt-metadata.h" + +#define MAX_BLOB_SIZE (4096 * 25) + +#define md_err(dev, fmt, args...) \ + dev_err(dev, "%s: "fmt, __func__, ##args) +#define md_warn(dev, fmt, args...) \ + dev_warn(dev, "%s: "fmt, __func__, ##args) +#define md_info(dev, fmt, args...) \ + dev_info(dev, "%s: "fmt, __func__, ##args) +#define md_dbg(dev, fmt, args...) \ + dev_dbg(dev, "%s: "fmt, __func__, ##args) + +static int xrt_md_setprop (struct device *dev,char *blob,int offset, +const char *prop,const void *val,int size); +static int xrt_md_overlay (struct device *dev,char *blob,int target, +const char *overlay_blob,int overlay_offset); +static int xrt_md_get_endpoint (struct device *dev,const char *blob, +const char *ep_name,const char *regmap_name,int *ep_offset); + +long xrt_md_size (struct device *dev,const char *blob) +{ +long len = (long )fdt_totalsize (blob); + +return (len >MAX_BLOB_SIZE ) ? -EINVAL : len; +} + +int xrt_md_create (struct device *dev,char **blob) +{ +int ret =0 ; + +WARN_ON (!blob); + + *blob =vmalloc (MAX_BLOB_SIZE ); +if (!*blob) +return -ENOMEM ; + + ret =fdt_create_empty_tree (*blob,MAX_BLOB_SIZE ); +if (ret) { +md_err (dev,"format blob failed, ret = %d" , ret); + goto failed; + } + + ret =fdt_next_node (*blob,-1 ,NULL ); +if (ret <0 ) { +md_err (dev,"No Node, ret = %d" , ret); + goto failed; + } + + ret =fdt_add_subnode (*blob, ret,NODE_ENDPOINTS ); +if (ret <0 ) +md_err (dev,"add node failed, ret = %d" , ret); + +failed: +if (ret <0 ) { +vfree (*blob); + *blob =NULL ; + }else + ret =0 ; + +return ret; +} + +int xrt_md_add_node (struct device *dev,char *blob,int parent_offset, +const char *ep_name) +{ +int ret; + + ret =fdt_add_subnode (blob, parent_offset, ep_name); +if (ret <0 && ret != -FDT_ERR_EXISTS ) +md_err (dev,"failed to add node %s. %d" , ep_name, ret); + +return ret; +} + +int xrt_md_del_endpoint (struct device *dev,char *blob,const char *ep_name, +char *regmap_name) +{ +int ret; +int ep_offset; + + ret =xrt_md_get_endpoint (dev, blob, ep_name, regmap_name, &ep_offset); +if (ret) { +md_err (dev,"can not find ep %s" , ep_name); +return -EINVAL ; + } + + ret =fdt_del_node (blob, ep_offset); +if (ret) +md_err (dev,"delete node %s failed, ret %d" , ep_name, ret); + +return ret; +} + +static int __xrt_md_add_endpoint (struct device *dev,char *blob, +struct xrt_md_endpoint *ep,int *offset,bool root) +{ +int ret =0 ; +int ep_offset; +u32 val, count =0 ; +u64 io_range[2 ]; +char comp[128 ]; + +if (!ep->ep_name) { +md_err (dev,"empty name" ); +return -EINVAL ; + } + +if (!root) { + ret =xrt_md_get_endpoint (dev, blob,NODE_ENDPOINTS ,NULL , + &ep_offset); +if (ret) { +md_err (dev,"invalid blob, ret = %d" , ret); +return -EINVAL ; + } + }else { + ep_offset =0 ; + } + + ep_offset =xrt_md_add_node (dev, blob, ep_offset, ep->ep_name); +if (ep_offset <0 ) { +md_err (dev,"add endpoint failed, ret = %d" , ret); +return -EINVAL ; + } +if (offset) + *offset = ep_offset; + +if (ep->size !=0 ) { + val =cpu_to_be32 (ep->bar); + ret =xrt_md_setprop (dev, blob, ep_offset,PROP_BAR_IDX , + &val,sizeof (u32)); +if (ret) { +md_err (dev,"set %s failed, ret %d" , +PROP_BAR_IDX , ret); + goto failed; + } + io_range[0 ] =cpu_to_be64 ((u64 )ep->bar_off); + io_range[1 ] =cpu_to_be64 ((u64 )ep->size); + ret =xrt_md_setprop (dev, blob, ep_offset,PROP_IO_OFFSET , + io_range,sizeof (io_range)); +if (ret) { +md_err (dev,"set %s failed, ret %d" , +PROP_IO_OFFSET , ret); + goto failed; + } + } + +if (ep->regmap) { +if (ep->regmap_ver) { + count =snprintf (comp,sizeof (comp), +"%s-%s" , ep->regmap, ep->regmap_ver); + count++; + } + + count +=snprintf (comp + count,sizeof (comp) - count, +"%s" , ep->regmap); + count++; + + ret =xrt_md_setprop (dev, blob, ep_offset,PROP_COMPATIBLE , + comp, count); +if (ret) { +md_err (dev,"set %s failed, ret %d" , +PROP_COMPATIBLE , ret); + goto failed; + } + } + +failed: +if (ret) +xrt_md_del_endpoint (dev, blob, ep->ep_name,NULL ); + +return ret; +} + +int xrt_md_add_endpoint (struct device *dev,char *blob, +struct xrt_md_endpoint *ep) +{ +return __xrt_md_add_endpoint (dev, blob, ep,NULL , false); +} + +static int xrt_md_get_endpoint (struct device *dev,const char *blob, +const char *ep_name,const char *regmap_name,int *ep_offset) +{ +int offset; +const char *name; + +for (offset =fdt_next_node (blob,-1 ,NULL ); + offset >=0 ; + offset =fdt_next_node (blob, offset,NULL )) { + name =fdt_get_name (blob, offset,NULL ); +if (!name ||strncmp (name, ep_name,strlen (ep_name) +1 )) +continue ; +if (!regmap_name || + !fdt_node_check_compatible (blob, offset, regmap_name)) +break ; + } +if (offset <0 ) +return -ENODEV ; + + *ep_offset = offset; + +return 0 ; +} + +int xrt_md_get_epname_pointer (struct device *dev,const char *blob, +const char *ep_name,const char *regmap_name,const char **epname) +{ +int offset; +int ret; + + ret =xrt_md_get_endpoint (dev, blob, ep_name, regmap_name, + &offset); +if (!ret && epname && offset >=0 ) + *epname =fdt_get_name (blob, offset,NULL ); + +return ret; +} + +int xrt_md_get_prop (struct device *dev,const char *blob,const char *ep_name, +const char *regmap_name,const char *prop,const void **val,int *size) +{ +int offset; +int ret; + +if (val) + *val =NULL ; +if (ep_name) { + ret =xrt_md_get_endpoint (dev, blob, ep_name, regmap_name, + &offset); +if (ret) { +md_err (dev,"cannot get ep %s, regmap %s, ret = %d" , + ep_name, regmap_name, ret); +return -EINVAL ; + } + }else { + offset =fdt_next_node (blob,-1 ,NULL ); +if (offset <0 ) { +md_err (dev,"internal error, ret = %d" , offset); +return -EINVAL ; + } + } + +if (val) { + *val =fdt_getprop (blob, offset, prop, size); +if (!*val) { +md_dbg (dev,"get ep %s, prop %s failed" , ep_name, prop); +return -EINVAL ; + } + } + +return 0 ; +} + +static int xrt_md_setprop (struct device *dev,char *blob,int offset, +const char *prop,const void *val,int size) +{ +int ret; + + ret =fdt_setprop (blob, offset, prop, val, size); +if (ret) +md_err (dev,"failed to set prop %d" , ret); + +return ret; +} + +int xrt_md_set_prop (struct device *dev,char *blob, +const char *ep_name,const char *regmap_name, +const char *prop,const void *val,int size) +{ +int offset; +int ret; + +if (ep_name) { + ret =xrt_md_get_endpoint (dev, blob, ep_name, + regmap_name, &offset); +if (ret) { +md_err (dev,"cannot get node %s, ret = %d" , + ep_name, ret); +return -EINVAL ; + } + }else { + offset =fdt_next_node (blob,-1 ,NULL ); +if (offset <0 ) { +md_err (dev,"internal error, ret = %d" , offset); +return -EINVAL ; + } + } + + ret =xrt_md_setprop (dev, blob, offset, prop, val, size); +if (ret) +md_err (dev,"set prop %s failed, ret = %d" , prop, ret); + +return ret; +} + +int xrt_md_copy_endpoint (struct device *dev,char *blob,const char *src_blob, +const char *ep_name,const char *regmap_name,const char *new_ep_name) +{ +int offset, target; +int ret; +struct xrt_md_endpoint ep = {0 }; +const char *newepnm = new_ep_name ? new_ep_name : ep_name; + + ret =xrt_md_get_endpoint (dev, src_blob, ep_name, regmap_name, + &offset); +if (ret) +return -EINVAL ; + + ret =xrt_md_get_endpoint (dev, blob, newepnm, regmap_name, &target); +if (ret) { + ep.ep_name = newepnm; + ret =__xrt_md_add_endpoint (dev, blob, &ep, &target, +fdt_parent_offset (src_blob, offset) ==0 ); +if (ret) +return -EINVAL ; + } + + ret =xrt_md_overlay (dev, blob, target, src_blob, offset); +if (ret) +md_err (dev,"overlay failed, ret = %d" , ret); + +return ret; +} + +int xrt_md_copy_all_eps (struct device *dev,char *blob,const char *src_blob) +{ +return xrt_md_copy_endpoint (dev, blob, src_blob,NODE_ENDPOINTS , +NULL ,NULL ); +} + +char *xrt_md_dup (struct device *dev,const char *blob) +{ +int ret; +char *dup_blob; + + ret =xrt_md_create (dev, &dup_blob); +if (ret) +return NULL ; + ret =xrt_md_overlay (dev, dup_blob,-1 , blob,-1 ); +if (ret) { +vfree (dup_blob); +return NULL ; + } + +return dup_blob; +} + +static int xrt_md_overlay (struct device *dev,char *blob,int target, +const char *overlay_blob,int overlay_offset) +{ +int property, subnode; +int ret; + +WARN_ON (!blob || !overlay_blob); + +if (!blob) { +md_err (dev,"blob is NULL" ); +return -EINVAL ; + } + +if (target <0 ) { + target =fdt_next_node (blob,-1 ,NULL ); +if (target <0 ) { +md_err (dev,"invalid target" ); +return -EINVAL ; + } + } +if (overlay_offset <0 ) { + overlay_offset =fdt_next_node (overlay_blob,-1 ,NULL ); +if (overlay_offset <0 ) { +md_err (dev,"invalid overlay" ); +return -EINVAL ; + } + } + +fdt_for_each_property_offset (property, overlay_blob, overlay_offset) { +const char *name; +const void *prop; +int prop_len; + + prop =fdt_getprop_by_offset (overlay_blob, property, &name, + &prop_len); +if (!prop || prop_len >=MAX_BLOB_SIZE ) { +md_err (dev,"internal error" ); +return -EINVAL ; + } + + ret =xrt_md_setprop (dev, blob, target, name, prop, + prop_len); +if (ret) { +md_err (dev,"setprop failed, ret = %d" , ret); +return ret; + } + } + +fdt_for_each_subnode (subnode, overlay_blob, overlay_offset) { +const char *name =fdt_get_name (overlay_blob, subnode,NULL ); +int nnode; + + nnode =xrt_md_add_node (dev, blob, target, name); +if (nnode == -FDT_ERR_EXISTS ) + nnode =fdt_subnode_offset (blob, target, name); +if (nnode <0 ) { +md_err (dev,"add node failed, ret = %d" , nnode); +return nnode; + } + + ret =xrt_md_overlay (dev, blob, nnode, overlay_blob, subnode); +if (ret) +return ret; + } + +return 0 ; +} + +int xrt_md_get_next_endpoint (struct device *dev,const char *blob, +const char *ep_name,const char *regmap_name, +char **next_ep,char **next_regmap) +{ +int offset, ret; + +if (!ep_name) { + ret =xrt_md_get_endpoint (dev, blob,NODE_ENDPOINTS ,NULL , + &offset); + }else { + ret =xrt_md_get_endpoint (dev, blob, ep_name, regmap_name, + &offset); + } + +if (ret) { + *next_ep =NULL ; + *next_regmap =NULL ; +return -EINVAL ; + } + + offset = ep_name ?fdt_next_subnode (blob, offset) : +fdt_first_subnode (blob, offset); +if (offset <0 ) { + *next_ep =NULL ; + *next_regmap =NULL ; +return -EINVAL ; + } + + *next_ep = (char *)fdt_get_name (blob, offset,NULL ); + *next_regmap = (char *)fdt_stringlist_get (blob, offset,PROP_COMPATIBLE , +0 ,NULL ); + +return 0 ; +} + +int xrt_md_get_compatible_epname (struct device *dev,const char *blob, +const char *regmap_name,const char **ep_name) +{ +int ep_offset; + + ep_offset =fdt_node_offset_by_compatible (blob,-1 , regmap_name); +if (ep_offset <0 ) { + *ep_name =NULL ; +return -ENOENT ; + } + + *ep_name = (char *)fdt_get_name (blob, ep_offset,NULL ); + +return 0 ; +} + +int xrt_md_uuid_strtoid (struct device *dev,const char *uuidstr,uuid_t *p_uuid) +{ +char *p; +const char *str; +char tmp[3 ] = {0 }; +int i, ret; + +memset (p_uuid,0 ,sizeof (*p_uuid)); + p = (char *)p_uuid; + str = uuidstr +strlen (uuidstr) -2 ; + +for (i =0 ; i <sizeof (*p_uuid) && str >= uuidstr; i++) { + tmp[0 ] = *str; + tmp[1 ] = *(str +1 ); + ret =kstrtou8 (tmp,16 , p); +if (ret) { +md_err (dev,"Invalid uuid %s" , uuidstr); +return -EINVAL ; + } + p++; + str -=2 ; + } + +return 0 ; +} + +void xrt_md_pack (struct device *dev,char *blob) +{ +int ret; + + ret =fdt_pack (blob); +if (ret) +md_err (dev,"pack failed %d" , ret); +} + +int xrt_md_get_intf_uuids (struct device *dev,const char *blob, +u32 *num_uuids,uuid_t *intf_uuids) +{ +int offset, count =0 ; +int ret; +const char *uuid_str; + + ret =xrt_md_get_endpoint (dev, blob,NODE_INTERFACES ,NULL , &offset); +if (ret) +return -ENOENT ; + +for (offset =fdt_first_subnode (blob, offset); + offset >=0 ; + offset =fdt_next_subnode (blob, offset)) { + uuid_str =fdt_getprop (blob, offset,PROP_INTERFACE_UUID , +NULL ); +if (!uuid_str) { +md_err (dev,"empty intf uuid node" ); +return -EINVAL ; + } + +if (intf_uuids && count < *num_uuids) { + ret =xrt_md_uuid_strtoid (dev, uuid_str, + &intf_uuids[count]); +if (ret) +return -EINVAL ; + } + count++; + } + + *num_uuids = count; + +return 0 ; +} + +int xrt_md_check_uuids (struct device *dev,const char *blob,char *subset_blob) +{ +const char *subset_int_uuid =NULL ; +const char *int_uuid =NULL ; +int offset, subset_offset, off; +int ret; + + ret =xrt_md_get_endpoint (dev, subset_blob,NODE_INTERFACES ,NULL , + &subset_offset); +if (ret) +return -EINVAL ; + + ret =xrt_md_get_endpoint (dev, blob,NODE_INTERFACES ,NULL , + &offset); +if (ret) +return -EINVAL ; + +for (subset_offset =fdt_first_subnode (subset_blob, subset_offset); + subset_offset >=0 ; + subset_offset =fdt_next_subnode (subset_blob, subset_offset)) { + subset_int_uuid =fdt_getprop (subset_blob, subset_offset, +PROP_INTERFACE_UUID ,NULL ); +if (!subset_int_uuid) +return -EINVAL ; + off = offset; + +for (off =fdt_first_subnode (blob, off); + off >=0 ; + off =fdt_next_subnode (blob, off)) { + int_uuid =fdt_getprop (blob, off, +PROP_INTERFACE_UUID ,NULL ); +if (!int_uuid) +return -EINVAL ; +if (!strcmp (int_uuid, subset_int_uuid)) +break ; + } +if (off <0 ) +return -ENOENT ; + } + +return 0 ; +}
drivers/fpga/alveo/common/xrt-root.c new file +744 -0
744 lines not on this page · raw message
drivers/fpga/alveo/common/xrt-root.h new file +24 -0
@@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XRT_ROOT_H_ +#define _XRT_ROOT_H_ + +#include <linux/pci.h> +#include "xrt-subdev.h" + +int xroot_probe (struct pci_dev *pdev,void **root); +void xroot_remove (void *root); +bool xroot_wait_for_bringup (void *root); +int xroot_add_vsec_node (void *root,char *dtb); +int xroot_create_partition (void *root,char *dtb); +int xroot_add_simple_node (void *root,char *dtb,const char *endpoint); +void xroot_hot_reset (struct pci_dev *pdev); +void xroot_broadcast (void *root,enum xrt_events evt); + +#endif /* _XRT_ROOT_H_ */
drivers/fpga/alveo/common/xrt-xclbin.c new file +387 -0
387 lines not on this page · raw message
drivers/fpga/alveo/common/xrt-xclbin.h new file +46 -0
46 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH 4/8 fpga: xrt: core infrastructure for xrt-lib module
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add xrt-lib kernel module infrastructrure code which defines APIs for working with device nodes, iteration and lookup of platform devices, common interfaces for platform devices, plumbing of function call and ioctls between platform devices and parent partitions.
--- drivers/fpga/alveo/lib/xrt-cdev.c | 234 +++++++ drivers/fpga/alveo/lib/xrt-main.c | 275 ++++++++ drivers/fpga/alveo/lib/xrt-main.h | 46 ++ drivers/fpga/alveo/lib/xrt-subdev.c | 1007 +++++++++++++++++++++++++++ 4 files changed, 1562 insertions(+) create mode 100644 drivers/fpga/alveo/lib/xrt-cdev.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.h create mode 100644 drivers/fpga/alveo/lib/xrt-subdev.c
drivers/fpga/alveo/lib/xrt-cdev.c new file +234 -0
@@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA device node helper functions. +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#include "xrt-subdev.h" + +extern struct class *xrt_class; + +#define XRT_CDEV_DIR "xfpga" +#define INODE2PDATA (inode) \ + container_of((inode)->i_cdev, struct xrt_subdev_platdata, xsp_cdev) +#define INODE2PDEV (inode) \ + to_platform_device(kobj_to_dev((inode)->i_cdev->kobj.parent)) +#define CDEV_NAME (sysdev) (strchr((sysdev)->kobj.name, '!') + 1) + +/* Allow it to be accessed from cdev. */ +static void xrt_devnode_allowed (struct platform_device *pdev) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); + +/* Allow new opens. */ +mutex_lock (&pdata->xsp_devnode_lock); + pdata->xsp_devnode_online = true; +mutex_unlock (&pdata->xsp_devnode_lock); +} + +/* Turn off access from cdev and wait for all existing user to go away. */ +static int xrt_devnode_disallowed (struct platform_device *pdev) +{ +int ret =0 ; +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); + +mutex_lock (&pdata->xsp_devnode_lock); + +/* Prevent new opens. */ + pdata->xsp_devnode_online = false; +/* Wait for existing user to close. */ +while (!ret && pdata->xsp_devnode_ref) { +int rc; + +mutex_unlock (&pdata->xsp_devnode_lock); + rc =wait_for_completion_killable (&pdata->xsp_devnode_comp); +mutex_lock (&pdata->xsp_devnode_lock); + +if (rc == -ERESTARTSYS ) { +/* Restore online state. */ + pdata->xsp_devnode_online = true; +xrt_err (pdev,"%s is in use, ref=%d" , +CDEV_NAME (pdata->xsp_sysdev), + pdata->xsp_devnode_ref); + ret = -EBUSY ; + } + } + +mutex_unlock (&pdata->xsp_devnode_lock); + +return ret; +} + +static struct platform_device * +__xrt_devnode_open (struct inode *inode,bool excl) +{ +struct xrt_subdev_platdata *pdata =INODE2PDATA (inode); +struct platform_device *pdev =INODE2PDEV (inode); +bool opened = false; + +mutex_lock (&pdata->xsp_devnode_lock); + +if (pdata->xsp_devnode_online) { +if (excl && pdata->xsp_devnode_ref) { +xrt_err (pdev,"%s has already been opened exclusively" , +CDEV_NAME (pdata->xsp_sysdev)); + }else if (!excl && pdata->xsp_devnode_excl) { +xrt_err (pdev,"%s has been opened exclusively" , +CDEV_NAME (pdata->xsp_sysdev)); + }else { + pdata->xsp_devnode_ref++; + pdata->xsp_devnode_excl = excl; + opened = true; +xrt_info (pdev,"opened %s, ref=%d" , +CDEV_NAME (pdata->xsp_sysdev), + pdata->xsp_devnode_ref); + } + }else { +xrt_err (pdev,"%s is offline" ,CDEV_NAME (pdata->xsp_sysdev)); + } + +mutex_unlock (&pdata->xsp_devnode_lock); + +return opened ? pdev :NULL ; +} + +struct platform_device * +xrt_devnode_open_excl (struct inode *inode) +{ +return __xrt_devnode_open (inode, true); +} + +struct platform_device * +xrt_devnode_open (struct inode *inode) +{ +return __xrt_devnode_open (inode, false); +} +EXPORT_SYMBOL_GPL (xrt_devnode_open); + +void xrt_devnode_close (struct inode *inode) +{ +struct xrt_subdev_platdata *pdata =INODE2PDATA (inode); +struct platform_device *pdev =INODE2PDEV (inode); +bool notify = false; + +mutex_lock (&pdata->xsp_devnode_lock); + + pdata->xsp_devnode_ref--; +if (pdata->xsp_devnode_ref ==0 ) { + pdata->xsp_devnode_excl = false; + notify = true; + } +if (notify) { +xrt_info (pdev,"closed %s, ref=%d" , +CDEV_NAME (pdata->xsp_sysdev), pdata->xsp_devnode_ref); + }else { +xrt_info (pdev,"closed %s, notifying waiter" , +CDEV_NAME (pdata->xsp_sysdev)); + } + +mutex_unlock (&pdata->xsp_devnode_lock); + +if (notify) +complete (&pdata->xsp_devnode_comp); +} +EXPORT_SYMBOL_GPL (xrt_devnode_close); + +static inline enum xrt_subdev_file_mode +devnode_mode (struct xrt_subdev_drvdata *drvdata) +{ +return drvdata->xsd_file_ops.xsf_mode; +} + +int xrt_devnode_create (struct platform_device *pdev,const char *file_name, +const char *inst_name) +{ +struct xrt_subdev_drvdata *drvdata =DEV_DRVDATA (pdev); +struct xrt_subdev_file_ops *fops = &drvdata->xsd_file_ops; +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +struct cdev *cdevp; +struct device *sysdev; +int ret =0 ; +char fname[256 ]; + +BUG_ON (fops->xsf_dev_t == (dev_t)-1 ); + +mutex_init (&pdata->xsp_devnode_lock); +init_completion (&pdata->xsp_devnode_comp); + + cdevp = &DEV_PDATA (pdev)->xsp_cdev; +cdev_init (cdevp, &fops->xsf_ops); + cdevp->owner = fops->xsf_ops.owner; + cdevp->dev =MKDEV (MAJOR (fops->xsf_dev_t), pdev->id); + +/* +* Set pdev as parent of cdev so that when pdev (and its platform +* data) will not be freed when cdev is not freed. +*/ +cdev_set_parent (cdevp, &DEV (pdev)->kobj); + + ret =cdev_add (cdevp, cdevp->dev,1 ); +if (ret) { +xrt_err (pdev,"failed to add cdev: %d" , ret); + goto failed; + } +if (!file_name) + file_name = pdev->name; +if (!inst_name) { +if (devnode_mode (drvdata) ==XRT_SUBDEV_FILE_MULTI_INST ) { +snprintf (fname,sizeof (fname),"%s/%s/%s.%u" , +XRT_CDEV_DIR ,DEV_PDATA (pdev)->xsp_root_name, + file_name, pdev->id); + }else { +snprintf (fname,sizeof (fname),"%s/%s/%s" , +XRT_CDEV_DIR ,DEV_PDATA (pdev)->xsp_root_name, + file_name); + } + }else { +snprintf (fname,sizeof (fname),"%s/%s/%s.%s" ,XRT_CDEV_DIR , +DEV_PDATA (pdev)->xsp_root_name, file_name, inst_name); + } + sysdev =device_create (xrt_class,NULL , cdevp->dev,NULL ,"%s" , fname); +if (IS_ERR (sysdev)) { + ret =PTR_ERR (sysdev); +xrt_err (pdev,"failed to create device node: %d" , ret); + goto failed; + } + pdata->xsp_sysdev = sysdev; + +xrt_devnode_allowed (pdev); + +xrt_info (pdev,"created (%d, %d): /dev/%s" , +MAJOR (cdevp->dev), pdev->id, fname); +return 0 ; + +failed: +device_destroy (xrt_class, cdevp->dev); +cdev_del (cdevp); + cdevp->owner =NULL ; +return ret; +} + +int xrt_devnode_destroy (struct platform_device *pdev) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +struct cdev *cdevp = &pdata->xsp_cdev; +dev_t dev = cdevp->dev; +int rc; + +BUG_ON (!cdevp->owner); + + rc =xrt_devnode_disallowed (pdev); +if (rc) +return rc; + +xrt_info (pdev,"removed (%d, %d): /dev/%s/%s" ,MAJOR (dev),MINOR (dev), +XRT_CDEV_DIR ,CDEV_NAME (pdata->xsp_sysdev)); +device_destroy (xrt_class, cdevp->dev); + pdata->xsp_sysdev =NULL ; +cdev_del (cdevp); +return 0 ; +}
drivers/fpga/alveo/lib/xrt-main.c new file +275 -0
275 lines not on this page · raw message
drivers/fpga/alveo/lib/xrt-main.h new file +46 -0
46 lines not on this page · raw message
drivers/fpga/alveo/lib/xrt-subdev.c new file +1007 -0
1,007 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH 5/8 fpga: xrt: platform drivers for subsystems in shell partition
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add platform drivers for HW subsystems found in shell partition. Each driver implements interfaces defined by xrt-subdev.h. The driver instances are created by parent partition to manage subsystem instances discovered by walking device tree. The platform drivers may populate their own sysfs nodes, create device nodes if needed and make calls into parent or other platform drivers. The platform drivers can also send and receive events.
--- drivers/fpga/alveo/lib/subdevs/xrt-axigate.c | 298 +++ drivers/fpga/alveo/lib/subdevs/xrt-calib.c | 291 +++ drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c | 214 ++ drivers/fpga/alveo/lib/subdevs/xrt-clock.c | 638 ++++++ .../fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c | 343 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h | 135 ++ .../fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c | 320 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c | 361 ++++ .../fpga/alveo/lib/subdevs/xrt-cmc-sensors.c | 445 ++++ drivers/fpga/alveo/lib/subdevs/xrt-cmc.c | 239 +++ drivers/fpga/alveo/lib/subdevs/xrt-gpio.c | 198 ++ drivers/fpga/alveo/lib/subdevs/xrt-icap.c | 306 +++ drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c | 1905 +++++++++++++++++ .../fpga/alveo/lib/subdevs/xrt-partition.c | 261 +++ drivers/fpga/alveo/lib/subdevs/xrt-qspi.c | 1347 ++++++++++++ drivers/fpga/alveo/lib/subdevs/xrt-srsr.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-test.c | 274 +++ drivers/fpga/alveo/lib/subdevs/xrt-ucs.c | 238 ++ .../fpga/alveo/lib/subdevs/xrt-vsec-golden.c | 238 ++ drivers/fpga/alveo/lib/subdevs/xrt-vsec.c | 337 +++ 21 files changed, 9032 insertions(+) create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-axigate.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-calib.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clock.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sensors.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-gpio.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-icap.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-partition.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-qspi.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-srsr.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-test.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-ucs.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec-golden.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec.c
drivers/fpga/alveo/lib/subdevs/xrt-axigate.c new file +298 -0
@@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA AXI Gate Driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou<[email protected]> +*/ + +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/io.h> +#include "xrt-metadata.h" +#include "xrt-subdev.h" +#include "xrt-parent.h" +#include "xrt-axigate.h" + +#define XRT_AXIGATE "xrt_axigate" + +struct axigate_regs { +u32 iag_wr; +u32 iag_rvsd; +u32 iag_rd; +} __packed; + +struct xrt_axigate { +struct platform_device *pdev; +void *base; +struct mutex gate_lock; + +void *evt_hdl; +const char *ep_name; + +bool gate_freezed; +}; + +#define reg_rd (g, r) \ + ioread32(&((struct axigate_regs *)g->base)->r) +#define reg_wr (g, v, r) \ + iowrite32(v, &((struct axigate_regs *)g->base)->r) + +#define freeze_gate (gate) \ + do { \ + reg_wr(gate, 0, iag_wr); \ + ndelay(500); \ + reg_rd(gate, iag_rd); \ + } while (0) + +#define free_gate (gate) \ + do { \ + reg_wr(gate, 0x2, iag_wr); \ + ndelay(500); \ + (void) reg_rd(gate, iag_rd); \ + reg_wr(gate, 0x3, iag_wr); \ + ndelay(500); \ + reg_rd(gate, iag_rd); \ + } while (0) \ + +static int xrt_axigate_epname_idx (struct platform_device *pdev) +{ +int i; +int ret; +struct resource *res; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +xrt_err (pdev,"Empty Resource!" ); +return -EINVAL ; + } + +for (i =0 ; xrt_axigate_epnames[i]; i++) { + ret =strncmp (xrt_axigate_epnames[i], res->name, +strlen (xrt_axigate_epnames[i]) +1 ); +if (!ret) +break ; + } + +return (xrt_axigate_epnames[i]) ? i : -EINVAL ; +} + +static bool xrt_axigate_leaf_match (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +const char *ep_name = arg; +struct resource *res; + +if (id !=XRT_SUBDEV_AXIGATE ) +return false; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +xrt_err (pdev,"Empty Resource!" ); +return false; + } + +if (strncmp (res->name, ep_name,strlen (res->name) +1 )) +return true; + +return false; +} + +static void xrt_axigate_freeze (struct platform_device *pdev) +{ +struct xrt_axigate *gate; +u32 freeze =0 ; + + gate =platform_get_drvdata (pdev); + +mutex_lock (&gate->gate_lock); + freeze =reg_rd (gate, iag_rd); +if (freeze) {/* gate is opened */ +xrt_subdev_broadcast_event (pdev,XRT_EVENT_PRE_GATE_CLOSE ); +freeze_gate (gate); + } + + gate->gate_freezed = true; +mutex_unlock (&gate->gate_lock); + +xrt_info (pdev,"freeze gate %s" , gate->ep_name); +} + +static void xrt_axigate_free (struct platform_device *pdev) +{ +struct xrt_axigate *gate; +u32 freeze; + + gate =platform_get_drvdata (pdev); + +mutex_lock (&gate->gate_lock); + freeze =reg_rd (gate, iag_rd); +if (!freeze) {/* gate is closed */ +free_gate (gate); +xrt_subdev_broadcast_event_async (pdev, +XRT_EVENT_POST_GATE_OPEN ,NULL ,NULL ); +/* xrt_axigate_free() could be called in event cb, thus +* we can not wait for the completes +*/ + } + + gate->gate_freezed = false; +mutex_unlock (&gate->gate_lock); + +xrt_info (pdev,"free gate %s" , gate->ep_name); +} + +static int +xrt_axigate_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct platform_device *leaf; +struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev *)arg; +enum xrt_subdev_id id; +int instance; + +switch (evt) { +case XRT_EVENT_POST_CREATION : +break ; +default : +return XRT_EVENT_CB_CONTINUE ; + } + + id = esd->xevt_subdev_id; + instance = esd->xevt_subdev_instance; + +/* +* higher level axigate instance created, +* make sure the gate is openned. This covers 1RP flow which +* has plp gate as well. +*/ + leaf =xrt_subdev_get_leaf_by_id (pdev, id, instance); +if (leaf) { +if (xrt_axigate_epname_idx (leaf) > +xrt_axigate_epname_idx (pdev)) +xrt_axigate_free (pdev); +else +xrt_subdev_ioctl (leaf,XRT_AXIGATE_FREE ,NULL ); +xrt_subdev_put_leaf (pdev, leaf); + } + +return XRT_EVENT_CB_CONTINUE ; +} + +static int +xrt_axigate_leaf_ioctl (struct platform_device *pdev,u32 cmd,void *arg) +{ +switch (cmd) { +case XRT_AXIGATE_FREEZE : +xrt_axigate_freeze (pdev); +break ; +case XRT_AXIGATE_FREE : +xrt_axigate_free (pdev); +break ; +default : +xrt_err (pdev,"unsupported cmd %d" , cmd); +return -EINVAL ; + } + +return 0 ; +} + +static int xrt_axigate_remove (struct platform_device *pdev) +{ +struct xrt_axigate *gate; + + gate =platform_get_drvdata (pdev); + +if (gate->base) +iounmap (gate->base); + +platform_set_drvdata (pdev,NULL ); +devm_kfree (&pdev->dev, gate); + +return 0 ; +} + +static int xrt_axigate_probe (struct platform_device *pdev) +{ +struct xrt_axigate *gate; +struct resource *res; +int ret; + + gate =devm_kzalloc (&pdev->dev,sizeof (*gate),GFP_KERNEL ); +if (!gate) +return -ENOMEM ; + + gate->pdev = pdev; +platform_set_drvdata (pdev, gate); + +xrt_info (pdev,"probing..." ); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +xrt_err (pdev,"Empty resource 0" ); + ret = -EINVAL ; + goto failed; + } + + gate->base =ioremap (res->start, res->end - res->start +1 ); +if (!gate->base) { +xrt_err (pdev,"map base iomem failed" ); + ret = -EFAULT ; + goto failed; + } + + gate->evt_hdl =xrt_subdev_add_event_cb (pdev, + xrt_axigate_leaf_match, (void *)res->name, + xrt_axigate_event_cb); + + gate->ep_name = res->name; + +mutex_init (&gate->gate_lock); + +return 0 ; + +failed: +xrt_axigate_remove (pdev); +return ret; +} + +struct xrt_subdev_endpoints xrt_axigate_endpoints[] = { + { + .xse_names = (struct xrt_subdev_ep_names []) { + { .ep_name ="ep_pr_isolate_ulp_00" }, + {NULL }, + }, + .xse_min_ep =1 , + }, + { + .xse_names = (struct xrt_subdev_ep_names []) { + { .ep_name ="ep_pr_isolate_plp_00" }, + {NULL }, + }, + .xse_min_ep =1 , + }, + {0 }, +}; + +struct xrt_subdev_drvdata xrt_axigate_data = { + .xsd_dev_ops = { + .xsd_ioctl = xrt_axigate_leaf_ioctl, + }, +}; + +static const struct platform_device_id xrt_axigate_table[] = { + {XRT_AXIGATE , (kernel_ulong_t)&xrt_axigate_data }, + { }, +}; + +struct platform_driver xrt_axigate_driver = { + .driver = { + .name =XRT_AXIGATE , + }, + .probe = xrt_axigate_probe, + .remove = xrt_axigate_remove, + .id_table = xrt_axigate_table, +};
drivers/fpga/alveo/lib/subdevs/xrt-calib.c new file +291 -0
291 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c new file +214 -0
214 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-clock.c new file +638 -0
638 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c new file +343 -0
343 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c new file +322 -0
322 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h new file +135 -0
135 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c new file +320 -0
320 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c new file +361 -0
361 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc-sensors.c new file +445 -0
78 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-cmc.c new file +239 -0
239 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-gpio.c new file +198 -0
198 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-icap.c new file +306 -0
306 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c new file +1905 -0
1,905 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-partition.c new file +261 -0
261 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-qspi.c new file +1347 -0
1,347 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-srsr.c new file +322 -0
322 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-test.c new file +274 -0
274 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-ucs.c new file +238 -0
238 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-vsec-golden.c new file +238 -0
238 lines not on this page · raw message
drivers/fpga/alveo/lib/subdevs/xrt-vsec.c new file +337 -0
337 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.17.1
Part of the diff is not shown here. View the raw message.
PATCH 6/8 fpga: xrt: header file for platform and parent drivers
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add private header files for platform and parent drivers. Each header file defines ioctls supported by the platform or parent driver. The header files also define core data structures for sending and receiving events by platform and parent drivers.
--- drivers/fpga/alveo/include/xmgmt-main.h | 34 +++ drivers/fpga/alveo/include/xrt-axigate.h | 31 ++ drivers/fpga/alveo/include/xrt-calib.h | 28 ++ drivers/fpga/alveo/include/xrt-clkfreq.h | 21 ++ drivers/fpga/alveo/include/xrt-clock.h | 29 ++ drivers/fpga/alveo/include/xrt-cmc.h | 23 ++ drivers/fpga/alveo/include/xrt-ddr-srsr.h | 29 ++ drivers/fpga/alveo/include/xrt-flash.h | 28 ++ drivers/fpga/alveo/include/xrt-gpio.h | 41 +++ drivers/fpga/alveo/include/xrt-icap.h | 27 ++ drivers/fpga/alveo/include/xrt-mailbox.h | 44 +++ drivers/fpga/alveo/include/xrt-metadata.h | 184 ++++++++++++ drivers/fpga/alveo/include/xrt-parent.h | 103 +++++++ drivers/fpga/alveo/include/xrt-partition.h | 33 ++ drivers/fpga/alveo/include/xrt-subdev.h | 333 +++++++++++++++++++++ drivers/fpga/alveo/include/xrt-ucs.h | 22 ++ 16 files changed, 1010 insertions(+) create mode 100644 drivers/fpga/alveo/include/xmgmt-main.h create mode 100644 drivers/fpga/alveo/include/xrt-axigate.h create mode 100644 drivers/fpga/alveo/include/xrt-calib.h create mode 100644 drivers/fpga/alveo/include/xrt-clkfreq.h create mode 100644 drivers/fpga/alveo/include/xrt-clock.h create mode 100644 drivers/fpga/alveo/include/xrt-cmc.h create mode 100644 drivers/fpga/alveo/include/xrt-ddr-srsr.h create mode 100644 drivers/fpga/alveo/include/xrt-flash.h create mode 100644 drivers/fpga/alveo/include/xrt-gpio.h create mode 100644 drivers/fpga/alveo/include/xrt-icap.h create mode 100644 drivers/fpga/alveo/include/xrt-mailbox.h create mode 100644 drivers/fpga/alveo/include/xrt-metadata.h create mode 100644 drivers/fpga/alveo/include/xrt-parent.h create mode 100644 drivers/fpga/alveo/include/xrt-partition.h create mode 100644 drivers/fpga/alveo/include/xrt-subdev.h create mode 100644 drivers/fpga/alveo/include/xrt-ucs.h
drivers/fpga/alveo/include/xmgmt-main.h new file +34 -0
@@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XMGMT_MAIN_H_ +#define _XMGMT_MAIN_H_ + +#include <linux/xrt/xclbin.h> + +enum xrt_mgmt_main_ioctl_cmd { +// section needs to be vfree'd by caller +XRT_MGMT_MAIN_GET_AXLF_SECTION =0 , +// vbnv needs to be kfree'd by caller +XRT_MGMT_MAIN_GET_VBNV , +}; + +enum provider_kind { +XMGMT_BLP , +XMGMT_PLP , +XMGMT_ULP , +}; + +struct xrt_mgmt_main_ioctl_get_axlf_section { +enum provider_kind xmmigas_axlf_kind; +enum axlf_section_kind xmmigas_section_kind; +void *xmmigas_section; +u64 xmmigas_section_size; +}; + +#endif /* _XMGMT_MAIN_H_ */
drivers/fpga/alveo/include/xrt-axigate.h new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_AXIGATE_H_ +#define _XRT_AXIGATE_H_ + + +#include "xrt-subdev.h" +#include "xrt-metadata.h" + +/* +* AXIGATE driver IOCTL calls. +*/ +enum xrt_axigate_ioctl_cmd { +XRT_AXIGATE_FREEZE =0 , +XRT_AXIGATE_FREE , +}; + +/* the ep names are in the order of hardware layers */ +static const char *const xrt_axigate_epnames[] = { +NODE_GATE_PLP , +NODE_GATE_ULP , +NULL +}; + +#endif /* _XRT_AXIGATE_H_ */
drivers/fpga/alveo/include/xrt-calib.h new file +28 -0
@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XRT_CALIB_H_ +#define _XRT_CALIB_H_ + +#include "xrt-subdev.h" +#include <linux/xrt/xclbin.h> + +/* +* Memory calibration driver IOCTL calls. +*/ +enum xrt_calib_results { +XRT_CALIB_UNKNOWN , +XRT_CALIB_SUCCEEDED , +XRT_CALIB_FAILED , +}; + +enum xrt_calib_ioctl_cmd { +XRT_CALIB_RESULT =0 , +}; + +#endif /* _XRT_CALIB_H_ */
drivers/fpga/alveo/include/xrt-clkfreq.h new file +21 -0
@@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_CLKFREQ_H_ +#define _XRT_CLKFREQ_H_ + +#include "xrt-subdev.h" + +/* +* CLKFREQ driver IOCTL calls. +*/ +enum xrt_clkfreq_ioctl_cmd { +XRT_CLKFREQ_READ =0 , +}; + +#endif /* _XRT_CLKFREQ_H_ */
drivers/fpga/alveo/include/xrt-clock.h new file +29 -0
@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_CLOCK_H_ +#define _XRT_CLOCK_H_ + +#include "xrt-subdev.h" +#include <linux/xrt/xclbin.h> + +/* +* CLOCK driver IOCTL calls. +*/ +enum xrt_clock_ioctl_cmd { +XRT_CLOCK_SET =0 , +XRT_CLOCK_GET , +XRT_CLOCK_VERIFY , +}; + +struct xrt_clock_ioctl_get { +u16 freq; +u32 freq_cnter; +}; + +#endif /* _XRT_CLOCK_H_ */
drivers/fpga/alveo/include/xrt-cmc.h new file +23 -0
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XRT_CMC_H_ +#define _XRT_CMC_H_ + +#include "xrt-subdev.h" +#include <linux/xrt/xclbin.h> + +/* +* CMC driver IOCTL calls. +*/ +enum xrt_cmc_ioctl_cmd { +XRT_CMC_READ_BOARD_INFO =0 , +XRT_CMC_READ_SENSORS , +}; + +#endif /* _XRT_CMC_H_ */
drivers/fpga/alveo/include/xrt-ddr-srsr.h new file +29 -0
@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_DDR_SRSR_H_ +#define _XRT_DDR_SRSR_H_ + +#include "xrt-subdev.h" + +/* +* ddr-srsr driver IOCTL calls. +*/ +enum xrt_ddr_srsr_ioctl_cmd { +XRT_SRSR_FAST_CALIB , +XRT_SRSR_CALIB , +XRT_SRSR_EP_NAME , +}; + +struct xrt_srsr_ioctl_calib { +void *xsic_buf; +u32 xsic_size; +bool xsic_retention; +}; + +#endif
drivers/fpga/alveo/include/xrt-flash.h new file +28 -0
@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XRT_FLASH_H_ +#define _XRT_FLASH_H_ + +#include "xrt-subdev.h" + +/* +* Flash controller driver IOCTL calls. +*/ +enum xrt_flash_ioctl_cmd { +XRT_FLASH_GET_SIZE =0 , +XRT_FLASH_READ , +}; + +struct xrt_flash_ioctl_read { +char *xfir_buf; +size_t xfir_size; +loff_t xfir_offset; +}; + +#endif /* _XRT_FLASH_H_ */
drivers/fpga/alveo/include/xrt-gpio.h new file +41 -0
41 lines not on this page · raw message
drivers/fpga/alveo/include/xrt-icap.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_ICAP_H_ +#define _XRT_ICAP_H_ + +#include "xrt-subdev.h" + +/* +* ICAP driver IOCTL calls. +*/ +enum xrt_icap_ioctl_cmd { +XRT_ICAP_WRITE =0 , +XRT_ICAP_IDCODE , +}; + +struct xrt_icap_ioctl_wr { +void *xiiw_bit_data; +u32 xiiw_data_len; +}; + +#endif /* _XRT_ICAP_H_ */
drivers/fpga/alveo/include/xrt-mailbox.h new file +44 -0
44 lines not on this page · raw message
drivers/fpga/alveo/include/xrt-metadata.h new file +184 -0
184 lines not on this page · raw message
drivers/fpga/alveo/include/xrt-parent.h new file +103 -0
103 lines not on this page · raw message
drivers/fpga/alveo/include/xrt-partition.h new file +33 -0
@@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XRT_PARTITION_H_ +#define _XRT_PARTITION_H_ + +#include "xrt-subdev.h" + +/* +* Partition driver IOCTL calls. +*/ +enum xrt_partition_ioctl_cmd { +XRT_PARTITION_GET_LEAF =0 , +XRT_PARTITION_PUT_LEAF , +XRT_PARTITION_INIT_CHILDREN , +XRT_PARTITION_FINI_CHILDREN , +XRT_PARTITION_EVENT , +}; + +struct xrt_partition_ioctl_event { +enum xrt_events xpie_evt; +struct xrt_parent_ioctl_evt_cb *xpie_cb; +}; + +extern int xrt_subdev_parent_ioctl (struct platform_device *pdev, +u32 cmd,void *arg); + +#endif /* _XRT_PARTITION_H_ */
drivers/fpga/alveo/include/xrt-subdev.h new file +333 -0
333 lines not on this page · raw message
drivers/fpga/alveo/include/xrt-ucs.h new file +22 -0
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#ifndef _XRT_UCS_H_ +#define _XRT_UCS_H_ + +#include "xrt-subdev.h" + +/* +* UCS driver IOCTL calls. +*/ +enum xrt_ucs_ioctl_cmd { +XRT_UCS_CHECK =0 , +XRT_UCS_ENABLE , +}; + +#endif /* _XRT_UCS_H_ */
Signature · 1 line
2.17.1
PATCH 7/8 fpga: xrt: Alveo management physical function driver
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Add management physical function driver core. The driver attaches to management physical function of Alveo devices. It instantiates the root driver and one or more partition drivers which in turn instantiate platform drivers. The instantiation of partition and platform drivers is completely data driven. The driver integrates with FPGA manager and provides xclbin download service.
--- drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930 +++++++++++++++++++ drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 +++++++++++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++++++ 7 files changed, 2597 insertions(+) create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.c
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +194 -0
@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#include <linux/cred.h> +#include <linux/efi.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/vmalloc.h> + +#include "xrt-subdev.h" +#include "xmgmt-fmgr.h" +#include "xrt-axigate.h" +#include "xmgmt-main-impl.h" + +/* +* Container to capture and cache full xclbin as it is passed in blocks by FPGA +* Manager. Driver needs access to full xclbin to walk through xclbin sections. +* FPGA Manager's .write() backend sends incremental blocks without any +* knowledge of xclbin format forcing us to collect the blocks and stitch them +* together here. +*/ + +struct xfpga_klass { +const struct platform_device *pdev; +struct axlf *blob; +char name[64 ]; +size_t count; +size_t total_count; +struct mutex axlf_lock; +int reader_ref; +enum fpga_mgr_states state; +enum xfpga_sec_level sec_level; +}; + +struct key *xfpga_keys; + +static int xmgmt_pr_write_init (struct fpga_manager *mgr, +struct fpga_image_info *info,const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +const struct axlf *bin = (const struct axlf *)buf; + +if (count <sizeof (struct axlf )) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } + +if (count > bin->m_header.m_length) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } + +/* Free up the previous blob */ +vfree (obj->blob); + obj->blob =vmalloc (bin->m_header.m_length); +if (!obj->blob) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -ENOMEM ; + } + +xrt_info (obj->pdev,"Begin download of xclbin %pUb of length %lld B" , + &bin->m_header.uuid, bin->m_header.m_length); + + obj->count =0 ; + obj->total_count = bin->m_header.m_length; + obj->state =FPGA_MGR_STATE_WRITE_INIT ; +return 0 ; +} + +static int xmgmt_pr_write (struct fpga_manager *mgr, +const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +char *curr = (char *)obj->blob; + +if ((obj->state !=FPGA_MGR_STATE_WRITE_INIT ) && + (obj->state !=FPGA_MGR_STATE_WRITE )) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + + curr += obj->count; + obj->count += count; + +/* +* The xclbin buffer should not be longer than advertised in the header +*/ +if (obj->total_count < obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + +xrt_info (obj->pdev,"Copying block of %zu B of xclbin" , count); +memcpy (curr, buf, count); + obj->state =FPGA_MGR_STATE_WRITE ; +return 0 ; +} + + +static int xmgmt_pr_write_complete (struct fpga_manager *mgr, +struct fpga_image_info *info) +{ +int result =0 ; +struct xfpga_klass *obj = mgr->priv; + +if (obj->state !=FPGA_MGR_STATE_WRITE ) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } + +/* Check if we got the complete xclbin */ +if (obj->blob->m_header.m_length != obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } + + result =xmgmt_ulp_download ((void *)obj->pdev, obj->blob); + + obj->state = result ?FPGA_MGR_STATE_WRITE_COMPLETE_ERR : +FPGA_MGR_STATE_WRITE_COMPLETE ; +xrt_info (obj->pdev,"Finish downloading of xclbin %pUb: %d" , + &obj->blob->m_header.uuid, result); +vfree (obj->blob); + obj->blob =NULL ; + obj->count =0 ; +return result; +} + +static enum fpga_mgr_states xmgmt_pr_state (struct fpga_manager *mgr) +{ +struct xfpga_klass *obj = mgr->priv; + +return obj->state; +} + +static const struct fpga_manager_ops xmgmt_pr_ops = { + .initial_header_size =sizeof (struct axlf ), + .write_init = xmgmt_pr_write_init, + .write = xmgmt_pr_write, + .write_complete = xmgmt_pr_write_complete, + .state = xmgmt_pr_state, +}; + + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev) +{ +struct fpga_manager *fmgr; +int ret =0 ; +struct xfpga_klass *obj =vzalloc (sizeof (struct xfpga_klass )); + +xrt_info (pdev,"probing..." ); +if (!obj) +return ERR_PTR (-ENOMEM ); + +snprintf (obj->name,sizeof (obj->name),"Xilinx Alveo FPGA Manager" ); + obj->state =FPGA_MGR_STATE_UNKNOWN ; + obj->pdev = pdev; + fmgr =fpga_mgr_create (&pdev->dev, + obj->name, + &xmgmt_pr_ops, + obj); +if (!fmgr) +return ERR_PTR (-ENOMEM ); + + obj->sec_level =XFPGA_SEC_NONE ; + ret =fpga_mgr_register (fmgr); +if (ret) { +fpga_mgr_free (fmgr); +kfree (obj); +return ERR_PTR (ret); + } +mutex_init (&obj->axlf_lock); +return fmgr; +} + +int xmgmt_fmgr_remove (struct fpga_manager *fmgr) +{ +struct xfpga_klass *obj = fmgr->priv; + +mutex_destroy (&obj->axlf_lock); + obj->state =FPGA_MGR_STATE_UNKNOWN ; +fpga_mgr_unregister (fmgr); +vfree (obj->blob); +vfree (obj); +return 0 ; +}
drivers/fpga/alveo/mgmt/xmgmt-fmgr.h new file +29 -0
@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#ifndef _XMGMT_FMGR_H_ +#define _XMGMT_FMGR_H_ + +#include <linux/fpga/fpga-mgr.h> +#include <linux/mutex.h> + +#include <linux/xrt/xclbin.h> + +enum xfpga_sec_level { +XFPGA_SEC_NONE =0 , +XFPGA_SEC_DEDICATE , +XFPGA_SEC_SYSTEM , +XFPGA_SEC_MAX =XFPGA_SEC_SYSTEM , +}; + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev); +int xmgmt_fmgr_remove (struct fpga_manager *fmgr); + +#endif
drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +36 -0
@@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XMGMT_MAIN_IMPL_H_ +#define _XMGMT_MAIN_IMPL_H_ + +#include "xrt-subdev.h" +#include "xmgmt-main.h" + +extern struct platform_driver xmgmt_main_driver; +extern struct xrt_subdev_endpoints xrt_mgmt_main_endpoints[]; + +extern int xmgmt_ulp_download (struct platform_device *pdev,const void *xclbin); +extern int bitstream_axlf_mailbox (struct platform_device *pdev, +const void *xclbin); +extern int xmgmt_hot_reset (struct platform_device *pdev); + +/* Getting dtb for specified partition. Caller should vfree returned dtb .*/ +extern char *xmgmt_get_dtb (struct platform_device *pdev, +enum provider_kind kind); +extern char *xmgmt_get_vbnv (struct platform_device *pdev); +extern int xmgmt_get_provider_uuid (struct platform_device *pdev, +enum provider_kind kind,uuid_t *uuid); + +extern void *xmgmt_pdev2mailbox (struct platform_device *pdev); +extern void *xmgmt_mailbox_probe (struct platform_device *pdev); +extern void xmgmt_mailbox_remove (void *handle); +extern void xmgmt_peer_notify_state (void *handle,bool online); + +#endif /* _XMGMT_MAIN_IMPL_H_ */
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +930 -0
930 lines not on this page · raw message
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +190 -0
190 lines not on this page · raw message
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +843 -0
843 lines not on this page · raw message
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +375 -0
375 lines not on this page · raw message
Signature · 1 line
2.17.1
Moritz Fischer
maintainerRe: [PATCH Xilinx Alveo 7/8] fpga: xrt: Alveo management physical function driver
Hi Sonal,
Quoted 54 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Add management physical function driver core. The driver attaches to management physical function of Alveo devices. It instantiates the root driver and one or more partition drivers which in turn instantiate platform drivers. The instantiation of partition and platform drivers is completely data driven. The driver integrates with FPGA manager and provides xclbin download service.
Signed-off-by Sonal Santan <[email protected]>--- drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930 +++++++++++++++++++ drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 +++++++++++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++++++ 7 files changed, 2597 insertions(+) create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.cdrivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +21
-0@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#include <linux/cred.h> +#include <linux/efi.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/vmalloc.h> + +#include "xrt-subdev.h" +#include "xmgmt-fmgr.h" +#include "xrt-axigate.h" +#include "xmgmt-main-impl.h"
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 31
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+ +/* +* Container to capture and cache full xclbin as it is passed in blocks by FPGA +* Manager. Driver needs access to full xclbin to walk through xclbin sections. +* FPGA Manager's .write() backend sends incremental blocks without any +* knowledge of xclbin format forcing us to collect the blocks and stitch them +* together here. +*/ + +struct xfpga_klass {
Nit: xfpga_priv or xfpga_drvdata?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 34
Quoted 3 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +3
-0+const struct platform_device *pdev; +struct axlf *blob; +char name[64 ];
Nit: 64 could be a named constant ?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 40
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +6
-0+size_t count; +size_t total_count; +struct mutex axlf_lock; +int reader_ref; +enum fpga_mgr_states state; +enum xfpga_sec_level sec_level;
This appears unused, do you want to add this with the code that uses it?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 41
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +1
-0+};
Maybe add some kerneldoc markup?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 43
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +2
-0+ +struct key *xfpga_keys;
Appears unused, can you introduce this together with the code using it?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 49
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +6
-0+ +static int xmgmt_pr_write_init (struct fpga_manager *mgr, +struct fpga_image_info *info,const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +const struct axlf *bin = (const struct axlf *)buf;
Nit: Reverse x-mas tree please.
xxxxxx
xxxx
xxx
x
Quoted 11 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +11
-0+ +if (count <sizeof (struct axlf )) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } + +if (count > bin->m_header.m_length) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } +
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 70
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+/* Free up the previous blob */ +vfree (obj->blob); + obj->blob =vmalloc (bin->m_header.m_length); +if (!obj->blob) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -ENOMEM ; + } + +xrt_info (obj->pdev,"Begin download of xclbin %pUb of length %lld B" , + &bin->m_header.uuid, bin->m_header.m_length);
We already have framework level prints for that (admittedly somewhat less verbose). Please remove.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 74
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +4
-0+ + obj->count =0 ; + obj->total_count = bin->m_header.m_length; + obj->state =FPGA_MGR_STATE_WRITE_INIT ;
Does the framework state tracking not work for you?
Quoted 17 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +17
-0+return 0 ; +} + +static int xmgmt_pr_write (struct fpga_manager *mgr, +const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +char *curr = (char *)obj->blob; + +if ((obj->state !=FPGA_MGR_STATE_WRITE_INIT ) && + (obj->state !=FPGA_MGR_STATE_WRITE )) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + + curr += obj->count; + obj->count += count;
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 101
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+ +/* +* The xclbin buffer should not be longer than advertised in the header +*/ +if (obj->total_count < obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + +xrt_info (obj->pdev,"Copying block of %zu B of xclbin" , count);
Please drop those.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 102
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +1
-0+memcpy (curr, buf, count);
I'm confused. Why are we just copying things around here. What picks this up afterwards?
Quoted 16 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +16
-0+ obj->state =FPGA_MGR_STATE_WRITE ; +return 0 ; +} + + +static int xmgmt_pr_write_complete (struct fpga_manager *mgr, +struct fpga_image_info *info) +{ +int result =0 ; +struct xfpga_klass *obj = mgr->priv; + +if (obj->state !=FPGA_MGR_STATE_WRITE ) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } +
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 128
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+/* Check if we got the complete xclbin */ +if (obj->blob->m_header.m_length != obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } + + result =xmgmt_ulp_download ((void *)obj->pdev, obj->blob); + + obj->state = result ?FPGA_MGR_STATE_WRITE_COMPLETE_ERR : +FPGA_MGR_STATE_WRITE_COMPLETE ;
Why the separate state tracking?
Quoted 21 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +21
-0+xrt_info (obj->pdev,"Finish downloading of xclbin %pUb: %d" , + &obj->blob->m_header.uuid, result); +vfree (obj->blob); + obj->blob =NULL ; + obj->count =0 ; +return result; +} + +static enum fpga_mgr_states xmgmt_pr_state (struct fpga_manager *mgr) +{ +struct xfpga_klass *obj = mgr->priv; + +return obj->state; +} + +static const struct fpga_manager_ops xmgmt_pr_ops = { + .initial_header_size =sizeof (struct axlf ), + .write_init = xmgmt_pr_write_init, + .write = xmgmt_pr_write, + .write_complete = xmgmt_pr_write_complete, + .state = xmgmt_pr_state,
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 159
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+}; + + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev) +{ +struct fpga_manager *fmgr; +int ret =0 ; +struct xfpga_klass *obj =vzalloc (sizeof (struct xfpga_klass )); + +xrt_info (pdev,"probing..." );
Drop this, please.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 169
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+if (!obj) +return ERR_PTR (-ENOMEM ); + +snprintf (obj->name,sizeof (obj->name),"Xilinx Alveo FPGA Manager" ); + obj->state =FPGA_MGR_STATE_UNKNOWN ; + obj->pdev = pdev; + fmgr =fpga_mgr_create (&pdev->dev, + obj->name, + &xmgmt_pr_ops, + obj);
I think (eyeballed) this fits on two lines?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 173
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +4
-0+if (!fmgr) +return ERR_PTR (-ENOMEM ); + + obj->sec_level =XFPGA_SEC_NONE ;
Seems unused so far, please drop until it's used.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 181
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +8
-0+ ret =fpga_mgr_register (fmgr); +if (ret) { +fpga_mgr_free (fmgr); +kfree (obj); +return ERR_PTR (ret); + } +mutex_init (&obj->axlf_lock); +return fmgr;
Since this patchset will wait at least till next cycle, you might want to look into the devm_* functions for registering and creating FPGA Managers.
Quoted 1,049 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +13
-0+} + +int xmgmt_fmgr_remove (struct fpga_manager *fmgr) +{ +struct xfpga_klass *obj = fmgr->priv; + +mutex_destroy (&obj->axlf_lock); + obj->state =FPGA_MGR_STATE_UNKNOWN ; +fpga_mgr_unregister (fmgr); +vfree (obj->blob); +vfree (obj); +return 0 ; +}drivers/fpga/alveo/mgmt/xmgmt-fmgr.h new file +29
-0@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#ifndef _XMGMT_FMGR_H_ +#define _XMGMT_FMGR_H_ + +#include <linux/fpga/fpga-mgr.h> +#include <linux/mutex.h> + +#include <linux/xrt/xclbin.h> + +enum xfpga_sec_level { +XFPGA_SEC_NONE =0 , +XFPGA_SEC_DEDICATE , +XFPGA_SEC_SYSTEM , +XFPGA_SEC_MAX =XFPGA_SEC_SYSTEM , +}; + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev); +int xmgmt_fmgr_remove (struct fpga_manager *fmgr); + +#endif drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +36
-0@@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XMGMT_MAIN_IMPL_H_ +#define _XMGMT_MAIN_IMPL_H_ + +#include "xrt-subdev.h" +#include "xmgmt-main.h" + +extern struct platform_driver xmgmt_main_driver; +extern struct xrt_subdev_endpoints xrt_mgmt_main_endpoints[]; + +extern int xmgmt_ulp_download (struct platform_device *pdev,const void *xclbin); +extern int bitstream_axlf_mailbox (struct platform_device *pdev, +const void *xclbin); +extern int xmgmt_hot_reset (struct platform_device *pdev); + +/* Getting dtb for specified partition. Caller should vfree returned dtb .*/ +extern char *xmgmt_get_dtb (struct platform_device *pdev, +enum provider_kind kind); +extern char *xmgmt_get_vbnv (struct platform_device *pdev); +extern int xmgmt_get_provider_uuid (struct platform_device *pdev, +enum provider_kind kind,uuid_t *uuid); + +extern void *xmgmt_pdev2mailbox (struct platform_device *pdev); +extern void *xmgmt_mailbox_probe (struct platform_device *pdev); +extern void xmgmt_mailbox_remove (void *handle); +extern void xmgmt_peer_notify_state (void *handle,bool online); + +#endif /* _XMGMT_MAIN_IMPL_H_ */ drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +930
-0@@ -0,0 +1,930 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Peer communication via mailbox +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#include <linux/crc32c.h> +#include <linux/xrt/mailbox_proto.h> +#include "xmgmt-main-impl.h" +#include "xrt-mailbox.h" +#include "xrt-cmc.h" +#include "xrt-metadata.h" +#include "xrt-xclbin.h" +#include "xrt-clock.h" +#include "xrt-calib.h" +#include "xrt-icap.h" + +struct xmgmt_mailbox { +struct platform_device *pdev; +struct platform_device *mailbox; +struct mutex lock; +void *evt_hdl; +char *test_msg; +bool peer_in_same_domain; +}; + +#define XMGMT_MAILBOX_PRT_REQ (xmbx, send, request, sw_ch) do { \ + const char *dir = (send) ? ">>>>>" : "<<<<<"; \ + \ + if ((request)->req == XCL_MAILBOX_REQ_PEER_DATA) { \ + struct xcl_mailbox_peer_data *p = \ + (struct xcl_mailbox_peer_data *)(request)->data;\ + \ + xrt_info((xmbx)->pdev, "%s(%s) %s%s", \ + mailbox_req2name((request)->req), \ + mailbox_group_kind2name(p->kind), \ + dir, mailbox_chan2name(sw_ch)); \ + } else { \ + xrt_info((xmbx)->pdev, "%s %s%s", \ + mailbox_req2name((request)->req), \ + dir, mailbox_chan2name(sw_ch)); \ + } \ +} while (0) +#define XMGMT_MAILBOX_PRT_REQ_SEND (xmbx, req, sw_ch) \ + XMGMT_MAILBOX_PRT_REQ(xmbx, true, req, sw_ch) +#define XMGMT_MAILBOX_PRT_REQ_RECV (xmbx, req, sw_ch) \ + XMGMT_MAILBOX_PRT_REQ(xmbx, false, req, sw_ch) +#define XMGMT_MAILBOX_PRT_RESP (xmbx, resp) \ + xrt_info((xmbx)->pdev, "respond %ld bytes >>>>>%s", \ + (resp)->xmip_data_size, mailbox_chan2name((resp)->xmip_sw_ch)) + +static inline struct xmgmt_mailbox *pdev2mbx (struct platform_device *pdev) +{ +return (struct xmgmt_mailbox *)xmgmt_pdev2mailbox (pdev); +} + +static void xmgmt_mailbox_post (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,void *buf,size_t len) +{ +int rc; +struct xrt_mailbox_ioctl_post post = { + .xmip_req_id = msgid, + .xmip_sw_ch = sw_ch, + .xmip_data = buf, + .xmip_data_size = len + }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); + +if (!xmbx->mailbox) { +xrt_err (xmbx->pdev,"mailbox not available" ); +return ; + } + +if (msgid ==0 ) { +XMGMT_MAILBOX_PRT_REQ_SEND (xmbx, + (struct xcl_mailbox_req *)buf, sw_ch); + }else { +XMGMT_MAILBOX_PRT_RESP (xmbx, &post); + } + + rc =xrt_subdev_ioctl (xmbx->mailbox,XRT_MAILBOX_POST , &post); +if (rc) +xrt_err (xmbx->pdev,"failed to post msg: %d" , rc); +} + +static void xmgmt_mailbox_notify (struct xmgmt_mailbox *xmbx,bool sw_ch, +struct xcl_mailbox_req *req,size_t len) +{ +xmgmt_mailbox_post (xmbx,0 , sw_ch, req, len); +} + +static void xmgmt_mailbox_respond (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,void *buf,size_t len) +{ +mutex_lock (&xmbx->lock); +xmgmt_mailbox_post (xmbx, msgid, sw_ch, buf, len); +mutex_unlock (&xmbx->lock); +} + +static void xmgmt_mailbox_resp_test_msg (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch) +{ +struct platform_device *pdev = xmbx->pdev; +char *msg; + +mutex_lock (&xmbx->lock); + +if (xmbx->test_msg ==NULL ) { +mutex_unlock (&xmbx->lock); +xrt_err (pdev,"test msg is not set, drop request" ); +return ; + } + msg = xmbx->test_msg; + xmbx->test_msg =NULL ; + +mutex_unlock (&xmbx->lock); + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, msg,strlen (msg) +1 ); +vfree (msg); +} + +static int xmgmt_mailbox_dtb_add_prop (struct platform_device *pdev, +char *dst_dtb,const char *ep_name,const char *regmap_name, +const char *prop,const void *val,int size) +{ +int rc =xrt_md_set_prop (DEV (pdev), dst_dtb, ep_name, regmap_name, + prop, val, size); + +if (rc) { +xrt_err (pdev,"failed to set %s@(%s, %s): %d" , + ep_name, regmap_name, prop, rc); + } +return rc; +} + +static int xmgmt_mailbox_dtb_add_vbnv (struct platform_device *pdev,char *dtb) +{ +int rc =0 ; +char *vbnv =xmgmt_get_vbnv (pdev); + +if (vbnv ==NULL ) { +xrt_err (pdev,"failed to get VBNV" ); +return -ENOENT ; + } + rc =xmgmt_mailbox_dtb_add_prop (pdev, dtb,NULL ,NULL , +PROP_VBNV , vbnv,strlen (vbnv) +1 ); +kfree (vbnv); +return rc; +} + +static int xmgmt_mailbox_dtb_copy_logic_uuid (struct platform_device *pdev, +const char *src_dtb,char *dst_dtb) +{ +const void *val; +int sz; +int rc =xrt_md_get_prop (DEV (pdev), src_dtb,NULL ,NULL , +PROP_LOGIC_UUID , &val, &sz); + +if (rc) { +xrt_err (pdev,"failed to get %s: %d" ,PROP_LOGIC_UUID , rc); +return rc; + } +return xmgmt_mailbox_dtb_add_prop (pdev, dst_dtb,NULL ,NULL , +PROP_LOGIC_UUID , val, sz); +} + +static int xmgmt_mailbox_dtb_add_vrom (struct platform_device *pdev, +const char *src_dtb,char *dst_dtb) +{ +/* For compatibility for legacy xrt driver. */ +enum FeatureBitMask { +UNIFIED_PLATFORM =0x0000000000000001 + ,XARE_ENBLD =0x0000000000000002 + ,BOARD_MGMT_ENBLD =0x0000000000000004 + ,MB_SCHEDULER =0x0000000000000008 + ,PROM_MASK =0x0000000000000070 + ,DEBUG_MASK =0x000000000000FF00 + ,PEER_TO_PEER =0x0000000000010000 + ,FBM_UUID =0x0000000000020000 + ,HBM =0x0000000000040000 + ,CDMA =0x0000000000080000 + ,QDMA =0x0000000000100000 + ,RUNTIME_CLK_SCALE =0x0000000000200000 + ,PASSTHROUGH_VIRTUALIZATION =0x0000000000400000 + }; +struct FeatureRomHeader { +unsigned char EntryPointString[4 ]; +uint8_t MajorVersion; +uint8_t MinorVersion; +uint32_t VivadoBuildID; +uint32_t IPBuildID; +uint64_t TimeSinceEpoch; +unsigned char FPGAPartName[64 ]; +unsigned char VBNVName[64 ]; +uint8_t DDRChannelCount; +uint8_t DDRChannelSize; +uint64_t DRBaseAddress; +uint64_t FeatureBitMap; +unsigned char uuid[16 ]; +uint8_t HBMCount; +uint8_t HBMSize; +uint32_t CDMABaseAddress[4 ]; + } header = {0 }; +char *vbnv =xmgmt_get_vbnv (pdev); +int rc; + + *(u32 *)header.EntryPointString =0x786e6c78 ; + +if (vbnv) +strncpy (header.VBNVName, vbnv,sizeof (header.VBNVName) -1 ); +kfree (vbnv); + + header.FeatureBitMap =UNIFIED_PLATFORM ; + rc =xrt_md_get_prop (DEV (pdev), src_dtb, +NODE_CMC_FW_MEM ,NULL ,PROP_IO_OFFSET ,NULL ,NULL ); +if (rc ==0 ) + header.FeatureBitMap |=BOARD_MGMT_ENBLD ; + rc =xrt_md_get_prop (DEV (pdev), src_dtb, +NODE_ERT_FW_MEM ,NULL ,PROP_IO_OFFSET ,NULL ,NULL ); +if (rc ==0 ) + header.FeatureBitMap |=MB_SCHEDULER ; + +return xmgmt_mailbox_dtb_add_prop (pdev, dst_dtb,NULL ,NULL , +PROP_VROM , &header,sizeof (header)); +} + +static u32 xmgmt_mailbox_dtb_user_pf (struct platform_device *pdev, +const char *dtb,const char *epname,const char *regmap) +{ +const u32 *pfnump; +int rc =xrt_md_get_prop (DEV (pdev), dtb, epname, regmap, +PROP_PF_NUM , (const void **)&pfnump,NULL ); + +if (rc) +return -1 ; +return be32_to_cpu (*pfnump); +} + +static int xmgmt_mailbox_dtb_copy_user_endpoints (struct platform_device *pdev, +const char *src,char *dst) +{ +int rc =0 ; +char *epname =NULL , *regmap =NULL ; +u32 pfnum =xmgmt_mailbox_dtb_user_pf (pdev, src, +NODE_MAILBOX_USER ,NULL ); +const u32 level =cpu_to_be32 (1 ); +struct device *dev =DEV (pdev); + +if (pfnum == (u32)-1 ) { +xrt_err (pdev,"failed to get user pf num" ); + rc = -EINVAL ; + } + +for (xrt_md_get_next_endpoint (dev, src,NULL ,NULL , &epname, ®map); + rc ==0 && epname !=NULL ; +xrt_md_get_next_endpoint (dev, src, epname, regmap, + &epname, ®map)) { +if (pfnum != +xmgmt_mailbox_dtb_user_pf (pdev, src, epname, regmap)) +continue ; + rc =xrt_md_copy_endpoint (dev, dst, src, epname, regmap,NULL ); +if (rc) { +xrt_err (pdev,"failed to copy (%s, %s): %d" , + epname, regmap, rc); + }else { + rc =xrt_md_set_prop (dev, dst, epname, regmap, +PROP_PARTITION_LEVEL , &level,sizeof (level)); +if (rc) { +xrt_err (pdev, +"can't set level for (%s, %s): %d" , + epname, regmap, rc); + } + } + } +return rc; +} + +static char *xmgmt_mailbox_user_dtb (struct platform_device *pdev) +{ +/* TODO: add support for PLP. */ +const char *src =NULL ; +char *dst =NULL ; +struct device *dev =DEV (pdev); +int rc =xrt_md_create (dev, &dst); + +if (rc || dst ==NULL ) +return NULL ; + + rc =xmgmt_mailbox_dtb_add_vbnv (pdev, dst); +if (rc) + goto fail; + + src =xmgmt_get_dtb (pdev,XMGMT_BLP ); +if (src ==NULL ) { +xrt_err (pdev,"failed to get BLP dtb" ); + goto fail; + } + + rc =xmgmt_mailbox_dtb_copy_logic_uuid (pdev, src, dst); +if (rc) + goto fail; + + rc =xmgmt_mailbox_dtb_add_vrom (pdev, src, dst); +if (rc) + goto fail; + + rc =xrt_md_copy_endpoint (dev, dst, src,NODE_PARTITION_INFO , +NULL ,NODE_PARTITION_INFO_BLP ); +if (rc) + goto fail; + + rc =xrt_md_copy_endpoint (dev, dst, src,NODE_INTERFACES ,NULL ,NULL ); +if (rc) + goto fail; + + rc =xmgmt_mailbox_dtb_copy_user_endpoints (pdev, src, dst); +if (rc) + goto fail; + +xrt_md_pack (dev, dst); +vfree (src); +return dst; + +fail: +vfree (src); +vfree (dst); +return NULL ; +} + +static void xmgmt_mailbox_resp_subdev (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +char *dtb =xmgmt_mailbox_user_dtb (pdev); +long dtbsz; +struct xcl_subdev *hdr; +u64 totalsz; + +if (dtb ==NULL ) +return ; + + dtbsz =xrt_md_size (DEV (pdev), dtb); + totalsz = dtbsz +sizeof (*hdr) -sizeof (hdr->data); +if (offset !=0 || totalsz > size) { +/* Only support fetching dtb in one shot. */ +vfree (dtb); +xrt_err (pdev,"need %lldB, user buffer size is %lldB, dropped" , + totalsz, size); +return ; + } + + hdr =vzalloc (totalsz); +if (hdr ==NULL ) { +vfree (dtb); +return ; + } + + hdr->ver =1 ; + hdr->size = dtbsz; + hdr->rtncode =XRT_MSG_SUBDEV_RTN_COMPLETE ; + (void )memcpy (hdr->data, dtb, dtbsz); + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, hdr, totalsz); + +vfree (dtb); +vfree (hdr); +} + +static void xmgmt_mailbox_resp_sensor (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +struct xcl_sensor sensors = {0 }; +struct platform_device *cmcpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CMC ,PLATFORM_DEVID_NONE ); +int rc; + +if (cmcpdev) { + rc =xrt_subdev_ioctl (cmcpdev,XRT_CMC_READ_SENSORS , &sensors); + (void )xrt_subdev_put_leaf (pdev, cmcpdev); +if (rc) +xrt_err (pdev,"can't read sensors: %d" , rc); + } + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, &sensors, +min ((u64 )sizeof (sensors), size)); +} + +static int xmgmt_mailbox_get_freq (struct xmgmt_mailbox *xmbx, +enum CLOCK_TYPE type,u64 *freq,u64 *freq_cnter) +{ +struct platform_device *pdev = xmbx->pdev; +const char *clkname = +clock_type2epname (type) ?clock_type2epname (type) :"UNKNOWN" ; +struct platform_device *clkpdev = +xrt_subdev_get_leaf_by_epname (pdev, clkname); +int rc; +struct xrt_clock_ioctl_get getfreq = {0 }; + +if (clkpdev ==NULL ) { +xrt_info (pdev,"%s clock is not available" , clkname); +return -ENOENT ; + } + + rc =xrt_subdev_ioctl (clkpdev,XRT_CLOCK_GET , &getfreq); + (void )xrt_subdev_put_leaf (pdev, clkpdev); +if (rc) { +xrt_err (pdev,"can't get %s clock frequency: %d" , clkname, rc); +return rc; + } + +if (freq) + *freq = getfreq.freq; +if (freq_cnter) + *freq_cnter = getfreq.freq_cnter; +return 0 ; +} + +static int xmgmt_mailbox_get_icap_idcode (struct xmgmt_mailbox *xmbx,u64 *id) +{ +struct platform_device *pdev = xmbx->pdev; +struct platform_device *icappdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_ICAP ,PLATFORM_DEVID_NONE ); +int rc; + +if (icappdev ==NULL ) { +xrt_err (pdev,"can't find icap" ); +return -ENOENT ; + } + + rc =xrt_subdev_ioctl (icappdev,XRT_ICAP_IDCODE , id); + (void )xrt_subdev_put_leaf (pdev, icappdev); +if (rc) +xrt_err (pdev,"can't get icap idcode: %d" , rc); +return rc; +} + +static int xmgmt_mailbox_get_mig_calib (struct xmgmt_mailbox *xmbx,u64 *calib) +{ +struct platform_device *pdev = xmbx->pdev; +struct platform_device *calibpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CALIB ,PLATFORM_DEVID_NONE ); +int rc; +enum xrt_calib_results res; + +if (calibpdev ==NULL ) { +xrt_err (pdev,"can't find mig calibration subdev" ); +return -ENOENT ; + } + + rc =xrt_subdev_ioctl (calibpdev,XRT_CALIB_RESULT , &res); + (void )xrt_subdev_put_leaf (pdev, calibpdev); +if (rc) { +xrt_err (pdev,"can't get mig calibration result: %d" , rc); + }else { +if (res ==XRT_CALIB_SUCCEEDED ) + *calib =1 ; +else + *calib =0 ; + } +return rc; +} + +static void xmgmt_mailbox_resp_icap (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +struct xcl_pr_region icap = {0 }; + + (void )xmgmt_mailbox_get_freq (xmbx, +CT_DATA , &icap.freq_data, &icap.freq_cntr_data); + (void )xmgmt_mailbox_get_freq (xmbx, +CT_KERNEL , &icap.freq_kernel, &icap.freq_cntr_kernel); + (void )xmgmt_mailbox_get_freq (xmbx, +CT_SYSTEM , &icap.freq_system, &icap.freq_cntr_system); + (void )xmgmt_mailbox_get_icap_idcode (xmbx, &icap.idcode); + (void )xmgmt_mailbox_get_mig_calib (xmbx, &icap.mig_calib); +BUG_ON (sizeof (icap.uuid) !=sizeof (uuid_t)); + (void )xmgmt_get_provider_uuid (pdev,XMGMT_ULP , (uuid_t *)&icap.uuid); + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, &icap, +min ((u64 )sizeof (icap), size)); +} + +static void xmgmt_mailbox_resp_bdinfo (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +struct xcl_board_info *info =vzalloc (sizeof (*info)); +struct platform_device *cmcpdev; +int rc; + +if (info ==NULL ) +return ; + + cmcpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CMC ,PLATFORM_DEVID_NONE ); +if (cmcpdev) { + rc =xrt_subdev_ioctl (cmcpdev,XRT_CMC_READ_BOARD_INFO , info); + (void )xrt_subdev_put_leaf (pdev, cmcpdev); +if (rc) +xrt_err (pdev,"can't read board info: %d" , rc); + } + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, info, +min ((u64 )sizeof (*info), size)); + +vfree (info); +} + +static void xmgmt_mailbox_simple_respond (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,int rc) +{ +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, &rc,sizeof (rc)); +} + +static void xmgmt_mailbox_resp_peer_data (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_req *req,size_t len,u64 msgid,bool sw_ch) +{ +struct xcl_mailbox_peer_data *pdata = + (struct xcl_mailbox_peer_data *)req->data; + +if (len < (sizeof (*req) +sizeof (*pdata) -1 )) { +xrt_err (xmbx->pdev,"received corrupted %s, dropped" , +mailbox_req2name (req->req)); +return ; + } + +switch (pdata->kind) { +case XCL_SENSOR : +xmgmt_mailbox_resp_sensor (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_ICAP : +xmgmt_mailbox_resp_icap (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_BDINFO : +xmgmt_mailbox_resp_bdinfo (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_SUBDEV : +xmgmt_mailbox_resp_subdev (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_MIG_ECC : +case XCL_FIREWALL : +case XCL_DNA :/* TODO **/ +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch,0 ); +break ; +default : +xrt_err (xmbx->pdev,"%s(%s) request not handled" , +mailbox_req2name (req->req), +mailbox_group_kind2name (pdata->kind)); +break ; + } +} + +static bool xmgmt_mailbox_is_same_domain (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_conn *mb_conn) +{ +uint32_t crc_chk; +phys_addr_t paddr; +struct platform_device *pdev = xmbx->pdev; + + paddr =virt_to_phys ((void *)mb_conn->kaddr); +if (paddr != (phys_addr_t )mb_conn->paddr) { +xrt_info (pdev,"paddrs differ, user 0x%llx, mgmt 0x%llx" , + mb_conn->paddr, paddr); +return false; + } + + crc_chk =crc32c_le (~0 , (void *)mb_conn->kaddr,PAGE_SIZE ); +if (crc_chk != mb_conn->crc32) { +xrt_info (pdev,"CRCs differ, user 0x%x, mgmt 0x%x" , + mb_conn->crc32, crc_chk); +return false; + } + +return true; +} + +static void xmgmt_mailbox_resp_user_probe (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_req *req,size_t len,u64 msgid,bool sw_ch) +{ +struct xcl_mailbox_conn_resp *resp =vzalloc (sizeof (*resp)); +struct xcl_mailbox_conn *conn = (struct xcl_mailbox_conn *)req->data; + +if (resp ==NULL ) +return ; + +if (len < (sizeof (*req) +sizeof (*conn) -1 )) { +xrt_err (xmbx->pdev,"received corrupted %s, dropped" , +mailbox_req2name (req->req)); +vfree (resp); +return ; + } + + resp->conn_flags |=XCL_MB_PEER_READY ; +if (xmgmt_mailbox_is_same_domain (xmbx, conn)) { + xmbx->peer_in_same_domain = true; + resp->conn_flags |=XCL_MB_PEER_SAME_DOMAIN ; + } + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, resp,sizeof (*resp)); +vfree (resp); +} + +static void xmgmt_mailbox_resp_hot_reset (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_req *req,size_t len,u64 msgid,bool sw_ch) +{ +int ret; +struct platform_device *pdev = xmbx->pdev; + +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch,0 ); + + ret =xmgmt_hot_reset (pdev); +if (ret) +xrt_err (pdev,"failed to hot reset: %d" , ret); +else +xmgmt_peer_notify_state (xmbx, true); +} + +static void xmgmt_mailbox_resp_load_xclbin (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_req *req,size_t len,u64 msgid,bool sw_ch) +{ +struct xcl_mailbox_bitstream_kaddr *kaddr = + (struct xcl_mailbox_bitstream_kaddr *)req->data; +void *xclbin = (void *)(uintptr_t )kaddr->addr; +int ret =bitstream_axlf_mailbox (xmbx->pdev, xclbin); + +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch, ret); +} + +static void xmgmt_mailbox_listener (void *arg,void *data,size_t len, +u64 msgid,int err,bool sw_ch) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)arg; +struct platform_device *pdev = xmbx->pdev; +struct xcl_mailbox_req *req = (struct xcl_mailbox_req *)data; + +if (err) { +xrt_err (pdev,"failed to receive request: %d" , err); +return ; + } +if (len <sizeof (*req)) { +xrt_err (pdev,"received corrupted request" ); +return ; + } + +XMGMT_MAILBOX_PRT_REQ_RECV (xmbx, req, sw_ch); +switch (req->req) { +case XCL_MAILBOX_REQ_TEST_READ : +xmgmt_mailbox_resp_test_msg (xmbx, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_PEER_DATA : +xmgmt_mailbox_resp_peer_data (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_READ_P2P_BAR_ADDR :/* TODO */ +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch, -ENOTSUPP ); +break ; +case XCL_MAILBOX_REQ_USER_PROBE : +xmgmt_mailbox_resp_user_probe (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_HOT_RESET : +xmgmt_mailbox_resp_hot_reset (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_LOAD_XCLBIN_KADDR : +if (xmbx->peer_in_same_domain) { +xmgmt_mailbox_resp_load_xclbin (xmbx, + req, len, msgid, sw_ch); + }else { +xrt_err (pdev,"%s not handled, not in same domain" , +mailbox_req2name (req->req)); + } +break ; +default : +xrt_err (pdev,"%s(%d) request not handled" , +mailbox_req2name (req->req), req->req); +break ; + } +} + +static void xmgmt_mailbox_reg_listener (struct xmgmt_mailbox *xmbx) +{ +struct xrt_mailbox_ioctl_listen listen = { + xmgmt_mailbox_listener, xmbx }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); +if (!xmbx->mailbox) +return ; + (void )xrt_subdev_ioctl (xmbx->mailbox,XRT_MAILBOX_LISTEN , &listen); +} + +static void xmgmt_mailbox_unreg_listener (struct xmgmt_mailbox *xmbx) +{ +struct xrt_mailbox_ioctl_listen listen = {0 }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); +BUG_ON (!xmbx->mailbox); + (void )xrt_subdev_ioctl (xmbx->mailbox,XRT_MAILBOX_LISTEN , &listen); +} + +static bool xmgmt_mailbox_leaf_match (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +return (id ==XRT_SUBDEV_MAILBOX ); +} + +static int xmgmt_mailbox_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); +struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev *)arg; + +switch (evt) { +case XRT_EVENT_POST_CREATION : +BUG_ON (esd->xevt_subdev_id !=XRT_SUBDEV_MAILBOX ); +BUG_ON (xmbx->mailbox); +mutex_lock (&xmbx->lock); + xmbx->mailbox =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_MAILBOX ,PLATFORM_DEVID_NONE ); +xmgmt_mailbox_reg_listener (xmbx); +mutex_unlock (&xmbx->lock); +break ; +case XRT_EVENT_PRE_REMOVAL : +BUG_ON (esd->xevt_subdev_id !=XRT_SUBDEV_MAILBOX ); +BUG_ON (!xmbx->mailbox); +mutex_lock (&xmbx->lock); +xmgmt_mailbox_unreg_listener (xmbx); + (void )xrt_subdev_put_leaf (pdev, xmbx->mailbox); + xmbx->mailbox =NULL ; +mutex_unlock (&xmbx->lock); +break ; +default : +break ; + } + +return XRT_EVENT_CB_CONTINUE ; +} + +static ssize_t xmgmt_mailbox_user_dtb_show (struct file *filp, +struct kobject *kobj,struct bin_attribute *attr, +char *buf,loff_t off,size_t count) +{ +struct device *dev =kobj_to_dev (kobj); +struct platform_device *pdev =to_platform_device (dev); +char *blob =NULL ; +long size; +ssize_t ret =0 ; + + blob =xmgmt_mailbox_user_dtb (pdev); +if (!blob) { + ret = -ENOENT ; + goto failed; + } + + size =xrt_md_size (dev, blob); +if (size <=0 ) { + ret = -EINVAL ; + goto failed; + } + +if (off >= size) + goto failed; +if (off + count > size) + count = size - off; +memcpy (buf, blob + off, count); + + ret = count; +failed: +vfree (blob); +return ret; +} + +static struct bin_attribute meta_data_attr = { + .attr = { + .name ="metadata_for_user" , + .mode =0400 + }, + .read = xmgmt_mailbox_user_dtb_show, + .size =0 +}; + +static struct bin_attribute *xmgmt_mailbox_bin_attrs[] = { + &meta_data_attr, +NULL , +}; + +int xmgmt_mailbox_get_test_msg (struct xmgmt_mailbox *xmbx,bool sw_ch, +char *buf,size_t *len) +{ +int rc; +struct platform_device *pdev = xmbx->pdev; +struct xcl_mailbox_req req = {0 ,XCL_MAILBOX_REQ_TEST_READ , }; +struct xrt_mailbox_ioctl_request leaf_req = { + .xmir_sw_ch = sw_ch, + .xmir_resp_ttl =1 , + .xmir_req = &req, + .xmir_req_size =sizeof (req), + .xmir_resp = buf, + .xmir_resp_size = *len + }; + +mutex_lock (&xmbx->lock); +if (xmbx->mailbox) { +XMGMT_MAILBOX_PRT_REQ_SEND (xmbx, &req, leaf_req.xmir_sw_ch); +/* +* mgmt should never send request to peer. it should send +* either notification or response. here is the only exception +* for debugging purpose. +*/ + rc =xrt_subdev_ioctl (xmbx->mailbox, +XRT_MAILBOX_REQUEST , &leaf_req); + }else { + rc = -ENODEV ; +xrt_err (pdev,"mailbox not available" ); + } +mutex_unlock (&xmbx->lock); + +if (rc ==0 ) + *len = leaf_req.xmir_resp_size; +return rc; +} + +int xmgmt_mailbox_set_test_msg (struct xmgmt_mailbox *xmbx, +char *buf,size_t len) +{ +mutex_lock (&xmbx->lock); + +if (xmbx->test_msg) +vfree (xmbx->test_msg); + xmbx->test_msg =vmalloc (len); +if (xmbx->test_msg ==NULL ) { +mutex_unlock (&xmbx->lock); +return -ENOMEM ; + } + (void )memcpy (xmbx->test_msg, buf, len); + +mutex_unlock (&xmbx->lock); +return 0 ; +} + +static ssize_t peer_msg_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +size_t len =4096 ; +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); +int ret =xmgmt_mailbox_get_test_msg (xmbx, false, buf, &len); + +return ret ==0 ? len : ret; +} +static ssize_t peer_msg_store (struct device *dev, +struct device_attribute *da,const char *buf,size_t count) +{ +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); +int ret =xmgmt_mailbox_set_test_msg (xmbx, (char *)buf, count); + +return ret ==0 ? count : ret; +} +/* Message test i/f. */ +static DEVICE_ATTR_RW (peer_msg); + +static struct attribute *xmgmt_mailbox_attrs[] = { + &dev_attr_peer_msg.attr, +NULL , +}; + +static const struct attribute_group xmgmt_mailbox_attrgroup = { + .bin_attrs = xmgmt_mailbox_bin_attrs, + .attrs = xmgmt_mailbox_attrs, +}; + +void *xmgmt_mailbox_probe (struct platform_device *pdev) +{ +struct xmgmt_mailbox *xmbx = +devm_kzalloc (DEV (pdev),sizeof (*xmbx),GFP_KERNEL ); + +if (!xmbx) +return NULL ; + xmbx->pdev = pdev; +mutex_init (&xmbx->lock); + + xmbx->evt_hdl =xrt_subdev_add_event_cb (pdev, + xmgmt_mailbox_leaf_match,NULL , xmgmt_mailbox_event_cb); + (void )sysfs_create_group (&DEV (pdev)->kobj, &xmgmt_mailbox_attrgroup); +return xmbx; +} + +void xmgmt_mailbox_remove (void *handle) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)handle; +struct platform_device *pdev = xmbx->pdev; + + (void )sysfs_remove_group (&DEV (pdev)->kobj, &xmgmt_mailbox_attrgroup); +if (xmbx->evt_hdl) + (void )xrt_subdev_remove_event_cb (pdev, xmbx->evt_hdl); +if (xmbx->mailbox) + (void )xrt_subdev_put_leaf (pdev, xmbx->mailbox); +if (xmbx->test_msg) +vfree (xmbx->test_msg); +} + +void xmgmt_peer_notify_state (void *handle,bool online) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)handle; +struct xcl_mailbox_peer_state *st; +struct xcl_mailbox_req *req; +size_t reqlen =sizeof (*req) +sizeof (*st) -1 ; + + req =vzalloc (reqlen); +if (req ==NULL ) +return ; + + req->req =XCL_MAILBOX_REQ_MGMT_STATE ; + st = (struct xcl_mailbox_peer_state *)req->data; + st->state_flags = online ?XCL_MB_STATE_ONLINE :XCL_MB_STATE_OFFLINE ; +mutex_lock (&xmbx->lock); +xmgmt_mailbox_notify (xmbx, false, req, reqlen); +mutex_unlock (&xmbx->lock); +}drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +17
-0@@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* xclbin download +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#include <linux/firmware.h> +#include <linux/uaccess.h> +#include "xrt-xclbin.h" +#include "xrt-metadata.h" +#include "xrt-subdev.h"
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c line 27
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +10
-0+#include "xrt-gpio.h" +#include "xmgmt-main.h" +#include "xrt-icap.h" +#include "xrt-axigate.h" + +static int xmgmt_download_bitstream (struct platform_device *pdev, +const void *xclbin) +{ +struct platform_device *icap_leaf =NULL ; +struct XHwIcap_Bit_Header bit_header = {0 };
Please fix the style error in struct name ...
Quoted 1,395 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +163
-0+struct xrt_icap_ioctl_wr arg; +char *bitstream =NULL ; +int ret; + + ret =xrt_xclbin_get_section (xclbin,BITSTREAM , (void **)&bitstream, +NULL ); +if (ret || !bitstream) { +xrt_err (pdev,"bitstream not found" ); +return -ENOENT ; + } + ret =xrt_xclbin_parse_header (bitstream, +DMA_HWICAP_BITFILE_BUFFER_SIZE , &bit_header); +if (ret) { + ret = -EINVAL ; +xrt_err (pdev,"invalid bitstream header" ); + goto done; + } + icap_leaf =xrt_subdev_get_leaf_by_id (pdev,XRT_SUBDEV_ICAP , +PLATFORM_DEVID_NONE ); +if (!icap_leaf) { + ret = -ENODEV ; +xrt_err (pdev,"icap does not exist" ); + goto done; + } + arg.xiiw_bit_data = bitstream + bit_header.HeaderLength; + arg.xiiw_data_len = bit_header.BitstreamLength; + ret =xrt_subdev_ioctl (icap_leaf,XRT_ICAP_WRITE , &arg); +if (ret) +xrt_err (pdev,"write bitstream failed, ret = %d" , ret); + +done: +if (icap_leaf) +xrt_subdev_put_leaf (pdev, icap_leaf); +vfree (bitstream); + +return ret; +} + +static bool match_shell (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +const char *ulp_gate; +int ret; + +if (!pdata ||xrt_md_size (&pdev->dev, pdata->xsp_dtb) <=0 ) +return false; + + ret =xrt_md_get_epname_pointer (&pdev->dev, pdata->xsp_dtb, +NODE_GATE_ULP ,NULL , &ulp_gate); +if (ret) +return false; + + ret =xrt_md_check_uuids (&pdev->dev, pdata->xsp_dtb, arg); +if (ret) +return false; + +return true; +} + +static bool match_ulp (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +const char *ulp_gate; +int ret; + +if (!pdata ||xrt_md_size (&pdev->dev, pdata->xsp_dtb) <=0 ) +return false; + + ret =xrt_md_check_uuids (&pdev->dev, pdata->xsp_dtb, arg); +if (ret) +return false; + + ret =xrt_md_get_epname_pointer (&pdev->dev, pdata->xsp_dtb, +NODE_GATE_ULP ,NULL , &ulp_gate); +if (!ret) +return false; + +return true; +} + +int xmgmt_ulp_download (struct platform_device *pdev,const void *xclbin) +{ +struct platform_device *axigate_leaf; +char *dtb =NULL ; +int ret =0 , part_inst; + + ret =xrt_xclbin_get_metadata (DEV (pdev), xclbin, &dtb); +if (ret) { +xrt_err (pdev,"can not get partition metadata, ret %d" , ret); + goto failed; + } + + part_inst =xrt_subdev_lookup_partition (pdev, match_shell, dtb); +if (part_inst <0 ) { +xrt_err (pdev,"not found matching plp." ); + ret = -ENODEV ; + goto failed; + } + +/* +* Find ulp partition with interface uuid from incoming xclbin, which +* is verified before with matching plp partition. +*/ + part_inst =xrt_subdev_lookup_partition (pdev, match_ulp, dtb); +if (part_inst >=0 ) { + ret =xrt_subdev_destroy_partition (pdev, part_inst); +if (ret) { +xrt_err (pdev,"failed to destroy existing ulp, %d" , + ret); + goto failed; + } + } + + axigate_leaf =xrt_subdev_get_leaf_by_epname (pdev,NODE_GATE_ULP ); + +/* gate may not be exist for 0rp */ +if (axigate_leaf) { + ret =xrt_subdev_ioctl (axigate_leaf,XRT_AXIGATE_FREEZE , +NULL ); +if (ret) { +xrt_err (pdev,"can not freeze gate %s, %d" , +NODE_GATE_ULP , ret); +xrt_subdev_put_leaf (pdev, axigate_leaf); + goto failed; + } + } + ret =xmgmt_download_bitstream (pdev, xclbin); +if (axigate_leaf) { +xrt_subdev_ioctl (axigate_leaf,XRT_AXIGATE_FREE ,NULL ); + +/* Do we really need this extra toggling gate before setting +* clocks? +* xrt_subdev_ioctl(axigate_leaf, XRT_AXIGATE_FREEZE, NULL); +* xrt_subdev_ioctl(axigate_leaf, XRT_AXIGATE_FREE, NULL); +*/ + +xrt_subdev_put_leaf (pdev, axigate_leaf); + } +if (ret) { +xrt_err (pdev,"bitstream download failed, ret %d" , ret); + goto failed; + } + ret =xrt_subdev_create_partition (pdev, dtb); +if (ret <0 ) { +xrt_err (pdev,"failed creating partition, ret %d" , ret); + goto failed; + } + + ret =xrt_subdev_wait_for_partition_bringup (pdev); +if (ret) +xrt_err (pdev,"partiton bringup failed, ret %d" , ret); + +/* +* TODO: needs to check individual subdevs to see if there +* is any error, such as clock setting, memory bank calibration. +*/ + +failed: +vfree (dtb); +return ret; +}drivers/fpga/alveo/mgmt/xmgmt-main.c new file +843
-0@@ -0,0 +1,843 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Sonal Santan <[email protected]> +*/ + +#include <linux/firmware.h> +#include <linux/uaccess.h> +#include "xrt-xclbin.h" +#include "xrt-metadata.h" +#include "xrt-flash.h" +#include "xrt-subdev.h" +#include <linux/xrt/flash_xrt_data.h> +#include <linux/xrt/xmgmt-ioctl.h> +#include "xrt-gpio.h" +#include "xmgmt-main.h" +#include "xmgmt-fmgr.h" +#include "xrt-icap.h" +#include "xrt-axigate.h" +#include "xmgmt-main-impl.h" + +#define XMGMT_MAIN "xmgmt_main" + +struct xmgmt_main { +struct platform_device *pdev; +void *evt_hdl; +char *firmware_blp; +char *firmware_plp; +char *firmware_ulp; +bool flash_ready; +bool gpio_ready; +struct fpga_manager *fmgr; +void *mailbox_hdl; +struct mutex busy_mutex; + +uuid_t *blp_intf_uuids; +u32 blp_intf_uuid_num; +}; + +char *xmgmt_get_vbnv (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +const char *vbnv; +char *ret; +int i; + +if (xmm->firmware_plp) { + vbnv = ((struct axlf *)xmm->firmware_plp)-> + m_header.m_platformVBNV; + }else if (xmm->firmware_blp) { + vbnv = ((struct axlf *)xmm->firmware_blp)-> + m_header.m_platformVBNV; + }else { +return NULL ; + } + + ret =kstrdup (vbnv,GFP_KERNEL ); +for (i =0 ; i <strlen (ret); i++) { +if (ret[i] ==':' || ret[i] =='.' ) + ret[i] ='_' ; + } +return ret; +} + +static bool xmgmt_main_leaf_match (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +if (id ==XRT_SUBDEV_GPIO ) +return xrt_subdev_has_epname (pdev, arg); +else if (id ==XRT_SUBDEV_QSPI ) +return true; + +return false; +} + +static int get_dev_uuid (struct platform_device *pdev,char *uuidstr,size_t len) +{ +char uuid[16 ]; +struct platform_device *gpio_leaf; +struct xrt_gpio_ioctl_rw gpio_arg = {0 }; +int err, i, count; + + gpio_leaf =xrt_subdev_get_leaf_by_epname (pdev,NODE_BLP_ROM ); +if (!gpio_leaf) { +xrt_err (pdev,"can not get %s" ,NODE_BLP_ROM ); +return -EINVAL ; + } + + gpio_arg.xgir_id =XRT_GPIO_ROM_UUID ; + gpio_arg.xgir_buf = uuid; + gpio_arg.xgir_len =sizeof (uuid); + gpio_arg.xgir_offset =0 ; + err =xrt_subdev_ioctl (gpio_leaf,XRT_GPIO_READ , &gpio_arg); +xrt_subdev_put_leaf (pdev, gpio_leaf); +if (err) { +xrt_err (pdev,"can not get uuid: %d" , err); +return err; + } + +for (count =0 , i =sizeof (uuid) -sizeof (u32); + i >=0 && len > count; i -=sizeof (u32)) { + count +=snprintf (uuidstr + count, len - count, +"%08x" , *(u32 *)&uuid[i]); + } +return 0 ; +} + +int xmgmt_hot_reset (struct platform_device *pdev) +{ +int ret =xrt_subdev_broadcast_event (pdev,XRT_EVENT_PRE_HOT_RESET ); + +if (ret) { +xrt_err (pdev,"offline failed, hot reset is canceled" ); +return ret; + } + + (void )xrt_subdev_hot_reset (pdev); +xrt_subdev_broadcast_event (pdev,XRT_EVENT_POST_HOT_RESET ); +return 0 ; +} + +static ssize_t reset_store (struct device *dev, +struct device_attribute *da,const char *buf,size_t count) +{ +struct platform_device *pdev =to_platform_device (dev); + + (void )xmgmt_hot_reset (pdev); +return count; +} +static DEVICE_ATTR_WO (reset); + +static ssize_t VBNV_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret; +char *vbnv; +struct platform_device *pdev =to_platform_device (dev); + + vbnv =xmgmt_get_vbnv (pdev); + ret =sprintf (buf,"%s\n" , vbnv); +kfree (vbnv); +return ret; +} +static DEVICE_ATTR_RO (VBNV ); + +static ssize_t logic_uuids_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret; +char uuid[80 ]; +struct platform_device *pdev =to_platform_device (dev); + +/* +* Getting UUID pointed to by VSEC, +* should be the same as logic UUID of BLP. +* TODO: add PLP logic UUID +*/ + ret =get_dev_uuid (pdev, uuid,sizeof (uuid)); +if (ret) +return ret; + ret =sprintf (buf,"%s\n" , uuid); +return ret; +} +static DEVICE_ATTR_RO (logic_uuids); + +static inline void uuid2str (const uuid_t *uuid,char *uuidstr,size_t len) +{ +int i, p; +u8 *u = (u8 *)uuid; + +BUG_ON (sizeof (uuid_t) *2 +1 > len); +for (p =0 , i =sizeof (uuid_t) -1 ; i >=0 ; p++, i--) + (void )snprintf (&uuidstr[p*2 ],3 ,"%02x" , u[i]); +} + +static ssize_t interface_uuids_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret =0 ; +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +u32 i; + +/* +* TODO: add PLP interface UUID +*/ +for (i =0 ; i < xmm->blp_intf_uuid_num; i++) { +char uuidstr[80 ]; + +uuid2str (&xmm->blp_intf_uuids[i], uuidstr,sizeof (uuidstr)); + ret +=sprintf (buf + ret,"%s\n" , uuidstr); + } +return ret; +} +static DEVICE_ATTR_RO (interface_uuids); + +static struct attribute *xmgmt_main_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_VBNV.attr, + &dev_attr_logic_uuids.attr, + &dev_attr_interface_uuids.attr, +NULL , +}; + +static ssize_t ulp_image_write (struct file *filp,struct kobject *kobj, +struct bin_attribute *attr,char *buffer,loff_t off,size_t count) +{ +struct xmgmt_main *xmm = + dev_get_drvdata(container_of(kobj, struct device, kobj)); +struct axlf *xclbin; +ulong len; + +if (off ==0 ) { +if (count <sizeof (*xclbin)) { +xrt_err (xmm->pdev,"count is too small %ld" , count); +return -EINVAL ; + } + +if (xmm->firmware_ulp) { +vfree (xmm->firmware_ulp); + xmm->firmware_ulp =NULL ; + } + xclbin = (struct axlf *)buffer; + xmm->firmware_ulp =vmalloc (xclbin->m_header.m_length); +if (!xmm->firmware_ulp) +return -ENOMEM ; + }else + xclbin = (struct axlf *)xmm->firmware_ulp; + + len = xclbin->m_header.m_length; +if (off + count >= len && off < len) { +memcpy (xmm->firmware_ulp + off, buffer, len - off); +xmgmt_ulp_download (xmm->pdev, xmm->firmware_ulp); + }else if (off + count < len) { +memcpy (xmm->firmware_ulp + off, buffer, count); + } + +return count; +} + +static struct bin_attribute ulp_image_attr = { + .attr = { + .name ="ulp_image" , + .mode =0200 + }, + .write = ulp_image_write, + .size =0 +}; + +static struct bin_attribute *xmgmt_main_bin_attrs[] = { + &ulp_image_attr, +NULL , +}; + +static const struct attribute_group xmgmt_main_attrgroup = { + .attrs = xmgmt_main_attrs, + .bin_attrs = xmgmt_main_bin_attrs, +}; + +static int load_firmware_from_flash (struct platform_device *pdev, +char **fw_buf,size_t *len) +{ +struct platform_device *flash_leaf =NULL ; +struct flash_data_header header = {0 }; +const size_t magiclen =sizeof (header.fdh_id_begin.fdi_magic); +size_t flash_size =0 ; +int ret =0 ; +char *buf =NULL ; +struct flash_data_ident id = {0 }; +struct xrt_flash_ioctl_read frd = {0 }; + +xrt_info (pdev,"try loading fw from flash" ); + + flash_leaf =xrt_subdev_get_leaf_by_id (pdev,XRT_SUBDEV_QSPI , +PLATFORM_DEVID_NONE ); +if (flash_leaf ==NULL ) { +xrt_err (pdev,"failed to hold flash leaf" ); +return -ENODEV ; + } + + (void )xrt_subdev_ioctl (flash_leaf,XRT_FLASH_GET_SIZE , &flash_size); +if (flash_size ==0 ) { +xrt_err (pdev,"failed to get flash size" ); + ret = -EINVAL ; + goto done; + } + + frd.xfir_buf = (char *)&header; + frd.xfir_size =sizeof (header); + frd.xfir_offset = flash_size -sizeof (header); + ret =xrt_subdev_ioctl (flash_leaf,XRT_FLASH_READ , &frd); +if (ret) { +xrt_err (pdev,"failed to read header from flash: %d" , ret); + goto done; + } + +/* Pick the end ident since header is aligned in the end of flash. */ + id = header.fdh_id_end; +if (strncmp (id.fdi_magic,XRT_DATA_MAGIC , magiclen)) { +char tmp[sizeof (id.fdi_magic) +1 ] = {0 }; + +memcpy (tmp, id.fdi_magic, magiclen); +xrt_info (pdev,"ignore meta data, bad magic: %s" , tmp); + ret = -ENOENT ; + goto done; + } +if (id.fdi_version !=0 ) { +xrt_info (pdev,"flash meta data version is not supported: %d" , + id.fdi_version); + ret = -EOPNOTSUPP ; + goto done; + } + + buf =vmalloc (header.fdh_data_len); +if (buf ==NULL ) { + ret = -ENOMEM ; + goto done; + } + + frd.xfir_buf = buf; + frd.xfir_size = header.fdh_data_len; + frd.xfir_offset = header.fdh_data_offset; + ret =xrt_subdev_ioctl (flash_leaf,XRT_FLASH_READ , &frd); +if (ret) { +xrt_err (pdev,"failed to read meta data from flash: %d" , ret); + goto done; + }else if (flash_xrt_data_get_parity32 (buf, header.fdh_data_len) ^ + header.fdh_data_parity) { +xrt_err (pdev,"meta data is corrupted" ); + ret = -EINVAL ; + goto done; + } + +xrt_info (pdev,"found meta data of %d bytes @0x%x" , + header.fdh_data_len, header.fdh_data_offset); + *fw_buf = buf; + *len = header.fdh_data_len; + +done: + (void )xrt_subdev_put_leaf (pdev, flash_leaf); +return ret; +} + +static int load_firmware_from_disk (struct platform_device *pdev,char **fw_buf, +size_t *len) +{ +char uuid[80 ]; +int err =0 ; +char fw_name[256 ]; +const struct firmware *fw; + + err =get_dev_uuid (pdev, uuid,sizeof (uuid)); +if (err) +return err; + + (void )snprintf (fw_name, +sizeof (fw_name),"xilinx/%s/partition.xsabin" , uuid); +xrt_info (pdev,"try loading fw: %s" , fw_name); + + err =request_firmware (&fw, fw_name,DEV (pdev)); +if (err) +return err; + + *fw_buf =vmalloc (fw->size); + *len = fw->size; +if (*fw_buf !=NULL ) +memcpy (*fw_buf, fw->data, fw->size); +else + err = -ENOMEM ; + +release_firmware (fw); +return 0 ; +} + +static const char *xmgmt_get_axlf_firmware (struct xmgmt_main *xmm, +enum provider_kind kind) +{ +switch (kind) { +case XMGMT_BLP : +return xmm->firmware_blp; +case XMGMT_PLP : +return xmm->firmware_plp; +case XMGMT_ULP : +return xmm->firmware_ulp; +default : +xrt_err (xmm->pdev,"unknown axlf kind: %d" , kind); +return NULL ; + } +} + +char *xmgmt_get_dtb (struct platform_device *pdev,enum provider_kind kind) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +char *dtb =NULL ; +const char *provider =xmgmt_get_axlf_firmware (xmm, kind); +int rc; + +if (provider ==NULL ) +return dtb; + + rc =xrt_xclbin_get_metadata (DEV (pdev), provider, &dtb); +if (rc) +xrt_err (pdev,"failed to find dtb: %d" , rc); +return dtb; +} + +static const char *get_uuid_from_firmware (struct platform_device *pdev, +const char *axlf) +{ +const void *uuid =NULL ; +const void *uuiddup =NULL ; +void *dtb =NULL ; +int rc; + + rc =xrt_xclbin_get_section (axlf,PARTITION_METADATA , &dtb,NULL ); +if (rc) +return NULL ; + + rc =xrt_md_get_prop (DEV (pdev), dtb,NULL ,NULL , +PROP_LOGIC_UUID , &uuid,NULL ); +if (!rc) + uuiddup =kstrdup (uuid,GFP_KERNEL ); +vfree (dtb); +return uuiddup; +} + +static bool is_valid_firmware (struct platform_device *pdev, +char *fw_buf,size_t fw_len) +{ +struct axlf *axlf = (struct axlf *)fw_buf; +size_t axlflen = axlf->m_header.m_length; +const char *fw_uuid; +char dev_uuid[80 ]; +int err; + + err =get_dev_uuid (pdev, dev_uuid,sizeof (dev_uuid)); +if (err) +return false; + +if (memcmp (fw_buf,ICAP_XCLBIN_V2 ,sizeof (ICAP_XCLBIN_V2 )) !=0 ) { +xrt_err (pdev,"unknown fw format" ); +return false; + } + +if (axlflen > fw_len) { +xrt_err (pdev,"truncated fw, length: %ld, expect: %ld" , + fw_len, axlflen); +return false; + } + + fw_uuid =get_uuid_from_firmware (pdev, fw_buf); +if (fw_uuid ==NULL ||strcmp (fw_uuid, dev_uuid) !=0 ) { +xrt_err (pdev,"bad fw UUID: %s, expect: %s" , + fw_uuid ? fw_uuid :"<none>" , dev_uuid); +kfree (fw_uuid); +return false; + } + +kfree (fw_uuid); +return true; +} + +int xmgmt_get_provider_uuid (struct platform_device *pdev, +enum provider_kind kind,uuid_t *uuid) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +const char *fwbuf; +const char *fw_uuid; +int rc = -ENOENT ; + +mutex_lock (&xmm->busy_mutex); + + fwbuf =xmgmt_get_axlf_firmware (xmm, kind); +if (fwbuf ==NULL ) + goto done; + + fw_uuid =get_uuid_from_firmware (pdev, fwbuf); +if (fw_uuid ==NULL ) + goto done; + + rc =xrt_md_uuid_strtoid (DEV (pdev), fw_uuid, uuid); +kfree (fw_uuid); + +done: +mutex_unlock (&xmm->busy_mutex); +return rc; +} + +static int xmgmt_create_blp (struct xmgmt_main *xmm) +{ +struct platform_device *pdev = xmm->pdev; +int rc =0 ; +char *dtb =NULL ; + + dtb =xmgmt_get_dtb (pdev,XMGMT_BLP ); +if (dtb) { + rc =xrt_subdev_create_partition (pdev, dtb); +if (rc <0 ) +xrt_err (pdev,"failed to create BLP: %d" , rc); +else + rc =0 ; + +BUG_ON (xmm->blp_intf_uuids); +xrt_md_get_intf_uuids (&pdev->dev, dtb, + &xmm->blp_intf_uuid_num,NULL ); +if (xmm->blp_intf_uuid_num >0 ) { + xmm->blp_intf_uuids =vzalloc (sizeof (uuid_t) * + xmm->blp_intf_uuid_num); +xrt_md_get_intf_uuids (&pdev->dev, dtb, + &xmm->blp_intf_uuid_num, xmm->blp_intf_uuids); + } + } + +vfree (dtb); +return rc; +} + +static int xmgmt_main_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev *)arg; +enum xrt_subdev_id id; +int instance; +size_t fwlen; + +switch (evt) { +case XRT_EVENT_POST_CREATION : { + id = esd->xevt_subdev_id; + instance = esd->xevt_subdev_instance; +xrt_info (pdev,"processing event %d for (%d, %d)" , + evt, id, instance); + +if (id ==XRT_SUBDEV_GPIO ) + xmm->gpio_ready = true; +else if (id ==XRT_SUBDEV_QSPI ) + xmm->flash_ready = true; +else +BUG_ON (1 ); + +if (xmm->gpio_ready && xmm->flash_ready) { +int rc; + + rc =load_firmware_from_disk (pdev, &xmm->firmware_blp, + &fwlen); +if (rc !=0 ) { + rc =load_firmware_from_flash (pdev, + &xmm->firmware_blp, &fwlen); + } +if (rc ==0 &&is_valid_firmware (pdev, + xmm->firmware_blp, fwlen)) + (void )xmgmt_create_blp (xmm); +else +xrt_err (pdev, +"failed to find firmware, giving up" ); + xmm->evt_hdl =NULL ; + } +break ; + } +case XRT_EVENT_POST_ATTACH : +xmgmt_peer_notify_state (xmm->mailbox_hdl, true); +break ; +case XRT_EVENT_PRE_DETACH : +xmgmt_peer_notify_state (xmm->mailbox_hdl, false); +break ; +default : +xrt_info (pdev,"ignored event %d" , evt); +break ; + } + +return XRT_EVENT_CB_CONTINUE ; +} + +static int xmgmt_main_probe (struct platform_device *pdev) +{ +struct xmgmt_main *xmm; + +xrt_info (pdev,"probing..." ); + + xmm =devm_kzalloc (DEV (pdev),sizeof (*xmm),GFP_KERNEL ); +if (!xmm) +return -ENOMEM ; + + xmm->pdev = pdev; +platform_set_drvdata (pdev, xmm); + xmm->fmgr =xmgmt_fmgr_probe (pdev); + xmm->mailbox_hdl =xmgmt_mailbox_probe (pdev); +mutex_init (&xmm->busy_mutex); + + xmm->evt_hdl =xrt_subdev_add_event_cb (pdev, + xmgmt_main_leaf_match,NODE_BLP_ROM , xmgmt_main_event_cb); + +/* Ready to handle req thru sysfs nodes. */ +if (sysfs_create_group (&DEV (pdev)->kobj, &xmgmt_main_attrgroup)) +xrt_err (pdev,"failed to create sysfs group" ); +return 0 ; +} + +static int xmgmt_main_remove (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); + +/* By now, partition driver should prevent any inter-leaf call. */ + +xrt_info (pdev,"leaving..." ); + +if (xmm->evt_hdl) + (void )xrt_subdev_remove_event_cb (pdev, xmm->evt_hdl); +vfree (xmm->blp_intf_uuids); +vfree (xmm->firmware_blp); +vfree (xmm->firmware_plp); +vfree (xmm->firmware_ulp); + (void )xmgmt_fmgr_remove (xmm->fmgr); +xmgmt_mailbox_remove (xmm->mailbox_hdl); + (void )sysfs_remove_group (&DEV (pdev)->kobj, &xmgmt_main_attrgroup); +return 0 ; +} + +static int +xmgmt_main_leaf_ioctl (struct platform_device *pdev,u32 cmd,void *arg) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +int ret =0 ; + +xrt_info (pdev,"handling IOCTL cmd: %d" , cmd); + +switch (cmd) { +case XRT_MGMT_MAIN_GET_AXLF_SECTION : { +struct xrt_mgmt_main_ioctl_get_axlf_section *get = + (struct xrt_mgmt_main_ioctl_get_axlf_section *)arg; +const char *firmware = +xmgmt_get_axlf_firmware (xmm, get->xmmigas_axlf_kind); + +if (firmware ==NULL ) { + ret = -ENOENT ; + }else { + ret =xrt_xclbin_get_section (firmware, + get->xmmigas_section_kind, + &get->xmmigas_section, + &get->xmmigas_section_size); + } +break ; + } +case XRT_MGMT_MAIN_GET_VBNV : { +char **vbnv_p = (char **)arg; + + *vbnv_p =xmgmt_get_vbnv (pdev); +break ; + } +default : +xrt_err (pdev,"unknown cmd: %d" , cmd); + ret = -EINVAL ; +break ; + } +return ret; +} + +static int xmgmt_main_open (struct inode *inode,struct file *file) +{ +struct platform_device *pdev =xrt_devnode_open (inode); + +/* Device may have gone already when we get here. */ +if (!pdev) +return -ENODEV ; + +xrt_info (pdev,"opened" ); + file->private_data =platform_get_drvdata (pdev); +return 0 ; +} + +static int xmgmt_main_close (struct inode *inode,struct file *file) +{ +struct xmgmt_main *xmm = file->private_data; + +xrt_devnode_close (inode); + +xrt_info (xmm->pdev,"closed" ); +return 0 ; +} + +static int xmgmt_bitstream_axlf_fpga_mgr (struct xmgmt_main *xmm, +void *axlf,size_t size) +{ +int ret; +struct fpga_image_info info = {0 }; + +BUG_ON (!mutex_is_locked (&xmm->busy_mutex)); + +/* +* Should any error happens during download, we can't trust +* the cached xclbin any more. +*/ +vfree (xmm->firmware_ulp); + xmm->firmware_ulp =NULL ; + + info.buf = (char *)axlf; + info.count = size; + ret =fpga_mgr_load (xmm->fmgr, &info); +if (ret ==0 ) + xmm->firmware_ulp = axlf; + +return ret; +} + +int bitstream_axlf_mailbox (struct platform_device *pdev,const void *axlf) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +void *copy_buffer =NULL ; +size_t copy_buffer_size =0 ; +const struct axlf *xclbin_obj = axlf; +int ret =0 ; + +if (memcmp (xclbin_obj->m_magic,ICAP_XCLBIN_V2 ,sizeof (ICAP_XCLBIN_V2 ))) +return -EINVAL ; + + copy_buffer_size = xclbin_obj->m_header.m_length; +if (copy_buffer_size >MAX_XCLBIN_SIZE ) +return -EINVAL ; + copy_buffer =vmalloc (copy_buffer_size); +if (copy_buffer ==NULL ) +return -ENOMEM ; + (void )memcpy (copy_buffer, axlf, copy_buffer_size); + +mutex_lock (&xmm->busy_mutex); + ret =xmgmt_bitstream_axlf_fpga_mgr (xmm, copy_buffer, copy_buffer_size); +mutex_unlock (&xmm->busy_mutex); +if (ret) +vfree (copy_buffer); +return ret; +} + +static int bitstream_axlf_ioctl (struct xmgmt_main *xmm,const void __user *arg) +{ +void *copy_buffer =NULL ; +size_t copy_buffer_size =0 ; +struct xmgmt_ioc_bitstream_axlf ioc_obj = {0 }; +struct axlf xclbin_obj = { {0 } }; +int ret =0 ; + +if (copy_from_user ((void *)&ioc_obj, arg,sizeof (ioc_obj))) +return -EFAULT ; +if (copy_from_user ((void *)&xclbin_obj, ioc_obj.xclbin, +sizeof (xclbin_obj))) +return -EFAULT ; +if (memcmp (xclbin_obj.m_magic,ICAP_XCLBIN_V2 ,sizeof (ICAP_XCLBIN_V2 ))) +return -EINVAL ; + + copy_buffer_size = xclbin_obj.m_header.m_length; +if (copy_buffer_size >MAX_XCLBIN_SIZE ) +return -EINVAL ; + copy_buffer =vmalloc (copy_buffer_size); +if (copy_buffer ==NULL ) +return -ENOMEM ; + +if (copy_from_user (copy_buffer, ioc_obj.xclbin, copy_buffer_size)) { +vfree (copy_buffer); +return -EFAULT ; + } + + ret =xmgmt_bitstream_axlf_fpga_mgr (xmm, copy_buffer, copy_buffer_size); +if (ret) +vfree (copy_buffer); + +return ret; +} + +static long xmgmt_main_ioctl (struct file *filp,unsigned int cmd, +unsigned long arg) +{ +long result =0 ; +struct xmgmt_main *xmm = filp->private_data; + +BUG_ON (!xmm); + +if (_IOC_TYPE (cmd) !=XMGMT_IOC_MAGIC ) +return -ENOTTY ; + +mutex_lock (&xmm->busy_mutex); + +xrt_info (xmm->pdev,"ioctl cmd %d, arg %ld" , cmd, arg); +switch (cmd) { +case XMGMT_IOCICAPDOWNLOAD_AXLF : + result =bitstream_axlf_ioctl (xmm, (const void __user *)arg); +break ; +default : + result = -ENOTTY ; +break ; + } + +mutex_unlock (&xmm->busy_mutex); +return result; +} + +void *xmgmt_pdev2mailbox (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); + +return xmm->mailbox_hdl; +} + +struct xrt_subdev_endpoints xrt_mgmt_main_endpoints[] = { + { + .xse_names = (struct xrt_subdev_ep_names []){ + { .ep_name =NODE_MGMT_MAIN }, + {NULL }, + }, + .xse_min_ep =1 , + }, + {0 }, +}; + +struct xrt_subdev_drvdata xmgmt_main_data = { + .xsd_dev_ops = { + .xsd_ioctl = xmgmt_main_leaf_ioctl, + }, + .xsd_file_ops = { + .xsf_ops = { + .owner =THIS_MODULE , + .open = xmgmt_main_open, + .release = xmgmt_main_close, + .unlocked_ioctl = xmgmt_main_ioctl, + }, + .xsf_dev_name ="xmgmt" , + }, +}; + +static const struct platform_device_id xmgmt_main_id_table[] = { + {XMGMT_MAIN , (kernel_ulong_t)&xmgmt_main_data }, + { }, +}; + +struct platform_driver xmgmt_main_driver = { + .driver = { + .name =XMGMT_MAIN , + }, + .probe = xmgmt_main_probe, + .remove = xmgmt_main_remove, + .id_table = xmgmt_main_id_table, +};drivers/fpga/alveo/mgmt/xmgmt-root.c new file +375
-0@@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/aer.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> + +#include "xrt-root.h" +#include "xrt-subdev.h" +#include "xmgmt-main-impl.h" +#include "xrt-metadata.h" + +#define XMGMT_MODULE_NAME "xmgmt" +#define XMGMT_DRIVER_VERSION "4.0.0" + +#define XMGMT_PDEV (xm) ((xm)->pdev) +#define XMGMT_DEV (xm) (&(XMGMT_PDEV(xm)->dev)) +#define xmgmt_err(xm, fmt, args...) \ + dev_err(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_warn(xm, fmt, args...) \ + dev_warn(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_info(xm, fmt, args...) \ + dev_info(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_dbg(xm, fmt, args...) \ + dev_dbg(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define XMGMT_DEV_ID (pdev) \ + ((pci_domain_nr(pdev->bus) << 16) | \ + PCI_DEVID(pdev->bus->number, 0)) + +static struct class *xmgmt_class; +static const struct pci_device_id xmgmt_pci_ids[] = { + {PCI_DEVICE (0x10EE ,0xd020 ), }, + {PCI_DEVICE (0x10EE ,0x5020 ), }, + {0 , } +}; + +struct xmgmt { +struct pci_dev *pdev; +void *root; + +/* save config for pci reset */ +u32 saved_config[8 ][16 ]; +bool ready; +}; + +static int xmgmt_config_pci (struct xmgmt *xm) +{ +struct pci_dev *pdev =XMGMT_PDEV (xm); +int rc; + + rc =pcim_enable_device (pdev); +if (rc <0 ) { +xmgmt_err (xm,"failed to enable device: %d" , rc); +return rc; + } + + rc =pci_enable_pcie_error_reporting (pdev); +if (rc) +xmgmt_warn (xm,"failed to enable AER: %d" , rc); + +pci_set_master (pdev); + + rc =pcie_get_readrq (pdev); +if (rc <0 ) { +xmgmt_err (xm,"failed to read mrrs %d" , rc); +return rc; + } +if (rc >512 ) { + rc =pcie_set_readrq (pdev,512 ); +if (rc) { +xmgmt_err (xm,"failed to force mrrs %d" , rc); +return rc; + } + } + +return 0 ; +} + +static void xmgmt_save_config_space (struct pci_dev *pdev,u32 *saved_config) +{ +int i; + +for (i =0 ; i <16 ; i++) +pci_read_config_dword (pdev, i *4 , &saved_config[i]); +} + +static int xmgmt_match_slot_and_save (struct device *dev,void *data) +{ +struct xmgmt *xm = data; +struct pci_dev *pdev =to_pci_dev (dev); + +if (XMGMT_DEV_ID (pdev) ==XMGMT_DEV_ID (xm->pdev)) { +pci_cfg_access_lock (pdev); +pci_save_state (pdev); +xmgmt_save_config_space (pdev, + xm->saved_config[PCI_FUNC (pdev->devfn)]); + } + +return 0 ; +} + +static void xmgmt_pci_save_config_all (struct xmgmt *xm) +{ +bus_for_each_dev (&pci_bus_type,NULL , xm, xmgmt_match_slot_and_save); +} + +static void xmgmt_restore_config_space (struct pci_dev *pdev,u32 *config_saved) +{ +int i; +u32 val; + +for (i =0 ; i <16 ; i++) { +pci_read_config_dword (pdev, i *4 , &val); +if (val == config_saved[i]) +continue ; + +pci_write_config_dword (pdev, i *4 , config_saved[i]); +pci_read_config_dword (pdev, i *4 , &val); +if (val != config_saved[i]) { +dev_err (&pdev->dev, +"restore config at %d failed" , i *4 ); + } + } +} + +static int xmgmt_match_slot_and_restore (struct device *dev,void *data) +{ +struct xmgmt *xm = data; +struct pci_dev *pdev =to_pci_dev (dev); + +if (XMGMT_DEV_ID (pdev) ==XMGMT_DEV_ID (xm->pdev)) { +xmgmt_restore_config_space (pdev, + xm->saved_config[PCI_FUNC (pdev->devfn)]); + +pci_restore_state (pdev); +pci_cfg_access_unlock (pdev); + } + +return 0 ; +} + +static void xmgmt_pci_restore_config_all (struct xmgmt *xm) +{ +bus_for_each_dev (&pci_bus_type,NULL , xm, xmgmt_match_slot_and_restore); +} + +void xroot_hot_reset (struct pci_dev *pdev) +{ +struct xmgmt *xm =pci_get_drvdata (pdev); +struct pci_bus *bus; +u8 pci_bctl; +u16 pci_cmd, devctl; +int i; + +xmgmt_info (xm,"hot reset start" ); + +xmgmt_pci_save_config_all (xm); + +pci_disable_device (pdev); + + bus = pdev->bus; + +/* +* When flipping the SBR bit, device can fall off the bus. This is +* usually no problem at all so long as drivers are working properly +* after SBR. However, some systems complain bitterly when the device +* falls off the bus. +* The quick solution is to temporarily disable the SERR reporting of +* switch port during SBR. +*/ + +pci_read_config_word (bus->self,PCI_COMMAND , &pci_cmd); +pci_write_config_word (bus->self,PCI_COMMAND , + (pci_cmd & ~PCI_COMMAND_SERR )); +pcie_capability_read_word (bus->self,PCI_EXP_DEVCTL , &devctl); +pcie_capability_write_word (bus->self,PCI_EXP_DEVCTL , + (devctl & ~PCI_EXP_DEVCTL_FERE )); +pci_read_config_byte (bus->self,PCI_BRIDGE_CONTROL , &pci_bctl); + pci_bctl |=PCI_BRIDGE_CTL_BUS_RESET ; +pci_write_config_byte (bus->self,PCI_BRIDGE_CONTROL , pci_bctl); + +msleep (100 ); + pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET ; +pci_write_config_byte (bus->self,PCI_BRIDGE_CONTROL , pci_bctl); +ssleep (1 ); + +pcie_capability_write_word (bus->self,PCI_EXP_DEVCTL , devctl); +pci_write_config_word (bus->self,PCI_COMMAND , pci_cmd); + +pci_enable_device (pdev); + +for (i =0 ; i <300 ; i++) { +pci_read_config_word (pdev,PCI_COMMAND , &pci_cmd); +if (pci_cmd !=0xffff ) +break ; +msleep (20 ); + } + +xmgmt_info (xm,"waiting for %d ms" , i *20 ); + +xmgmt_pci_restore_config_all (xm); + +xmgmt_config_pci (xm); +} + +static int xmgmt_create_root_metadata (struct xmgmt *xm,char **root_dtb) +{ +char *dtb =NULL ; +int ret; + + ret =xrt_md_create (DEV (xm->pdev), &dtb); +if (ret) { +xmgmt_err (xm,"create metadata failed, ret %d" , ret); + goto failed; + } + + ret =xroot_add_simple_node (xm->root, dtb,NODE_TEST ); +if (ret) + goto failed; + + ret =xroot_add_vsec_node (xm->root, dtb); +if (ret == -ENOENT ) { +/* +* We may be dealing with a MFG board. +* Try vsec-golden which will bring up all hard-coded leaves +* at hard-coded offsets. +*/ + ret =xroot_add_simple_node (xm, dtb,NODE_VSEC_GOLDEN ); + }else if (ret ==0 ) { + ret =xroot_add_simple_node (xm->root, dtb,NODE_MGMT_MAIN ); + } +if (ret) + goto failed; + + *root_dtb = dtb; +return 0 ; + +failed: +vfree (dtb); +return ret; +} + +static ssize_t ready_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +struct pci_dev *pdev =to_pci_dev (dev); +struct xmgmt *xm =pci_get_drvdata (pdev); + +return sprintf (buf,"%d\n" , xm->ready); +} +static DEVICE_ATTR_RO (ready); + +static struct attribute *xmgmt_root_attrs[] = { + &dev_attr_ready.attr, +NULL +}; + +static struct attribute_group xmgmt_root_attr_group = { + .attrs = xmgmt_root_attrs, +}; + +static int xmgmt_probe (struct pci_dev *pdev,const struct pci_device_id *id) +{ +int ret; +struct device *dev =DEV (pdev); +struct xmgmt *xm =devm_kzalloc (dev,sizeof (*xm),GFP_KERNEL ); +char *dtb =NULL ; + +if (!xm) +return -ENOMEM ; + xm->pdev = pdev; +pci_set_drvdata (pdev, xm); + + ret =xmgmt_config_pci (xm); +if (ret) + goto failed; + + ret =xroot_probe (pdev, &xm->root); +if (ret) + goto failed; + + ret =xmgmt_create_root_metadata (xm, &dtb); +if (ret) + goto failed_metadata; + + ret =xroot_create_partition (xm->root, dtb); +vfree (dtb); +if (ret) +xmgmt_err (xm,"failed to create root partition: %d" , ret); + +if (!xroot_wait_for_bringup (xm->root)) +xmgmt_err (xm,"failed to bringup all partitions" ); +else + xm->ready = true; + + ret =sysfs_create_group (&pdev->dev.kobj, &xmgmt_root_attr_group); +if (ret) { +/* Warning instead of failing the probe. */ +xrt_warn (pdev,"create xmgmt root attrs failed: %d" , ret); + } + +xroot_broadcast (xm->root,XRT_EVENT_POST_ATTACH ); +xmgmt_info (xm,"%s started successfully" ,XMGMT_MODULE_NAME ); +return 0 ; + +failed_metadata: + (void )xroot_remove (xm->root); +failed: +pci_set_drvdata (pdev,NULL ); +return ret; +} + +static void xmgmt_remove (struct pci_dev *pdev) +{ +struct xmgmt *xm =pci_get_drvdata (pdev); + +xroot_broadcast (xm->root,XRT_EVENT_PRE_DETACH ); +sysfs_remove_group (&pdev->dev.kobj, &xmgmt_root_attr_group); + (void )xroot_remove (xm->root); +pci_disable_pcie_error_reporting (xm->pdev); +xmgmt_info (xm,"%s cleaned up successfully" ,XMGMT_MODULE_NAME ); +} + +static struct pci_driver xmgmt_driver = { + .name =XMGMT_MODULE_NAME , + .id_table = xmgmt_pci_ids, + .probe = xmgmt_probe, + .remove = xmgmt_remove, +}; + +static int __init xmgmt_init (void ) +{ +int res =xrt_subdev_register_external_driver (XRT_SUBDEV_MGMT_MAIN , + &xmgmt_main_driver, xrt_mgmt_main_endpoints); + +if (res) +return res; + + xmgmt_class =class_create (THIS_MODULE ,XMGMT_MODULE_NAME ); +if (IS_ERR (xmgmt_class)) +return PTR_ERR (xmgmt_class); + + res =pci_register_driver (&xmgmt_driver); +if (res) { +class_destroy (xmgmt_class); +return res; + } + +return 0 ; +} + +static __exit void xmgmt_exit(void) +{ +pci_unregister_driver (&xmgmt_driver); +class_destroy (xmgmt_class); +xrt_subdev_unregister_external_driver (XRT_SUBDEV_MGMT_MAIN ); +} + +module_init (xmgmt_init); +module_exit (xmgmt_exit); + +MODULE_DEVICE_TABLE (pci, xmgmt_pci_ids); +MODULE_VERSION (XMGMT_DRIVER_VERSION ); +MODULE_AUTHOR ("XRT Team <[email protected]>" ); +MODULE_DESCRIPTION ("Xilinx Alveo management function driver" ); +MODULE_LICENSE ("GPL v2" );Signature · 1 line
2.17.1
I have not yet looked at the whole thing, but why does the FPGA Manager only copy things around?
Any reason your partitions cannot be modelled as FPGA regions/Bridges?
It would be helpful to split this up into smaller chunks, that make it easier to review. The FPGA Manager driver should be a separate patch, etc.
- Moritz
Quoted 1 line
A message that is not in the archive (sent off-list or not yet received): BY5PR02MB60683E3470179E6AD10FEE26B9F20@BY5PR02MB6068.namprd02.prod.outlook.com
RE: [PATCH Xilinx Alveo 7/8] fpga: xrt: Alveo management physical function driver
Hello Moritz,
Quoted 5 lines
-----Original Message-----
From: Moritz Fischer <[email protected]>
Sent: Tuesday, December 1, 2020 12:52
To: Sonal Santan <[email protected]>
Cc: [email protected]; [email protected]; Max Zhen
<[email protected]>; Lizhi Hou <[email protected]>; Michal
Quoted 1 line
Simek <[email protected]>; Stefano Stabellini <[email protected]>;
Quoted 1 line
Subject: Re: [PATCH Xilinx Alveo 7/8] fpga: xrt: Alveo management physical
function driver
Quoted 20 lines
Hi Sonal,
Quoted 15 lines · Sonal Santan
From: Sonal Santan <[email protected]>
Add management physical function driver core. The driver attaches to management physical function of Alveo devices. It instantiates the root driver and one or more partition drivers which in turn instantiate platform drivers. The instantiation of partition and platform drivers is completely data driven. The driver integrates with FPGA manager and provides xclbin download service.
Signed-off-by Sonal Santan <[email protected]>--- drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930
+++++++++++++++++++
Quoted 12 lines
Quoted 12 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 +++++++++++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++++++ 7 files changed, 2597 insertions(+) create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 1 line
Review
Quoted 1 line
(quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c
Quoted 21 lines
Quoted 21 lines
new file mode 100644
index 000000000000..d451b5a2c291drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +16
-0@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#include <linux/cred.h> +#include <linux/efi.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/vmalloc.h>
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +8
-0+ +#include "xrt-subdev.h" +#include "xmgmt-fmgr.h" +#include "xrt-axigate.h" +#include "xmgmt-main-impl.h" + +/* +* Container to capture and cache full xclbin as it is passed in blocks by
FPGA
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 25
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +1
-0+* Manager. Driver needs access to full xclbin to walk through xclbin
sections.
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 27
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +2
-0+* FPGA Manager's .write() backend sends incremental blocks without any +* knowledge of xclbin format forcing us to collect the blocks and stitch
them
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 31
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +4
-0+* together here. +*/ + +struct xfpga_klass {Nit:
xfpga_privorxfpga_drvdata?drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 34
Quoted 3 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +3
-0+const struct platform_device *pdev; +struct axlf *blob; +char name[64 ];
Quoted 8 lines
Nit: 64 could be a named constant ?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 40
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +6
-0+size_t count; +size_t total_count; +struct mutex axlf_lock; +int reader_ref; +enum fpga_mgr_states state; +enum xfpga_sec_level sec_level;This appears unused, do you want to add this with the code that uses it?
This hook is for validating signature of FPGA image. Will look into adding it into the next version of the patch.
Quoted 3 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 41
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +1
-0+};Maybe add some kerneldoc markup?
Will do in the next version
Quoted 11 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 43
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +2
-0+ +struct key *xfpga_keys;Appears unused, can you introduce this together with the code using it?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 49
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +6
-0+ +static int xmgmt_pr_write_init (struct fpga_manager *mgr, +struct fpga_image_info *info,const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +const struct axlf *bin = (const struct axlf *)buf;Nit: Reverse x-mas tree please.
Quoted 4 lines
xxxxxx
xxxx
xxx
x
Will update in the next version
Quoted 15 lines
Quoted 15 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +15
-0+ +if (count <sizeof (struct axlf )) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } + +if (count > bin->m_header.m_length) { + obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -EINVAL ; + } + +/* Free up the previous blob */ +vfree (obj->blob); + obj->blob =vmalloc (bin->m_header.m_length); +if (!obj->blob) {
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 70
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +6
-0+ obj->state =FPGA_MGR_STATE_WRITE_INIT_ERR ; +return -ENOMEM ; + } + +xrt_info (obj->pdev,"Begin download of xclbin %pUb of length %lld B" , + &bin->m_header.uuid, bin->m_header.m_length);We already have framework level prints for that (admittedly somewhat less verbose). Please remove.
Will update in the next version
Quoted 33 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 74
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +4
-0+ + obj->count =0 ; + obj->total_count = bin->m_header.m_length; + obj->state =FPGA_MGR_STATE_WRITE_INIT ;Does the framework state tracking not work for you?
Quoted 17 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +17
-0+return 0 ; +} + +static int xmgmt_pr_write (struct fpga_manager *mgr, +const char *buf,size_t count) +{ +struct xfpga_klass *obj = mgr->priv; +char *curr = (char *)obj->blob; + +if ((obj->state !=FPGA_MGR_STATE_WRITE_INIT ) && + (obj->state !=FPGA_MGR_STATE_WRITE )) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + + curr += obj->count; + obj->count += count;drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 101
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+ +/* +* The xclbin buffer should not be longer than advertised in the header +*/ +if (obj->total_count < obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_ERR ; +return -EINVAL ; + } + +xrt_info (obj->pdev,"Copying block of %zu B of xclbin" , count);Please drop those.
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 102
Quoted 1 line
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +1
-0+memcpy (curr, buf, count);I'm confused. Why are we just copying things around here. What picks this up afterwards?
The current implementation caches the full FPGA image in a local buffer so we can walk various segments of the xclbin container to identify bitstreams, clock scaling metadata, etc. Full image is also needed for signature verification. Does the framework guarantee one .write call in case fpga_image_info is created with complete buffer? That will remove the need to cache the buffer.
Quoted 27 lines
Quoted 16 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +16
-0+ obj->state =FPGA_MGR_STATE_WRITE ; +return 0 ; +} + + +static int xmgmt_pr_write_complete (struct fpga_manager *mgr, +struct fpga_image_info *info) +{ +int result =0 ; +struct xfpga_klass *obj = mgr->priv; + +if (obj->state !=FPGA_MGR_STATE_WRITE ) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } +drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 128
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+/* Check if we got the complete xclbin */ +if (obj->blob->m_header.m_length != obj->count) { + obj->state =FPGA_MGR_STATE_WRITE_COMPLETE_ERR ; +return -EINVAL ; + } + + result =xmgmt_ulp_download ((void *)obj->pdev, obj->blob); + + obj->state = result ?FPGA_MGR_STATE_WRITE_COMPLETE_ERR : +FPGA_MGR_STATE_WRITE_COMPLETE ;Why the separate state tracking?
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +9
-0+xrt_info (obj->pdev,"Finish downloading of xclbin %pUb: %d" , + &obj->blob->m_header.uuid, result); +vfree (obj->blob); + obj->blob =NULL ; + obj->count =0 ; +return result; +} + +static enum fpga_mgr_states xmgmt_pr_state(struct fpga_manager
*mgr)
Quoted 47 lines
Quoted 12 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +12
-0+{ +struct xfpga_klass *obj = mgr->priv; + +return obj->state; +} + +static const struct fpga_manager_ops xmgmt_pr_ops = { + .initial_header_size =sizeof (struct axlf ), + .write_init = xmgmt_pr_write_init, + .write = xmgmt_pr_write, + .write_complete = xmgmt_pr_write_complete, + .state = xmgmt_pr_state,drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 159
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+}; + + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev) +{ +struct fpga_manager *fmgr; +int ret =0 ; +struct xfpga_klass *obj =vzalloc (sizeof (struct xfpga_klass )); + +xrt_info (pdev,"probing..." );Drop this, please.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 169
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +10
-0+if (!obj) +return ERR_PTR (-ENOMEM ); + +snprintf (obj->name,sizeof (obj->name),"Xilinx Alveo FPGA Manager" ); + obj->state =FPGA_MGR_STATE_UNKNOWN ; + obj->pdev = pdev; + fmgr =fpga_mgr_create (&pdev->dev, + obj->name, + &xmgmt_pr_ops, + obj);I think (eyeballed) this fits on two lines?
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 173
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +4
-0+if (!fmgr) +return ERR_PTR (-ENOMEM ); + + obj->sec_level =XFPGA_SEC_NONE ;Seems unused so far, please drop until it's used.
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c line 181
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +8
-0+ ret =fpga_mgr_register (fmgr); +if (ret) { +fpga_mgr_free (fmgr); +kfree (obj); +return ERR_PTR (ret); + } +mutex_init (&obj->axlf_lock); +return fmgr;
Quoted 3 lines
Since this patchset will wait at least till next cycle, you might want to look into the devm_* functions for registering and creating FPGA Managers.
Will address this in next revision of the patch.
Quoted 15 lines
Review
Quoted 15 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c new file +13
-0+} + +int xmgmt_fmgr_remove (struct fpga_manager *fmgr) +{ +struct xfpga_klass *obj = fmgr->priv; + +mutex_destroy (&obj->axlf_lock); + obj->state =FPGA_MGR_STATE_UNKNOWN ; +fpga_mgr_unregister (fmgr); +vfree (obj->blob); +vfree (obj); +return 0 ; +}(quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-fmgr.h
Quoted 27 lines
Quoted 27 lines
new file mode 100644
index 000000000000..2beba649609fdrivers/fpga/alveo/mgmt/xmgmt-fmgr.h new file +22
-0@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2019-2020 Xilinx, Inc. +* Bulk of the code borrowed from XRT mgmt driver file, fmgr.c +* +* Authors: [email protected] +*/ + +#ifndef _XMGMT_FMGR_H_ +#define _XMGMT_FMGR_H_ + +#include <linux/fpga/fpga-mgr.h> +#include <linux/mutex.h> + +#include <linux/xrt/xclbin.h> + +enum xfpga_sec_level { +XFPGA_SEC_NONE =0 , +XFPGA_SEC_DEDICATE , + XFPGA_SEC_SYSTEM,
Quoted 8 lines
Review
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-fmgr.h new file +7
-0+ XFPGA_SEC_MAX = XFPGA_SEC_SYSTEM, +}; + +struct fpga_manager *xmgmt_fmgr_probe (struct platform_device *pdev); +int xmgmt_fmgr_remove (struct fpga_manager *fmgr); + +#endif (quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-main-impl.h
Quoted 16 lines
Quoted 16 lines
new file mode 100644
index 000000000000..c89024cb8d46drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +11
-0@@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Lizhi Hou <[email protected]> +* Cheng Zhen <[email protected]> +*/ + +#ifndef _XMGMT_MAIN_IMPL_H_ +#define _XMGMT_MAIN_IMPL_H_
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-impl.h
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +8
-0+ +#include "xrt-subdev.h" +#include "xmgmt-main.h" + +extern struct platform_driver xmgmt_main_driver; +extern struct xrt_subdev_endpoints xrt_mgmt_main_endpoints[]; + +extern int xmgmt_ulp_download(struct platform_device *pdev, const void
*xclbin);
Quoted 10 lines
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +10
-0+extern int bitstream_axlf_mailbox (struct platform_device *pdev, +const void *xclbin); +extern int xmgmt_hot_reset (struct platform_device *pdev); + +/* Getting dtb for specified partition. Caller should vfree returned dtb .*/ +extern char *xmgmt_get_dtb (struct platform_device *pdev, +enum provider_kind kind); +extern char *xmgmt_get_vbnv (struct platform_device *pdev); +extern int xmgmt_get_provider_uuid (struct platform_device *pdev, +enum provider_kind kind,uuid_t *uuid);
Quoted 8 lines
Review
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-impl.h new file +7
-0+ +extern void *xmgmt_pdev2mailbox (struct platform_device *pdev); +extern void *xmgmt_mailbox_probe (struct platform_device *pdev); +extern void xmgmt_mailbox_remove (void *handle); +extern void xmgmt_peer_notify_state (void *handle,bool online); + +#endif /* _XMGMT_MAIN_IMPL_H_ */ (quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 30 lines
Quoted 30 lines
new file mode 100644
index 000000000000..b3d82fc3618bdrivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +25
-0@@ -0,0 +1,930 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Peer communication via mailbox +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#include <linux/crc32c.h> +#include <linux/xrt/mailbox_proto.h> +#include "xmgmt-main-impl.h" +#include "xrt-mailbox.h" +#include "xrt-cmc.h" +#include "xrt-metadata.h" +#include "xrt-xclbin.h" +#include "xrt-clock.h" +#include "xrt-calib.h" +#include "xrt-icap.h" + +struct xmgmt_mailbox { +struct platform_device *pdev;
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+struct platform_device *mailbox; +struct mutex lock; +void *evt_hdl; +char *test_msg; +bool peer_in_same_domain; +}; + +#define XMGMT_MAILBOX_PRT_REQ (xmbx, send, request, sw_ch)
do { \
Quoted 9 lines
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +9
-0+const char *dir = (send) ?">>>>>" :"<<<<<" ; \ + \ +if ((request)->req ==XCL_MAILBOX_REQ_PEER_DATA ) { \ +struct xcl_mailbox_peer_data *p = \ + (struct xcl_mailbox_peer_data *)(request)->data;\ + \ + xrt_info((xmbx)->pdev, "%s(%s) %s%s", \ + mailbox_req2name((request)->req), \ + mailbox_group_kind2name(p->kind), \
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ dir, mailbox_chan2name(sw_ch)); \ + }else { \ +xrt_info ((xmbx)->pdev,"%s %s%s" , \ +mailbox_req2name ((request)->req), \ + dir,mailbox_chan2name (sw_ch)); \ + } \ +}while (0 ) +#define XMGMT_MAILBOX_PRT_REQ_SEND(xmbx, req, sw_ch)
\
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c line 52
Quoted 2 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +2
-0+ XMGMT_MAILBOX_PRT_REQ(xmbx, true, req, sw_ch) +#define XMGMT_MAILBOX_PRT_REQ_RECV (xmbx, req, sw_ch)
\
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +6
-0+ XMGMT_MAILBOX_PRT_REQ(xmbx, false, req, sw_ch) +#define XMGMT_MAILBOX_PRT_RESP (xmbx, resp) \ + xrt_info((xmbx)->pdev, "respond %ld bytes >>>>>%s", \ + (resp)->xmip_data_size, mailbox_chan2name((resp)->xmip_sw_ch)) + +static inline struct xmgmt_mailbox *pdev2mbx(struct platform_device
*pdev)
Quoted 27 lines
Quoted 27 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +27
-0+{ +return (struct xmgmt_mailbox *)xmgmt_pdev2mailbox (pdev); +} + +static void xmgmt_mailbox_post (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,void *buf,size_t len) +{ +int rc; +struct xrt_mailbox_ioctl_post post = { + .xmip_req_id = msgid, + .xmip_sw_ch = sw_ch, + .xmip_data = buf, + .xmip_data_size = len + }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); + +if (!xmbx->mailbox) { +xrt_err (xmbx->pdev,"mailbox not available" ); +return ; + } + +if (msgid ==0 ) { +XMGMT_MAILBOX_PRT_REQ_SEND (xmbx, + (struct xcl_mailbox_req *)buf, sw_ch); + }else { +XMGMT_MAILBOX_PRT_RESP (xmbx, &post);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ } + + rc =xrt_subdev_ioctl (xmbx->mailbox,XRT_MAILBOX_POST , &post); +if (rc) +xrt_err (xmbx->pdev,"failed to post msg: %d" , rc); +} + +static void xmgmt_mailbox_notify(struct xmgmt_mailbox *xmbx, bool
sw_ch,
Quoted 32 lines
Quoted 32 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +32
-0+ struct xcl_mailbox_req *req, size_t len) +{ + xmgmt_mailbox_post(xmbx, 0, sw_ch, req, len); +} + +static void xmgmt_mailbox_respond (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,void *buf,size_t len) +{ +mutex_lock (&xmbx->lock); +xmgmt_mailbox_post (xmbx, msgid, sw_ch, buf, len); +mutex_unlock (&xmbx->lock); +} + +static void xmgmt_mailbox_resp_test_msg (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch) +{ +struct platform_device *pdev = xmbx->pdev; +char *msg; + +mutex_lock (&xmbx->lock); + +if (xmbx->test_msg ==NULL ) { +mutex_unlock (&xmbx->lock); +xrt_err (pdev,"test msg is not set, drop request" ); +return ; + } + msg = xmbx->test_msg; + xmbx->test_msg =NULL ; + +mutex_unlock (&xmbx->lock); + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, msg,strlen (msg) +1 );
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+vfree (msg); +} + +static int xmgmt_mailbox_dtb_add_prop (struct platform_device *pdev, +char *dst_dtb,const char *ep_name,const char *regmap_name, +const char *prop,const void *val,int size) +{ + int rc = xrt_md_set_prop(DEV(pdev), dst_dtb, ep_name,
regmap_name,
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +10
-0+ prop, val, size); + +if (rc) { +xrt_err (pdev,"failed to set %s@(%s, %s): %d" , + ep_name, regmap_name, prop, rc); + } +return rc; +} + +static int xmgmt_mailbox_dtb_add_vbnv(struct platform_device *pdev,
char *dtb)
Quoted 7 lines
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +7
-0+{ +int rc =0 ; +char *vbnv =xmgmt_get_vbnv (pdev); + +if (vbnv ==NULL ) { +xrt_err (pdev,"failed to get VBNV" ); +return -ENOENT ;
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ } + rc =xmgmt_mailbox_dtb_add_prop (pdev, dtb,NULL ,NULL , +PROP_VBNV , vbnv,strlen (vbnv) +1 ); +kfree (vbnv); +return rc; +} + +static int xmgmt_mailbox_dtb_copy_logic_uuid(struct platform_device
*pdev,
Quoted 80 lines
Quoted 80 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +80
-0+ const char *src_dtb, char *dst_dtb) +{ + const void *val; +int sz; +int rc =xrt_md_get_prop (DEV (pdev), src_dtb,NULL ,NULL , +PROP_LOGIC_UUID , &val, &sz); + +if (rc) { +xrt_err (pdev,"failed to get %s: %d" ,PROP_LOGIC_UUID , rc); +return rc; + } +return xmgmt_mailbox_dtb_add_prop (pdev, dst_dtb,NULL ,NULL , +PROP_LOGIC_UUID , val, sz); +} + +static int xmgmt_mailbox_dtb_add_vrom (struct platform_device *pdev, +const char *src_dtb,char *dst_dtb) +{ +/* For compatibility for legacy xrt driver. */ +enum FeatureBitMask { +UNIFIED_PLATFORM =0x0000000000000001 + ,XARE_ENBLD =0x0000000000000002 + ,BOARD_MGMT_ENBLD =0x0000000000000004 + ,MB_SCHEDULER =0x0000000000000008 + ,PROM_MASK =0x0000000000000070 + ,DEBUG_MASK =0x000000000000FF00 + ,PEER_TO_PEER =0x0000000000010000 + ,FBM_UUID =0x0000000000020000 + ,HBM =0x0000000000040000 + ,CDMA =0x0000000000080000 + ,QDMA =0x0000000000100000 + ,RUNTIME_CLK_SCALE =0x0000000000200000 + ,PASSTHROUGH_VIRTUALIZATION =0x0000000000400000 + }; +struct FeatureRomHeader { +unsigned char EntryPointString[4 ]; +uint8_t MajorVersion; +uint8_t MinorVersion; +uint32_t VivadoBuildID; +uint32_t IPBuildID; +uint64_t TimeSinceEpoch; +unsigned char FPGAPartName[64 ]; +unsigned char VBNVName[64 ]; +uint8_t DDRChannelCount; +uint8_t DDRChannelSize; +uint64_t DRBaseAddress; +uint64_t FeatureBitMap; +unsigned char uuid[16 ]; +uint8_t HBMCount; +uint8_t HBMSize; +uint32_t CDMABaseAddress[4 ]; + } header = {0 }; +char *vbnv =xmgmt_get_vbnv (pdev); +int rc; + + *(u32 *)header.EntryPointString =0x786e6c78 ; + +if (vbnv) +strncpy (header.VBNVName, vbnv,sizeof (header.VBNVName) -1 ); +kfree (vbnv); + + header.FeatureBitMap =UNIFIED_PLATFORM ; + rc =xrt_md_get_prop (DEV (pdev), src_dtb, +NODE_CMC_FW_MEM ,NULL ,PROP_IO_OFFSET ,NULL ,NULL ); +if (rc ==0 ) + header.FeatureBitMap |=BOARD_MGMT_ENBLD ; + rc =xrt_md_get_prop (DEV (pdev), src_dtb, +NODE_ERT_FW_MEM ,NULL ,PROP_IO_OFFSET ,NULL ,NULL ); +if (rc ==0 ) + header.FeatureBitMap |=MB_SCHEDULER ; + +return xmgmt_mailbox_dtb_add_prop (pdev, dst_dtb,NULL ,NULL , +PROP_VROM , &header,sizeof (header)); +} + +static u32 xmgmt_mailbox_dtb_user_pf (struct platform_device *pdev, +const char *dtb,const char *epname,const char *regmap) +{ +const u32 *pfnump; + int rc = xrt_md_get_prop(DEV(pdev), dtb, epname, regmap,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ PROP_PF_NUM, (const void **)&pfnump, NULL); + +if (rc) +return -1 ; +return be32_to_cpu (*pfnump); +} + +static int xmgmt_mailbox_dtb_copy_user_endpoints(struct
platform_device *pdev,
Quoted 7 lines
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +7
-0+ const char *src, char *dst) +{ + int rc = 0; +char *epname =NULL , *regmap =NULL ; +u32 pfnum =xmgmt_mailbox_dtb_user_pf (pdev, src, +NODE_MAILBOX_USER ,NULL ); +const u32 level =cpu_to_be32 (1 );
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+struct device *dev =DEV (pdev); + +if (pfnum == (u32)-1 ) { +xrt_err (pdev,"failed to get user pf num" ); + rc = -EINVAL ; + } + + for (xrt_md_get_next_endpoint(dev, src, NULL, NULL, &epname,
®map);
Quoted 50 lines
Quoted 50 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +50
-0+ rc ==0 && epname !=NULL ; + xrt_md_get_next_endpoint(dev, src, epname, regmap, + &epname, ®map)) { +if (pfnum != +xmgmt_mailbox_dtb_user_pf (pdev, src, epname, regmap)) +continue ; + rc =xrt_md_copy_endpoint (dev, dst, src, epname, regmap,NULL ); +if (rc) { +xrt_err (pdev,"failed to copy (%s, %s): %d" , + epname, regmap, rc); + }else { + rc =xrt_md_set_prop (dev, dst, epname, regmap, +PROP_PARTITION_LEVEL , &level,sizeof (level)); +if (rc) { +xrt_err (pdev, +"can't set level for (%s, %s): %d" , + epname, regmap, rc); + } + } + } +return rc; +} + +static char *xmgmt_mailbox_user_dtb (struct platform_device *pdev) +{ +/* TODO: add support for PLP. */ +const char *src =NULL ; +char *dst =NULL ; +struct device *dev =DEV (pdev); +int rc =xrt_md_create (dev, &dst); + +if (rc || dst ==NULL ) +return NULL ; + + rc =xmgmt_mailbox_dtb_add_vbnv (pdev, dst); +if (rc) + goto fail; + + src =xmgmt_get_dtb (pdev,XMGMT_BLP ); +if (src ==NULL ) { +xrt_err (pdev,"failed to get BLP dtb" ); + goto fail; + } + + rc =xmgmt_mailbox_dtb_copy_logic_uuid (pdev, src, dst); +if (rc) + goto fail; + + rc =xmgmt_mailbox_dtb_add_vrom (pdev, src, dst); +if (rc)
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ goto fail; + + rc =xrt_md_copy_endpoint (dev, dst, src,NODE_PARTITION_INFO , +NULL ,NODE_PARTITION_INFO_BLP ); +if (rc) + goto fail; + + rc = xrt_md_copy_endpoint(dev, dst, src, NODE_INTERFACES, NULL,
NULL);
Quoted 59 lines
Quoted 59 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +59
-0+if (rc) + goto fail; + + rc =xmgmt_mailbox_dtb_copy_user_endpoints (pdev, src, dst); +if (rc) + goto fail; + +xrt_md_pack (dev, dst); +vfree (src); +return dst; + +fail: +vfree (src); +vfree (dst); +return NULL ; +} + +static void xmgmt_mailbox_resp_subdev (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +char *dtb =xmgmt_mailbox_user_dtb (pdev); +long dtbsz; +struct xcl_subdev *hdr; +u64 totalsz; + +if (dtb ==NULL ) +return ; + + dtbsz =xrt_md_size (DEV (pdev), dtb); + totalsz = dtbsz +sizeof (*hdr) -sizeof (hdr->data); +if (offset !=0 || totalsz > size) { +/* Only support fetching dtb in one shot. */ +vfree (dtb); +xrt_err (pdev,"need %lldB, user buffer size is %lldB, dropped" , + totalsz, size); +return ; + } + + hdr =vzalloc (totalsz); +if (hdr ==NULL ) { +vfree (dtb); +return ; + } + + hdr->ver =1 ; + hdr->size = dtbsz; + hdr->rtncode =XRT_MSG_SUBDEV_RTN_COMPLETE ; + (void )memcpy (hdr->data, dtb, dtbsz); + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, hdr, totalsz); + +vfree (dtb); +vfree (hdr); +} + +static void xmgmt_mailbox_resp_sensor (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+struct platform_device *pdev = xmbx->pdev; +struct xcl_sensor sensors = {0 }; +struct platform_device *cmcpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CMC ,PLATFORM_DEVID_NONE ); +int rc; + +if (cmcpdev) { + rc = xrt_subdev_ioctl(cmcpdev, XRT_CMC_READ_SENSORS,
&sensors);
Quoted 7 lines
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +7
-0+ (void )xrt_subdev_put_leaf (pdev, cmcpdev); +if (rc) +xrt_err (pdev,"can't read sensors: %d" , rc); + } + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, &sensors, +min ((u64 )sizeof (sensors), size));
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+} + +static int xmgmt_mailbox_get_freq (struct xmgmt_mailbox *xmbx, +enum CLOCK_TYPE type,u64 *freq,u64 *freq_cnter) +{ +struct platform_device *pdev = xmbx->pdev; +const char *clkname = + clock_type2epname(type) ? clock_type2epname(type) :
"UNKNOWN";
Quoted 17 lines
Quoted 17 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +17
-0+struct platform_device *clkpdev = +xrt_subdev_get_leaf_by_epname (pdev, clkname); +int rc; +struct xrt_clock_ioctl_get getfreq = {0 }; + +if (clkpdev ==NULL ) { +xrt_info (pdev,"%s clock is not available" , clkname); +return -ENOENT ; + } + + rc =xrt_subdev_ioctl (clkpdev,XRT_CLOCK_GET , &getfreq); + (void )xrt_subdev_put_leaf (pdev, clkpdev); +if (rc) { +xrt_err (pdev,"can't get %s clock frequency: %d" , clkname, rc); +return rc; + } +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+if (freq) + *freq = getfreq.freq; +if (freq_cnter) + *freq_cnter = getfreq.freq_cnter; +return 0 ; +} + +static int xmgmt_mailbox_get_icap_idcode(struct xmgmt_mailbox *xmbx,
u64 *id)
Quoted 11 lines
Quoted 11 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +11
-0+{ +struct platform_device *pdev = xmbx->pdev; +struct platform_device *icappdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_ICAP ,PLATFORM_DEVID_NONE ); +int rc; + +if (icappdev ==NULL ) { +xrt_err (pdev,"can't find icap" ); +return -ENOENT ; + } +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ rc =xrt_subdev_ioctl (icappdev,XRT_ICAP_IDCODE , id); + (void )xrt_subdev_put_leaf (pdev, icappdev); +if (rc) +xrt_err (pdev,"can't get icap idcode: %d" , rc); +return rc; +} + +static int xmgmt_mailbox_get_mig_calib(struct xmgmt_mailbox *xmbx,
u64 *calib)
Quoted 33 lines
Quoted 33 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +33
-0+{ +struct platform_device *pdev = xmbx->pdev; +struct platform_device *calibpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CALIB ,PLATFORM_DEVID_NONE ); +int rc; +enum xrt_calib_results res; + +if (calibpdev ==NULL ) { +xrt_err (pdev,"can't find mig calibration subdev" ); +return -ENOENT ; + } + + rc =xrt_subdev_ioctl (calibpdev,XRT_CALIB_RESULT , &res); + (void )xrt_subdev_put_leaf (pdev, calibpdev); +if (rc) { +xrt_err (pdev,"can't get mig calibration result: %d" , rc); + }else { +if (res ==XRT_CALIB_SUCCEEDED ) + *calib =1 ; +else + *calib =0 ; + } +return rc; +} + +static void xmgmt_mailbox_resp_icap (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +struct xcl_pr_region icap = {0 }; + + (void )xmgmt_mailbox_get_freq (xmbx, +CT_DATA , &icap.freq_data, &icap.freq_cntr_data);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ (void )xmgmt_mailbox_get_freq (xmbx, +CT_KERNEL , &icap.freq_kernel, &icap.freq_cntr_kernel); + (void )xmgmt_mailbox_get_freq (xmbx, +CT_SYSTEM , &icap.freq_system, &icap.freq_cntr_system); + (void )xmgmt_mailbox_get_icap_idcode (xmbx, &icap.idcode); + (void )xmgmt_mailbox_get_mig_calib (xmbx, &icap.mig_calib); +BUG_ON (sizeof (icap.uuid) !=sizeof (uuid_t)); + (void) xmgmt_get_provider_uuid(pdev, XMGMT_ULP, (uuid_t
*)&icap.uuid);
Quoted 12 lines
Quoted 12 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +12
-0+ +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, &icap, +min ((u64 )sizeof (icap), size)); +} + +static void xmgmt_mailbox_resp_bdinfo (struct xmgmt_mailbox *xmbx, +u64 msgid,bool sw_ch,u64 offset,u64 size) +{ +struct platform_device *pdev = xmbx->pdev; +struct xcl_board_info *info =vzalloc (sizeof (*info)); +struct platform_device *cmcpdev; +int rc;
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ +if (info ==NULL ) +return ; + + cmcpdev =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_CMC ,PLATFORM_DEVID_NONE ); +if (cmcpdev) { + rc = xrt_subdev_ioctl(cmcpdev, XRT_CMC_READ_BOARD_INFO,
info);
Quoted 4 lines
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +4
-0+ (void )xrt_subdev_put_leaf (pdev, cmcpdev); +if (rc) +xrt_err (pdev,"can't read board info: %d" , rc); + }
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, info, +min ((u64 )sizeof (*info), size)); + +vfree (info); +} + +static void xmgmt_mailbox_simple_respond(struct xmgmt_mailbox
*xmbx,
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +6
-0+ u64 msgid, bool sw_ch, int rc) +{ + xmgmt_mailbox_respond(xmbx, msgid, sw_ch, &rc, sizeof(rc)); +} + +static void xmgmt_mailbox_resp_peer_data(struct xmgmt_mailbox
*xmbx,
Quoted 34 lines
Quoted 34 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +34
-0+ struct xcl_mailbox_req *req, size_t len, u64 msgid, bool sw_ch) +{ + struct xcl_mailbox_peer_data *pdata = + (struct xcl_mailbox_peer_data *)req->data; + +if (len < (sizeof (*req) +sizeof (*pdata) -1 )) { +xrt_err (xmbx->pdev,"received corrupted %s, dropped" , +mailbox_req2name (req->req)); +return ; + } + +switch (pdata->kind) { +case XCL_SENSOR : +xmgmt_mailbox_resp_sensor (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_ICAP : +xmgmt_mailbox_resp_icap (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_BDINFO : +xmgmt_mailbox_resp_bdinfo (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_SUBDEV : +xmgmt_mailbox_resp_subdev (xmbx, msgid, sw_ch, + pdata->offset, pdata->size); +break ; +case XCL_MIG_ECC : +case XCL_FIREWALL : +case XCL_DNA :/* TODO **/ +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch,0 ); +break ; +default :
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+xrt_err (xmbx->pdev,"%s(%s) request not handled" , +mailbox_req2name (req->req), +mailbox_group_kind2name (pdata->kind)); +break ; + } +} + +static bool xmgmt_mailbox_is_same_domain(struct xmgmt_mailbox
*xmbx,
Quoted 16 lines
Quoted 16 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +16
-0+ struct xcl_mailbox_conn *mb_conn) +{ +uint32_t crc_chk; +phys_addr_t paddr; +struct platform_device *pdev = xmbx->pdev; + + paddr =virt_to_phys ((void *)mb_conn->kaddr); +if (paddr != (phys_addr_t )mb_conn->paddr) { +xrt_info (pdev,"paddrs differ, user 0x%llx, mgmt 0x%llx" , + mb_conn->paddr, paddr); +return false; + } + + crc_chk =crc32c_le (~0 , (void *)mb_conn->kaddr,PAGE_SIZE ); +if (crc_chk != mb_conn->crc32) { + xrt_info(pdev, "CRCs differ, user 0x%x, mgmt 0x%x",
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ mb_conn->crc32, crc_chk); +return false; + } + +return true; +} + +static void xmgmt_mailbox_resp_user_probe(struct xmgmt_mailbox
*xmbx,
Quoted 33 lines
Quoted 33 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +33
-0+ struct xcl_mailbox_req *req, size_t len, u64 msgid, bool sw_ch) +{ + struct xcl_mailbox_conn_resp *resp = vzalloc(sizeof(*resp)); +struct xcl_mailbox_conn *conn = (struct xcl_mailbox_conn *)req->data; + +if (resp ==NULL ) +return ; + +if (len < (sizeof (*req) +sizeof (*conn) -1 )) { +xrt_err (xmbx->pdev,"received corrupted %s, dropped" , +mailbox_req2name (req->req)); +vfree (resp); +return ; + } + + resp->conn_flags |=XCL_MB_PEER_READY ; +if (xmgmt_mailbox_is_same_domain (xmbx, conn)) { + xmbx->peer_in_same_domain = true; + resp->conn_flags |=XCL_MB_PEER_SAME_DOMAIN ; + } + +xmgmt_mailbox_respond (xmbx, msgid, sw_ch, resp,sizeof (*resp)); +vfree (resp); +} + +static void xmgmt_mailbox_resp_hot_reset (struct xmgmt_mailbox *xmbx, +struct xcl_mailbox_req *req,size_t len,u64 msgid,bool sw_ch) +{ +int ret; +struct platform_device *pdev = xmbx->pdev; + +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch,0 ); +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ ret =xmgmt_hot_reset (pdev); +if (ret) +xrt_err (pdev,"failed to hot reset: %d" , ret); +else +xmgmt_peer_notify_state (xmbx, true); +} + +static void xmgmt_mailbox_resp_load_xclbin(struct xmgmt_mailbox
*xmbx,
Quoted 28 lines
Quoted 28 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +28
-0+ struct xcl_mailbox_req *req, size_t len, u64 msgid, bool sw_ch) +{ + struct xcl_mailbox_bitstream_kaddr *kaddr = + (struct xcl_mailbox_bitstream_kaddr *)req->data; +void *xclbin = (void *)(uintptr_t )kaddr->addr; +int ret =bitstream_axlf_mailbox (xmbx->pdev, xclbin); + +xmgmt_mailbox_simple_respond (xmbx, msgid, sw_ch, ret); +} + +static void xmgmt_mailbox_listener (void *arg,void *data,size_t len, +u64 msgid,int err,bool sw_ch) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)arg; +struct platform_device *pdev = xmbx->pdev; +struct xcl_mailbox_req *req = (struct xcl_mailbox_req *)data; + +if (err) { +xrt_err (pdev,"failed to receive request: %d" , err); +return ; + } +if (len <sizeof (*req)) { +xrt_err (pdev,"received corrupted request" ); +return ; + } + +XMGMT_MAILBOX_PRT_REQ_RECV (xmbx, req, sw_ch); +switch (req->req) {
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+case XCL_MAILBOX_REQ_TEST_READ : +xmgmt_mailbox_resp_test_msg (xmbx, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_PEER_DATA : +xmgmt_mailbox_resp_peer_data (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_READ_P2P_BAR_ADDR :/* TODO */ + xmgmt_mailbox_simple_respond(xmbx, msgid, sw_ch, -
ENOTSUPP);
Quoted 24 lines
Quoted 24 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +24
-0+break ; +case XCL_MAILBOX_REQ_USER_PROBE : +xmgmt_mailbox_resp_user_probe (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_HOT_RESET : +xmgmt_mailbox_resp_hot_reset (xmbx, req, len, msgid, sw_ch); +break ; +case XCL_MAILBOX_REQ_LOAD_XCLBIN_KADDR : +if (xmbx->peer_in_same_domain) { +xmgmt_mailbox_resp_load_xclbin (xmbx, + req, len, msgid, sw_ch); + }else { +xrt_err (pdev,"%s not handled, not in same domain" , +mailbox_req2name (req->req)); + } +break ; +default : +xrt_err (pdev,"%s(%d) request not handled" , +mailbox_req2name (req->req), req->req); +break ; + } +} + +static void xmgmt_mailbox_reg_listener (struct xmgmt_mailbox *xmbx)
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+{ +struct xrt_mailbox_ioctl_listen listen = { + xmgmt_mailbox_listener, xmbx }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); +if (!xmbx->mailbox) +return ; + (void) xrt_subdev_ioctl(xmbx->mailbox, XRT_MAILBOX_LISTEN,
&listen);
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +9
-0+} + +static void xmgmt_mailbox_unreg_listener (struct xmgmt_mailbox *xmbx) +{ +struct xrt_mailbox_ioctl_listen listen = {0 }; + +BUG_ON (!mutex_is_locked (&xmbx->lock)); +BUG_ON (!xmbx->mailbox); + (void) xrt_subdev_ioctl(xmbx->mailbox, XRT_MAILBOX_LISTEN,
&listen);
Quoted 5 lines
Quoted 5 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +5
-0+} + +static bool xmgmt_mailbox_leaf_match (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+return (id ==XRT_SUBDEV_MAILBOX ); +} + +static int xmgmt_mailbox_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); + struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev
*)arg;
Quoted 68 lines
Quoted 68 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +68
-0+ +switch (evt) { +case XRT_EVENT_POST_CREATION : +BUG_ON (esd->xevt_subdev_id !=XRT_SUBDEV_MAILBOX ); +BUG_ON (xmbx->mailbox); +mutex_lock (&xmbx->lock); + xmbx->mailbox =xrt_subdev_get_leaf_by_id (pdev, +XRT_SUBDEV_MAILBOX ,PLATFORM_DEVID_NONE ); +xmgmt_mailbox_reg_listener (xmbx); +mutex_unlock (&xmbx->lock); +break ; +case XRT_EVENT_PRE_REMOVAL : +BUG_ON (esd->xevt_subdev_id !=XRT_SUBDEV_MAILBOX ); +BUG_ON (!xmbx->mailbox); +mutex_lock (&xmbx->lock); +xmgmt_mailbox_unreg_listener (xmbx); + (void )xrt_subdev_put_leaf (pdev, xmbx->mailbox); + xmbx->mailbox =NULL ; +mutex_unlock (&xmbx->lock); +break ; +default : +break ; + } + +return XRT_EVENT_CB_CONTINUE ; +} + +static ssize_t xmgmt_mailbox_user_dtb_show (struct file *filp, +struct kobject *kobj,struct bin_attribute *attr, +char *buf,loff_t off,size_t count) +{ +struct device *dev =kobj_to_dev (kobj); +struct platform_device *pdev =to_platform_device (dev); +char *blob =NULL ; +long size; +ssize_t ret =0 ; + + blob =xmgmt_mailbox_user_dtb (pdev); +if (!blob) { + ret = -ENOENT ; + goto failed; + } + + size =xrt_md_size (dev, blob); +if (size <=0 ) { + ret = -EINVAL ; + goto failed; + } + +if (off >= size) + goto failed; +if (off + count > size) + count = size - off; +memcpy (buf, blob + off, count); + + ret = count; +failed: +vfree (blob); +return ret; +} + +static struct bin_attribute meta_data_attr = { + .attr = { + .name ="metadata_for_user" , + .mode =0400 + }, + .read = xmgmt_mailbox_user_dtb_show, + .size =0
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+}; + +static struct bin_attribute *xmgmt_mailbox_bin_attrs[] = { + &meta_data_attr, +NULL , +}; + +int xmgmt_mailbox_get_test_msg(struct xmgmt_mailbox *xmbx, bool
sw_ch,
Quoted 9 lines
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +9
-0+ char *buf, size_t *len) +{ + int rc; +struct platform_device *pdev = xmbx->pdev; +struct xcl_mailbox_req req = {0 ,XCL_MAILBOX_REQ_TEST_READ , }; + struct xrt_mailbox_ioctl_request leaf_req = { + .xmir_sw_ch = sw_ch, + .xmir_resp_ttl = 1, + .xmir_req = &req,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ .xmir_req_size = sizeof(req), + .xmir_resp = buf, + .xmir_resp_size = *len + }; + +mutex_lock (&xmbx->lock); +if (xmbx->mailbox) { + XMGMT_MAILBOX_PRT_REQ_SEND(xmbx, &req,
leaf_req.xmir_sw_ch);
Quoted 73 lines
Quoted 73 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +73
-0+/* +* mgmt should never send request to peer. it should send +* either notification or response. here is the only exception +* for debugging purpose. +*/ + rc =xrt_subdev_ioctl (xmbx->mailbox, +XRT_MAILBOX_REQUEST , &leaf_req); + }else { + rc = -ENODEV ; +xrt_err (pdev,"mailbox not available" ); + } +mutex_unlock (&xmbx->lock); + +if (rc ==0 ) + *len = leaf_req.xmir_resp_size; +return rc; +} + +int xmgmt_mailbox_set_test_msg (struct xmgmt_mailbox *xmbx, +char *buf,size_t len) +{ +mutex_lock (&xmbx->lock); + +if (xmbx->test_msg) +vfree (xmbx->test_msg); + xmbx->test_msg =vmalloc (len); +if (xmbx->test_msg ==NULL ) { +mutex_unlock (&xmbx->lock); +return -ENOMEM ; + } + (void )memcpy (xmbx->test_msg, buf, len); + +mutex_unlock (&xmbx->lock); +return 0 ; +} + +static ssize_t peer_msg_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +size_t len =4096 ; +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); +int ret =xmgmt_mailbox_get_test_msg (xmbx, false, buf, &len); + +return ret ==0 ? len : ret; +} +static ssize_t peer_msg_store (struct device *dev, +struct device_attribute *da,const char *buf,size_t count) +{ +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_mailbox *xmbx =pdev2mbx (pdev); +int ret =xmgmt_mailbox_set_test_msg (xmbx, (char *)buf, count); + +return ret ==0 ? count : ret; +} +/* Message test i/f. */ +static DEVICE_ATTR_RW (peer_msg); + +static struct attribute *xmgmt_mailbox_attrs[] = { + &dev_attr_peer_msg.attr, +NULL , +}; + +static const struct attribute_group xmgmt_mailbox_attrgroup = { + .bin_attrs = xmgmt_mailbox_bin_attrs, + .attrs = xmgmt_mailbox_attrs, +}; + +void *xmgmt_mailbox_probe (struct platform_device *pdev) +{ +struct xmgmt_mailbox *xmbx = +devm_kzalloc (DEV (pdev),sizeof (*xmbx),GFP_KERNEL ); +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+if (!xmbx) +return NULL ; + xmbx->pdev = pdev; +mutex_init (&xmbx->lock); + + xmbx->evt_hdl =xrt_subdev_add_event_cb (pdev, + xmgmt_mailbox_leaf_match,NULL , xmgmt_mailbox_event_cb); + (void) sysfs_create_group(&DEV(pdev)->kobj,
&xmgmt_mailbox_attrgroup);
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 9 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +9
-0+return xmbx; +} + +void xmgmt_mailbox_remove (void *handle) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)handle; +struct platform_device *pdev = xmbx->pdev; + + (void) sysfs_remove_group(&DEV(pdev)->kobj,
&xmgmt_mailbox_attrgroup);
Quoted 14 lines
Quoted 14 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +14
-0+if (xmbx->evt_hdl) + (void )xrt_subdev_remove_event_cb (pdev, xmbx->evt_hdl); +if (xmbx->mailbox) + (void )xrt_subdev_put_leaf (pdev, xmbx->mailbox); +if (xmbx->test_msg) +vfree (xmbx->test_msg); +} + +void xmgmt_peer_notify_state (void *handle,bool online) +{ +struct xmgmt_mailbox *xmbx = (struct xmgmt_mailbox *)handle; +struct xcl_mailbox_peer_state *st; +struct xcl_mailbox_req *req; +size_t reqlen =sizeof (*req) +sizeof (*st) -1 ;
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +8
-0+ + req =vzalloc (reqlen); +if (req ==NULL ) +return ; + + req->req =XCL_MAILBOX_REQ_MGMT_STATE ; + st = (struct xcl_mailbox_peer_state *)req->data; + st->state_flags = online ? XCL_MB_STATE_ONLINE :
XCL_MB_STATE_OFFLINE;
Quoted 5 lines
Review
Quoted 5 lines
drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c new file +4
-0+mutex_lock (&xmbx->lock); +xmgmt_mailbox_notify (xmbx, false, req, reqlen); +mutex_unlock (&xmbx->lock); +}(quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c
Quoted 108 lines
Quoted 22 lines
new file mode 100644
index 000000000000..042d86fcef41drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +17
-0@@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* xclbin download +* +* Authors: +* Lizhi Hou <[email protected]> +*/ + +#include <linux/firmware.h> +#include <linux/uaccess.h> +#include "xrt-xclbin.h" +#include "xrt-metadata.h" +#include "xrt-subdev.h" drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c line 27
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +10
-0+#include "xrt-gpio.h" +#include "xmgmt-main.h" +#include "xrt-icap.h" +#include "xrt-axigate.h" + +static int xmgmt_download_bitstream (struct platform_device *pdev, +const void *xclbin) +{ +struct platform_device *icap_leaf =NULL ; +struct XHwIcap_Bit_Header bit_header = {0 };Please fix the style error in struct name ...
Quoted 75 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +75
-0+struct xrt_icap_ioctl_wr arg; +char *bitstream =NULL ; +int ret; + + ret =xrt_xclbin_get_section (xclbin,BITSTREAM , (void **)&bitstream, +NULL ); +if (ret || !bitstream) { +xrt_err (pdev,"bitstream not found" ); +return -ENOENT ; + } + ret =xrt_xclbin_parse_header (bitstream, +DMA_HWICAP_BITFILE_BUFFER_SIZE , &bit_header); +if (ret) { + ret = -EINVAL ; +xrt_err (pdev,"invalid bitstream header" ); + goto done; + } + icap_leaf =xrt_subdev_get_leaf_by_id (pdev,XRT_SUBDEV_ICAP , +PLATFORM_DEVID_NONE ); +if (!icap_leaf) { + ret = -ENODEV ; +xrt_err (pdev,"icap does not exist" ); + goto done; + } + arg.xiiw_bit_data = bitstream + bit_header.HeaderLength; + arg.xiiw_data_len = bit_header.BitstreamLength; + ret =xrt_subdev_ioctl (icap_leaf,XRT_ICAP_WRITE , &arg); +if (ret) +xrt_err (pdev,"write bitstream failed, ret = %d" , ret); + +done: +if (icap_leaf) +xrt_subdev_put_leaf (pdev, icap_leaf); +vfree (bitstream); + +return ret; +} + +static bool match_shell (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +const char *ulp_gate; +int ret; + +if (!pdata ||xrt_md_size (&pdev->dev, pdata->xsp_dtb) <=0 ) +return false; + + ret =xrt_md_get_epname_pointer (&pdev->dev, pdata->xsp_dtb, +NODE_GATE_ULP ,NULL , &ulp_gate); +if (ret) +return false; + + ret =xrt_md_check_uuids (&pdev->dev, pdata->xsp_dtb, arg); +if (ret) +return false; + +return true; +} + +static bool match_ulp (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +struct xrt_subdev_platdata *pdata =DEV_PDATA (pdev); +const char *ulp_gate; +int ret; + +if (!pdata ||xrt_md_size (&pdev->dev, pdata->xsp_dtb) <=0 ) +return false; + + ret =xrt_md_check_uuids (&pdev->dev, pdata->xsp_dtb, arg); +if (ret) +return false; + + ret = xrt_md_get_epname_pointer(&pdev->dev, pdata->xsp_dtb,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +8
-0+ NODE_GATE_ULP, NULL, &ulp_gate); +if (!ret) +return false; + +return true; +} + +int xmgmt_ulp_download(struct platform_device *pdev, const void
*xclbin)
Quoted 25 lines
Quoted 25 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +25
-0+{ +struct platform_device *axigate_leaf; +char *dtb =NULL ; +int ret =0 , part_inst; + + ret =xrt_xclbin_get_metadata (DEV (pdev), xclbin, &dtb); +if (ret) { +xrt_err (pdev,"can not get partition metadata, ret %d" , ret); + goto failed; + } + + part_inst =xrt_subdev_lookup_partition (pdev, match_shell, dtb); +if (part_inst <0 ) { +xrt_err (pdev,"not found matching plp." ); + ret = -ENODEV ; + goto failed; + } + +/* +* Find ulp partition with interface uuid from incoming xclbin, which +* is verified before with matching plp partition. +*/ + part_inst =xrt_subdev_lookup_partition (pdev, match_ulp, dtb); +if (part_inst >=0 ) { + ret =xrt_subdev_destroy_partition (pdev, part_inst);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +8
-0+if (ret) { +xrt_err (pdev,"failed to destroy existing ulp, %d" , + ret); + goto failed; + } + } + + axigate_leaf = xrt_subdev_get_leaf_by_epname(pdev,
NODE_GATE_ULP);
Quoted 40 lines
Quoted 40 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +40
-0+ +/* gate may not be exist for 0rp */ +if (axigate_leaf) { + ret =xrt_subdev_ioctl (axigate_leaf,XRT_AXIGATE_FREEZE , +NULL ); +if (ret) { +xrt_err (pdev,"can not freeze gate %s, %d" , +NODE_GATE_ULP , ret); +xrt_subdev_put_leaf (pdev, axigate_leaf); + goto failed; + } + } + ret =xmgmt_download_bitstream (pdev, xclbin); +if (axigate_leaf) { +xrt_subdev_ioctl (axigate_leaf,XRT_AXIGATE_FREE ,NULL ); + +/* Do we really need this extra toggling gate before setting +* clocks? +* xrt_subdev_ioctl(axigate_leaf, XRT_AXIGATE_FREEZE, NULL); +* xrt_subdev_ioctl(axigate_leaf, XRT_AXIGATE_FREE, NULL); +*/ + +xrt_subdev_put_leaf (pdev, axigate_leaf); + } +if (ret) { +xrt_err (pdev,"bitstream download failed, ret %d" , ret); + goto failed; + } + ret =xrt_subdev_create_partition (pdev, dtb); +if (ret <0 ) { +xrt_err (pdev,"failed creating partition, ret %d" , ret); + goto failed; + } + + ret =xrt_subdev_wait_for_partition_bringup (pdev); +if (ret) +xrt_err (pdev,"partiton bringup failed, ret %d" , ret); + +/* +* TODO: needs to check individual subdevs to see if there
Quoted 8 lines
Review
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c new file +7
-0+* is any error, such as clock setting, memory bank calibration. +*/ + +failed: +vfree (dtb); +return ret; +}(quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 77 lines
Quoted 77 lines
new file mode 100644
index 000000000000..23e68e3a4ae1drivers/fpga/alveo/mgmt/xmgmt-main.c new file +72
-0@@ -0,0 +1,843 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo FPGA MGMT PF entry point driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Sonal Santan <[email protected]> +*/ + +#include <linux/firmware.h> +#include <linux/uaccess.h> +#include "xrt-xclbin.h" +#include "xrt-metadata.h" +#include "xrt-flash.h" +#include "xrt-subdev.h" +#include <linux/xrt/flash_xrt_data.h> +#include <linux/xrt/xmgmt-ioctl.h> +#include "xrt-gpio.h" +#include "xmgmt-main.h" +#include "xmgmt-fmgr.h" +#include "xrt-icap.h" +#include "xrt-axigate.h" +#include "xmgmt-main-impl.h" + +#define XMGMT_MAIN "xmgmt_main" + +struct xmgmt_main { +struct platform_device *pdev; +void *evt_hdl; +char *firmware_blp; +char *firmware_plp; +char *firmware_ulp; +bool flash_ready; +bool gpio_ready; +struct fpga_manager *fmgr; +void *mailbox_hdl; +struct mutex busy_mutex; + +uuid_t *blp_intf_uuids; +u32 blp_intf_uuid_num; +}; + +char *xmgmt_get_vbnv (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +const char *vbnv; +char *ret; +int i; + +if (xmm->firmware_plp) { + vbnv = ((struct axlf *)xmm->firmware_plp)-> + m_header.m_platformVBNV; + }else if (xmm->firmware_blp) { + vbnv = ((struct axlf *)xmm->firmware_blp)-> + m_header.m_platformVBNV; + }else { +return NULL ; + } + + ret =kstrdup (vbnv,GFP_KERNEL ); +for (i =0 ; i <strlen (ret); i++) { +if (ret[i] ==':' || ret[i] =='.' ) + ret[i] ='_' ; + } +return ret; +} + +static bool xmgmt_main_leaf_match (enum xrt_subdev_id id, +struct platform_device *pdev,void *arg) +{ +if (id ==XRT_SUBDEV_GPIO )
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+return xrt_subdev_has_epname (pdev, arg); + else if (id == XRT_SUBDEV_QSPI) + return true; + +return false; +} + +static int get_dev_uuid(struct platform_device *pdev, char *uuidstr, size_t
len)
Quoted 26 lines
Quoted 26 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +26
-0+{ +char uuid[16 ]; +struct platform_device *gpio_leaf; +struct xrt_gpio_ioctl_rw gpio_arg = {0 }; +int err, i, count; + + gpio_leaf =xrt_subdev_get_leaf_by_epname (pdev,NODE_BLP_ROM ); +if (!gpio_leaf) { +xrt_err (pdev,"can not get %s" ,NODE_BLP_ROM ); +return -EINVAL ; + } + + gpio_arg.xgir_id =XRT_GPIO_ROM_UUID ; + gpio_arg.xgir_buf = uuid; + gpio_arg.xgir_len =sizeof (uuid); + gpio_arg.xgir_offset =0 ; + err =xrt_subdev_ioctl (gpio_leaf,XRT_GPIO_READ , &gpio_arg); +xrt_subdev_put_leaf (pdev, gpio_leaf); +if (err) { +xrt_err (pdev,"can not get uuid: %d" , err); +return err; + } + +for (count =0 , i =sizeof (uuid) -sizeof (u32); + i >=0 && len > count; i -=sizeof (u32)) { + count += snprintf(uuidstr + count, len - count,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+ "%08x", *(u32 *)&uuid[i]); + } +return 0 ; +} + +int xmgmt_hot_reset (struct platform_device *pdev) +{ + int ret = xrt_subdev_broadcast_event(pdev,
XRT_EVENT_PRE_HOT_RESET);
Quoted 226 lines
Quoted 226 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +226
-0+ +if (ret) { +xrt_err (pdev,"offline failed, hot reset is canceled" ); +return ret; + } + + (void )xrt_subdev_hot_reset (pdev); +xrt_subdev_broadcast_event (pdev,XRT_EVENT_POST_HOT_RESET ); +return 0 ; +} + +static ssize_t reset_store (struct device *dev, +struct device_attribute *da,const char *buf,size_t count) +{ +struct platform_device *pdev =to_platform_device (dev); + + (void )xmgmt_hot_reset (pdev); +return count; +} +static DEVICE_ATTR_WO (reset); + +static ssize_t VBNV_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret; +char *vbnv; +struct platform_device *pdev =to_platform_device (dev); + + vbnv =xmgmt_get_vbnv (pdev); + ret =sprintf (buf,"%s\n" , vbnv); +kfree (vbnv); +return ret; +} +static DEVICE_ATTR_RO (VBNV ); + +static ssize_t logic_uuids_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret; +char uuid[80 ]; +struct platform_device *pdev =to_platform_device (dev); + +/* +* Getting UUID pointed to by VSEC, +* should be the same as logic UUID of BLP. +* TODO: add PLP logic UUID +*/ + ret =get_dev_uuid (pdev, uuid,sizeof (uuid)); +if (ret) +return ret; + ret =sprintf (buf,"%s\n" , uuid); +return ret; +} +static DEVICE_ATTR_RO (logic_uuids); + +static inline void uuid2str (const uuid_t *uuid,char *uuidstr,size_t len) +{ +int i, p; +u8 *u = (u8 *)uuid; + +BUG_ON (sizeof (uuid_t) *2 +1 > len); +for (p =0 , i =sizeof (uuid_t) -1 ; i >=0 ; p++, i--) + (void )snprintf (&uuidstr[p*2 ],3 ,"%02x" , u[i]); +} + +static ssize_t interface_uuids_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +ssize_t ret =0 ; +struct platform_device *pdev =to_platform_device (dev); +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +u32 i; + +/* +* TODO: add PLP interface UUID +*/ +for (i =0 ; i < xmm->blp_intf_uuid_num; i++) { +char uuidstr[80 ]; + +uuid2str (&xmm->blp_intf_uuids[i], uuidstr,sizeof (uuidstr)); + ret +=sprintf (buf + ret,"%s\n" , uuidstr); + } +return ret; +} +static DEVICE_ATTR_RO (interface_uuids); + +static struct attribute *xmgmt_main_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_VBNV.attr, + &dev_attr_logic_uuids.attr, + &dev_attr_interface_uuids.attr, +NULL , +}; + +static ssize_t ulp_image_write (struct file *filp,struct kobject *kobj, +struct bin_attribute *attr,char *buffer,loff_t off,size_t count) +{ +struct xmgmt_main *xmm = + dev_get_drvdata(container_of(kobj, struct device, kobj)); +struct axlf *xclbin; +ulong len; + +if (off ==0 ) { +if (count <sizeof (*xclbin)) { +xrt_err (xmm->pdev,"count is too small %ld" , count); +return -EINVAL ; + } + +if (xmm->firmware_ulp) { +vfree (xmm->firmware_ulp); + xmm->firmware_ulp =NULL ; + } + xclbin = (struct axlf *)buffer; + xmm->firmware_ulp =vmalloc (xclbin->m_header.m_length); +if (!xmm->firmware_ulp) +return -ENOMEM ; + }else + xclbin = (struct axlf *)xmm->firmware_ulp; + + len = xclbin->m_header.m_length; +if (off + count >= len && off < len) { +memcpy (xmm->firmware_ulp + off, buffer, len - off); +xmgmt_ulp_download (xmm->pdev, xmm->firmware_ulp); + }else if (off + count < len) { +memcpy (xmm->firmware_ulp + off, buffer, count); + } + +return count; +} + +static struct bin_attribute ulp_image_attr = { + .attr = { + .name ="ulp_image" , + .mode =0200 + }, + .write = ulp_image_write, + .size =0 +}; + +static struct bin_attribute *xmgmt_main_bin_attrs[] = { + &ulp_image_attr, +NULL , +}; + +static const struct attribute_group xmgmt_main_attrgroup = { + .attrs = xmgmt_main_attrs, + .bin_attrs = xmgmt_main_bin_attrs, +}; + +static int load_firmware_from_flash (struct platform_device *pdev, +char **fw_buf,size_t *len) +{ +struct platform_device *flash_leaf =NULL ; +struct flash_data_header header = {0 }; +const size_t magiclen =sizeof (header.fdh_id_begin.fdi_magic); +size_t flash_size =0 ; +int ret =0 ; +char *buf =NULL ; +struct flash_data_ident id = {0 }; +struct xrt_flash_ioctl_read frd = {0 }; + +xrt_info (pdev,"try loading fw from flash" ); + + flash_leaf =xrt_subdev_get_leaf_by_id (pdev,XRT_SUBDEV_QSPI , +PLATFORM_DEVID_NONE ); +if (flash_leaf ==NULL ) { +xrt_err (pdev,"failed to hold flash leaf" ); +return -ENODEV ; + } + + (void )xrt_subdev_ioctl (flash_leaf,XRT_FLASH_GET_SIZE , &flash_size); +if (flash_size ==0 ) { +xrt_err (pdev,"failed to get flash size" ); + ret = -EINVAL ; + goto done; + } + + frd.xfir_buf = (char *)&header; + frd.xfir_size =sizeof (header); + frd.xfir_offset = flash_size -sizeof (header); + ret =xrt_subdev_ioctl (flash_leaf,XRT_FLASH_READ , &frd); +if (ret) { +xrt_err (pdev,"failed to read header from flash: %d" , ret); + goto done; + } + +/* Pick the end ident since header is aligned in the end of flash. */ + id = header.fdh_id_end; +if (strncmp (id.fdi_magic,XRT_DATA_MAGIC , magiclen)) { +char tmp[sizeof (id.fdi_magic) +1 ] = {0 }; + +memcpy (tmp, id.fdi_magic, magiclen); +xrt_info (pdev,"ignore meta data, bad magic: %s" , tmp); + ret = -ENOENT ; + goto done; + } +if (id.fdi_version !=0 ) { +xrt_info (pdev,"flash meta data version is not supported: %d" , + id.fdi_version); + ret = -EOPNOTSUPP ; + goto done; + } + + buf =vmalloc (header.fdh_data_len); +if (buf ==NULL ) { + ret = -ENOMEM ; + goto done; + } + + frd.xfir_buf = buf; + frd.xfir_size = header.fdh_data_len; + frd.xfir_offset = header.fdh_data_offset; + ret =xrt_subdev_ioctl (flash_leaf,XRT_FLASH_READ , &frd); +if (ret) { +xrt_err (pdev,"failed to read meta data from flash: %d" , ret); + goto done; + }else if (flash_xrt_data_get_parity32 (buf, header.fdh_data_len) ^ + header.fdh_data_parity) { +xrt_err (pdev,"meta data is corrupted" ); + ret = -EINVAL ; + goto done; + } + +xrt_info (pdev,"found meta data of %d bytes @0x%x" , + header.fdh_data_len, header.fdh_data_offset); + *fw_buf = buf;
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+ *len = header.fdh_data_len; + +done: + (void )xrt_subdev_put_leaf (pdev, flash_leaf); +return ret; +} + +static int load_firmware_from_disk(struct platform_device *pdev, char
**fw_buf,
Quoted 39 lines
Quoted 39 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +39
-0+ size_t *len) +{ +char uuid[80 ]; +int err =0 ; +char fw_name[256 ]; +const struct firmware *fw; + + err =get_dev_uuid (pdev, uuid,sizeof (uuid)); +if (err) +return err; + + (void )snprintf (fw_name, +sizeof (fw_name),"xilinx/%s/partition.xsabin" , uuid); +xrt_info (pdev,"try loading fw: %s" , fw_name); + + err =request_firmware (&fw, fw_name,DEV (pdev)); +if (err) +return err; + + *fw_buf =vmalloc (fw->size); + *len = fw->size; +if (*fw_buf !=NULL ) +memcpy (*fw_buf, fw->data, fw->size); +else + err = -ENOMEM ; + +release_firmware (fw); +return 0 ; +} + +static const char *xmgmt_get_axlf_firmware (struct xmgmt_main *xmm, +enum provider_kind kind) +{ +switch (kind) { +case XMGMT_BLP : +return xmm->firmware_blp; +case XMGMT_PLP : +return xmm->firmware_plp; +case XMGMT_ULP :
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+return xmm->firmware_ulp; +default : +xrt_err (xmm->pdev,"unknown axlf kind: %d" , kind); +return NULL ; + } +} + +char *xmgmt_get_dtb(struct platform_device *pdev, enum provider_kind
kind)
Quoted 123 lines
Quoted 123 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +123
-0+{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +char *dtb =NULL ; +const char *provider =xmgmt_get_axlf_firmware (xmm, kind); +int rc; + +if (provider ==NULL ) +return dtb; + + rc =xrt_xclbin_get_metadata (DEV (pdev), provider, &dtb); +if (rc) +xrt_err (pdev,"failed to find dtb: %d" , rc); +return dtb; +} + +static const char *get_uuid_from_firmware (struct platform_device *pdev, +const char *axlf) +{ +const void *uuid =NULL ; +const void *uuiddup =NULL ; +void *dtb =NULL ; +int rc; + + rc =xrt_xclbin_get_section (axlf,PARTITION_METADATA , &dtb,NULL ); +if (rc) +return NULL ; + + rc =xrt_md_get_prop (DEV (pdev), dtb,NULL ,NULL , +PROP_LOGIC_UUID , &uuid,NULL ); +if (!rc) + uuiddup =kstrdup (uuid,GFP_KERNEL ); +vfree (dtb); +return uuiddup; +} + +static bool is_valid_firmware (struct platform_device *pdev, +char *fw_buf,size_t fw_len) +{ +struct axlf *axlf = (struct axlf *)fw_buf; +size_t axlflen = axlf->m_header.m_length; +const char *fw_uuid; +char dev_uuid[80 ]; +int err; + + err =get_dev_uuid (pdev, dev_uuid,sizeof (dev_uuid)); +if (err) +return false; + +if (memcmp (fw_buf,ICAP_XCLBIN_V2 ,sizeof (ICAP_XCLBIN_V2 )) !=0 ) { +xrt_err (pdev,"unknown fw format" ); +return false; + } + +if (axlflen > fw_len) { +xrt_err (pdev,"truncated fw, length: %ld, expect: %ld" , + fw_len, axlflen); +return false; + } + + fw_uuid =get_uuid_from_firmware (pdev, fw_buf); +if (fw_uuid ==NULL ||strcmp (fw_uuid, dev_uuid) !=0 ) { +xrt_err (pdev,"bad fw UUID: %s, expect: %s" , + fw_uuid ? fw_uuid :"<none>" , dev_uuid); +kfree (fw_uuid); +return false; + } + +kfree (fw_uuid); +return true; +} + +int xmgmt_get_provider_uuid (struct platform_device *pdev, +enum provider_kind kind,uuid_t *uuid) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +const char *fwbuf; +const char *fw_uuid; +int rc = -ENOENT ; + +mutex_lock (&xmm->busy_mutex); + + fwbuf =xmgmt_get_axlf_firmware (xmm, kind); +if (fwbuf ==NULL ) + goto done; + + fw_uuid =get_uuid_from_firmware (pdev, fwbuf); +if (fw_uuid ==NULL ) + goto done; + + rc =xrt_md_uuid_strtoid (DEV (pdev), fw_uuid, uuid); +kfree (fw_uuid); + +done: +mutex_unlock (&xmm->busy_mutex); +return rc; +} + +static int xmgmt_create_blp (struct xmgmt_main *xmm) +{ +struct platform_device *pdev = xmm->pdev; +int rc =0 ; +char *dtb =NULL ; + + dtb =xmgmt_get_dtb (pdev,XMGMT_BLP ); +if (dtb) { + rc =xrt_subdev_create_partition (pdev, dtb); +if (rc <0 ) +xrt_err (pdev,"failed to create BLP: %d" , rc); +else + rc =0 ; + +BUG_ON (xmm->blp_intf_uuids); +xrt_md_get_intf_uuids (&pdev->dev, dtb, + &xmm->blp_intf_uuid_num,NULL ); +if (xmm->blp_intf_uuid_num >0 ) { + xmm->blp_intf_uuids =vzalloc (sizeof (uuid_t) * + xmm->blp_intf_uuid_num); +xrt_md_get_intf_uuids (&pdev->dev, dtb, + &xmm->blp_intf_uuid_num, xmm->blp_intf_uuids); + } + } + +vfree (dtb);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+return rc; +} + +static int xmgmt_main_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); + struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev
*)arg;
Quoted 61 lines
Quoted 61 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +61
-0+enum xrt_subdev_id id; +int instance; +size_t fwlen; + +switch (evt) { +case XRT_EVENT_POST_CREATION : { + id = esd->xevt_subdev_id; + instance = esd->xevt_subdev_instance; +xrt_info (pdev,"processing event %d for (%d, %d)" , + evt, id, instance); + +if (id ==XRT_SUBDEV_GPIO ) + xmm->gpio_ready = true; +else if (id ==XRT_SUBDEV_QSPI ) + xmm->flash_ready = true; +else +BUG_ON (1 ); + +if (xmm->gpio_ready && xmm->flash_ready) { +int rc; + + rc =load_firmware_from_disk (pdev, &xmm->firmware_blp, + &fwlen); +if (rc !=0 ) { + rc =load_firmware_from_flash (pdev, + &xmm->firmware_blp, &fwlen); + } +if (rc ==0 &&is_valid_firmware (pdev, + xmm->firmware_blp, fwlen)) + (void )xmgmt_create_blp (xmm); +else +xrt_err (pdev, +"failed to find firmware, giving up" ); + xmm->evt_hdl =NULL ; + } +break ; + } +case XRT_EVENT_POST_ATTACH : +xmgmt_peer_notify_state (xmm->mailbox_hdl, true); +break ; +case XRT_EVENT_PRE_DETACH : +xmgmt_peer_notify_state (xmm->mailbox_hdl, false); +break ; +default : +xrt_info (pdev,"ignored event %d" , evt); +break ; + } + +return XRT_EVENT_CB_CONTINUE ; +} + +static int xmgmt_main_probe (struct platform_device *pdev) +{ +struct xmgmt_main *xmm; + +xrt_info (pdev,"probing..." ); + + xmm =devm_kzalloc (DEV (pdev),sizeof (*xmm),GFP_KERNEL ); +if (!xmm) +return -ENOMEM ; +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+ xmm->pdev = pdev; +platform_set_drvdata (pdev, xmm); + xmm->fmgr =xmgmt_fmgr_probe (pdev); + xmm->mailbox_hdl =xmgmt_mailbox_probe (pdev); +mutex_init (&xmm->busy_mutex); + + xmm->evt_hdl = xrt_subdev_add_event_cb(pdev, + xmgmt_main_leaf_match, NODE_BLP_ROM,
xmgmt_main_event_cb);
Quoted 16 lines
Quoted 16 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +16
-0+ +/* Ready to handle req thru sysfs nodes. */ +if (sysfs_create_group (&DEV (pdev)->kobj, &xmgmt_main_attrgroup)) +xrt_err (pdev,"failed to create sysfs group" ); +return 0 ; +} + +static int xmgmt_main_remove (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); + +/* By now, partition driver should prevent any inter-leaf call. */ + +xrt_info (pdev,"leaving..." ); + +if (xmm->evt_hdl)
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+ (void )xrt_subdev_remove_event_cb (pdev, xmm->evt_hdl); +vfree (xmm->blp_intf_uuids); +vfree (xmm->firmware_blp); +vfree (xmm->firmware_plp); +vfree (xmm->firmware_ulp); + (void )xmgmt_fmgr_remove (xmm->fmgr); +xmgmt_mailbox_remove (xmm->mailbox_hdl); + (void) sysfs_remove_group(&DEV(pdev)->kobj,
&xmgmt_main_attrgroup);
Quoted 5 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 5 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +5
-0+return 0 ; +} + +static int +xmgmt_main_leaf_ioctl(struct platform_device *pdev, u32 cmd, void
*arg)
Quoted 85 lines
Quoted 85 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +85
-0+{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +int ret =0 ; + +xrt_info (pdev,"handling IOCTL cmd: %d" , cmd); + +switch (cmd) { +case XRT_MGMT_MAIN_GET_AXLF_SECTION : { +struct xrt_mgmt_main_ioctl_get_axlf_section *get = + (struct xrt_mgmt_main_ioctl_get_axlf_section *)arg; +const char *firmware = +xmgmt_get_axlf_firmware (xmm, get->xmmigas_axlf_kind); + +if (firmware ==NULL ) { + ret = -ENOENT ; + }else { + ret =xrt_xclbin_get_section (firmware, + get->xmmigas_section_kind, + &get->xmmigas_section, + &get->xmmigas_section_size); + } +break ; + } +case XRT_MGMT_MAIN_GET_VBNV : { +char **vbnv_p = (char **)arg; + + *vbnv_p =xmgmt_get_vbnv (pdev); +break ; + } +default : +xrt_err (pdev,"unknown cmd: %d" , cmd); + ret = -EINVAL ; +break ; + } +return ret; +} + +static int xmgmt_main_open (struct inode *inode,struct file *file) +{ +struct platform_device *pdev =xrt_devnode_open (inode); + +/* Device may have gone already when we get here. */ +if (!pdev) +return -ENODEV ; + +xrt_info (pdev,"opened" ); + file->private_data =platform_get_drvdata (pdev); +return 0 ; +} + +static int xmgmt_main_close (struct inode *inode,struct file *file) +{ +struct xmgmt_main *xmm = file->private_data; + +xrt_devnode_close (inode); + +xrt_info (xmm->pdev,"closed" ); +return 0 ; +} + +static int xmgmt_bitstream_axlf_fpga_mgr (struct xmgmt_main *xmm, +void *axlf,size_t size) +{ +int ret; +struct fpga_image_info info = {0 }; + +BUG_ON (!mutex_is_locked (&xmm->busy_mutex)); + +/* +* Should any error happens during download, we can't trust +* the cached xclbin any more. +*/ +vfree (xmm->firmware_ulp); + xmm->firmware_ulp =NULL ; + + info.buf = (char *)axlf; + info.count = size; + ret =fpga_mgr_load (xmm->fmgr, &info); +if (ret ==0 ) + xmm->firmware_ulp = axlf; + +return ret; +} + +int bitstream_axlf_mailbox (struct platform_device *pdev,const void *axlf)
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +void *copy_buffer =NULL ; +size_t copy_buffer_size =0 ; +const struct axlf *xclbin_obj = axlf; +int ret =0 ; + + if (memcmp(xclbin_obj->m_magic, ICAP_XCLBIN_V2,
sizeof(ICAP_XCLBIN_V2)))
Quoted 4 lines
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +4
-0+return -EINVAL ; + + copy_buffer_size = xclbin_obj->m_header.m_length; +if (copy_buffer_size >MAX_XCLBIN_SIZE )
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+return -EINVAL ; + copy_buffer =vmalloc (copy_buffer_size); +if (copy_buffer ==NULL ) +return -ENOMEM ; + (void )memcpy (copy_buffer, axlf, copy_buffer_size); + +mutex_lock (&xmm->busy_mutex); + ret = xmgmt_bitstream_axlf_fpga_mgr(xmm, copy_buffer,
copy_buffer_size);
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +7
-0+mutex_unlock (&xmm->busy_mutex); +if (ret) +vfree (copy_buffer); +return ret; +} + +static int bitstream_axlf_ioctl(struct xmgmt_main *xmm, const void
__user *arg)
Quoted 5 lines
Quoted 5 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +5
-0+{ +void *copy_buffer =NULL ; +size_t copy_buffer_size =0 ; +struct xmgmt_ioc_bitstream_axlf ioc_obj = {0 }; +struct axlf xclbin_obj = { {0 } };
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+int ret =0 ; + +if (copy_from_user ((void *)&ioc_obj, arg,sizeof (ioc_obj))) +return -EFAULT ; +if (copy_from_user ((void *)&xclbin_obj, ioc_obj.xclbin, +sizeof (xclbin_obj))) +return -EFAULT ; + if (memcmp(xclbin_obj.m_magic, ICAP_XCLBIN_V2,
sizeof(ICAP_XCLBIN_V2)))
Quoted 7 lines
Quoted 7 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +7
-0+return -EINVAL ; + + copy_buffer_size = xclbin_obj.m_header.m_length; +if (copy_buffer_size >MAX_XCLBIN_SIZE ) +return -EINVAL ; + copy_buffer =vmalloc (copy_buffer_size); +if (copy_buffer ==NULL )
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +8
-0+return -ENOMEM ; + +if (copy_from_user (copy_buffer, ioc_obj.xclbin, copy_buffer_size)) { +vfree (copy_buffer); +return -EFAULT ; + } + + ret = xmgmt_bitstream_axlf_fpga_mgr(xmm, copy_buffer,
copy_buffer_size);
Quoted 72 lines
Quoted 72 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +72
-0+if (ret) +vfree (copy_buffer); + +return ret; +} + +static long xmgmt_main_ioctl (struct file *filp,unsigned int cmd, +unsigned long arg) +{ +long result =0 ; +struct xmgmt_main *xmm = filp->private_data; + +BUG_ON (!xmm); + +if (_IOC_TYPE (cmd) !=XMGMT_IOC_MAGIC ) +return -ENOTTY ; + +mutex_lock (&xmm->busy_mutex); + +xrt_info (xmm->pdev,"ioctl cmd %d, arg %ld" , cmd, arg); +switch (cmd) { +case XMGMT_IOCICAPDOWNLOAD_AXLF : + result =bitstream_axlf_ioctl (xmm, (const void __user *)arg); +break ; +default : + result = -ENOTTY ; +break ; + } + +mutex_unlock (&xmm->busy_mutex); +return result; +} + +void *xmgmt_pdev2mailbox (struct platform_device *pdev) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); + +return xmm->mailbox_hdl; +} + +struct xrt_subdev_endpoints xrt_mgmt_main_endpoints[] = { + { + .xse_names = (struct xrt_subdev_ep_names []){ + { .ep_name =NODE_MGMT_MAIN }, + {NULL }, + }, + .xse_min_ep =1 , + }, + {0 }, +}; + +struct xrt_subdev_drvdata xmgmt_main_data = { + .xsd_dev_ops = { + .xsd_ioctl = xmgmt_main_leaf_ioctl, + }, + .xsd_file_ops = { + .xsf_ops = { + .owner =THIS_MODULE , + .open = xmgmt_main_open, + .release = xmgmt_main_close, + .unlocked_ioctl = xmgmt_main_ioctl, + }, + .xsf_dev_name ="xmgmt" , + }, +}; + +static const struct platform_device_id xmgmt_main_id_table[] = { + {XMGMT_MAIN , (kernel_ulong_t)&xmgmt_main_data }, + { }, +}; + +struct platform_driver xmgmt_main_driver = {
Quoted 8 lines
Review
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +7
-0+ .driver = { + .name = XMGMT_MAIN, + }, + .probe = xmgmt_main_probe, + .remove = xmgmt_main_remove, + .id_table = xmgmt_main_id_table, +};(quoted diff) +0
-0
b/drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 85 lines
Quoted 85 lines
new file mode 100644
index 000000000000..005fd5e42651drivers/fpga/alveo/mgmt/xmgmt-root.c new file +80
-0@@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Xilinx Alveo Management Function Driver +* +* Copyright (C) 2020 Xilinx, Inc. +* +* Authors: +* Cheng Zhen <[email protected]> +*/ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/aer.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> + +#include "xrt-root.h" +#include "xrt-subdev.h" +#include "xmgmt-main-impl.h" +#include "xrt-metadata.h" + +#define XMGMT_MODULE_NAME "xmgmt" +#define XMGMT_DRIVER_VERSION "4.0.0" + +#define XMGMT_PDEV (xm) ((xm)->pdev) +#define XMGMT_DEV (xm) (&(XMGMT_PDEV(xm)->dev)) +#define xmgmt_err(xm, fmt, args...) \ + dev_err(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_warn(xm, fmt, args...) \ + dev_warn(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_info(xm, fmt, args...) \ + dev_info(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define xmgmt_dbg(xm, fmt, args...) \ + dev_dbg(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args) +#define XMGMT_DEV_ID (pdev) \ + ((pci_domain_nr(pdev->bus) << 16) | \ + PCI_DEVID(pdev->bus->number, 0)) + +static struct class *xmgmt_class; +static const struct pci_device_id xmgmt_pci_ids[] = { + {PCI_DEVICE (0x10EE ,0xd020 ), }, + {PCI_DEVICE (0x10EE ,0x5020 ), }, + {0 , } +}; + +struct xmgmt { +struct pci_dev *pdev; +void *root; + +/* save config for pci reset */ +u32 saved_config[8 ][16 ]; +bool ready; +}; + +static int xmgmt_config_pci (struct xmgmt *xm) +{ +struct pci_dev *pdev =XMGMT_PDEV (xm); +int rc; + + rc =pcim_enable_device (pdev); +if (rc <0 ) { +xmgmt_err (xm,"failed to enable device: %d" , rc); +return rc; + } + + rc =pci_enable_pcie_error_reporting (pdev); +if (rc) +xmgmt_warn (xm,"failed to enable AER: %d" , rc); + +pci_set_master (pdev); + + rc =pcie_get_readrq (pdev); +if (rc <0 ) { +xmgmt_err (xm,"failed to read mrrs %d" , rc); +return rc; + } +if (rc >512 ) { + rc =pcie_set_readrq (pdev,512 ); +if (rc) { +xmgmt_err (xm,"failed to force mrrs %d" , rc);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c line 88
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+return rc; + } + } + +return 0 ; +} + +static void xmgmt_save_config_space(struct pci_dev *pdev, u32
*saved_config)
Quoted 17 lines
Quoted 17 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +17
-0+{ +int i; + +for (i =0 ; i <16 ; i++) +pci_read_config_dword (pdev, i *4 , &saved_config[i]); +} + +static int xmgmt_match_slot_and_save (struct device *dev,void *data) +{ +struct xmgmt *xm = data; +struct pci_dev *pdev =to_pci_dev (dev); + +if (XMGMT_DEV_ID (pdev) ==XMGMT_DEV_ID (xm->pdev)) { +pci_cfg_access_lock (pdev); +pci_save_state (pdev); +xmgmt_save_config_space (pdev, + xm->saved_config[PCI_FUNC (pdev->devfn)]);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+ } + +return 0 ; +} + +static void xmgmt_pci_save_config_all (struct xmgmt *xm) +{ + bus_for_each_dev(&pci_bus_type, NULL, xm,
xmgmt_match_slot_and_save);
Quoted 3 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c line 116
Quoted 3 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +3
-0+} + +static void xmgmt_restore_config_space(struct pci_dev *pdev, u32
*config_saved)
Quoted 29 lines
Quoted 29 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +29
-0+{ +int i; +u32 val; + +for (i =0 ; i <16 ; i++) { +pci_read_config_dword (pdev, i *4 , &val); +if (val == config_saved[i]) +continue ; + +pci_write_config_dword (pdev, i *4 , config_saved[i]); +pci_read_config_dword (pdev, i *4 , &val); +if (val != config_saved[i]) { +dev_err (&pdev->dev, +"restore config at %d failed" , i *4 ); + } + } +} + +static int xmgmt_match_slot_and_restore (struct device *dev,void *data) +{ +struct xmgmt *xm = data; +struct pci_dev *pdev =to_pci_dev (dev); + +if (XMGMT_DEV_ID (pdev) ==XMGMT_DEV_ID (xm->pdev)) { +xmgmt_restore_config_space (pdev, + xm->saved_config[PCI_FUNC (pdev->devfn)]); + +pci_restore_state (pdev); +pci_cfg_access_unlock (pdev);
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+ } + +return 0 ; +} + +static void xmgmt_pci_restore_config_all (struct xmgmt *xm) +{ + bus_for_each_dev(&pci_bus_type, NULL, xm,
xmgmt_match_slot_and_restore);
Quoted 54 lines
Quoted 54 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +54
-0+} + +void xroot_hot_reset (struct pci_dev *pdev) +{ +struct xmgmt *xm =pci_get_drvdata (pdev); +struct pci_bus *bus; +u8 pci_bctl; +u16 pci_cmd, devctl; +int i; + +xmgmt_info (xm,"hot reset start" ); + +xmgmt_pci_save_config_all (xm); + +pci_disable_device (pdev); + + bus = pdev->bus; + +/* +* When flipping the SBR bit, device can fall off the bus. This is +* usually no problem at all so long as drivers are working properly +* after SBR. However, some systems complain bitterly when the device +* falls off the bus. +* The quick solution is to temporarily disable the SERR reporting of +* switch port during SBR. +*/ + +pci_read_config_word (bus->self,PCI_COMMAND , &pci_cmd); +pci_write_config_word (bus->self,PCI_COMMAND , + (pci_cmd & ~PCI_COMMAND_SERR )); +pcie_capability_read_word (bus->self,PCI_EXP_DEVCTL , &devctl); +pcie_capability_write_word (bus->self,PCI_EXP_DEVCTL , + (devctl & ~PCI_EXP_DEVCTL_FERE )); +pci_read_config_byte (bus->self,PCI_BRIDGE_CONTROL , &pci_bctl); + pci_bctl |=PCI_BRIDGE_CTL_BUS_RESET ; +pci_write_config_byte (bus->self,PCI_BRIDGE_CONTROL , pci_bctl); + +msleep (100 ); + pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET ; +pci_write_config_byte (bus->self,PCI_BRIDGE_CONTROL , pci_bctl); +ssleep (1 ); + +pcie_capability_write_word (bus->self,PCI_EXP_DEVCTL , devctl); +pci_write_config_word (bus->self,PCI_COMMAND , pci_cmd); + +pci_enable_device (pdev); + +for (i =0 ; i <300 ; i++) { +pci_read_config_word (pdev,PCI_COMMAND , &pci_cmd); +if (pci_cmd !=0xffff ) +break ; +msleep (20 ); + } +
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+xmgmt_info (xm,"waiting for %d ms" , i *20 ); + +xmgmt_pci_restore_config_all (xm); + +xmgmt_config_pci (xm); +} + +static int xmgmt_create_root_metadata(struct xmgmt *xm, char
**root_dtb)
Quoted 16 lines
Quoted 16 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +16
-0+{ +char *dtb =NULL ; +int ret; + + ret =xrt_md_create (DEV (xm->pdev), &dtb); +if (ret) { +xmgmt_err (xm,"create metadata failed, ret %d" , ret); + goto failed; + } + + ret =xroot_add_simple_node (xm->root, dtb,NODE_TEST ); +if (ret) + goto failed; + + ret =xroot_add_vsec_node (xm->root, dtb); +if (ret == -ENOENT ) {
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+/* +* We may be dealing with a MFG board. +* Try vsec-golden which will bring up all hard-coded leaves +* at hard-coded offsets. +*/ + ret =xroot_add_simple_node (xm, dtb,NODE_VSEC_GOLDEN ); + }else if (ret ==0 ) { + ret = xroot_add_simple_node(xm->root, dtb,
NODE_MGMT_MAIN);
Quoted 24 lines
Quoted 24 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +24
-0+ } +if (ret) + goto failed; + + *root_dtb = dtb; +return 0 ; + +failed: +vfree (dtb); +return ret; +} + +static ssize_t ready_show (struct device *dev, +struct device_attribute *da,char *buf) +{ +struct pci_dev *pdev =to_pci_dev (dev); +struct xmgmt *xm =pci_get_drvdata (pdev); + +return sprintf (buf,"%d\n" , xm->ready); +} +static DEVICE_ATTR_RO (ready); + +static struct attribute *xmgmt_root_attrs[] = { + &dev_attr_ready.attr,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+NULL +}; + +static struct attribute_group xmgmt_root_attr_group = { + .attrs = xmgmt_root_attrs, +}; + +static int xmgmt_probe(struct pci_dev *pdev, const struct pci_device_id
*id)
Quoted 51 lines
Quoted 51 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +51
-0+{ +int ret; +struct device *dev =DEV (pdev); +struct xmgmt *xm =devm_kzalloc (dev,sizeof (*xm),GFP_KERNEL ); +char *dtb =NULL ; + +if (!xm) +return -ENOMEM ; + xm->pdev = pdev; +pci_set_drvdata (pdev, xm); + + ret =xmgmt_config_pci (xm); +if (ret) + goto failed; + + ret =xroot_probe (pdev, &xm->root); +if (ret) + goto failed; + + ret =xmgmt_create_root_metadata (xm, &dtb); +if (ret) + goto failed_metadata; + + ret =xroot_create_partition (xm->root, dtb); +vfree (dtb); +if (ret) +xmgmt_err (xm,"failed to create root partition: %d" , ret); + +if (!xroot_wait_for_bringup (xm->root)) +xmgmt_err (xm,"failed to bringup all partitions" ); +else + xm->ready = true; + + ret =sysfs_create_group (&pdev->dev.kobj, &xmgmt_root_attr_group); +if (ret) { +/* Warning instead of failing the probe. */ +xrt_warn (pdev,"create xmgmt root attrs failed: %d" , ret); + } + +xroot_broadcast (xm->root,XRT_EVENT_POST_ATTACH ); +xmgmt_info (xm,"%s started successfully" ,XMGMT_MODULE_NAME ); +return 0 ; + +failed_metadata: + (void )xroot_remove (xm->root); +failed: +pci_set_drvdata (pdev,NULL ); +return ret; +} + +static void xmgmt_remove (struct pci_dev *pdev)
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+{ +struct xmgmt *xm =pci_get_drvdata (pdev); + +xroot_broadcast (xm->root,XRT_EVENT_PRE_DETACH ); +sysfs_remove_group (&pdev->dev.kobj, &xmgmt_root_attr_group); + (void )xroot_remove (xm->root); +pci_disable_pcie_error_reporting (xm->pdev); + xmgmt_info(xm, "%s cleaned up successfully",
XMGMT_MODULE_NAME);
Quoted 4 lines
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +4
-0+} + +static struct pci_driver xmgmt_driver = { + .name =XMGMT_MODULE_NAME ,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +8
-0+ .id_table = xmgmt_pci_ids, + .probe = xmgmt_probe, + .remove = xmgmt_remove, +}; + +static int __init xmgmt_init (void ) +{ + int res =
xrt_subdev_register_external_driver(XRT_SUBDEV_MGMT_MAIN,
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c
Quoted 6 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +6
-0+ &xmgmt_main_driver, xrt_mgmt_main_endpoints); + +if (res) +return res; + + xmgmt_class = class_create(THIS_MODULE,
XMGMT_MODULE_NAME);
Quoted 33 lines
Quoted 28 lines
drivers/fpga/alveo/mgmt/xmgmt-root.c new file +27
-1+if (IS_ERR (xmgmt_class)) +return PTR_ERR (xmgmt_class); + + res =pci_register_driver (&xmgmt_driver); +if (res) { +class_destroy (xmgmt_class); +return res; + } + +return 0 ; +} + +static __exit void xmgmt_exit(void) +{ +pci_unregister_driver (&xmgmt_driver); +class_destroy (xmgmt_class); +xrt_subdev_unregister_external_driver (XRT_SUBDEV_MGMT_MAIN ); +} + +module_init (xmgmt_init); +module_exit (xmgmt_exit); + +MODULE_DEVICE_TABLE (pci, xmgmt_pci_ids); +MODULE_VERSION (XMGMT_DRIVER_VERSION ); +MODULE_AUTHOR ("XRT Team <[email protected]>" ); +MODULE_DESCRIPTION ("Xilinx Alveo management function driver" ); +MODULE_LICENSE ("GPL v2" ); --Quoted 1 line
2.17.1
I have not yet looked at the whole thing, but why does the FPGA Manager only copy things around?
Quoted 2 lines
Any reason your partitions cannot be modelled as FPGA regions/Bridges?
We will address this as Max explained in the other email.
Quoted 4 lines
It would be helpful to split this up into smaller chunks, that make it easier to review. The FPGA Manager driver should be a separate patch, etc.
Will resolve in the next revision of the patch series.
Thanks for your feedback.
-Sonal
Quoted 2 lines
- Moritz
Xu Yilun
maintainerRe: [PATCH Xilinx Alveo 7/8] fpga: xrt: Alveo management physical function driver
In reply to Sonal SantanQuoted 21 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +21
-0+static int xmgmt_main_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev *)arg; +enum xrt_subdev_id id; +int instance; +size_t fwlen; + +switch (evt) { +case XRT_EVENT_POST_CREATION : { + id = esd->xevt_subdev_id; + instance = esd->xevt_subdev_instance; +xrt_info (pdev,"processing event %d for (%d, %d)" , + evt, id, instance); + +if (id ==XRT_SUBDEV_GPIO ) + xmm->gpio_ready = true; +else if (id ==XRT_SUBDEV_QSPI ) + xmm->flash_ready = true; +else
drivers/fpga/alveo/mgmt/xmgmt-main.c line 552
Quoted 10 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +10
-0+BUG_ON (1 ); + +if (xmm->gpio_ready && xmm->flash_ready) { +int rc; + + rc =load_firmware_from_disk (pdev, &xmm->firmware_blp, + &fwlen); +if (rc !=0 ) { + rc =load_firmware_from_flash (pdev, + &xmm->firmware_blp, &fwlen);
I'm curious that before the shell metadata is loaded, how the QSPI subdev is enumerated and get to work? The QSPI DT info itself is stored in metadata, is it?
I didn't find the creation of leaf platform devices, maybe I can find the answer in the missing Patch #5?
Thanks,
Yilun
Quoted 11 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +11
-0+ } +if (rc ==0 &&is_valid_firmware (pdev, + xmm->firmware_blp, fwlen)) + (void )xmgmt_create_blp (xmm); +else +xrt_err (pdev, +"failed to find firmware, giving up" ); + xmm->evt_hdl =NULL ; + } +break ; + }
Re: [PATCH Xilinx Alveo 7/8] fpga: xrt: Alveo management physical function driver
Hi Yilun,
Quoted 29 lines · Xu Yilun
Quoted 29 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +27
-0+static int xmgmt_main_event_cb (struct platform_device *pdev, +enum xrt_events evt,void *arg) +{ +struct xmgmt_main *xmm =platform_get_drvdata (pdev); +struct xrt_event_arg_subdev *esd = (struct xrt_event_arg_subdev *)arg; +enum xrt_subdev_id id; +int instance; +size_t fwlen; + +switch (evt) { +case XRT_EVENT_POST_CREATION : { + id = esd->xevt_subdev_id; + instance = esd->xevt_subdev_instance; +xrt_info (pdev,"processing event %d for (%d, %d)" , + evt, id, instance); + +if (id ==XRT_SUBDEV_GPIO ) + xmm->gpio_ready = true; +else if (id ==XRT_SUBDEV_QSPI ) + xmm->flash_ready = true; +else +BUG_ON (1 ); + +if (xmm->gpio_ready && xmm->flash_ready) { +int rc; + + rc = load_firmware_from_disk(pdev, &xmm->firmware_blp,
Quoted 8 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c line 552
Quoted 4 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +4
-0+ &fwlen); +if (rc !=0 ) { + rc =load_firmware_from_flash (pdev, + &xmm->firmware_blp, &fwlen);I'm curious that before the shell metadata is loaded, how the QSPI subdev is enumerated and get to work? The QSPI DT info itself is stored in metadata, is it?
No, it is not from the shell metadata. The QSPI subdev info is discovered from a rom located on the PCIE BAR pointed to by VSEC cap found in config space.
Quoted 3 lines
I didn't find the creation of leaf platform devices, maybe I can find the answer in the missing Patch #5?
Leaf driver is children of partition driver. They are created in xrt_part_create_leaves() in xrt-partition.c.
Thanks,
Max
Quoted 15 lines
Thanks,
YilunQuoted 11 lines
drivers/fpga/alveo/mgmt/xmgmt-main.c new file +11
-0+ } +if (rc ==0 &&is_valid_firmware (pdev, + xmm->firmware_blp, fwlen)) + (void )xmgmt_create_blp (xmm); +else +xrt_err (pdev, +"failed to find firmware, giving up" ); + xmm->evt_hdl =NULL ; + } +break ; + }
PATCH 8/8 fpga: xrt: Kconfig and Makefile updates for XRT drivers
In reply to Sonal SantanFrom: Sonal Santan <[email protected]>
Update fpga Kconfig/Makefile and add Kconfig/Makefile for new drivers.
--- drivers/fpga/Kconfig | 2 ++ drivers/fpga/Makefile | 3 +++ drivers/fpga/alveo/Kconfig | 7 ++++++ drivers/fpga/alveo/lib/Kconfig | 11 +++++++++ drivers/fpga/alveo/lib/Makefile | 42 ++++++++++++++++++++++++++++++++ drivers/fpga/alveo/mgmt/Kconfig | 11 +++++++++ drivers/fpga/alveo/mgmt/Makefile | 28 +++++++++++++++++++++ 7 files changed, 104 insertions(+) create mode 100644 drivers/fpga/alveo/Kconfig create mode 100644 drivers/fpga/alveo/lib/Kconfig create mode 100644 drivers/fpga/alveo/lib/Makefile create mode 100644 drivers/fpga/alveo/mgmt/Kconfig create mode 100644 drivers/fpga/alveo/mgmt/Makefile
drivers/fpga/Kconfig +2 -0
@@ -215,4 +215,6 @@ config FPGA_MGR_ZYNQMP_FPGA to configure the programmable logic(PL) through PS on ZynqMP SoC. +source "drivers/fpga/alveo/Kconfig" + endif # FPGA
drivers/fpga/Makefile +3 -0
@@ -46,3 +46,6 @@ dfl-afu-objs += dfl-afu-error.o # Drivers for FPGAs which implement DFL obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o + +obj-$(CONFIG_FPGA_ALVEO_LIB) += alveo/lib/ +obj-$(CONFIG_FPGA_ALVEO_XMGMT) += alveo/mgmt/
drivers/fpga/alveo/Kconfig new file +7 -0
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Xilinx Alveo FPGA device configuration +# + +source "drivers/fpga/alveo/lib/Kconfig" +source "drivers/fpga/alveo/mgmt/Kconfig"
drivers/fpga/alveo/lib/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Xilinx Alveo FPGA device configuration +# + +config FPGA_ALVEO_LIB + tristate "Xilinx Alveo Driver Library" + depends on HWMON && PCI + select LIBFDT + help + Xilinx Alveo FPGA PCIe device driver common library.
drivers/fpga/alveo/lib/Makefile new file +42 -0
42 lines not on this page · raw message
drivers/fpga/alveo/mgmt/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Xilinx Alveo FPGA device configuration +# + +config FPGA_ALVEO_XMGMT + tristate "Xilinx Alveo Management Driver" + depends on HWMON && PCI && FPGA_ALVEO_LIB + select LIBFDT + help + Xilinx Alveo FPGA PCIe device driver for Management Physical Function.
drivers/fpga/alveo/mgmt/Makefile new file +28 -0
@@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved. +# +# Authors: [email protected] +# + +FULL_ALVEO_PATH=$(srctree)/$(src)/.. +FULL_DTC_PATH=$(srctree)/scripts/dtc/libfdt + +obj-$(CONFIG_FPGA_ALVEO_XMGMT) += xmgmt.o + +commondir := ../common + +xmgmt-objs := xmgmt-root.o \ + xmgmt-main.o \ + xmgmt-fmgr-drv.o \ + xmgmt-main-ulp.o \ + xmgmt-main-mailbox.o \ + $(commondir)/xrt-root.o \ + $(commondir)/xrt-metadata.o \ + $(commondir)/xrt-xclbin.o + + + +ccflags-y := -I$(FULL_ALVEO_PATH)/include \ + -I$(FULL_ALVEO_PATH)/common \ + -I$(FULL_DTC_PATH)
Signature · 1 line
2.17.1
Quoted 64 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards, https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.The patch depends on the "PATCH Xilinx Alveo libfdt prep" which was posted before.
ALVEO PLATFORM ARCHITECTURE
Alveo PCIe FPGA based platforms have a static *shell* partition and a partial re-configurable *user* partition. The shell partition is automatically loaded from flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be changed till the next cold reboot. The shell exposes two PCIe physical functions:
1. management physical function
2. user physical functionThe patch series includes
Documentation/xrt.rstwhich describes Alveo platform, xmgmt driver architecture and deployment model in more more detail.Users compile their high level design in C/C++/OpenCL or RTL into FPGA image using Vitis https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The image is packaged as xclbin and contains partial bitstream for the user partition and necessary metadata. Users can dynamically swap the image running on the user partition in order to switch between different workloads.ALVEO DRIVERS
Alveo Linux kernel driver *xmgmt* binds to management physical function of Alveo platform. The modular driver framework is organized into several platform drivers which primarily handle the following functionality:
1. Loading firmware container also called xsabin at driver attach time 2. Loading of user compiled xclbin with FPGA Manager integration 3. Clock scaling of image running on user partition 4. In-band sensors: temp, voltage, power, etc. 5. Device reset and rescan 6. Flashing static *shell* partitionThe platform drivers are packaged into *xrt-lib* helper module with a well defined interfaces the details of which can be found in
Documentation/xrt.rst.xmgmt driver is second generation Alveo management driver and evolution of the first generation (out of tree) Alveo management driver, xclmgmt. The sources of the first generation drivers were posted on LKML last year--
https://lore.kernel.org/lkml/[email protected]/Changes since the first generation driver include the following: the driver has been re-architected as data driven modular driver; the driver has been split into xmgmt and xrt-lib; user physical function driver has been removed from the patch series.
Alveo/XRT security and platform architecture is documented on the following GitHub pages:
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.htmlUser physical function driver is not included in this patch series.
TESTING AND VALIDATION
Quoted 8 lines
xmgmt driver can be tested with full XRT open source stack which includes user space libraries, board utilities and (out of tree) first generation user physical function driver xocl. XRT open source runtime stack is available at https://github.com/Xilinx/XRT. This patch series has been validated on Alveo U50 platform.
Complete documentation for XRT open source stack can be found here--
https://xilinx.github.io/XRT/master/html/index.html
I've not gotten into the patch details, but I'm not clear on what the lifecycle of the DT looks like here. What's the starting point and what manipulations to the DT are being done? I'm trying to understand if using libfdt is the right way versus operating on an unflattened tree.
Rob
Hi,
Quoted 91 lines
-----Original Message-----
From: Rob Herring <[email protected]>
Sent: Monday, November 30, 2020 10:09 AM
To: Sonal Santan <[email protected]>
Cc: [email protected]; Sonal Santan <[email protected]>; linux- [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 0/8] Xilinx Alveo/XRT patch overviewQuoted 11 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards,
https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.The patch depends on the "PATCH Xilinx Alveo libfdt prep" which was posted before.
Quoted 6 lines
ALVEO PLATFORM ARCHITECTURE
Alveo PCIe FPGA based platforms have a static *shell* partition and a partial re-configurable *user* partition. The shell partition is automatically loaded from flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be changed till the next cold reboot. The
shell exposes two PCIe physical functions:
Quoted 6 lines
1. management physical function
2. user physical functionThe patch series includes
Documentation/xrt.rstwhich describes Alveo platform, xmgmt driver architecture and deployment model in more moredetail.
Quoted 7 lines
Users compile their high level design in C/C++/OpenCL or RTL into FPGA image using Vitis
https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The image is packaged as xclbin and contains partial bitstream for the user partition and necessary metadata. Users can dynamically swap the image running on the user partition in order to switch betweendifferent workloads.
Quoted 6 lines
ALVEO DRIVERS
Alveo Linux kernel driver *xmgmt* binds to management physical function of Alveo platform. The modular driver framework is organized into several platform drivers which primarily handle the following
functionality:
Quoted 10 lines
1. Loading firmware container also called xsabin at driver attach time 2. Loading of user compiled xclbin with FPGA Manager integration
3. Clock scaling of image running on user partition 4. In-band
sensors: temp, voltage, power, etc.
5. Device reset and rescan
6. Flashing static *shell* partitionThe platform drivers are packaged into *xrt-lib* helper module with a well defined interfaces the details of which can be found in
Documentation/xrt.rst.Quoted 28 lines
xmgmt driver is second generation Alveo management driver and evolution of the first generation (out of tree) Alveo management driver, xclmgmt. The sources of the first generation drivers were posted on LKML last year--
https://lore.kernel.org/lkml/20190319215401.6562-1-sonal.santan@xilinx
.com/Changes since the first generation driver include the following: the driver has been re-architected as data driven modular driver; the driver has been split into xmgmt and xrt-lib; user physical function driver has been removed from the patch series.
Alveo/XRT security and platform architecture is documented on the following GitHub pages:
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.htmlUser physical function driver is not included in this patch series.
TESTING AND VALIDATION
xmgmt driver can be tested with full XRT open source stack which includes user space libraries, board utilities and (out of tree) first generation user physical function driver xocl. XRT open source runtime stack is available at https://github.com/Xilinx/XRT. This patch series has been validated on Alveo U50 platform.
Quoted 7 lines
Quoted 2 lines
Complete documentation for XRT open source stack can be found here--
https://xilinx.github.io/XRT/master/html/index.htmlI've not gotten into the patch details, but I'm not clear on what the lifecycle of the DT looks like here. What's the starting point and what manipulations to the DT are being done? I'm trying to understand if using libfdt is the right way versus operating on an unflattened tree.
The DT is created when *xmgmt* driver attaches to the device and reads the xsabin. The xsabin defines the shell and HW subsystems contained in the shell. Since the shell is live for the lifetime of the driver the DT is captured in the partition subdev. The partition then looks for "addressable_endpoints" node and walks the list of child end point nodes each of which is then copied into its own instance of subdev. The life cycle of the copied nodes is same as the owning subdev. All the DT nodes are released when the partition together with its child subdevs goes away which happens when the driver is unloaded.
xmgmt driver also collects all end points which advertise "pcie_physical_function = <0x01>" and then constructs a DT on the fly which is then sent to the user physical function driver via mailbox. This requires support for manipulating device tree nodes.
In the next revision of the driver we would like to add support for a variation of platform which has three partitions: base, shell and user--
https://xilinx.github.io/XRT/master/html/platforms_partitions.html#two-stage-platforms
In this model, *base* is initialized like described above. However *shell* can be changed dynamically by service provider. This means xmgmt would load DT corresponding to shell partition when shell is loaded and tear it down when shell is unloaded. The DT corresponding to *base* remains unaffected.
Thanks,
-Sonal
Quoted 2 lines
Rob
Xu Yilun
maintainerQuoted 75 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards, https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.The patch depends on the "PATCH Xilinx Alveo libfdt prep" which was posted before.
ALVEO PLATFORM ARCHITECTURE
Alveo PCIe FPGA based platforms have a static *shell* partition and a partial re-configurable *user* partition. The shell partition is automatically loaded from flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be changed till the next cold reboot. The shell exposes two PCIe physical functions:
1. management physical function
2. user physical functionThe patch series includes
Documentation/xrt.rstwhich describes Alveo platform, xmgmt driver architecture and deployment model in more more detail.Users compile their high level design in C/C++/OpenCL or RTL into FPGA image using Vitis https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The image is packaged as xclbin and contains partial bitstream for the user partition and necessary metadata. Users can dynamically swap the image running on the user partition in order to switch between different workloads.ALVEO DRIVERS
Alveo Linux kernel driver *xmgmt* binds to management physical function of Alveo platform. The modular driver framework is organized into several platform drivers which primarily handle the following functionality:
1. Loading firmware container also called xsabin at driver attach time 2. Loading of user compiled xclbin with FPGA Manager integration 3. Clock scaling of image running on user partition 4. In-band sensors: temp, voltage, power, etc. 5. Device reset and rescan 6. Flashing static *shell* partitionThe platform drivers are packaged into *xrt-lib* helper module with a well defined interfaces the details of which can be found in
Documentation/xrt.rst.xmgmt driver is second generation Alveo management driver and evolution of the first generation (out of tree) Alveo management driver, xclmgmt. The sources of the first generation drivers were posted on LKML last year--
https://lore.kernel.org/lkml/[email protected]/Changes since the first generation driver include the following: the driver has been re-architected as data driven modular driver; the driver has been split into xmgmt and xrt-lib; user physical function driver has been removed from the patch series.
Alveo/XRT security and platform architecture is documented on the following GitHub pages:
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.htmlUser physical function driver is not included in this patch series.
TESTING AND VALIDATION
xmgmt driver can be tested with full XRT open source stack which includes user space libraries, board utilities and (out of tree) first generation user physical function driver xocl. XRT open source runtime stack is available at https://github.com/Xilinx/XRT. This patch series has been validated on Alveo U50 platform.
Complete documentation for XRT open source stack can be found here--
https://xilinx.github.io/XRT/master/html/index.htmlThanks,
-Sonal
Quoted 6 lines
Sonal Santan (8):
Documentation: fpga: Add a document describing Alveo XRT drivers
fpga: xrt: Add UAPI header files
fpga: xrt: infrastructure support for xmgmt driver
fpga: xrt: core infrastructure for xrt-lib module
fpga: xrt: platform drivers for subsystems in shell partition
Seems the Patch #5 is missing in this seriies.
Thanks,
Yilun
Quoted 139 lines
fpga: xrt: header file for platform and parent drivers
fpga: xrt: Alveo management physical function driver
fpga: xrt:KconfigandMakefileupdates for XRT driversDocumentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588 +++++ drivers/fpga/Kconfig | 2 + drivers/fpga/Makefile | 3 + drivers/fpga/alveo/Kconfig | 7 + drivers/fpga/alveo/common/xrt-metadata.c | 590 +++++ drivers/fpga/alveo/common/xrt-root.c | 744 +++++++ drivers/fpga/alveo/common/xrt-root.h | 24 + drivers/fpga/alveo/common/xrt-xclbin.c | 387 ++++ drivers/fpga/alveo/common/xrt-xclbin.h | 46 + drivers/fpga/alveo/include/xmgmt-main.h | 34 + drivers/fpga/alveo/include/xrt-axigate.h | 31 + drivers/fpga/alveo/include/xrt-calib.h | 28 + drivers/fpga/alveo/include/xrt-clkfreq.h | 21 + drivers/fpga/alveo/include/xrt-clock.h | 29 + drivers/fpga/alveo/include/xrt-cmc.h | 23 + drivers/fpga/alveo/include/xrt-ddr-srsr.h | 29 + drivers/fpga/alveo/include/xrt-flash.h | 28 + drivers/fpga/alveo/include/xrt-gpio.h | 41 + drivers/fpga/alveo/include/xrt-icap.h | 27 + drivers/fpga/alveo/include/xrt-mailbox.h | 44 + drivers/fpga/alveo/include/xrt-metadata.h | 184 ++ drivers/fpga/alveo/include/xrt-parent.h | 103 + drivers/fpga/alveo/include/xrt-partition.h | 33 + drivers/fpga/alveo/include/xrt-subdev.h | 333 +++ drivers/fpga/alveo/include/xrt-ucs.h | 22 + drivers/fpga/alveo/lib/Kconfig | 11 + drivers/fpga/alveo/lib/Makefile | 42 + drivers/fpga/alveo/lib/subdevs/xrt-axigate.c | 298 +++ drivers/fpga/alveo/lib/subdevs/xrt-calib.c | 291 +++ drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c | 214 ++ drivers/fpga/alveo/lib/subdevs/xrt-clock.c | 638 ++++++ .../fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c | 343 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h | 135 ++ .../fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c | 320 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c | 361 ++++ .../fpga/alveo/lib/subdevs/xrt-cmc-sensors.c | 445 ++++ drivers/fpga/alveo/lib/subdevs/xrt-cmc.c | 239 +++ drivers/fpga/alveo/lib/subdevs/xrt-gpio.c | 198 ++ drivers/fpga/alveo/lib/subdevs/xrt-icap.c | 306 +++ drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c | 1905 +++++++++++++++++ .../fpga/alveo/lib/subdevs/xrt-partition.c | 261 +++ drivers/fpga/alveo/lib/subdevs/xrt-qspi.c | 1347 ++++++++++++ drivers/fpga/alveo/lib/subdevs/xrt-srsr.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-test.c | 274 +++ drivers/fpga/alveo/lib/subdevs/xrt-ucs.c | 238 ++ .../fpga/alveo/lib/subdevs/xrt-vsec-golden.c | 238 ++ drivers/fpga/alveo/lib/subdevs/xrt-vsec.c | 337 +++ drivers/fpga/alveo/lib/xrt-cdev.c | 234 ++ drivers/fpga/alveo/lib/xrt-main.c | 275 +++ drivers/fpga/alveo/lib/xrt-main.h | 46 + drivers/fpga/alveo/lib/xrt-subdev.c | 1007 +++++++++ drivers/fpga/alveo/mgmt/Kconfig | 11 + drivers/fpga/alveo/mgmt/Makefile | 28 + drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++ include/uapi/linux/xrt/flash_xrt_data.h | 67 + include/uapi/linux/xrt/mailbox_proto.h | 394 ++++ include/uapi/linux/xrt/mailbox_transport.h | 74 + include/uapi/linux/xrt/xclbin.h | 418 ++++ include/uapi/linux/xrt/xmgmt-ioctl.h | 72 + 67 files changed, 17710 insertions(+) create mode 100644 Documentation/fpga/xrt.rst create mode 100644 drivers/fpga/alveo/Kconfig create mode 100644 drivers/fpga/alveo/common/xrt-metadata.c create mode 100644 drivers/fpga/alveo/common/xrt-root.c create mode 100644 drivers/fpga/alveo/common/xrt-root.h create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.c create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.h create mode 100644 drivers/fpga/alveo/include/xmgmt-main.h create mode 100644 drivers/fpga/alveo/include/xrt-axigate.h create mode 100644 drivers/fpga/alveo/include/xrt-calib.h create mode 100644 drivers/fpga/alveo/include/xrt-clkfreq.h create mode 100644 drivers/fpga/alveo/include/xrt-clock.h create mode 100644 drivers/fpga/alveo/include/xrt-cmc.h create mode 100644 drivers/fpga/alveo/include/xrt-ddr-srsr.h create mode 100644 drivers/fpga/alveo/include/xrt-flash.h create mode 100644 drivers/fpga/alveo/include/xrt-gpio.h create mode 100644 drivers/fpga/alveo/include/xrt-icap.h create mode 100644 drivers/fpga/alveo/include/xrt-mailbox.h create mode 100644 drivers/fpga/alveo/include/xrt-metadata.h create mode 100644 drivers/fpga/alveo/include/xrt-parent.h create mode 100644 drivers/fpga/alveo/include/xrt-partition.h create mode 100644 drivers/fpga/alveo/include/xrt-subdev.h create mode 100644 drivers/fpga/alveo/include/xrt-ucs.h create mode 100644 drivers/fpga/alveo/lib/Kconfig create mode 100644 drivers/fpga/alveo/lib/Makefile create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-axigate.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-calib.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clock.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sensors.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-gpio.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-icap.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-partition.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-qspi.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-srsr.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-test.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-ucs.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec-golden.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec.c create mode 100644 drivers/fpga/alveo/lib/xrt-cdev.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.h create mode 100644 drivers/fpga/alveo/lib/xrt-subdev.c create mode 100644 drivers/fpga/alveo/mgmt/Kconfig create mode 100644 drivers/fpga/alveo/mgmt/Makefile create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.c create mode 100644 include/uapi/linux/xrt/flash_xrt_data.h create mode 100644 include/uapi/linux/xrt/mailbox_proto.h create mode 100644 include/uapi/linux/xrt/mailbox_transport.h create mode 100644 include/uapi/linux/xrt/xclbin.h create mode 100644 include/uapi/linux/xrt/xmgmt-ioctl.h--
2.17.1
Quoted 97 lines
-----Original Message-----
From: Xu Yilun <[email protected]>
Sent: Tuesday, December 1, 2020 6:14 PM
To: Sonal Santan <[email protected]>
Cc: [email protected]; Sonal Santan <[email protected]>; linux- [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 0/8] Xilinx Alveo/XRT patch overviewQuoted 10 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards,
https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.The patch depends on the "PATCH Xilinx Alveo libfdt prep" which was posted before.
Quoted 6 lines
ALVEO PLATFORM ARCHITECTURE
Alveo PCIe FPGA based platforms have a static *shell* partition and a partial re-configurable *user* partition. The shell partition is automatically loaded from flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be changed till the next cold reboot. The
shell exposes two PCIe physical functions:
Quoted 6 lines
1. management physical function
2. user physical functionThe patch series includes
Documentation/xrt.rstwhich describes Alveo platform, xmgmt driver architecture and deployment model in more moredetail.
Quoted 7 lines
Users compile their high level design in C/C++/OpenCL or RTL into FPGA image using Vitis
https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The image is packaged as xclbin and contains partial bitstream for the user partition and necessary metadata. Users can dynamically swap the image running on the user partition in order to switch betweendifferent workloads.
Quoted 6 lines
ALVEO DRIVERS
Alveo Linux kernel driver *xmgmt* binds to management physical function of Alveo platform. The modular driver framework is organized into several platform drivers which primarily handle the following
functionality:
Quoted 10 lines
1. Loading firmware container also called xsabin at driver attach time 2. Loading of user compiled xclbin with FPGA Manager integration
3. Clock scaling of image running on user partition 4. In-band
sensors: temp, voltage, power, etc.
5. Device reset and rescan
6. Flashing static *shell* partitionThe platform drivers are packaged into *xrt-lib* helper module with a well defined interfaces the details of which can be found in
Documentation/xrt.rst.Quoted 34 lines
xmgmt driver is second generation Alveo management driver and evolution of the first generation (out of tree) Alveo management driver, xclmgmt. The sources of the first generation drivers were posted on LKML last year--
https://lore.kernel.org/lkml/20190319215401.6562-1-sonal.santan@xilinx
.com/Changes since the first generation driver include the following: the driver has been re-architected as data driven modular driver; the driver has been split into xmgmt and xrt-lib; user physical function driver has been removed from the patch series.
Alveo/XRT security and platform architecture is documented on the following GitHub pages:
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.htmlUser physical function driver is not included in this patch series.
TESTING AND VALIDATION
xmgmt driver can be tested with full XRT open source stack which includes user space libraries, board utilities and (out of tree) first generation user physical function driver xocl. XRT open source runtime stack is available at https://github.com/Xilinx/XRT. This patch series has been validated on Alveo U50 platform.
Complete documentation for XRT open source stack can be found here--
https://xilinx.github.io/XRT/master/html/index.htmlThanks,
-Sonal
Quoted 8 lines
Quoted 6 lines
Sonal Santan (8):
Documentation: fpga: Add a document describing Alveo XRT drivers
fpga: xrt: Add UAPI header files
fpga: xrt: infrastructure support for xmgmt driver
fpga: xrt: core infrastructure for xrt-lib module
fpga: xrt: platform drivers for subsystems in shell partitionSeems the Patch #5 is missing in this seriies.
Patch #5 was posted along with the rest. You can find a copy here--
https://lore.kernel.org/lkml/[email protected]/
Thanks,
Sonal
Quoted 143 lines
Thanks,
YilunQuoted 139 lines
fpga: xrt: header file for platform and parent drivers
fpga: xrt: Alveo management physical function driver
fpga: xrt:KconfigandMakefileupdates for XRT driversDocumentation/fpga/index.rst | 1 + Documentation/fpga/xrt.rst | 588 +++++ drivers/fpga/Kconfig | 2 + drivers/fpga/Makefile | 3 + drivers/fpga/alveo/Kconfig | 7 + drivers/fpga/alveo/common/xrt-metadata.c | 590 +++++ drivers/fpga/alveo/common/xrt-root.c | 744 +++++++ drivers/fpga/alveo/common/xrt-root.h | 24 + drivers/fpga/alveo/common/xrt-xclbin.c | 387 ++++ drivers/fpga/alveo/common/xrt-xclbin.h | 46 + drivers/fpga/alveo/include/xmgmt-main.h | 34 + drivers/fpga/alveo/include/xrt-axigate.h | 31 + drivers/fpga/alveo/include/xrt-calib.h | 28 + drivers/fpga/alveo/include/xrt-clkfreq.h | 21 + drivers/fpga/alveo/include/xrt-clock.h | 29 + drivers/fpga/alveo/include/xrt-cmc.h | 23 + drivers/fpga/alveo/include/xrt-ddr-srsr.h | 29 + drivers/fpga/alveo/include/xrt-flash.h | 28 + drivers/fpga/alveo/include/xrt-gpio.h | 41 + drivers/fpga/alveo/include/xrt-icap.h | 27 + drivers/fpga/alveo/include/xrt-mailbox.h | 44 + drivers/fpga/alveo/include/xrt-metadata.h | 184 ++ drivers/fpga/alveo/include/xrt-parent.h | 103 + drivers/fpga/alveo/include/xrt-partition.h | 33 + drivers/fpga/alveo/include/xrt-subdev.h | 333 +++ drivers/fpga/alveo/include/xrt-ucs.h | 22 + drivers/fpga/alveo/lib/Kconfig | 11 + drivers/fpga/alveo/lib/Makefile | 42 + drivers/fpga/alveo/lib/subdevs/xrt-axigate.c | 298 +++ drivers/fpga/alveo/lib/subdevs/xrt-calib.c | 291 +++ drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c | 214 ++ drivers/fpga/alveo/lib/subdevs/xrt-clock.c | 638 ++++++ .../fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c | 343 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h | 135 ++ .../fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c | 320 +++ drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c | 361 ++++ .../fpga/alveo/lib/subdevs/xrt-cmc-sensors.c | 445 ++++ drivers/fpga/alveo/lib/subdevs/xrt-cmc.c | 239 +++ drivers/fpga/alveo/lib/subdevs/xrt-gpio.c | 198 ++ drivers/fpga/alveo/lib/subdevs/xrt-icap.c | 306 +++ drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c | 1905 +++++++++++++++++ .../fpga/alveo/lib/subdevs/xrt-partition.c | 261 +++ drivers/fpga/alveo/lib/subdevs/xrt-qspi.c | 1347 ++++++++++++ drivers/fpga/alveo/lib/subdevs/xrt-srsr.c | 322 +++ drivers/fpga/alveo/lib/subdevs/xrt-test.c | 274 +++ drivers/fpga/alveo/lib/subdevs/xrt-ucs.c | 238 ++ .../fpga/alveo/lib/subdevs/xrt-vsec-golden.c | 238 ++ drivers/fpga/alveo/lib/subdevs/xrt-vsec.c | 337 +++ drivers/fpga/alveo/lib/xrt-cdev.c | 234 ++ drivers/fpga/alveo/lib/xrt-main.c | 275 +++ drivers/fpga/alveo/lib/xrt-main.h | 46 + drivers/fpga/alveo/lib/xrt-subdev.c | 1007 +++++++++ drivers/fpga/alveo/mgmt/Kconfig | 11 + drivers/fpga/alveo/mgmt/Makefile | 28 + drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c | 194 ++ drivers/fpga/alveo/mgmt/xmgmt-fmgr.h | 29 + drivers/fpga/alveo/mgmt/xmgmt-main-impl.h | 36 + drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c | 930 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c | 190 ++ drivers/fpga/alveo/mgmt/xmgmt-main.c | 843 ++++++++ drivers/fpga/alveo/mgmt/xmgmt-root.c | 375 ++++ include/uapi/linux/xrt/flash_xrt_data.h | 67 + include/uapi/linux/xrt/mailbox_proto.h | 394 ++++ include/uapi/linux/xrt/mailbox_transport.h | 74 + include/uapi/linux/xrt/xclbin.h | 418 ++++ include/uapi/linux/xrt/xmgmt-ioctl.h | 72 + 67 files changed, 17710 insertions(+) create mode 100644 Documentation/fpga/xrt.rst create mode 100644 drivers/fpga/alveo/Kconfig create mode 100644 drivers/fpga/alveo/common/xrt-metadata.c create mode 100644 drivers/fpga/alveo/common/xrt-root.c create mode 100644 drivers/fpga/alveo/common/xrt-root.h create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.c create mode 100644 drivers/fpga/alveo/common/xrt-xclbin.h create mode 100644 drivers/fpga/alveo/include/xmgmt-main.h create mode 100644 drivers/fpga/alveo/include/xrt-axigate.h create mode 100644 drivers/fpga/alveo/include/xrt-calib.h create mode 100644 drivers/fpga/alveo/include/xrt-clkfreq.h create mode 100644 drivers/fpga/alveo/include/xrt-clock.h create mode 100644 drivers/fpga/alveo/include/xrt-cmc.h create mode 100644 drivers/fpga/alveo/include/xrt-ddr-srsr.h create mode 100644 drivers/fpga/alveo/include/xrt-flash.h create mode 100644 drivers/fpga/alveo/include/xrt-gpio.h create mode 100644 drivers/fpga/alveo/include/xrt-icap.h create mode 100644 drivers/fpga/alveo/include/xrt-mailbox.h create mode 100644 drivers/fpga/alveo/include/xrt-metadata.h create mode 100644 drivers/fpga/alveo/include/xrt-parent.h create mode 100644 drivers/fpga/alveo/include/xrt-partition.h create mode 100644 drivers/fpga/alveo/include/xrt-subdev.h create mode 100644 drivers/fpga/alveo/include/xrt-ucs.h create mode 100644 drivers/fpga/alveo/lib/Kconfig create mode 100644 drivers/fpga/alveo/lib/Makefile create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-axigate.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-calib.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clkfreq.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-clock.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-bdinfo.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-ctrl.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-impl.h create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc-sensors.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-cmc.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-gpio.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-icap.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-mailbox.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-partition.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-qspi.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-srsr.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-test.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-ucs.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec-golden.c create mode 100644 drivers/fpga/alveo/lib/subdevs/xrt-vsec.c create mode 100644 drivers/fpga/alveo/lib/xrt-cdev.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.c create mode 100644 drivers/fpga/alveo/lib/xrt-main.h create mode 100644 drivers/fpga/alveo/lib/xrt-subdev.c create mode 100644 drivers/fpga/alveo/mgmt/Kconfig create mode 100644 drivers/fpga/alveo/mgmt/Makefile create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr-drv.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-fmgr.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-impl.h create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-mailbox.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main-ulp.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-main.c create mode 100644 drivers/fpga/alveo/mgmt/xmgmt-root.c create mode 100644 include/uapi/linux/xrt/flash_xrt_data.h create mode 100644 include/uapi/linux/xrt/mailbox_proto.h create mode 100644 include/uapi/linux/xrt/mailbox_transport.h create mode 100644 include/uapi/linux/xrt/xclbin.h create mode100644
include/uapi/linux/xrt/xmgmt-ioctl.h--
2.17.1
Tom Rix
reviewerQuoted 5 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards, https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.
A few general things.
Use scripts/get_maintainer.pl to find who a patch should go to, i should have been on the cc line.
Each patch should at a minimum pass scripts/checkpatch.pl, none do.
Looking broadly at the files, there are competing names xrt or alveo.
It seems like xrt is the dfl equivalent, so maybe
drivers/fpga/alveo should be drivers/fpga/xrt
There are a lot of files with unnecessary prefixes
ex/
fpga/alveo/include/xrt-ucs.h could just be fpga/alveo/include/ucs.h
individual subdev's may not belong in the fpga subsystem.
I think it would be better to submit these one at a time as is done for dfl.
So this will not block getting the basics done, in the next revision, can you leave the subdev's out ?
Because of the checkpatch.pl failures, I will wait for the next revision.
Tom
Hello Tom,
Quoted 18 lines
-----Original Message-----
From: Tom Rix <[email protected]>
Sent: Sunday, December 6, 2020 8:31 AM
To: Sonal Santan <[email protected]>; [email protected]
Cc: Sonal Santan <[email protected]>; [email protected]; Max Zhen <[email protected]>; Lizhi Hou <[email protected]>; Michal Simek <[email protected]>; Stefano Stabellini <[email protected]>; [email protected]
Subject: Re: [PATCH Xilinx Alveo 0/8] Xilinx Alveo/XRT patch overviewQuoted 6 lines · Sonal Santan
Hello,
This patch series adds management physical function driver for Xilinx Alveo PCIe accelerator cards,
https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.
Quoted 5 lines
A few general things.
Use
scripts/get_maintainer.plto find who a patch should go to, i should have been on the cc line.
Will do.
Quoted 2 lines
Each patch should at a minimum pass
scripts/checkpatch.pl, none do.
Looks like a few files missed our checkpatch process. Will address in the upcoming patch series.
Quoted 6 lines
Looking broadly at the files, there are competing names xrt or alveo.
It seems like xrt is the dfl equivalent, so maybe
drivers/fpga/alveoshould bedrivers/fpga/xrt
Agreed. Will address in the next patch series.
Quoted 6 lines
There are a lot of files with unnecessary prefixes
ex/
fpga/alveo/include/xrt-ucs.hcould just befpga/alveo/include/ucs.h
Would work on separating xrt infrastructure and subdevs header files into separate directories and drop the xrt prefix.
Quoted 4 lines
individual subdev's may not belong in the fpga subsystem.
I think it would be better to submit these one at a time as is done for dfl.
In the upcoming patch revision, will drop the subdevs except bare minimum necessary to perform bitstream download.
Quoted 4 lines
So this will not block getting the basics done, in the next revision, can you leave the subdev's out ?
Thanks for the feedback.
-Sonal
Quoted 5 lines
Because of the checkpatch.pl failures, I will wait for the next revision.
Tom