lkml.org 
[lkml]   [2020]   [Oct]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRE: [PATCH char-misc-next 1/1] misc: mic: remove the MIC drivers
Date


> Subject: [PATCH char-misc-next 1/1] misc: mic: remove the MIC drivers
>
> This patch removes the MIC drivers from the kernel tree
> since the corresponding devices have been discontinued.
>
> Removing the dma and char-misc changes in one patch and
> merging via the char-misc tree is best to avoid any
> potential build breakage.
>
> Cc: Nikhil Rao <nikhil.rao@intel.com>
> Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
> Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com>

Reviewed-by: Sherry Sun <sherry.sun@nxp.com>

> ---
> Documentation/misc-devices/mic/index.rst | 16 -
> .../misc-devices/mic/mic_overview.rst | 85 -
> .../misc-devices/mic/scif_overview.rst | 108 -
> MAINTAINERS | 16 -
> drivers/dma/Kconfig | 18 -
> drivers/dma/Makefile | 1 -
> drivers/dma/mic_x100_dma.c | 770 -------
> drivers/dma/mic_x100_dma.h | 275 ---
> drivers/misc/Kconfig | 1 -
> drivers/misc/Makefile | 1 -
> drivers/misc/mic/Kconfig | 141 --
> drivers/misc/mic/Makefile | 12 -
> drivers/misc/mic/bus/Makefile | 9 -
> drivers/misc/mic/bus/cosm_bus.c | 130 --
> drivers/misc/mic/bus/cosm_bus.h | 125 --
> drivers/misc/mic/bus/mic_bus.c | 194 --
> drivers/misc/mic/bus/scif_bus.c | 201 --
> drivers/misc/mic/bus/scif_bus.h | 125 --
> drivers/misc/mic/bus/vop_bus.c | 194 --
> drivers/misc/mic/bus/vop_bus.h | 129 --
> drivers/misc/mic/card/Makefile | 11 -
> drivers/misc/mic/card/mic_debugfs.c | 85 -
> drivers/misc/mic/card/mic_device.c | 417 ----
> drivers/misc/mic/card/mic_device.h | 137 --
> drivers/misc/mic/card/mic_x100.c | 347 ---
> drivers/misc/mic/card/mic_x100.h | 37 -
> drivers/misc/mic/common/mic_dev.h | 55 -
> drivers/misc/mic/cosm/Makefile | 11 -
> drivers/misc/mic/cosm/cosm_debugfs.c | 116 -
> drivers/misc/mic/cosm/cosm_main.c | 382 ----
> drivers/misc/mic/cosm/cosm_main.h | 61 -
> drivers/misc/mic/cosm/cosm_scif_server.c | 399 ----
> drivers/misc/mic/cosm/cosm_sysfs.c | 449 ----
> drivers/misc/mic/cosm_client/Makefile | 8 -
> .../misc/mic/cosm_client/cosm_scif_client.c | 269 ---
> drivers/misc/mic/host/Makefile | 12 -
> drivers/misc/mic/host/mic_boot.c | 588 -----
> drivers/misc/mic/host/mic_debugfs.c | 149 --
> drivers/misc/mic/host/mic_device.h | 157 --
> drivers/misc/mic/host/mic_intr.c | 635 ------
> drivers/misc/mic/host/mic_intr.h | 137 --
> drivers/misc/mic/host/mic_main.c | 335 ---
> drivers/misc/mic/host/mic_smpt.c | 427 ----
> drivers/misc/mic/host/mic_smpt.h | 87 -
> drivers/misc/mic/host/mic_x100.c | 585 -----
> drivers/misc/mic/host/mic_x100.h | 77 -
> drivers/misc/mic/scif/Makefile | 21 -
> drivers/misc/mic/scif/scif_api.c | 1485 -------------
> drivers/misc/mic/scif/scif_debugfs.c | 116 -
> drivers/misc/mic/scif/scif_dma.c | 1940 -----------------
> drivers/misc/mic/scif/scif_epd.c | 357 ---
> drivers/misc/mic/scif/scif_epd.h | 200 --
> drivers/misc/mic/scif/scif_fd.c | 462 ----
> drivers/misc/mic/scif/scif_fence.c | 783 -------
> drivers/misc/mic/scif/scif_main.c | 351 ---
> drivers/misc/mic/scif/scif_main.h | 274 ---
> drivers/misc/mic/scif/scif_map.h | 127 --
> drivers/misc/mic/scif/scif_mmap.c | 690 ------
> drivers/misc/mic/scif/scif_nm.c | 229 --
> drivers/misc/mic/scif/scif_nodeqp.c | 1349 ------------
> drivers/misc/mic/scif/scif_nodeqp.h | 221 --
> drivers/misc/mic/scif/scif_peer_bus.c | 175 --
> drivers/misc/mic/scif/scif_peer_bus.h | 23 -
> drivers/misc/mic/scif/scif_ports.c | 116 -
> drivers/misc/mic/scif/scif_rb.c | 240 --
> drivers/misc/mic/scif/scif_rb.h | 100 -
> drivers/misc/mic/scif/scif_rma.c | 1760 ---------------
> drivers/misc/mic/scif/scif_rma.h | 477 ----
> drivers/misc/mic/scif/scif_rma_list.c | 282 ---
> drivers/misc/mic/scif/scif_rma_list.h | 48 -
> drivers/misc/mic/vop/Makefile | 10 -
> drivers/misc/mic/vop/vop_debugfs.c | 184 --
> drivers/misc/mic/vop/vop_main.c | 784 -------
> drivers/misc/mic/vop/vop_main.h | 158 --
> drivers/misc/mic/vop/vop_vringh.c | 1166 ----------
> include/linux/mic_bus.h | 100 -
> include/linux/scif.h | 1339 ------------
> include/uapi/linux/mic_common.h | 235 --
> include/uapi/linux/mic_ioctl.h | 77 -
> samples/mic/mpssd/.gitignore | 2 -
> samples/mic/mpssd/Makefile | 28 -
> samples/mic/mpssd/micctrl | 162 --
> samples/mic/mpssd/mpss | 189 --
> samples/mic/mpssd/mpssd.c | 1815 ---------------
> samples/mic/mpssd/mpssd.h | 89 -
> samples/mic/mpssd/sysfs.c | 91 -
> 86 files changed, 26779 deletions(-)
> delete mode 100644 Documentation/misc-devices/mic/index.rst
> delete mode 100644 Documentation/misc-devices/mic/mic_overview.rst
> delete mode 100644 Documentation/misc-devices/mic/scif_overview.rst
> delete mode 100644 drivers/dma/mic_x100_dma.c
> delete mode 100644 drivers/dma/mic_x100_dma.h
> delete mode 100644 drivers/misc/mic/Kconfig
> delete mode 100644 drivers/misc/mic/Makefile
> delete mode 100644 drivers/misc/mic/bus/Makefile
> delete mode 100644 drivers/misc/mic/bus/cosm_bus.c
> delete mode 100644 drivers/misc/mic/bus/cosm_bus.h
> delete mode 100644 drivers/misc/mic/bus/mic_bus.c
> delete mode 100644 drivers/misc/mic/bus/scif_bus.c
> delete mode 100644 drivers/misc/mic/bus/scif_bus.h
> delete mode 100644 drivers/misc/mic/bus/vop_bus.c
> delete mode 100644 drivers/misc/mic/bus/vop_bus.h
> delete mode 100644 drivers/misc/mic/card/Makefile
> delete mode 100644 drivers/misc/mic/card/mic_debugfs.c
> delete mode 100644 drivers/misc/mic/card/mic_device.c
> delete mode 100644 drivers/misc/mic/card/mic_device.h
> delete mode 100644 drivers/misc/mic/card/mic_x100.c
> delete mode 100644 drivers/misc/mic/card/mic_x100.h
> delete mode 100644 drivers/misc/mic/common/mic_dev.h
> delete mode 100644 drivers/misc/mic/cosm/Makefile
> delete mode 100644 drivers/misc/mic/cosm/cosm_debugfs.c
> delete mode 100644 drivers/misc/mic/cosm/cosm_main.c
> delete mode 100644 drivers/misc/mic/cosm/cosm_main.h
> delete mode 100644 drivers/misc/mic/cosm/cosm_scif_server.c
> delete mode 100644 drivers/misc/mic/cosm/cosm_sysfs.c
> delete mode 100644 drivers/misc/mic/cosm_client/Makefile
> delete mode 100644 drivers/misc/mic/cosm_client/cosm_scif_client.c
> delete mode 100644 drivers/misc/mic/host/Makefile
> delete mode 100644 drivers/misc/mic/host/mic_boot.c
> delete mode 100644 drivers/misc/mic/host/mic_debugfs.c
> delete mode 100644 drivers/misc/mic/host/mic_device.h
> delete mode 100644 drivers/misc/mic/host/mic_intr.c
> delete mode 100644 drivers/misc/mic/host/mic_intr.h
> delete mode 100644 drivers/misc/mic/host/mic_main.c
> delete mode 100644 drivers/misc/mic/host/mic_smpt.c
> delete mode 100644 drivers/misc/mic/host/mic_smpt.h
> delete mode 100644 drivers/misc/mic/host/mic_x100.c
> delete mode 100644 drivers/misc/mic/host/mic_x100.h
> delete mode 100644 drivers/misc/mic/scif/Makefile
> delete mode 100644 drivers/misc/mic/scif/scif_api.c
> delete mode 100644 drivers/misc/mic/scif/scif_debugfs.c
> delete mode 100644 drivers/misc/mic/scif/scif_dma.c
> delete mode 100644 drivers/misc/mic/scif/scif_epd.c
> delete mode 100644 drivers/misc/mic/scif/scif_epd.h
> delete mode 100644 drivers/misc/mic/scif/scif_fd.c
> delete mode 100644 drivers/misc/mic/scif/scif_fence.c
> delete mode 100644 drivers/misc/mic/scif/scif_main.c
> delete mode 100644 drivers/misc/mic/scif/scif_main.h
> delete mode 100644 drivers/misc/mic/scif/scif_map.h
> delete mode 100644 drivers/misc/mic/scif/scif_mmap.c
> delete mode 100644 drivers/misc/mic/scif/scif_nm.c
> delete mode 100644 drivers/misc/mic/scif/scif_nodeqp.c
> delete mode 100644 drivers/misc/mic/scif/scif_nodeqp.h
> delete mode 100644 drivers/misc/mic/scif/scif_peer_bus.c
> delete mode 100644 drivers/misc/mic/scif/scif_peer_bus.h
> delete mode 100644 drivers/misc/mic/scif/scif_ports.c
> delete mode 100644 drivers/misc/mic/scif/scif_rb.c
> delete mode 100644 drivers/misc/mic/scif/scif_rb.h
> delete mode 100644 drivers/misc/mic/scif/scif_rma.c
> delete mode 100644 drivers/misc/mic/scif/scif_rma.h
> delete mode 100644 drivers/misc/mic/scif/scif_rma_list.c
> delete mode 100644 drivers/misc/mic/scif/scif_rma_list.h
> delete mode 100644 drivers/misc/mic/vop/Makefile
> delete mode 100644 drivers/misc/mic/vop/vop_debugfs.c
> delete mode 100644 drivers/misc/mic/vop/vop_main.c
> delete mode 100644 drivers/misc/mic/vop/vop_main.h
> delete mode 100644 drivers/misc/mic/vop/vop_vringh.c
> delete mode 100644 include/linux/mic_bus.h
> delete mode 100644 include/linux/scif.h
> delete mode 100644 include/uapi/linux/mic_common.h
> delete mode 100644 include/uapi/linux/mic_ioctl.h
> delete mode 100644 samples/mic/mpssd/.gitignore
> delete mode 100644 samples/mic/mpssd/Makefile
> delete mode 100755 samples/mic/mpssd/micctrl
> delete mode 100755 samples/mic/mpssd/mpss
> delete mode 100644 samples/mic/mpssd/mpssd.c
> delete mode 100644 samples/mic/mpssd/mpssd.h
> delete mode 100644 samples/mic/mpssd/sysfs.c
>
> diff --git a/Documentation/misc-devices/mic/index.rst
> b/Documentation/misc-devices/mic/index.rst
> deleted file mode 100644
> index 3a8d06367ef1..000000000000
> --- a/Documentation/misc-devices/mic/index.rst
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -=============================================
> -Intel Many Integrated Core (MIC) architecture
> -=============================================
> -
> -.. toctree::
> - :maxdepth: 1
> -
> - mic_overview
> - scif_overview
> -
> -.. only:: subproject and html
> -
> - Indices
> - =======
> -
> - * :ref:`genindex`
> diff --git a/Documentation/misc-devices/mic/mic_overview.rst
> b/Documentation/misc-devices/mic/mic_overview.rst
> deleted file mode 100644
> index 17d956bdaf7c..000000000000
> --- a/Documentation/misc-devices/mic/mic_overview.rst
> +++ /dev/null
> @@ -1,85 +0,0 @@
> -======================================================
> -Intel Many Integrated Core (MIC) architecture overview
> -======================================================
> -
> -An Intel MIC X100 device is a PCIe form factor add-in coprocessor
> -card based on the Intel Many Integrated Core (MIC) architecture
> -that runs a Linux OS. It is a PCIe endpoint in a platform and therefore
> -implements the three required standard address spaces i.e. configuration,
> -memory and I/O. The host OS loads a device driver as is typical for
> -PCIe devices. The card itself runs a bootstrap after reset that
> -transfers control to the card OS downloaded from the host driver. The
> -host driver supports OSPM suspend and resume operations. It shuts down
> -the card during suspend and reboots the card OS during resume.
> -The card OS as shipped by Intel is a Linux kernel with modifications
> -for the X100 devices.
> -
> -Since it is a PCIe card, it does not have the ability to host hardware
> -devices for networking, storage and console. We provide these devices
> -on X100 coprocessors thus enabling a self-bootable equivalent
> -environment for applications. A key benefit of our solution is that it
> -leverages the standard virtio framework for network, disk and console
> -devices, though in our case the virtio framework is used across a PCIe
> -bus. A Virtio Over PCIe (VOP) driver allows creating user space
> -backends or devices on the host which are used to probe virtio drivers
> -for these devices on the MIC card. The existing VRINGH infrastructure
> -in the kernel is used to access virtio rings from the host. The card
> -VOP driver allows card virtio drivers to communicate with their user
> -space backends on the host via a device page. Ring 3 apps on the host
> -can add, remove and configure virtio devices. A thin MIC specific
> -virtio_config_ops is implemented which is borrowed heavily from
> -previous similar implementations in lguest and s390.
> -
> -MIC PCIe card has a dma controller with 8 channels. These channels are
> -shared between the host s/w and the card s/w. 0 to 3 are used by host
> -and 4 to 7 by card. As the dma device doesn't show up as PCIe device,
> -a virtual bus called mic bus is created and virtual dma devices are
> -created on it by the host/card drivers. On host the channels are private
> -and used only by the host driver to transfer data for the virtio devices.
> -
> -The Symmetric Communication Interface (SCIF (pronounced as skiff)) is a
> -low level communications API across PCIe currently implemented for MIC.
> -More details are available at scif_overview.txt.
> -
> -The Coprocessor State Management (COSM) driver on the host allows for
> -boot, shutdown and reset of Intel MIC devices. It communicates with a
> COSM
> -"client" driver on the MIC cards over SCIF to perform these functions.
> -
> -Here is a block diagram of the various components described above. The
> -virtio backends are situated on the host rather than the card given better
> -single threaded performance for the host compared to MIC, the ability of
> -the host to initiate DMA's to/from the card using the MIC DMA engine and
> -the fact that the virtio block storage backend can only be on the host::
> -
> - +----------+ | +----------+
> - | Card OS | | | Host OS |
> - +----------+ | +----------+
> - |
> - +-------+ +--------+ +------+ | +---------+ +--------+ +--------+
> - | Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio |
> - | Net | |Console | |Block | | |Net | |Console | |Block |
> - | Driver| |Driver | |Driver| | |backend | |backend | |backend |
> - +---+---+ +---+----+ +--+---+ | +---------+ +----+---+ +--------+
> - | | | | | | |
> - | | | |User | | |
> - | | | |------|------------|--+------|-------
> - +---------+---------+ |Kernel |
> - | | |
> - +---------+ +---+----+ +------+ | +------+ +------+ +--+---+ +-------+
> - |MIC DMA | | VOP | | SCIF | | | SCIF | | COSM | | VOP | |MIC DMA|
> - +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+
> - | | | | | | |
> - +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+
> - |MIC | | VOP | |SCIF | | |SCIF | | COSM | | VOP | | MIC |
> - |HW Bus | | HW Bus| |HW Bus| | |HW Bus| | Bus | |HW Bus| |HW
> Bus |
> - +---------+ +--------+ +--+---+ | +--+---+ +------+ +------+ +-------+
> - | | | | | | |
> - | +-----------+--+ | | | +---------------+ |
> - | |Intel MIC | | | | |Intel MIC | |
> - | |Card Driver | | | | |Host Driver | |
> - +---+--------------+------+ | +----+---------------+-----+
> - | | |
> - +-------------------------------------------------------------+
> - | |
> - | PCIe Bus |
> - +-------------------------------------------------------------+
> diff --git a/Documentation/misc-devices/mic/scif_overview.rst
> b/Documentation/misc-devices/mic/scif_overview.rst
> deleted file mode 100644
> index 4c8ad9e43706..000000000000
> --- a/Documentation/misc-devices/mic/scif_overview.rst
> +++ /dev/null
> @@ -1,108 +0,0 @@
> -========================================
> -Symmetric Communication Interface (SCIF)
> -========================================
> -
> -The Symmetric Communication Interface (SCIF (pronounced as skiff)) is a
> low
> -level communications API across PCIe currently implemented for MIC.
> Currently
> -SCIF provides inter-node communication within a single host platform,
> where a
> -node is a MIC Coprocessor or Xeon based host. SCIF abstracts the details of
> -communicating over the PCIe bus while providing an API that is symmetric
> -across all the nodes in the PCIe network. An important design objective for
> SCIF
> -is to deliver the maximum possible performance given the communication
> -abilities of the hardware. SCIF has been used to implement an offload
> compiler
> -runtime and OFED support for MPI implementations for MIC coprocessors.
> -
> -SCIF API Components
> -===================
> -
> -The SCIF API has the following parts:
> -
> -1. Connection establishment using a client server model
> -2. Byte stream messaging intended for short messages
> -3. Node enumeration to determine online nodes
> -4. Poll semantics for detection of incoming connections and messages
> -5. Memory registration to pin down pages
> -6. Remote memory mapping for low latency CPU accesses via mmap
> -7. Remote DMA (RDMA) for high bandwidth DMA transfers
> -8. Fence APIs for RDMA synchronization
> -
> -SCIF exposes the notion of a connection which can be used by peer
> processes on
> -nodes in a SCIF PCIe "network" to share memory "windows" and to
> communicate. A
> -process in a SCIF node initiates a SCIF connection to a peer process on a
> -different node via a SCIF "endpoint". SCIF endpoints support messaging APIs
> -which are similar to connection oriented socket APIs. Connected SCIF
> endpoints
> -can also register local memory which is followed by data transfer using
> either
> -DMA, CPU copies or remote memory mapping via mmap. SCIF supports
> both user and
> -kernel mode clients which are functionally equivalent.
> -
> -SCIF Performance for MIC
> -========================
> -
> -DMA bandwidth comparison between the TCP (over ethernet over PCIe)
> stack versus
> -SCIF shows the performance advantages of SCIF for HPC applications and
> -runtimes::
> -
> - Comparison of TCP and SCIF based BW
> -
> - Throughput (GB/sec)
> - 8 + PCIe Bandwidth ******
> - + TCP ######
> - 7 + ************************************** SCIF %%%%%%
> - | %%%%%%%%%%%%%%%%%%%
> - 6 + %%%%
> - | %%
> - | %%%
> - 5 + %%
> - | %%
> - 4 + %%
> - | %%
> - 3 + %%
> - | %
> - 2 + %%
> - | %%
> - | %
> - 1 +
> - + ######################################
> - 0 +++---+++--+--+-+--+--+-++-+--+-++-+--+-++-+-
> - 1 10 100 1000 10000 100000
> - Transfer Size (KBytes)
> -
> -SCIF allows memory sharing via mmap(..) between processes on different
> PCIe
> -nodes and thus provides bare-metal PCIe latency. The round trip SCIF mmap
> -latency from the host to an x100 MIC for an 8 byte message is 0.44 usecs.
> -
> -SCIF has a user space library which is a thin IOCTL wrapper providing a user
> -space API similar to the kernel API in scif.h. The SCIF user space library
> -is distributed @
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591938987%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=JazqZ0AMWUqcOWdQVOC3NNlFj1C9kr7ZbZvVUyJDNKY%3D&amp;res
> erved=0
> -
> -Here is some pseudo code for an example of how two applications on two
> PCIe
> -nodes would typically use the SCIF API::
> -
> - Process A (on node A) Process B (on node B)
> -
> - /* get online node information */
> - scif_get_node_ids(..) scif_get_node_ids(..)
> - scif_open(..) scif_open(..)
> - scif_bind(..) scif_bind(..)
> - scif_listen(..)
> - scif_accept(..) scif_connect(..)
> - /* SCIF connection established */
> -
> - /* Send and receive short messages */
> - scif_send(..)/scif_recv(..) scif_send(..)/scif_recv(..)
> -
> - /* Register memory */
> - scif_register(..) scif_register(..)
> -
> - /* RDMA */
> - scif_readfrom(..)/scif_writeto(..) scif_readfrom(..)/scif_writeto(..)
> -
> - /* Fence DMAs */
> - scif_fence_signal(..) scif_fence_signal(..)
> -
> - mmap(..) mmap(..)
> -
> - /* Access remote registered memory */
> -
> - /* Close the endpoints */
> - scif_close(..) scif_close(..)
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e73636b75f29..9289a9b43a51 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8976,22 +8976,6 @@ S: Supported
> W:
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%
> 2F01.org%2Flinux-
> acpi&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc4f87f9
> 3e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637
> 394520591938987%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAi
> LCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=v
> Eqv097LekcuBg9%2BGkD5wKYBSujDYSO2MCp129b6O2k%3D&amp;reserved=
> 0
> F: drivers/platform/x86/intel_menlow.c
>
> -INTEL MIC DRIVERS (mic)
> -M: Sudeep Dutt <sudeep.dutt@intel.com>
> -M: Ashutosh Dixit <ashutosh.dixit@intel.com>
> -S: Supported
> -W:
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%
> 2Fgithub.com%2Fsudeepdutt%2Fmic&amp;data=04%7C01%7Csherry.sun%4
> 0nxp.com%7Cf4d4a5577fcc4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92
> cd99c5c301635%7C0%7C0%7C637394520591938987%7CUnknown%7CTWFp
> bGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI
> 6Mn0%3D%7C1000&amp;sdata=6CC4zdrpmy6vpT%2F%2FHnGH21D%2Fs8lr
> VVYSJBDuqm449hA%3D&amp;reserved=0
> -W:
> https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2
> Fsoftware.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591938987%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=EYeS%2B8VAjYKOzOZ5CuVm%2FB1lxNVgIY5K2kzmyOSCXsA%3D&amp;
> reserved=0
> -F: Documentation/misc-devices/mic/
> -F: drivers/dma/mic_x100_dma.c
> -F: drivers/dma/mic_x100_dma.h
> -F: drivers/misc/mic/
> -F: include/linux/mic_bus.h
> -F: include/linux/scif.h
> -F: include/uapi/linux/mic_common.h
> -F: include/uapi/linux/mic_ioctl.h
> -F: include/uapi/linux/scif_ioctl.h
> -
> INTEL P-Unit IPC DRIVER
> M: Zha Qipeng <qipeng.zha@intel.com>
> L: platform-driver-x86@vger.kernel.org
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 518a1437862a..90284ffda58a 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -318,24 +318,6 @@ config INTEL_IOP_ADMA
> help
> Enable support for the Intel(R) IOP Series RAID engines.
>
> -config INTEL_MIC_X100_DMA
> - tristate "Intel MIC X100 DMA Driver"
> - depends on 64BIT && X86 && INTEL_MIC_BUS
> - select DMA_ENGINE
> - help
> - This enables DMA support for the Intel Many Integrated Core
> - (MIC) family of PCIe form factor coprocessor X100 devices that
> - run a 64 bit Linux OS. This driver will be used by both MIC
> - host and card drivers.
> -
> - If you are building host kernel with a MIC device or a card
> - kernel for a MIC device, then say M (recommended) or Y, else
> - say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> config K3_DMA
> tristate "Hisilicon K3 DMA support"
> depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> index e60f81331d4c..948a8da05f8b 100644
> --- a/drivers/dma/Makefile
> +++ b/drivers/dma/Makefile
> @@ -44,7 +44,6 @@ obj-$(CONFIG_INTEL_IDMA64) += idma64.o
> obj-$(CONFIG_INTEL_IOATDMA) += ioat/
> obj-$(CONFIG_INTEL_IDXD) += idxd/
> obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
> -obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
> obj-$(CONFIG_K3_DMA) += k3dma.o
> obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
> obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
> diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
> deleted file mode 100644
> index fea8608a7810..000000000000
> --- a/drivers/dma/mic_x100_dma.c
> +++ /dev/null
> @@ -1,770 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel MIC X100 DMA Driver.
> - *
> - * Adapted from IOAT dma driver.
> - */
> -#include <linux/module.h>
> -#include <linux/io.h>
> -#include <linux/seq_file.h>
> -#include <linux/vmalloc.h>
> -
> -#include "mic_x100_dma.h"
> -
> -#define MIC_DMA_MAX_XFER_SIZE_CARD (1 * 1024 * 1024 -\
> - MIC_DMA_ALIGN_BYTES)
> -#define MIC_DMA_MAX_XFER_SIZE_HOST (1 * 1024 * 1024 >> 1)
> -#define MIC_DMA_DESC_TYPE_SHIFT 60
> -#define MIC_DMA_MEMCPY_LEN_SHIFT 46
> -#define MIC_DMA_STAT_INTR_SHIFT 59
> -
> -/* high-water mark for pushing dma descriptors */
> -static int mic_dma_pending_level = 4;
> -
> -/* Status descriptor is used to write a 64 bit value to a memory location */
> -enum mic_dma_desc_format_type {
> - MIC_DMA_MEMCPY = 1,
> - MIC_DMA_STATUS,
> -};
> -
> -static inline u32 mic_dma_hw_ring_inc(u32 val)
> -{
> - return (val + 1) % MIC_DMA_DESC_RX_SIZE;
> -}
> -
> -static inline u32 mic_dma_hw_ring_dec(u32 val)
> -{
> - return val ? val - 1 : MIC_DMA_DESC_RX_SIZE - 1;
> -}
> -
> -static inline void mic_dma_hw_ring_inc_head(struct mic_dma_chan *ch)
> -{
> - ch->head = mic_dma_hw_ring_inc(ch->head);
> -}
> -
> -/* Prepare a memcpy desc */
> -static inline void mic_dma_memcpy_desc(struct mic_dma_desc *desc,
> - dma_addr_t src_phys, dma_addr_t dst_phys, u64 size)
> -{
> - u64 qw0, qw1;
> -
> - qw0 = src_phys;
> - qw0 |= (size >> MIC_DMA_ALIGN_SHIFT) <<
> MIC_DMA_MEMCPY_LEN_SHIFT;
> - qw1 = MIC_DMA_MEMCPY;
> - qw1 <<= MIC_DMA_DESC_TYPE_SHIFT;
> - qw1 |= dst_phys;
> - desc->qw0 = qw0;
> - desc->qw1 = qw1;
> -}
> -
> -/* Prepare a status desc. with @data to be written at @dst_phys */
> -static inline void mic_dma_prep_status_desc(struct mic_dma_desc *desc,
> u64 data,
> - dma_addr_t dst_phys, bool generate_intr)
> -{
> - u64 qw0, qw1;
> -
> - qw0 = data;
> - qw1 = (u64) MIC_DMA_STATUS << MIC_DMA_DESC_TYPE_SHIFT |
> dst_phys;
> - if (generate_intr)
> - qw1 |= (1ULL << MIC_DMA_STAT_INTR_SHIFT);
> - desc->qw0 = qw0;
> - desc->qw1 = qw1;
> -}
> -
> -static void mic_dma_cleanup(struct mic_dma_chan *ch)
> -{
> - struct dma_async_tx_descriptor *tx;
> - u32 tail;
> - u32 last_tail;
> -
> - spin_lock(&ch->cleanup_lock);
> - tail = mic_dma_read_cmp_cnt(ch);
> - /*
> - * This is the barrier pair for smp_wmb() in fn.
> - * mic_dma_tx_submit_unlock. It's required so that we read the
> - * updated cookie value from tx->cookie.
> - */
> - smp_rmb();
> - for (last_tail = ch->last_tail; tail != last_tail;) {
> - tx = &ch->tx_array[last_tail];
> - if (tx->cookie) {
> - dma_cookie_complete(tx);
> - dmaengine_desc_get_callback_invoke(tx, NULL);
> - tx->callback = NULL;
> - }
> - last_tail = mic_dma_hw_ring_inc(last_tail);
> - }
> - /* finish all completion callbacks before incrementing tail */
> - smp_mb();
> - ch->last_tail = last_tail;
> - spin_unlock(&ch->cleanup_lock);
> -}
> -
> -static u32 mic_dma_ring_count(u32 head, u32 tail)
> -{
> - u32 count;
> -
> - if (head >= tail)
> - count = (tail - 0) + (MIC_DMA_DESC_RX_SIZE - head);
> - else
> - count = tail - head;
> - return count - 1;
> -}
> -
> -/* Returns the num. of free descriptors on success, -ENOMEM on failure */
> -static int mic_dma_avail_desc_ring_space(struct mic_dma_chan *ch, int
> required)
> -{
> - struct device *dev = mic_dma_ch_to_device(ch);
> - u32 count;
> -
> - count = mic_dma_ring_count(ch->head, ch->last_tail);
> - if (count < required) {
> - mic_dma_cleanup(ch);
> - count = mic_dma_ring_count(ch->head, ch->last_tail);
> - }
> -
> - if (count < required) {
> - dev_dbg(dev, "Not enough desc space");
> - dev_dbg(dev, "%s %d required=%u, avail=%u\n",
> - __func__, __LINE__, required, count);
> - return -ENOMEM;
> - } else {
> - return count;
> - }
> -}
> -
> -/* Program memcpy descriptors into the descriptor ring and update s/w
> head ptr*/
> -static int mic_dma_prog_memcpy_desc(struct mic_dma_chan *ch,
> dma_addr_t src,
> - dma_addr_t dst, size_t len)
> -{
> - size_t current_transfer_len;
> - size_t max_xfer_size = to_mic_dma_dev(ch)->max_xfer_size;
> - /* 3 is added to make sure we have enough space for status desc */
> - int num_desc = len / max_xfer_size + 3;
> - int ret;
> -
> - if (len % max_xfer_size)
> - num_desc++;
> -
> - ret = mic_dma_avail_desc_ring_space(ch, num_desc);
> - if (ret < 0)
> - return ret;
> - do {
> - current_transfer_len = min(len, max_xfer_size);
> - mic_dma_memcpy_desc(&ch->desc_ring[ch->head],
> - src, dst, current_transfer_len);
> - mic_dma_hw_ring_inc_head(ch);
> - len -= current_transfer_len;
> - dst = dst + current_transfer_len;
> - src = src + current_transfer_len;
> - } while (len > 0);
> - return 0;
> -}
> -
> -/* It's a h/w quirk and h/w needs 2 status descriptors for every status desc
> */
> -static void mic_dma_prog_intr(struct mic_dma_chan *ch)
> -{
> - mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
> - ch->status_dest_micpa, false);
> - mic_dma_hw_ring_inc_head(ch);
> - mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
> - ch->status_dest_micpa, true);
> - mic_dma_hw_ring_inc_head(ch);
> -}
> -
> -/* Wrapper function to program memcpy descriptors/status descriptors */
> -static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags,
> dma_addr_t src,
> - dma_addr_t dst, size_t len)
> -{
> - if (len && -ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst,
> len)) {
> - return -ENOMEM;
> - } else {
> - /* 3 is the maximum number of status descriptors */
> - int ret = mic_dma_avail_desc_ring_space(ch, 3);
> -
> - if (ret < 0)
> - return ret;
> - }
> -
> - /* Above mic_dma_prog_memcpy_desc() makes sure we have
> enough space */
> - if (flags & DMA_PREP_FENCE) {
> - mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
> - ch->status_dest_micpa, false);
> - mic_dma_hw_ring_inc_head(ch);
> - }
> -
> - if (flags & DMA_PREP_INTERRUPT)
> - mic_dma_prog_intr(ch);
> -
> - return 0;
> -}
> -
> -static inline void mic_dma_issue_pending(struct dma_chan *ch)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> -
> - spin_lock(&mic_ch->issue_lock);
> - /*
> - * Write to head triggers h/w to act on the descriptors.
> - * On MIC, writing the same head value twice causes
> - * a h/w error. On second write, h/w assumes we filled
> - * the entire ring & overwrote some of the descriptors.
> - */
> - if (mic_ch->issued == mic_ch->submitted)
> - goto out;
> - mic_ch->issued = mic_ch->submitted;
> - /*
> - * make descriptor updates visible before advancing head,
> - * this is purposefully not smp_wmb() since we are also
> - * publishing the descriptor updates to a dma device
> - */
> - wmb();
> - mic_dma_write_reg(mic_ch, MIC_DMA_REG_DHPR, mic_ch->issued);
> -out:
> - spin_unlock(&mic_ch->issue_lock);
> -}
> -
> -static inline void mic_dma_update_pending(struct mic_dma_chan *ch)
> -{
> - if (mic_dma_ring_count(ch->issued, ch->submitted)
> - > mic_dma_pending_level)
> - mic_dma_issue_pending(&ch->api_ch);
> -}
> -
> -static dma_cookie_t mic_dma_tx_submit_unlock(struct
> dma_async_tx_descriptor *tx)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(tx->chan);
> - dma_cookie_t cookie;
> -
> - dma_cookie_assign(tx);
> - cookie = tx->cookie;
> - /*
> - * We need an smp write barrier here because another CPU might
> see
> - * an update to submitted and update h/w head even before we
> - * assigned a cookie to this tx.
> - */
> - smp_wmb();
> - mic_ch->submitted = mic_ch->head;
> - spin_unlock(&mic_ch->prep_lock);
> - mic_dma_update_pending(mic_ch);
> - return cookie;
> -}
> -
> -static inline struct dma_async_tx_descriptor *
> -allocate_tx(struct mic_dma_chan *ch)
> -{
> - u32 idx = mic_dma_hw_ring_dec(ch->head);
> - struct dma_async_tx_descriptor *tx = &ch->tx_array[idx];
> -
> - dma_async_tx_descriptor_init(tx, &ch->api_ch);
> - tx->tx_submit = mic_dma_tx_submit_unlock;
> - return tx;
> -}
> -
> -/* Program a status descriptor with dst as address and value to be written
> */
> -static struct dma_async_tx_descriptor *
> -mic_dma_prep_status_lock(struct dma_chan *ch, dma_addr_t dst, u64
> src_val,
> - unsigned long flags)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> - int result;
> -
> - spin_lock(&mic_ch->prep_lock);
> - result = mic_dma_avail_desc_ring_space(mic_ch, 4);
> - if (result < 0)
> - goto error;
> - mic_dma_prep_status_desc(&mic_ch->desc_ring[mic_ch->head],
> src_val, dst,
> - false);
> - mic_dma_hw_ring_inc_head(mic_ch);
> - result = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
> - if (result < 0)
> - goto error;
> -
> - return allocate_tx(mic_ch);
> -error:
> - dev_err(mic_dma_ch_to_device(mic_ch),
> - "Error enqueueing dma status descriptor, error=%d\n",
> result);
> - spin_unlock(&mic_ch->prep_lock);
> - return NULL;
> -}
> -
> -/*
> - * Prepare a memcpy descriptor to be added to the ring.
> - * Note that the temporary descriptor adds an extra overhead of copying the
> - * descriptor to ring. So, we copy directly to the descriptor ring
> - */
> -static struct dma_async_tx_descriptor *
> -mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest,
> - dma_addr_t dma_src, size_t len, unsigned long flags)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> - struct device *dev = mic_dma_ch_to_device(mic_ch);
> - int result;
> -
> - if (!len && !flags)
> - return NULL;
> -
> - spin_lock(&mic_ch->prep_lock);
> - result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len);
> - if (result >= 0)
> - return allocate_tx(mic_ch);
> - dev_err(dev, "Error enqueueing dma, error=%d\n", result);
> - spin_unlock(&mic_ch->prep_lock);
> - return NULL;
> -}
> -
> -static struct dma_async_tx_descriptor *
> -mic_dma_prep_interrupt_lock(struct dma_chan *ch, unsigned long flags)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> - int ret;
> -
> - spin_lock(&mic_ch->prep_lock);
> - ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
> - if (!ret)
> - return allocate_tx(mic_ch);
> - spin_unlock(&mic_ch->prep_lock);
> - return NULL;
> -}
> -
> -/* Return the status of the transaction */
> -static enum dma_status
> -mic_dma_tx_status(struct dma_chan *ch, dma_cookie_t cookie,
> - struct dma_tx_state *txstate)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> -
> - if (DMA_COMPLETE != dma_cookie_status(ch, cookie, txstate))
> - mic_dma_cleanup(mic_ch);
> -
> - return dma_cookie_status(ch, cookie, txstate);
> -}
> -
> -static irqreturn_t mic_dma_thread_fn(int irq, void *data)
> -{
> - mic_dma_cleanup((struct mic_dma_chan *)data);
> - return IRQ_HANDLED;
> -}
> -
> -static irqreturn_t mic_dma_intr_handler(int irq, void *data)
> -{
> - struct mic_dma_chan *ch = ((struct mic_dma_chan *)data);
> -
> - mic_dma_ack_interrupt(ch);
> - return IRQ_WAKE_THREAD;
> -}
> -
> -static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch)
> -{
> - u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch-
> >desc_ring);
> - struct device *dev = &to_mbus_device(ch)->dev;
> -
> - desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
> - ch->desc_ring = kzalloc(desc_ring_size, GFP_KERNEL);
> -
> - if (!ch->desc_ring)
> - return -ENOMEM;
> -
> - ch->desc_ring_micpa = dma_map_single(dev, ch->desc_ring,
> - desc_ring_size,
> DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(dev, ch->desc_ring_micpa))
> - goto map_error;
> -
> - ch->tx_array = vzalloc(array_size(MIC_DMA_DESC_RX_SIZE,
> - sizeof(*ch->tx_array)));
> - if (!ch->tx_array)
> - goto tx_error;
> - return 0;
> -tx_error:
> - dma_unmap_single(dev, ch->desc_ring_micpa, desc_ring_size,
> - DMA_BIDIRECTIONAL);
> -map_error:
> - kfree(ch->desc_ring);
> - return -ENOMEM;
> -}
> -
> -static void mic_dma_free_desc_ring(struct mic_dma_chan *ch)
> -{
> - u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch-
> >desc_ring);
> -
> - vfree(ch->tx_array);
> - desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
> - dma_unmap_single(&to_mbus_device(ch)->dev, ch-
> >desc_ring_micpa,
> - desc_ring_size, DMA_BIDIRECTIONAL);
> - kfree(ch->desc_ring);
> - ch->desc_ring = NULL;
> -}
> -
> -static void mic_dma_free_status_dest(struct mic_dma_chan *ch)
> -{
> - dma_unmap_single(&to_mbus_device(ch)->dev, ch-
> >status_dest_micpa,
> - L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
> - kfree(ch->status_dest);
> -}
> -
> -static int mic_dma_alloc_status_dest(struct mic_dma_chan *ch)
> -{
> - struct device *dev = &to_mbus_device(ch)->dev;
> -
> - ch->status_dest = kzalloc(L1_CACHE_BYTES, GFP_KERNEL);
> - if (!ch->status_dest)
> - return -ENOMEM;
> - ch->status_dest_micpa = dma_map_single(dev, ch->status_dest,
> - L1_CACHE_BYTES,
> DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(dev, ch->status_dest_micpa)) {
> - kfree(ch->status_dest);
> - ch->status_dest = NULL;
> - return -ENOMEM;
> - }
> - return 0;
> -}
> -
> -static int mic_dma_check_chan(struct mic_dma_chan *ch)
> -{
> - if (mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR) ||
> - mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) &
> MIC_DMA_CHAN_QUIESCE) {
> - mic_dma_disable_chan(ch);
> - mic_dma_chan_mask_intr(ch);
> - dev_err(mic_dma_ch_to_device(ch),
> - "%s %d error setting up mic dma chan %d\n",
> - __func__, __LINE__, ch->ch_num);
> - return -EBUSY;
> - }
> - return 0;
> -}
> -
> -static int mic_dma_chan_setup(struct mic_dma_chan *ch)
> -{
> - if (MIC_DMA_CHAN_MIC == ch->owner)
> - mic_dma_chan_set_owner(ch);
> - mic_dma_disable_chan(ch);
> - mic_dma_chan_mask_intr(ch);
> - mic_dma_write_reg(ch, MIC_DMA_REG_DCHERRMSK, 0);
> - mic_dma_chan_set_desc_ring(ch);
> - ch->last_tail = mic_dma_read_reg(ch, MIC_DMA_REG_DTPR);
> - ch->head = ch->last_tail;
> - ch->issued = 0;
> - mic_dma_chan_unmask_intr(ch);
> - mic_dma_enable_chan(ch);
> - return mic_dma_check_chan(ch);
> -}
> -
> -static void mic_dma_chan_destroy(struct mic_dma_chan *ch)
> -{
> - mic_dma_disable_chan(ch);
> - mic_dma_chan_mask_intr(ch);
> -}
> -
> -static int mic_dma_setup_irq(struct mic_dma_chan *ch)
> -{
> - ch->cookie =
> - to_mbus_hw_ops(ch)-
> >request_threaded_irq(to_mbus_device(ch),
> - mic_dma_intr_handler, mic_dma_thread_fn,
> - "mic dma_channel", ch, ch->ch_num);
> - return PTR_ERR_OR_ZERO(ch->cookie);
> -}
> -
> -static inline void mic_dma_free_irq(struct mic_dma_chan *ch)
> -{
> - to_mbus_hw_ops(ch)->free_irq(to_mbus_device(ch), ch->cookie, ch);
> -}
> -
> -static int mic_dma_chan_init(struct mic_dma_chan *ch)
> -{
> - int ret = mic_dma_alloc_desc_ring(ch);
> -
> - if (ret)
> - goto ring_error;
> - ret = mic_dma_alloc_status_dest(ch);
> - if (ret)
> - goto status_error;
> - ret = mic_dma_chan_setup(ch);
> - if (ret)
> - goto chan_error;
> - return ret;
> -chan_error:
> - mic_dma_free_status_dest(ch);
> -status_error:
> - mic_dma_free_desc_ring(ch);
> -ring_error:
> - return ret;
> -}
> -
> -static int mic_dma_drain_chan(struct mic_dma_chan *ch)
> -{
> - struct dma_async_tx_descriptor *tx;
> - int err = 0;
> - dma_cookie_t cookie;
> -
> - tx = mic_dma_prep_memcpy_lock(&ch->api_ch, 0, 0, 0,
> DMA_PREP_FENCE);
> - if (!tx) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie))
> - err = -ENOMEM;
> - else
> - err = dma_sync_wait(&ch->api_ch, cookie);
> - if (err) {
> - dev_err(mic_dma_ch_to_device(ch), "%s %d TO chan
> 0x%x\n",
> - __func__, __LINE__, ch->ch_num);
> - err = -EIO;
> - }
> -error:
> - mic_dma_cleanup(ch);
> - return err;
> -}
> -
> -static inline void mic_dma_chan_uninit(struct mic_dma_chan *ch)
> -{
> - mic_dma_chan_destroy(ch);
> - mic_dma_cleanup(ch);
> - mic_dma_free_status_dest(ch);
> - mic_dma_free_desc_ring(ch);
> -}
> -
> -static int mic_dma_init(struct mic_dma_device *mic_dma_dev,
> - enum mic_dma_chan_owner owner)
> -{
> - int i, first_chan = mic_dma_dev->start_ch;
> - struct mic_dma_chan *ch;
> - int ret;
> -
> - for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
> - ch = &mic_dma_dev->mic_ch[i];
> - ch->ch_num = i;
> - ch->owner = owner;
> - spin_lock_init(&ch->cleanup_lock);
> - spin_lock_init(&ch->prep_lock);
> - spin_lock_init(&ch->issue_lock);
> - ret = mic_dma_setup_irq(ch);
> - if (ret)
> - goto error;
> - }
> - return 0;
> -error:
> - for (i = i - 1; i >= first_chan; i--)
> - mic_dma_free_irq(ch);
> - return ret;
> -}
> -
> -static void mic_dma_uninit(struct mic_dma_device *mic_dma_dev)
> -{
> - int i, first_chan = mic_dma_dev->start_ch;
> - struct mic_dma_chan *ch;
> -
> - for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
> - ch = &mic_dma_dev->mic_ch[i];
> - mic_dma_free_irq(ch);
> - }
> -}
> -
> -static int mic_dma_alloc_chan_resources(struct dma_chan *ch)
> -{
> - int ret = mic_dma_chan_init(to_mic_dma_chan(ch));
> - if (ret)
> - return ret;
> - return MIC_DMA_DESC_RX_SIZE;
> -}
> -
> -static void mic_dma_free_chan_resources(struct dma_chan *ch)
> -{
> - struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
> - mic_dma_drain_chan(mic_ch);
> - mic_dma_chan_uninit(mic_ch);
> -}
> -
> -/* Set the fn. handlers and register the dma device with dma api */
> -static int mic_dma_register_dma_device(struct mic_dma_device
> *mic_dma_dev,
> - enum mic_dma_chan_owner owner)
> -{
> - int i, first_chan = mic_dma_dev->start_ch;
> -
> - dma_cap_zero(mic_dma_dev->dma_dev.cap_mask);
> - /*
> - * This dma engine is not capable of host memory to host memory
> - * transfers
> - */
> - dma_cap_set(DMA_MEMCPY, mic_dma_dev->dma_dev.cap_mask);
> -
> - if (MIC_DMA_CHAN_HOST == owner)
> - dma_cap_set(DMA_PRIVATE, mic_dma_dev-
> >dma_dev.cap_mask);
> - mic_dma_dev->dma_dev.device_alloc_chan_resources =
> - mic_dma_alloc_chan_resources;
> - mic_dma_dev->dma_dev.device_free_chan_resources =
> - mic_dma_free_chan_resources;
> - mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status;
> - mic_dma_dev->dma_dev.device_prep_dma_memcpy =
> mic_dma_prep_memcpy_lock;
> - mic_dma_dev->dma_dev.device_prep_dma_imm_data =
> - mic_dma_prep_status_lock;
> - mic_dma_dev->dma_dev.device_prep_dma_interrupt =
> - mic_dma_prep_interrupt_lock;
> - mic_dma_dev->dma_dev.device_issue_pending =
> mic_dma_issue_pending;
> - mic_dma_dev->dma_dev.copy_align = MIC_DMA_ALIGN_SHIFT;
> - INIT_LIST_HEAD(&mic_dma_dev->dma_dev.channels);
> - for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
> - mic_dma_dev->mic_ch[i].api_ch.device = &mic_dma_dev-
> >dma_dev;
> - dma_cookie_init(&mic_dma_dev->mic_ch[i].api_ch);
> - list_add_tail(&mic_dma_dev->mic_ch[i].api_ch.device_node,
> - &mic_dma_dev->dma_dev.channels);
> - }
> - return dmaenginem_async_device_register(&mic_dma_dev-
> >dma_dev);
> -}
> -
> -/*
> - * Initializes dma channels and registers the dma device with the
> - * dma engine api.
> - */
> -static struct mic_dma_device *mic_dma_dev_reg(struct mbus_device
> *mbdev,
> - enum mic_dma_chan_owner
> owner)
> -{
> - struct mic_dma_device *mic_dma_dev;
> - int ret;
> - struct device *dev = &mbdev->dev;
> -
> - mic_dma_dev = devm_kzalloc(dev, sizeof(*mic_dma_dev),
> GFP_KERNEL);
> - if (!mic_dma_dev) {
> - ret = -ENOMEM;
> - goto alloc_error;
> - }
> - mic_dma_dev->mbdev = mbdev;
> - mic_dma_dev->dma_dev.dev = dev;
> - mic_dma_dev->mmio = mbdev->mmio_va;
> - if (MIC_DMA_CHAN_HOST == owner) {
> - mic_dma_dev->start_ch = 0;
> - mic_dma_dev->max_xfer_size =
> MIC_DMA_MAX_XFER_SIZE_HOST;
> - } else {
> - mic_dma_dev->start_ch = 4;
> - mic_dma_dev->max_xfer_size =
> MIC_DMA_MAX_XFER_SIZE_CARD;
> - }
> - ret = mic_dma_init(mic_dma_dev, owner);
> - if (ret)
> - goto init_error;
> - ret = mic_dma_register_dma_device(mic_dma_dev, owner);
> - if (ret)
> - goto reg_error;
> - return mic_dma_dev;
> -reg_error:
> - mic_dma_uninit(mic_dma_dev);
> -init_error:
> - mic_dma_dev = NULL;
> -alloc_error:
> - dev_err(dev, "Error at %s %d ret=%d\n", __func__, __LINE__, ret);
> - return mic_dma_dev;
> -}
> -
> -static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev)
> -{
> - mic_dma_uninit(mic_dma_dev);
> -}
> -
> -/* DEBUGFS CODE */
> -static int mic_dma_reg_show(struct seq_file *s, void *pos)
> -{
> - struct mic_dma_device *mic_dma_dev = s->private;
> - int i, chan_num, first_chan = mic_dma_dev->start_ch;
> - struct mic_dma_chan *ch;
> -
> - seq_printf(s, "SBOX_DCR: %#x\n",
> - mic_dma_mmio_read(&mic_dma_dev->mic_ch[first_chan],
> - MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR));
> - seq_puts(s, "DMA Channel Registers\n");
> - seq_printf(s, "%-10s| %-10s %-10s %-10s %-10s %-10s",
> - "Channel", "DCAR", "DTPR", "DHPR", "DRAR_HI",
> "DRAR_LO");
> - seq_printf(s, " %-11s %-14s %-10s\n", "DCHERR", "DCHERRMSK",
> "DSTAT");
> - for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
> - ch = &mic_dma_dev->mic_ch[i];
> - chan_num = ch->ch_num;
> - seq_printf(s, "%-10i| %-#10x %-#10x %-#10x %-#10x",
> - chan_num,
> - mic_dma_read_reg(ch, MIC_DMA_REG_DCAR),
> - mic_dma_read_reg(ch, MIC_DMA_REG_DTPR),
> - mic_dma_read_reg(ch, MIC_DMA_REG_DHPR),
> - mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_HI));
> - seq_printf(s, " %-#10x %-#10x %-#14x %-#10x\n",
> - mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_LO),
> - mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR),
> - mic_dma_read_reg(ch,
> MIC_DMA_REG_DCHERRMSK),
> - mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT));
> - }
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(mic_dma_reg);
> -
> -/* Debugfs parent dir */
> -static struct dentry *mic_dma_dbg;
> -
> -static int mic_dma_driver_probe(struct mbus_device *mbdev)
> -{
> - struct mic_dma_device *mic_dma_dev;
> - enum mic_dma_chan_owner owner;
> -
> - if (MBUS_DEV_DMA_MIC == mbdev->id.device)
> - owner = MIC_DMA_CHAN_MIC;
> - else
> - owner = MIC_DMA_CHAN_HOST;
> -
> - mic_dma_dev = mic_dma_dev_reg(mbdev, owner);
> - dev_set_drvdata(&mbdev->dev, mic_dma_dev);
> -
> - if (mic_dma_dbg) {
> - mic_dma_dev->dbg_dir =
> debugfs_create_dir(dev_name(&mbdev->dev),
> - mic_dma_dbg);
> - debugfs_create_file("mic_dma_reg", 0444, mic_dma_dev-
> >dbg_dir,
> - mic_dma_dev, &mic_dma_reg_fops);
> - }
> - return 0;
> -}
> -
> -static void mic_dma_driver_remove(struct mbus_device *mbdev)
> -{
> - struct mic_dma_device *mic_dma_dev;
> -
> - mic_dma_dev = dev_get_drvdata(&mbdev->dev);
> - debugfs_remove_recursive(mic_dma_dev->dbg_dir);
> - mic_dma_dev_unreg(mic_dma_dev);
> -}
> -
> -static struct mbus_device_id id_table[] = {
> - {MBUS_DEV_DMA_MIC, MBUS_DEV_ANY_ID},
> - {MBUS_DEV_DMA_HOST, MBUS_DEV_ANY_ID},
> - {0},
> -};
> -
> -static struct mbus_driver mic_dma_driver = {
> - .driver.name = KBUILD_MODNAME,
> - .driver.owner = THIS_MODULE,
> - .id_table = id_table,
> - .probe = mic_dma_driver_probe,
> - .remove = mic_dma_driver_remove,
> -};
> -
> -static int __init mic_x100_dma_init(void)
> -{
> - int rc = mbus_register_driver(&mic_dma_driver);
> - if (rc)
> - return rc;
> - mic_dma_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
> - return 0;
> -}
> -
> -static void __exit mic_x100_dma_exit(void)
> -{
> - debugfs_remove_recursive(mic_dma_dbg);
> - mbus_unregister_driver(&mic_dma_driver);
> -}
> -
> -module_init(mic_x100_dma_init);
> -module_exit(mic_x100_dma_exit);
> -
> -MODULE_DEVICE_TABLE(mbus, id_table);
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC X100 DMA Driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/dma/mic_x100_dma.h b/drivers/dma/mic_x100_dma.h
> deleted file mode 100644
> index 68ef43a91714..000000000000
> --- a/drivers/dma/mic_x100_dma.h
> +++ /dev/null
> @@ -1,275 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel MIC X100 DMA Driver.
> - *
> - * Adapted from IOAT dma driver.
> - */
> -#ifndef _MIC_X100_DMA_H_
> -#define _MIC_X100_DMA_H_
> -
> -#include <linux/kernel.h>
> -#include <linux/delay.h>
> -#include <linux/sched.h>
> -#include <linux/debugfs.h>
> -#include <linux/slab.h>
> -#include <linux/interrupt.h>
> -#include <linux/mic_bus.h>
> -
> -#include "dmaengine.h"
> -
> -/*
> - * MIC has a total of 8 dma channels.
> - * Four channels are assigned for host SW use & the remaining for MIC SW.
> - * MIC DMA transfer size & addresses need to be 64 byte aligned.
> - */
> -#define MIC_DMA_MAX_NUM_CHAN 8
> -#define MIC_DMA_NUM_CHAN 4
> -#define MIC_DMA_ALIGN_SHIFT DMAENGINE_ALIGN_64_BYTES
> -#define MIC_DMA_ALIGN_BYTES (1 << MIC_DMA_ALIGN_SHIFT)
> -#define MIC_DMA_DESC_RX_SIZE (128 * 1024 - 4)
> -
> -/*
> - * Register descriptions
> - * All the registers are 32 bit registers.
> - * DCR is a global register and all others are per-channel.
> - * DCR - bits 0, 2, 4, 6, 8, 10, 12, 14 - enable bits for channels 0 to 7
> - * bits 1, 3, 5, 7, 9, 11, 13, 15 - owner bits for channels 0 to 7
> - * DCAR - bit 24 & 25 interrupt masks for mic owned & host owned channels
> - * DHPR - head of the descriptor ring updated by s/w
> - * DTPR - tail of the descriptor ring updated by h/w
> - * DRAR_LO - lower 32 bits of descriptor ring's mic address
> - * DRAR_HI - 3:0 - remaining 4 bits of descriptor ring's mic address
> - * 20:4 descriptor ring size
> - * 25:21 mic smpt entry number
> - * DSTAT - 16:0 h/w completion count; 31:28 dma engine status
> - * DCHERR - this register is non-zero on error
> - * DCHERRMSK - interrupt mask register
> - */
> -#define MIC_DMA_HW_CMP_CNT_MASK 0x1ffff
> -#define MIC_DMA_CHAN_QUIESCE 0x20000000
> -#define MIC_DMA_SBOX_BASE 0x00010000
> -#define MIC_DMA_SBOX_DCR 0x0000A280
> -#define MIC_DMA_SBOX_CH_BASE 0x0001A000
> -#define MIC_DMA_SBOX_CHAN_OFF 0x40
> -#define MIC_DMA_SBOX_DCAR_IM0 (0x1 << 24)
> -#define MIC_DMA_SBOX_DCAR_IM1 (0x1 << 25)
> -#define MIC_DMA_SBOX_DRARHI_SYS_MASK (0x1 << 26)
> -#define MIC_DMA_REG_DCAR 0
> -#define MIC_DMA_REG_DHPR 4
> -#define MIC_DMA_REG_DTPR 8
> -#define MIC_DMA_REG_DRAR_LO 20
> -#define MIC_DMA_REG_DRAR_HI 24
> -#define MIC_DMA_REG_DSTAT 32
> -#define MIC_DMA_REG_DCHERR 44
> -#define MIC_DMA_REG_DCHERRMSK 48
> -
> -/* HW dma desc */
> -struct mic_dma_desc {
> - u64 qw0;
> - u64 qw1;
> -};
> -
> -enum mic_dma_chan_owner {
> - MIC_DMA_CHAN_MIC = 0,
> - MIC_DMA_CHAN_HOST
> -};
> -
> -/*
> - * mic_dma_chan - channel specific information
> - * @ch_num: channel number
> - * @owner: owner of this channel
> - * @last_tail: cached value of descriptor ring tail
> - * @head: index of next descriptor in desc_ring
> - * @issued: hardware notification point
> - * @submitted: index that will be used to submit descriptors to h/w
> - * @api_ch: dma engine api channel
> - * @desc_ring: dma descriptor ring
> - * @desc_ring_micpa: mic physical address of desc_ring
> - * @status_dest: destination for status (fence) descriptor
> - * @status_dest_micpa: mic address for status_dest,
> - * DMA controller uses this address
> - * @tx_array: array of async_tx
> - * @cleanup_lock: lock held when processing completed tx
> - * @prep_lock: lock held in prep_memcpy & released in tx_submit
> - * @issue_lock: lock used to synchronize writes to head
> - * @cookie: mic_irq cookie used with mic irq request
> - */
> -struct mic_dma_chan {
> - int ch_num;
> - enum mic_dma_chan_owner owner;
> - u32 last_tail;
> - u32 head;
> - u32 issued;
> - u32 submitted;
> - struct dma_chan api_ch;
> - struct mic_dma_desc *desc_ring;
> - dma_addr_t desc_ring_micpa;
> - u64 *status_dest;
> - dma_addr_t status_dest_micpa;
> - struct dma_async_tx_descriptor *tx_array;
> - spinlock_t cleanup_lock;
> - spinlock_t prep_lock;
> - spinlock_t issue_lock;
> - struct mic_irq *cookie;
> -};
> -
> -/*
> - * struct mic_dma_device - per mic device
> - * @mic_ch: dma channels
> - * @dma_dev: underlying dma device
> - * @mbdev: mic bus dma device
> - * @mmio: virtual address of the mmio space
> - * @dbg_dir: debugfs directory
> - * @start_ch: first channel number that can be used
> - * @max_xfer_size: maximum transfer size per dma descriptor
> - */
> -struct mic_dma_device {
> - struct mic_dma_chan mic_ch[MIC_DMA_MAX_NUM_CHAN];
> - struct dma_device dma_dev;
> - struct mbus_device *mbdev;
> - void __iomem *mmio;
> - struct dentry *dbg_dir;
> - int start_ch;
> - size_t max_xfer_size;
> -};
> -
> -static inline struct mic_dma_chan *to_mic_dma_chan(struct dma_chan *ch)
> -{
> - return container_of(ch, struct mic_dma_chan, api_ch);
> -}
> -
> -static inline struct mic_dma_device *to_mic_dma_dev(struct mic_dma_chan
> *ch)
> -{
> - return
> - container_of((const typeof(((struct mic_dma_device *)0)->mic_ch)*)
> - (ch - ch->ch_num), struct mic_dma_device, mic_ch);
> -}
> -
> -static inline struct mbus_device *to_mbus_device(struct mic_dma_chan *ch)
> -{
> - return to_mic_dma_dev(ch)->mbdev;
> -}
> -
> -static inline struct mbus_hw_ops *to_mbus_hw_ops(struct mic_dma_chan
> *ch)
> -{
> - return to_mbus_device(ch)->hw_ops;
> -}
> -
> -static inline struct device *mic_dma_ch_to_device(struct mic_dma_chan *ch)
> -{
> - return to_mic_dma_dev(ch)->dma_dev.dev;
> -}
> -
> -static inline void __iomem *mic_dma_chan_to_mmio(struct mic_dma_chan
> *ch)
> -{
> - return to_mic_dma_dev(ch)->mmio;
> -}
> -
> -static inline u32 mic_dma_read_reg(struct mic_dma_chan *ch, u32 reg)
> -{
> - return ioread32(mic_dma_chan_to_mmio(ch) +
> MIC_DMA_SBOX_CH_BASE +
> - ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
> -}
> -
> -static inline void mic_dma_write_reg(struct mic_dma_chan *ch, u32 reg, u32
> val)
> -{
> - iowrite32(val, mic_dma_chan_to_mmio(ch) +
> MIC_DMA_SBOX_CH_BASE +
> - ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
> -}
> -
> -static inline u32 mic_dma_mmio_read(struct mic_dma_chan *ch, u32 offset)
> -{
> - return ioread32(mic_dma_chan_to_mmio(ch) + offset);
> -}
> -
> -static inline void mic_dma_mmio_write(struct mic_dma_chan *ch, u32 val,
> - u32 offset)
> -{
> - iowrite32(val, mic_dma_chan_to_mmio(ch) + offset);
> -}
> -
> -static inline u32 mic_dma_read_cmp_cnt(struct mic_dma_chan *ch)
> -{
> - return mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) &
> - MIC_DMA_HW_CMP_CNT_MASK;
> -}
> -
> -static inline void mic_dma_chan_set_owner(struct mic_dma_chan *ch)
> -{
> - u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> - u32 chan_num = ch->ch_num;
> -
> - dcr = (dcr & ~(0x1 << (chan_num * 2))) | (ch->owner << (chan_num *
> 2));
> - mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> -}
> -
> -static inline void mic_dma_enable_chan(struct mic_dma_chan *ch)
> -{
> - u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> -
> - dcr |= 2 << (ch->ch_num << 1);
> - mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> -}
> -
> -static inline void mic_dma_disable_chan(struct mic_dma_chan *ch)
> -{
> - u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> -
> - dcr &= ~(2 << (ch->ch_num << 1));
> - mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE +
> MIC_DMA_SBOX_DCR);
> -}
> -
> -static void mic_dma_chan_set_desc_ring(struct mic_dma_chan *ch)
> -{
> - u32 drar_hi;
> - dma_addr_t desc_ring_micpa = ch->desc_ring_micpa;
> -
> - drar_hi = (MIC_DMA_DESC_RX_SIZE & 0x1ffff) << 4;
> - if (MIC_DMA_CHAN_MIC == ch->owner) {
> - drar_hi |= (desc_ring_micpa >> 32) & 0xf;
> - } else {
> - drar_hi |= MIC_DMA_SBOX_DRARHI_SYS_MASK;
> - drar_hi |= ((desc_ring_micpa >> 34)
> - & 0x1f) << 21;
> - drar_hi |= (desc_ring_micpa >> 32) & 0x3;
> - }
> - mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_LO, (u32)
> desc_ring_micpa);
> - mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_HI, drar_hi);
> -}
> -
> -static inline void mic_dma_chan_mask_intr(struct mic_dma_chan *ch)
> -{
> - u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
> -
> - if (MIC_DMA_CHAN_MIC == ch->owner)
> - dcar |= MIC_DMA_SBOX_DCAR_IM0;
> - else
> - dcar |= MIC_DMA_SBOX_DCAR_IM1;
> - mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
> -}
> -
> -static inline void mic_dma_chan_unmask_intr(struct mic_dma_chan *ch)
> -{
> - u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
> -
> - if (MIC_DMA_CHAN_MIC == ch->owner)
> - dcar &= ~MIC_DMA_SBOX_DCAR_IM0;
> - else
> - dcar &= ~MIC_DMA_SBOX_DCAR_IM1;
> - mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
> -}
> -
> -static void mic_dma_ack_interrupt(struct mic_dma_chan *ch)
> -{
> - if (MIC_DMA_CHAN_MIC == ch->owner) {
> - /* HW errata */
> - mic_dma_chan_mask_intr(ch);
> - mic_dma_chan_unmask_intr(ch);
> - }
> - to_mbus_hw_ops(ch)->ack_interrupt(to_mbus_device(ch), ch-
> >ch_num);
> -}
> -#endif
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index d5ce8082b0a0..fafa8b0d8099 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -474,7 +474,6 @@ source "drivers/misc/lis3lv02d/Kconfig"
> source "drivers/misc/altera-stapl/Kconfig"
> source "drivers/misc/mei/Kconfig"
> source "drivers/misc/vmw_vmci/Kconfig"
> -source "drivers/misc/mic/Kconfig"
> source "drivers/misc/genwqe/Kconfig"
> source "drivers/misc/echo/Kconfig"
> source "drivers/misc/cxl/Kconfig"
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 2521359e8ef7..d23231e73330 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -46,7 +46,6 @@ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
> obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
> obj-$(CONFIG_SRAM) += sram.o
> obj-$(CONFIG_SRAM_EXEC) += sram-exec.o
> -obj-y += mic/
> obj-$(CONFIG_GENWQE) += genwqe/
> obj-$(CONFIG_ECHO) += echo/
> obj-$(CONFIG_CXL_BASE) += cxl/
> diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
> deleted file mode 100644
> index 8a7c2c5711d5..000000000000
> --- a/drivers/misc/mic/Kconfig
> +++ /dev/null
> @@ -1,141 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -menu "Intel MIC & related support"
> -
> -config INTEL_MIC_BUS
> - tristate "Intel MIC Bus Driver"
> - depends on 64BIT && PCI && X86
> - select DMA_OPS
> - help
> - This option is selected by any driver which registers a
> - device or driver on the MIC Bus, such as CONFIG_INTEL_MIC_HOST,
> - CONFIG_INTEL_MIC_CARD, CONFIG_INTEL_MIC_X100_DMA etc.
> -
> - If you are building a host/card kernel with an Intel MIC device
> - then say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config SCIF_BUS
> - tristate "SCIF Bus Driver"
> - depends on 64BIT && PCI && X86
> - select DMA_OPS
> - help
> - This option is selected by any driver which registers a
> - device or driver on the SCIF Bus, such as CONFIG_INTEL_MIC_HOST
> - and CONFIG_INTEL_MIC_CARD.
> -
> - If you are building a host/card kernel with an Intel MIC device
> - then say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config VOP_BUS
> - tristate "VOP Bus Driver"
> - depends on HAS_DMA
> - select DMA_OPS
> - help
> - This option is selected by any driver which registers a
> - device or driver on the VOP Bus, such as CONFIG_INTEL_MIC_HOST
> - and CONFIG_INTEL_MIC_CARD.
> -
> - If you are building a host/card kernel with an Intel MIC device
> - then say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config INTEL_MIC_HOST
> - tristate "Intel MIC Host Driver"
> - depends on 64BIT && PCI && X86
> - depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM &&
> VOP_BUS
> - select DMA_OPS
> - help
> - This enables Host Driver support for the Intel Many Integrated
> - Core (MIC) family of PCIe form factor coprocessor devices that
> - run a 64 bit Linux OS. The driver manages card OS state and
> - enables communication between host and card. Intel MIC X100
> - devices are currently supported.
> -
> - If you are building a host kernel with an Intel MIC device then
> - say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config INTEL_MIC_CARD
> - tristate "Intel MIC Card Driver"
> - depends on 64BIT && X86
> - depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM &&
> VOP_BUS
> - select VIRTIO
> - help
> - This enables card driver support for the Intel Many Integrated
> - Core (MIC) device family. The card driver communicates shutdown/
> - crash events to the host and allows registration/configuration of
> - virtio devices. Intel MIC X100 devices are currently supported.
> -
> - If you are building a card kernel for an Intel MIC device then
> - say M (recommended) or Y, else say N. If unsure say N.
> -
> - For more information see
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config SCIF
> - tristate "SCIF Driver"
> - depends on 64BIT && PCI && X86 && SCIF_BUS &&
> IOMMU_SUPPORT
> - select IOMMU_IOVA
> - help
> - This enables SCIF Driver support for the Intel Many Integrated
> - Core (MIC) family of PCIe form factor coprocessor devices that
> - run a 64 bit Linux OS. The Symmetric Communication Interface
> - (SCIF (pronounced as skiff)) is a low level communications API
> - across PCIe currently implemented for MIC.
> -
> - If you are building a host kernel with an Intel MIC device then
> - say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config MIC_COSM
> - tristate "Intel MIC Coprocessor State Management (COSM) Drivers"
> - depends on 64BIT && PCI && X86 && SCIF
> - help
> - This enables COSM driver support for the Intel Many
> - Integrated Core (MIC) family of PCIe form factor coprocessor
> - devices. COSM drivers implement functions such as boot,
> - shutdown, reset and reboot of MIC devices.
> -
> - If you are building a host kernel with an Intel MIC device then
> - say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591943962%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=p3GqcxhfjjI76nVd2ejarp1i49GXx5%2Be6pvcFgHdiDI%3D&amp;reserve
> d=0>.
> -
> -config VOP
> - tristate "VOP Driver"
> - depends on VOP_BUS
> - select VHOST_RING
> - select VIRTIO
> - help
> - This enables VOP (Virtio over PCIe) Driver support for the Intel
> - Many Integrated Core (MIC) family of PCIe form factor coprocessor
> - devices. The VOP driver allows virtio drivers, e.g. net, console
> - and block drivers, on the card connect to user space virtio
> - devices on the host.
> -
> - If you are building a host kernel with an Intel MIC device then
> - say M (recommended) or Y, else say N. If unsure say N.
> -
> - More information about the Intel MIC family as well as the Linux
> - OS and tools for MIC to use with this driver are available from
> -
> <https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fsoftw
> are.intel.com%2Fen-us%2Fmic-
> developer&amp;data=04%7C01%7Csherry.sun%40nxp.com%7Cf4d4a5577fcc
> 4f87f93e08d87af0768e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0
> %7C637394520591948943%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
> AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;
> sdata=vgbArTat4RQ2quACATuImDmQr2vnfhvXFKAEKm2few8%3D&amp;rese
> rved=0>.
> -
> -endmenu
> diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
> deleted file mode 100644
> index 1a43622b183f..000000000000
> --- a/drivers/misc/mic/Makefile
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -#
> -# Makefile - Intel MIC Linux driver.
> -# Copyright(c) 2013, Intel Corporation.
> -#
> -obj-$(CONFIG_INTEL_MIC_HOST) += host/
> -obj-$(CONFIG_INTEL_MIC_CARD) += card/
> -obj-y += bus/
> -obj-$(CONFIG_SCIF) += scif/
> -obj-$(CONFIG_MIC_COSM) += cosm/
> -obj-$(CONFIG_MIC_COSM) += cosm_client/
> -obj-$(CONFIG_VOP) += vop/
> diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile
> deleted file mode 100644
> index 0a6aa21b2f67..000000000000
> --- a/drivers/misc/mic/bus/Makefile
> +++ /dev/null
> @@ -1,9 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -# Makefile - Intel MIC Linux driver.
> -# Copyright(c) 2014, Intel Corporation.
> -#
> -obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o
> -obj-$(CONFIG_SCIF_BUS) += scif_bus.o
> -obj-$(CONFIG_MIC_COSM) += cosm_bus.o
> -obj-$(CONFIG_VOP_BUS) += vop_bus.o
> diff --git a/drivers/misc/mic/bus/cosm_bus.c
> b/drivers/misc/mic/bus/cosm_bus.c
> deleted file mode 100644
> index 5f2141c71738..000000000000
> --- a/drivers/misc/mic/bus/cosm_bus.c
> +++ /dev/null
> @@ -1,130 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC COSM Bus Driver
> - */
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/idr.h>
> -#include "cosm_bus.h"
> -
> -/* Unique numbering for cosm devices. */
> -static DEFINE_IDA(cosm_index_ida);
> -
> -static int cosm_dev_probe(struct device *d)
> -{
> - struct cosm_device *dev = dev_to_cosm(d);
> - struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
> -
> - return drv->probe(dev);
> -}
> -
> -static int cosm_dev_remove(struct device *d)
> -{
> - struct cosm_device *dev = dev_to_cosm(d);
> - struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
> -
> - drv->remove(dev);
> - return 0;
> -}
> -
> -static struct bus_type cosm_bus = {
> - .name = "cosm_bus",
> - .probe = cosm_dev_probe,
> - .remove = cosm_dev_remove,
> -};
> -
> -int cosm_register_driver(struct cosm_driver *driver)
> -{
> - driver->driver.bus = &cosm_bus;
> - return driver_register(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(cosm_register_driver);
> -
> -void cosm_unregister_driver(struct cosm_driver *driver)
> -{
> - driver_unregister(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(cosm_unregister_driver);
> -
> -static inline void cosm_release_dev(struct device *d)
> -{
> - struct cosm_device *cdev = dev_to_cosm(d);
> -
> - kfree(cdev);
> -}
> -
> -struct cosm_device *
> -cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops)
> -{
> - struct cosm_device *cdev;
> - int ret;
> -
> - cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
> - if (!cdev)
> - return ERR_PTR(-ENOMEM);
> -
> - cdev->dev.parent = pdev;
> - cdev->dev.release = cosm_release_dev;
> - cdev->hw_ops = hw_ops;
> - dev_set_drvdata(&cdev->dev, cdev);
> - cdev->dev.bus = &cosm_bus;
> -
> - /* Assign a unique device index and hence name */
> - ret = ida_simple_get(&cosm_index_ida, 0, 0, GFP_KERNEL);
> - if (ret < 0)
> - goto free_cdev;
> -
> - cdev->index = ret;
> - cdev->dev.id = ret;
> - dev_set_name(&cdev->dev, "cosm-dev%u", cdev->index);
> -
> - ret = device_register(&cdev->dev);
> - if (ret)
> - goto ida_remove;
> - return cdev;
> -ida_remove:
> - ida_simple_remove(&cosm_index_ida, cdev->index);
> -free_cdev:
> - put_device(&cdev->dev);
> - return ERR_PTR(ret);
> -}
> -EXPORT_SYMBOL_GPL(cosm_register_device);
> -
> -void cosm_unregister_device(struct cosm_device *dev)
> -{
> - int index = dev->index; /* save for after device release */
> -
> - device_unregister(&dev->dev);
> - ida_simple_remove(&cosm_index_ida, index);
> -}
> -EXPORT_SYMBOL_GPL(cosm_unregister_device);
> -
> -struct cosm_device *cosm_find_cdev_by_id(int id)
> -{
> - struct device *dev = subsys_find_device_by_id(&cosm_bus, id, NULL);
> -
> - return dev ? container_of(dev, struct cosm_device, dev) : NULL;
> -}
> -EXPORT_SYMBOL_GPL(cosm_find_cdev_by_id);
> -
> -static int __init cosm_init(void)
> -{
> - return bus_register(&cosm_bus);
> -}
> -
> -static void __exit cosm_exit(void)
> -{
> - bus_unregister(&cosm_bus);
> - ida_destroy(&cosm_index_ida);
> -}
> -
> -core_initcall(cosm_init);
> -module_exit(cosm_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC card OS state management bus
> driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/bus/cosm_bus.h
> b/drivers/misc/mic/bus/cosm_bus.h
> deleted file mode 100644
> index d50d7aea168d..000000000000
> --- a/drivers/misc/mic/bus/cosm_bus.h
> +++ /dev/null
> @@ -1,125 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC COSM Bus Driver
> - */
> -#ifndef _COSM_BUS_H_
> -#define _COSM_BUS_H_
> -
> -#include <linux/scif.h>
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -
> -/**
> - * cosm_device - representation of a cosm device
> - *
> - * @attr_group: Pointer to list of sysfs attribute groups.
> - * @sdev: Device for sysfs entries.
> - * @state: MIC state.
> - * @prev_state: MIC state previous to MIC_RESETTING
> - * @shutdown_status: MIC status reported by card for shutdown/crashes.
> - * @shutdown_status_int: Internal shutdown status maintained by the
> driver
> - * @cosm_mutex: Mutex for synchronizing access to data structures.
> - * @reset_trigger_work: Work for triggering reset requests.
> - * @scif_work: Work for handling per device SCIF connections
> - * @cmdline: Kernel command line.
> - * @firmware: Firmware file name.
> - * @ramdisk: Ramdisk file name.
> - * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
> - * @log_buf_addr: Log buffer address for MIC.
> - * @log_buf_len: Log buffer length address for MIC.
> - * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
> - * @hw_ops: the hardware bus ops for this device.
> - * @dev: underlying device.
> - * @index: unique position on the cosm bus
> - * @dbg_dir: debug fs directory
> - * @newepd: new endpoint from scif accept to be assigned to this cdev
> - * @epd: SCIF endpoint for this cdev
> - * @heartbeat_watchdog_enable: if heartbeat watchdog is enabled for this
> cdev
> - * @sysfs_heartbeat_enable: sysfs setting for disabling heartbeat
> notification
> - */
> -struct cosm_device {
> - const struct attribute_group **attr_group;
> - struct device *sdev;
> - u8 state;
> - u8 prev_state;
> - u8 shutdown_status;
> - u8 shutdown_status_int;
> - struct mutex cosm_mutex;
> - struct work_struct reset_trigger_work;
> - struct work_struct scif_work;
> - char *cmdline;
> - char *firmware;
> - char *ramdisk;
> - char *bootmode;
> - void *log_buf_addr;
> - int *log_buf_len;
> - struct kernfs_node *state_sysfs;
> - struct cosm_hw_ops *hw_ops;
> - struct device dev;
> - int index;
> - struct dentry *dbg_dir;
> - scif_epd_t newepd;
> - scif_epd_t epd;
> - bool heartbeat_watchdog_enable;
> - bool sysfs_heartbeat_enable;
> -};
> -
> -/**
> - * cosm_driver - operations for a cosm driver
> - *
> - * @driver: underlying device driver (populate name and owner).
> - * @probe: the function to call when a device is found. Returns 0 or -errno.
> - * @remove: the function to call when a device is removed.
> - */
> -struct cosm_driver {
> - struct device_driver driver;
> - int (*probe)(struct cosm_device *dev);
> - void (*remove)(struct cosm_device *dev);
> -};
> -
> -/**
> - * cosm_hw_ops - cosm bus ops
> - *
> - * @reset: trigger MIC reset
> - * @force_reset: force MIC reset
> - * @post_reset: inform MIC reset is complete
> - * @ready: is MIC ready for OS download
> - * @start: boot MIC
> - * @stop: prepare MIC for reset
> - * @family: return MIC HW family string
> - * @stepping: return MIC HW stepping string
> - * @aper: return MIC PCIe aperture
> - */
> -struct cosm_hw_ops {
> - void (*reset)(struct cosm_device *cdev);
> - void (*force_reset)(struct cosm_device *cdev);
> - void (*post_reset)(struct cosm_device *cdev, enum mic_states state);
> - bool (*ready)(struct cosm_device *cdev);
> - int (*start)(struct cosm_device *cdev, int id);
> - void (*stop)(struct cosm_device *cdev, bool force);
> - ssize_t (*family)(struct cosm_device *cdev, char *buf);
> - ssize_t (*stepping)(struct cosm_device *cdev, char *buf);
> - struct mic_mw *(*aper)(struct cosm_device *cdev);
> -};
> -
> -struct cosm_device *
> -cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops);
> -void cosm_unregister_device(struct cosm_device *dev);
> -int cosm_register_driver(struct cosm_driver *drv);
> -void cosm_unregister_driver(struct cosm_driver *drv);
> -struct cosm_device *cosm_find_cdev_by_id(int id);
> -
> -static inline struct cosm_device *dev_to_cosm(struct device *dev)
> -{
> - return container_of(dev, struct cosm_device, dev);
> -}
> -
> -static inline struct cosm_driver *drv_to_cosm(struct device_driver *drv)
> -{
> - return container_of(drv, struct cosm_driver, driver);
> -}
> -#endif /* _COSM_BUS_H */
> diff --git a/drivers/misc/mic/bus/mic_bus.c
> b/drivers/misc/mic/bus/mic_bus.c
> deleted file mode 100644
> index a08cb29692a8..000000000000
> --- a/drivers/misc/mic/bus/mic_bus.c
> +++ /dev/null
> @@ -1,194 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel MIC Bus driver.
> - *
> - * This implementation is very similar to the the virtio bus driver
> - * implementation @ drivers/virtio/virtio.c
> - */
> -#include <linux/dma-map-ops.h>
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/idr.h>
> -#include <linux/mic_bus.h>
> -
> -static ssize_t device_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct mbus_device *dev = dev_to_mbus(d);
> - return sprintf(buf, "0x%04x\n", dev->id.device);
> -}
> -static DEVICE_ATTR_RO(device);
> -
> -static ssize_t vendor_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct mbus_device *dev = dev_to_mbus(d);
> - return sprintf(buf, "0x%04x\n", dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(vendor);
> -
> -static ssize_t modalias_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct mbus_device *dev = dev_to_mbus(d);
> - return sprintf(buf, "mbus:d%08Xv%08X\n",
> - dev->id.device, dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(modalias);
> -
> -static struct attribute *mbus_dev_attrs[] = {
> - &dev_attr_device.attr,
> - &dev_attr_vendor.attr,
> - &dev_attr_modalias.attr,
> - NULL,
> -};
> -ATTRIBUTE_GROUPS(mbus_dev);
> -
> -static inline int mbus_id_match(const struct mbus_device *dev,
> - const struct mbus_device_id *id)
> -{
> - if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID)
> - return 0;
> -
> - return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev-
> >id.vendor;
> -}
> -
> -/*
> - * This looks through all the IDs a driver claims to support. If any of them
> - * match, we return 1 and the kernel will call mbus_dev_probe().
> - */
> -static int mbus_dev_match(struct device *dv, struct device_driver *dr)
> -{
> - unsigned int i;
> - struct mbus_device *dev = dev_to_mbus(dv);
> - const struct mbus_device_id *ids;
> -
> - ids = drv_to_mbus(dr)->id_table;
> - for (i = 0; ids[i].device; i++)
> - if (mbus_id_match(dev, &ids[i]))
> - return 1;
> - return 0;
> -}
> -
> -static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env)
> -{
> - struct mbus_device *dev = dev_to_mbus(dv);
> -
> - return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X",
> - dev->id.device, dev->id.vendor);
> -}
> -
> -static int mbus_dev_probe(struct device *d)
> -{
> - int err;
> - struct mbus_device *dev = dev_to_mbus(d);
> - struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
> -
> - err = drv->probe(dev);
> - if (!err)
> - if (drv->scan)
> - drv->scan(dev);
> - return err;
> -}
> -
> -static int mbus_dev_remove(struct device *d)
> -{
> - struct mbus_device *dev = dev_to_mbus(d);
> - struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
> -
> - drv->remove(dev);
> - return 0;
> -}
> -
> -static struct bus_type mic_bus = {
> - .name = "mic_bus",
> - .match = mbus_dev_match,
> - .dev_groups = mbus_dev_groups,
> - .uevent = mbus_uevent,
> - .probe = mbus_dev_probe,
> - .remove = mbus_dev_remove,
> -};
> -
> -int mbus_register_driver(struct mbus_driver *driver)
> -{
> - driver->driver.bus = &mic_bus;
> - return driver_register(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(mbus_register_driver);
> -
> -void mbus_unregister_driver(struct mbus_driver *driver)
> -{
> - driver_unregister(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(mbus_unregister_driver);
> -
> -static void mbus_release_dev(struct device *d)
> -{
> - struct mbus_device *mbdev = dev_to_mbus(d);
> - kfree(mbdev);
> -}
> -
> -struct mbus_device *
> -mbus_register_device(struct device *pdev, int id, const struct
> dma_map_ops *dma_ops,
> - struct mbus_hw_ops *hw_ops, int index,
> - void __iomem *mmio_va)
> -{
> - int ret;
> - struct mbus_device *mbdev;
> -
> - mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL);
> - if (!mbdev)
> - return ERR_PTR(-ENOMEM);
> -
> - mbdev->mmio_va = mmio_va;
> - mbdev->dev.parent = pdev;
> - mbdev->id.device = id;
> - mbdev->id.vendor = MBUS_DEV_ANY_ID;
> - mbdev->dev.dma_ops = dma_ops;
> - mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask;
> - dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64));
> - mbdev->dev.release = mbus_release_dev;
> - mbdev->hw_ops = hw_ops;
> - mbdev->dev.bus = &mic_bus;
> - mbdev->index = index;
> - dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index);
> - /*
> - * device_register() causes the bus infrastructure to look for a
> - * matching driver.
> - */
> - ret = device_register(&mbdev->dev);
> - if (ret)
> - goto free_mbdev;
> - return mbdev;
> -free_mbdev:
> - put_device(&mbdev->dev);
> - return ERR_PTR(ret);
> -}
> -EXPORT_SYMBOL_GPL(mbus_register_device);
> -
> -void mbus_unregister_device(struct mbus_device *mbdev)
> -{
> - device_unregister(&mbdev->dev);
> -}
> -EXPORT_SYMBOL_GPL(mbus_unregister_device);
> -
> -static int __init mbus_init(void)
> -{
> - return bus_register(&mic_bus);
> -}
> -
> -static void __exit mbus_exit(void)
> -{
> - bus_unregister(&mic_bus);
> -}
> -
> -core_initcall(mbus_init);
> -module_exit(mbus_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC Bus driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/bus/scif_bus.c
> b/drivers/misc/mic/bus/scif_bus.c
> deleted file mode 100644
> index ad7c3604f151..000000000000
> --- a/drivers/misc/mic/bus/scif_bus.c
> +++ /dev/null
> @@ -1,201 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel Symmetric Communications Interface Bus driver.
> - */
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/idr.h>
> -#include <linux/dma-map-ops.h>
> -
> -#include "scif_bus.h"
> -
> -static ssize_t device_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(d);
> -
> - return sprintf(buf, "0x%04x\n", dev->id.device);
> -}
> -static DEVICE_ATTR_RO(device);
> -
> -static ssize_t vendor_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(d);
> -
> - return sprintf(buf, "0x%04x\n", dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(vendor);
> -
> -static ssize_t modalias_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(d);
> -
> - return sprintf(buf, "scif:d%08Xv%08X\n",
> - dev->id.device, dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(modalias);
> -
> -static struct attribute *scif_dev_attrs[] = {
> - &dev_attr_device.attr,
> - &dev_attr_vendor.attr,
> - &dev_attr_modalias.attr,
> - NULL,
> -};
> -ATTRIBUTE_GROUPS(scif_dev);
> -
> -static inline int scif_id_match(const struct scif_hw_dev *dev,
> - const struct scif_hw_dev_id *id)
> -{
> - if (id->device != dev->id.device && id->device != SCIF_DEV_ANY_ID)
> - return 0;
> -
> - return id->vendor == SCIF_DEV_ANY_ID || id->vendor == dev-
> >id.vendor;
> -}
> -
> -/*
> - * This looks through all the IDs a driver claims to support. If any of them
> - * match, we return 1 and the kernel will call scif_dev_probe().
> - */
> -static int scif_dev_match(struct device *dv, struct device_driver *dr)
> -{
> - unsigned int i;
> - struct scif_hw_dev *dev = dev_to_scif(dv);
> - const struct scif_hw_dev_id *ids;
> -
> - ids = drv_to_scif(dr)->id_table;
> - for (i = 0; ids[i].device; i++)
> - if (scif_id_match(dev, &ids[i]))
> - return 1;
> - return 0;
> -}
> -
> -static int scif_uevent(struct device *dv, struct kobj_uevent_env *env)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(dv);
> -
> - return add_uevent_var(env, "MODALIAS=scif:d%08Xv%08X",
> - dev->id.device, dev->id.vendor);
> -}
> -
> -static int scif_dev_probe(struct device *d)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(d);
> - struct scif_driver *drv = drv_to_scif(dev->dev.driver);
> -
> - return drv->probe(dev);
> -}
> -
> -static int scif_dev_remove(struct device *d)
> -{
> - struct scif_hw_dev *dev = dev_to_scif(d);
> - struct scif_driver *drv = drv_to_scif(dev->dev.driver);
> -
> - drv->remove(dev);
> - return 0;
> -}
> -
> -static struct bus_type scif_bus = {
> - .name = "scif_bus",
> - .match = scif_dev_match,
> - .dev_groups = scif_dev_groups,
> - .uevent = scif_uevent,
> - .probe = scif_dev_probe,
> - .remove = scif_dev_remove,
> -};
> -
> -int scif_register_driver(struct scif_driver *driver)
> -{
> - driver->driver.bus = &scif_bus;
> - return driver_register(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(scif_register_driver);
> -
> -void scif_unregister_driver(struct scif_driver *driver)
> -{
> - driver_unregister(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(scif_unregister_driver);
> -
> -static void scif_release_dev(struct device *d)
> -{
> - struct scif_hw_dev *sdev = dev_to_scif(d);
> -
> - kfree(sdev);
> -}
> -
> -struct scif_hw_dev *
> -scif_register_device(struct device *pdev, int id, const struct dma_map_ops
> *dma_ops,
> - struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
> - struct mic_mw *mmio, struct mic_mw *aper, void *dp,
> - void __iomem *rdp, struct dma_chan **chan, int
> num_chan,
> - bool card_rel_da)
> -{
> - int ret;
> - struct scif_hw_dev *sdev;
> -
> - sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
> - if (!sdev)
> - return ERR_PTR(-ENOMEM);
> -
> - sdev->dev.parent = pdev;
> - sdev->id.device = id;
> - sdev->id.vendor = SCIF_DEV_ANY_ID;
> - sdev->dev.dma_ops = dma_ops;
> - sdev->dev.release = scif_release_dev;
> - sdev->hw_ops = hw_ops;
> - sdev->dnode = dnode;
> - sdev->snode = snode;
> - dev_set_drvdata(&sdev->dev, sdev);
> - sdev->dev.bus = &scif_bus;
> - sdev->mmio = mmio;
> - sdev->aper = aper;
> - sdev->dp = dp;
> - sdev->rdp = rdp;
> - sdev->dev.dma_mask = &sdev->dev.coherent_dma_mask;
> - dma_set_mask(&sdev->dev, DMA_BIT_MASK(64));
> - sdev->dma_ch = chan;
> - sdev->num_dma_ch = num_chan;
> - sdev->card_rel_da = card_rel_da;
> - dev_set_name(&sdev->dev, "scif-dev%u", sdev->dnode);
> - /*
> - * device_register() causes the bus infrastructure to look for a
> - * matching driver.
> - */
> - ret = device_register(&sdev->dev);
> - if (ret)
> - goto free_sdev;
> - return sdev;
> -free_sdev:
> - put_device(&sdev->dev);
> - return ERR_PTR(ret);
> -}
> -EXPORT_SYMBOL_GPL(scif_register_device);
> -
> -void scif_unregister_device(struct scif_hw_dev *sdev)
> -{
> - device_unregister(&sdev->dev);
> -}
> -EXPORT_SYMBOL_GPL(scif_unregister_device);
> -
> -static int __init scif_init(void)
> -{
> - return bus_register(&scif_bus);
> -}
> -
> -static void __exit scif_exit(void)
> -{
> - bus_unregister(&scif_bus);
> -}
> -
> -core_initcall(scif_init);
> -module_exit(scif_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) SCIF Bus driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/bus/scif_bus.h
> b/drivers/misc/mic/bus/scif_bus.h
> deleted file mode 100644
> index 4981eb56f879..000000000000
> --- a/drivers/misc/mic/bus/scif_bus.h
> +++ /dev/null
> @@ -1,125 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel Symmetric Communications Interface Bus driver.
> - */
> -#ifndef _SCIF_BUS_H_
> -#define _SCIF_BUS_H_
> -/*
> - * Everything a scif driver needs to work with any particular scif
> - * hardware abstraction layer.
> - */
> -#include <linux/dma-map-ops.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -
> -struct scif_hw_dev_id {
> - u32 device;
> - u32 vendor;
> -};
> -
> -#define MIC_SCIF_DEV 1
> -#define SCIF_DEV_ANY_ID 0xffffffff
> -
> -/**
> - * scif_hw_dev - representation of a hardware device abstracted for scif
> - * @hw_ops: the hardware ops supported by this device
> - * @id: the device type identification (used to match it with a driver)
> - * @mmio: MMIO memory window
> - * @aper: Aperture memory window
> - * @dev: underlying device
> - * @dnode - The destination node which this device will communicate with.
> - * @snode - The source node for this device.
> - * @dp - Self device page
> - * @rdp - Remote device page
> - * @dma_ch - Array of DMA channels
> - * @num_dma_ch - Number of DMA channels available
> - * @card_rel_da - Set to true if DMA addresses programmed in the DMA
> engine
> - * are relative to the card point of view
> - */
> -struct scif_hw_dev {
> - struct scif_hw_ops *hw_ops;
> - struct scif_hw_dev_id id;
> - struct mic_mw *mmio;
> - struct mic_mw *aper;
> - struct device dev;
> - u8 dnode;
> - u8 snode;
> - void *dp;
> - void __iomem *rdp;
> - struct dma_chan **dma_ch;
> - int num_dma_ch;
> - bool card_rel_da;
> -};
> -
> -/**
> - * scif_driver - operations for a scif I/O driver
> - * @driver: underlying device driver (populate name and owner).
> - * @id_table: the ids serviced by this driver.
> - * @probe: the function to call when a device is found. Returns 0 or -errno.
> - * @remove: the function to call when a device is removed.
> - */
> -struct scif_driver {
> - struct device_driver driver;
> - const struct scif_hw_dev_id *id_table;
> - int (*probe)(struct scif_hw_dev *dev);
> - void (*remove)(struct scif_hw_dev *dev);
> -};
> -
> -/**
> - * scif_hw_ops - Hardware operations for accessing a SCIF device on the SCIF
> bus.
> - *
> - * @next_db: Obtain the next available doorbell.
> - * @request_irq: Request an interrupt on a particular doorbell.
> - * @free_irq: Free an interrupt requested previously.
> - * @ack_interrupt: acknowledge an interrupt in the ISR.
> - * @send_intr: Send an interrupt to the remote node on a specified doorbell.
> - * @send_p2p_intr: Send an interrupt to the peer node on a specified
> doorbell
> - * which is specifically targeted for a peer to peer node.
> - * @remap: Map a buffer with the specified physical address and length.
> - * @unmap: Unmap a buffer previously mapped.
> - */
> -struct scif_hw_ops {
> - int (*next_db)(struct scif_hw_dev *sdev);
> - struct mic_irq * (*request_irq)(struct scif_hw_dev *sdev,
> - irqreturn_t (*func)(int irq,
> - void *data),
> - const char *name, void *data,
> - int db);
> - void (*free_irq)(struct scif_hw_dev *sdev,
> - struct mic_irq *cookie, void *data);
> - void (*ack_interrupt)(struct scif_hw_dev *sdev, int num);
> - void (*send_intr)(struct scif_hw_dev *sdev, int db);
> - void (*send_p2p_intr)(struct scif_hw_dev *sdev, int db,
> - struct mic_mw *mw);
> - void __iomem * (*remap)(struct scif_hw_dev *sdev,
> - phys_addr_t pa, size_t len);
> - void (*unmap)(struct scif_hw_dev *sdev, void __iomem *va);
> -};
> -
> -int scif_register_driver(struct scif_driver *driver);
> -void scif_unregister_driver(struct scif_driver *driver);
> -struct scif_hw_dev *
> -scif_register_device(struct device *pdev, int id,
> - const struct dma_map_ops *dma_ops,
> - struct scif_hw_ops *hw_ops, u8 dnode, u8 snode,
> - struct mic_mw *mmio, struct mic_mw *aper,
> - void *dp, void __iomem *rdp,
> - struct dma_chan **chan, int num_chan,
> - bool card_rel_da);
> -void scif_unregister_device(struct scif_hw_dev *sdev);
> -
> -static inline struct scif_hw_dev *dev_to_scif(struct device *dev)
> -{
> - return container_of(dev, struct scif_hw_dev, dev);
> -}
> -
> -static inline struct scif_driver *drv_to_scif(struct device_driver *drv)
> -{
> - return container_of(drv, struct scif_driver, driver);
> -}
> -#endif /* _SCIF_BUS_H */
> diff --git a/drivers/misc/mic/bus/vop_bus.c
> b/drivers/misc/mic/bus/vop_bus.c
> deleted file mode 100644
> index 6935ddca1bd5..000000000000
> --- a/drivers/misc/mic/bus/vop_bus.c
> +++ /dev/null
> @@ -1,194 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Intel Virtio Over PCIe (VOP) Bus driver.
> - */
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/idr.h>
> -#include <linux/dma-map-ops.h>
> -
> -#include "vop_bus.h"
> -
> -static ssize_t device_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> -
> - return sprintf(buf, "0x%04x\n", dev->id.device);
> -}
> -static DEVICE_ATTR_RO(device);
> -
> -static ssize_t vendor_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> -
> - return sprintf(buf, "0x%04x\n", dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(vendor);
> -
> -static ssize_t modalias_show(struct device *d,
> - struct device_attribute *attr, char *buf)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> -
> - return sprintf(buf, "vop:d%08Xv%08X\n",
> - dev->id.device, dev->id.vendor);
> -}
> -static DEVICE_ATTR_RO(modalias);
> -
> -static struct attribute *vop_dev_attrs[] = {
> - &dev_attr_device.attr,
> - &dev_attr_vendor.attr,
> - &dev_attr_modalias.attr,
> - NULL,
> -};
> -ATTRIBUTE_GROUPS(vop_dev);
> -
> -static inline int vop_id_match(const struct vop_device *dev,
> - const struct vop_device_id *id)
> -{
> - if (id->device != dev->id.device && id->device != VOP_DEV_ANY_ID)
> - return 0;
> -
> - return id->vendor == VOP_DEV_ANY_ID || id->vendor == dev-
> >id.vendor;
> -}
> -
> -/*
> - * This looks through all the IDs a driver claims to support. If any of them
> - * match, we return 1 and the kernel will call vop_dev_probe().
> - */
> -static int vop_dev_match(struct device *dv, struct device_driver *dr)
> -{
> - unsigned int i;
> - struct vop_device *dev = dev_to_vop(dv);
> - const struct vop_device_id *ids;
> -
> - ids = drv_to_vop(dr)->id_table;
> - for (i = 0; ids[i].device; i++)
> - if (vop_id_match(dev, &ids[i]))
> - return 1;
> - return 0;
> -}
> -
> -static int vop_uevent(struct device *dv, struct kobj_uevent_env *env)
> -{
> - struct vop_device *dev = dev_to_vop(dv);
> -
> - return add_uevent_var(env, "MODALIAS=vop:d%08Xv%08X",
> - dev->id.device, dev->id.vendor);
> -}
> -
> -static int vop_dev_probe(struct device *d)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> - struct vop_driver *drv = drv_to_vop(dev->dev.driver);
> -
> - return drv->probe(dev);
> -}
> -
> -static int vop_dev_remove(struct device *d)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> - struct vop_driver *drv = drv_to_vop(dev->dev.driver);
> -
> - drv->remove(dev);
> - return 0;
> -}
> -
> -static struct bus_type vop_bus = {
> - .name = "vop_bus",
> - .match = vop_dev_match,
> - .dev_groups = vop_dev_groups,
> - .uevent = vop_uevent,
> - .probe = vop_dev_probe,
> - .remove = vop_dev_remove,
> -};
> -
> -int vop_register_driver(struct vop_driver *driver)
> -{
> - driver->driver.bus = &vop_bus;
> - return driver_register(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(vop_register_driver);
> -
> -void vop_unregister_driver(struct vop_driver *driver)
> -{
> - driver_unregister(&driver->driver);
> -}
> -EXPORT_SYMBOL_GPL(vop_unregister_driver);
> -
> -static void vop_release_dev(struct device *d)
> -{
> - struct vop_device *dev = dev_to_vop(d);
> -
> - kfree(dev);
> -}
> -
> -struct vop_device *
> -vop_register_device(struct device *pdev, int id,
> - const struct dma_map_ops *dma_ops,
> - struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw
> *aper,
> - struct dma_chan *chan)
> -{
> - int ret;
> - struct vop_device *vdev;
> -
> - vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
> - if (!vdev)
> - return ERR_PTR(-ENOMEM);
> -
> - vdev->dev.parent = pdev;
> - vdev->id.device = id;
> - vdev->id.vendor = VOP_DEV_ANY_ID;
> - vdev->dev.dma_ops = dma_ops;
> - vdev->dev.dma_mask = &vdev->dev.coherent_dma_mask;
> - dma_set_mask(&vdev->dev, DMA_BIT_MASK(64));
> - vdev->dev.release = vop_release_dev;
> - vdev->hw_ops = hw_ops;
> - vdev->dev.bus = &vop_bus;
> - vdev->dnode = dnode;
> - vdev->aper = aper;
> - vdev->dma_ch = chan;
> - vdev->index = dnode - 1;
> - dev_set_name(&vdev->dev, "vop-dev%u", vdev->index);
> - /*
> - * device_register() causes the bus infrastructure to look for a
> - * matching driver.
> - */
> - ret = device_register(&vdev->dev);
> - if (ret)
> - goto free_vdev;
> - return vdev;
> -free_vdev:
> - put_device(&vdev->dev);
> - return ERR_PTR(ret);
> -}
> -EXPORT_SYMBOL_GPL(vop_register_device);
> -
> -void vop_unregister_device(struct vop_device *dev)
> -{
> - device_unregister(&dev->dev);
> -}
> -EXPORT_SYMBOL_GPL(vop_unregister_device);
> -
> -static int __init vop_init(void)
> -{
> - return bus_register(&vop_bus);
> -}
> -
> -static void __exit vop_exit(void)
> -{
> - bus_unregister(&vop_bus);
> -}
> -
> -core_initcall(vop_init);
> -module_exit(vop_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) VOP Bus driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/bus/vop_bus.h
> b/drivers/misc/mic/bus/vop_bus.h
> deleted file mode 100644
> index 4fa02808c1e2..000000000000
> --- a/drivers/misc/mic/bus/vop_bus.h
> +++ /dev/null
> @@ -1,129 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Intel Virtio over PCIe Bus driver.
> - */
> -#ifndef _VOP_BUS_H_
> -#define _VOP_BUS_H_
> -/*
> - * Everything a vop driver needs to work with any particular vop
> - * implementation.
> - */
> -#include <linux/dmaengine.h>
> -#include <linux/interrupt.h>
> -
> -#include "../common/mic_dev.h"
> -
> -struct vop_device_id {
> - u32 device;
> - u32 vendor;
> -};
> -
> -#define VOP_DEV_TRNSP 1
> -#define VOP_DEV_ANY_ID 0xffffffff
> -/*
> - * Size of the internal buffer used during DMA's as an intermediate buffer
> - * for copy to/from user. Must be an integral number of pages.
> - */
> -#define VOP_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
> -
> -/**
> - * vop_device - representation of a device using vop
> - * @hw_ops: the hardware ops supported by this device.
> - * @id: the device type identification (used to match it with a driver).
> - * @dev: underlying device.
> - * @dnode - The destination node which this device will communicate with.
> - * @aper: Aperture memory window
> - * @dma_ch - DMA channel
> - * @index: unique position on the vop bus
> - */
> -struct vop_device {
> - struct vop_hw_ops *hw_ops;
> - struct vop_device_id id;
> - struct device dev;
> - u8 dnode;
> - struct mic_mw *aper;
> - struct dma_chan *dma_ch;
> - int index;
> -};
> -
> -/**
> - * vop_driver - operations for a vop I/O driver
> - * @driver: underlying device driver (populate name and owner).
> - * @id_table: the ids serviced by this driver.
> - * @probe: the function to call when a device is found. Returns 0 or -errno.
> - * @remove: the function to call when a device is removed.
> - */
> -struct vop_driver {
> - struct device_driver driver;
> - const struct vop_device_id *id_table;
> - int (*probe)(struct vop_device *dev);
> - void (*remove)(struct vop_device *dev);
> -};
> -
> -/**
> - * vop_hw_ops - Hardware operations for accessing a VOP device on the
> VOP bus.
> - *
> - * @next_db: Obtain the next available doorbell.
> - * @request_irq: Request an interrupt on a particular doorbell.
> - * @free_irq: Free an interrupt requested previously.
> - * @ack_interrupt: acknowledge an interrupt in the ISR.
> - * @get_remote_dp: Get access to the virtio device page used by the remote
> - * node to add/remove/configure virtio devices.
> - * @get_dp: Get access to the virtio device page used by the self
> - * node to add/remove/configure virtio devices.
> - * @send_intr: Send an interrupt to the peer node on a specified doorbell.
> - * @remap: Map a buffer with the specified DMA address and length.
> - * @unmap: Unmap a buffer previously mapped.
> - * @dma_filter: The DMA filter function to use for obtaining access to
> - * a DMA channel on the peer node.
> - */
> -struct vop_hw_ops {
> - int (*next_db)(struct vop_device *vpdev);
> - struct mic_irq *(*request_irq)(struct vop_device *vpdev,
> - irqreturn_t (*func)(int irq, void *data),
> - const char *name, void *data,
> - int intr_src);
> - void (*free_irq)(struct vop_device *vpdev,
> - struct mic_irq *cookie, void *data);
> - void (*ack_interrupt)(struct vop_device *vpdev, int num);
> - void __iomem * (*get_remote_dp)(struct vop_device *vpdev);
> - void * (*get_dp)(struct vop_device *vpdev);
> - void (*send_intr)(struct vop_device *vpdev, int db);
> - void __iomem * (*remap)(struct vop_device *vpdev,
> - dma_addr_t pa, size_t len);
> - void (*unmap)(struct vop_device *vpdev, void __iomem *va);
> -};
> -
> -struct vop_device *
> -vop_register_device(struct device *pdev, int id,
> - const struct dma_map_ops *dma_ops,
> - struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw
> *aper,
> - struct dma_chan *chan);
> -void vop_unregister_device(struct vop_device *dev);
> -int vop_register_driver(struct vop_driver *drv);
> -void vop_unregister_driver(struct vop_driver *drv);
> -
> -/*
> - * module_vop_driver() - Helper macro for drivers that don't do
> - * anything special in module init/exit. This eliminates a lot of
> - * boilerplate. Each module may only use this macro once, and
> - * calling it replaces module_init() and module_exit()
> - */
> -#define module_vop_driver(__vop_driver) \
> - module_driver(__vop_driver, vop_register_driver, \
> - vop_unregister_driver)
> -
> -static inline struct vop_device *dev_to_vop(struct device *dev)
> -{
> - return container_of(dev, struct vop_device, dev);
> -}
> -
> -static inline struct vop_driver *drv_to_vop(struct device_driver *drv)
> -{
> - return container_of(drv, struct vop_driver, driver);
> -}
> -#endif /* _VOP_BUS_H */
> diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
> deleted file mode 100644
> index 921a7e7e0fbd..000000000000
> --- a/drivers/misc/mic/card/Makefile
> +++ /dev/null
> @@ -1,11 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -#
> -# Makefile - Intel MIC Linux driver.
> -# Copyright(c) 2013, Intel Corporation.
> -#
> -ccflags-y += -DINTEL_MIC_CARD
> -
> -obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
> -mic_card-y += mic_x100.o
> -mic_card-y += mic_device.o
> -mic_card-y += mic_debugfs.o
> diff --git a/drivers/misc/mic/card/mic_debugfs.c
> b/drivers/misc/mic/card/mic_debugfs.c
> deleted file mode 100644
> index 4c326e8f4d99..000000000000
> --- a/drivers/misc/mic/card/mic_debugfs.c
> +++ /dev/null
> @@ -1,85 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Disclaimer: The codes contained in these modules may be specific to
> - * the Intel Software Development Platform codenamed: Knights Ferry, and
> - * the Intel product codenamed: Knights Corner, and are not backward
> - * compatible with other Intel products. Additionally, Intel will NOT
> - * support the codes or instruction set in future products.
> - *
> - * Intel MIC Card driver.
> - */
> -#include <linux/debugfs.h>
> -#include <linux/delay.h>
> -#include <linux/seq_file.h>
> -#include <linux/interrupt.h>
> -#include <linux/device.h>
> -
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -
> -/* Debugfs parent dir */
> -static struct dentry *mic_dbg;
> -
> -/*
> - * mic_intr_show - Send interrupts to host.
> - */
> -static int mic_intr_show(struct seq_file *s, void *unused)
> -{
> - struct mic_driver *mdrv = s->private;
> - struct mic_device *mdev = &mdrv->mdev;
> -
> - mic_send_intr(mdev, 0);
> - msleep(1000);
> - mic_send_intr(mdev, 1);
> - msleep(1000);
> - mic_send_intr(mdev, 2);
> - msleep(1000);
> - mic_send_intr(mdev, 3);
> - msleep(1000);
> -
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(mic_intr);
> -
> -/*
> - * mic_create_card_debug_dir - Initialize MIC debugfs entries.
> - */
> -void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
> -{
> - if (!mic_dbg)
> - return;
> -
> - mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
> -
> - debugfs_create_file("intr_test", 0444, mdrv->dbg_dir, mdrv,
> - &mic_intr_fops);
> -}
> -
> -/*
> - * mic_delete_card_debug_dir - Uninitialize MIC debugfs entries.
> - */
> -void mic_delete_card_debug_dir(struct mic_driver *mdrv)
> -{
> - debugfs_remove_recursive(mdrv->dbg_dir);
> -}
> -
> -/*
> - * mic_init_card_debugfs - Initialize global debugfs entry.
> - */
> -void __init mic_init_card_debugfs(void)
> -{
> - mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
> -}
> -
> -/*
> - * mic_exit_card_debugfs - Uninitialize global debugfs entry
> - */
> -void mic_exit_card_debugfs(void)
> -{
> - debugfs_remove(mic_dbg);
> -}
> diff --git a/drivers/misc/mic/card/mic_device.c
> b/drivers/misc/mic/card/mic_device.c
> deleted file mode 100644
> index a15606259bdc..000000000000
> --- a/drivers/misc/mic/card/mic_device.c
> +++ /dev/null
> @@ -1,417 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Disclaimer: The codes contained in these modules may be specific to
> - * the Intel Software Development Platform codenamed: Knights Ferry, and
> - * the Intel product codenamed: Knights Corner, and are not backward
> - * compatible with other Intel products. Additionally, Intel will NOT
> - * support the codes or instruction set in future products.
> - *
> - * Intel MIC Card driver.
> - */
> -#include <linux/module.h>
> -#include <linux/pci.h>
> -#include <linux/interrupt.h>
> -#include <linux/reboot.h>
> -#include <linux/dmaengine.h>
> -#include <linux/kmod.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -
> -static struct mic_driver *g_drv;
> -
> -static int __init mic_dp_init(void)
> -{
> - struct mic_driver *mdrv = g_drv;
> - struct mic_device *mdev = &mdrv->mdev;
> - struct mic_bootparam __iomem *bootparam;
> - u64 lo, hi, dp_dma_addr;
> - u32 magic;
> -
> - lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD);
> - hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD);
> -
> - dp_dma_addr = lo | (hi << 32);
> - mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE);
> - if (!mdrv->dp) {
> - dev_err(mdrv->dev, "Cannot remap Aperture BAR\n");
> - return -ENOMEM;
> - }
> - bootparam = mdrv->dp;
> - magic = ioread32(&bootparam->magic);
> - if (MIC_MAGIC != magic) {
> - dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n",
> magic);
> - return -EIO;
> - }
> - return 0;
> -}
> -
> -/* Uninitialize the device page */
> -static void mic_dp_uninit(void)
> -{
> - mic_card_unmap(&g_drv->mdev, g_drv->dp);
> -}
> -
> -/**
> - * mic_request_card_irq - request an irq.
> - *
> - * @handler: interrupt handler passed to request_threaded_irq.
> - * @thread_fn: thread fn. passed to request_threaded_irq.
> - * @name: The ASCII name of the callee requesting the irq.
> - * @data: private data that is returned back when calling the
> - * function handler.
> - * @index: The doorbell index of the requester.
> - *
> - * returns: The cookie that is transparent to the caller. Passed
> - * back when calling mic_free_irq. An appropriate error code
> - * is returned on failure. Caller needs to use IS_ERR(return_val)
> - * to check for failure and PTR_ERR(return_val) to obtained the
> - * error code.
> - *
> - */
> -struct mic_irq *
> -mic_request_card_irq(irq_handler_t handler,
> - irq_handler_t thread_fn, const char *name,
> - void *data, int index)
> -{
> - int rc = 0;
> - unsigned long cookie;
> - struct mic_driver *mdrv = g_drv;
> -
> - rc = request_threaded_irq(mic_db_to_irq(mdrv, index), handler,
> - thread_fn, 0, name, data);
> - if (rc) {
> - dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n",
> rc);
> - goto err;
> - }
> - mdrv->irq_info.irq_usage_count[index]++;
> - cookie = index;
> - return (struct mic_irq *)cookie;
> -err:
> - return ERR_PTR(rc);
> -}
> -
> -/**
> - * mic_free_card_irq - free irq.
> - *
> - * @cookie: cookie obtained during a successful call to
> mic_request_threaded_irq
> - * @data: private data specified by the calling function during the
> - * mic_request_threaded_irq
> - *
> - * returns: none.
> - */
> -void mic_free_card_irq(struct mic_irq *cookie, void *data)
> -{
> - int index;
> - struct mic_driver *mdrv = g_drv;
> -
> - index = (unsigned long)cookie & 0xFFFFU;
> - free_irq(mic_db_to_irq(mdrv, index), data);
> - mdrv->irq_info.irq_usage_count[index]--;
> -}
> -
> -/**
> - * mic_next_card_db - Get the doorbell with minimum usage count.
> - *
> - * Returns the irq index.
> - */
> -int mic_next_card_db(void)
> -{
> - int i;
> - int index = 0;
> - struct mic_driver *mdrv = g_drv;
> -
> - for (i = 0; i < mdrv->intr_info.num_intr; i++) {
> - if (mdrv->irq_info.irq_usage_count[i] <
> - mdrv->irq_info.irq_usage_count[index])
> - index = i;
> - }
> -
> - return index;
> -}
> -
> -/**
> - * mic_init_irq - Initialize irq information.
> - *
> - * Returns 0 in success. Appropriate error code on failure.
> - */
> -static int mic_init_irq(void)
> -{
> - struct mic_driver *mdrv = g_drv;
> -
> - mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) *
> - mdrv->intr_info.num_intr),
> - GFP_KERNEL);
> - if (!mdrv->irq_info.irq_usage_count)
> - return -ENOMEM;
> - return 0;
> -}
> -
> -/**
> - * mic_uninit_irq - Uninitialize irq information.
> - *
> - * None.
> - */
> -static void mic_uninit_irq(void)
> -{
> - struct mic_driver *mdrv = g_drv;
> -
> - kfree(mdrv->irq_info.irq_usage_count);
> -}
> -
> -static inline struct mic_driver *scdev_to_mdrv(struct scif_hw_dev *scdev)
> -{
> - return dev_get_drvdata(scdev->dev.parent);
> -}
> -
> -static struct mic_irq *
> -___mic_request_irq(struct scif_hw_dev *scdev,
> - irqreturn_t (*func)(int irq, void *data),
> - const char *name, void *data,
> - int db)
> -{
> - return mic_request_card_irq(func, NULL, name, data, db);
> -}
> -
> -static void
> -___mic_free_irq(struct scif_hw_dev *scdev,
> - struct mic_irq *cookie, void *data)
> -{
> - return mic_free_card_irq(cookie, data);
> -}
> -
> -static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num)
> -{
> - struct mic_driver *mdrv = scdev_to_mdrv(scdev);
> -
> - mic_ack_interrupt(&mdrv->mdev);
> -}
> -
> -static int ___mic_next_db(struct scif_hw_dev *scdev)
> -{
> - return mic_next_card_db();
> -}
> -
> -static void ___mic_send_intr(struct scif_hw_dev *scdev, int db)
> -{
> - struct mic_driver *mdrv = scdev_to_mdrv(scdev);
> -
> - mic_send_intr(&mdrv->mdev, db);
> -}
> -
> -static void ___mic_send_p2p_intr(struct scif_hw_dev *scdev, int db,
> - struct mic_mw *mw)
> -{
> - mic_send_p2p_intr(db, mw);
> -}
> -
> -static void __iomem *
> -___mic_ioremap(struct scif_hw_dev *scdev,
> - phys_addr_t pa, size_t len)
> -{
> - struct mic_driver *mdrv = scdev_to_mdrv(scdev);
> -
> - return mic_card_map(&mdrv->mdev, pa, len);
> -}
> -
> -static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va)
> -{
> - struct mic_driver *mdrv = scdev_to_mdrv(scdev);
> -
> - mic_card_unmap(&mdrv->mdev, va);
> -}
> -
> -static struct scif_hw_ops scif_hw_ops = {
> - .request_irq = ___mic_request_irq,
> - .free_irq = ___mic_free_irq,
> - .ack_interrupt = ___mic_ack_interrupt,
> - .next_db = ___mic_next_db,
> - .send_intr = ___mic_send_intr,
> - .send_p2p_intr = ___mic_send_p2p_intr,
> - .remap = ___mic_ioremap,
> - .unmap = ___mic_iounmap,
> -};
> -
> -static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev)
> -{
> - return dev_get_drvdata(vpdev->dev.parent);
> -}
> -
> -static struct mic_irq *
> -__mic_request_irq(struct vop_device *vpdev,
> - irqreturn_t (*func)(int irq, void *data),
> - const char *name, void *data, int intr_src)
> -{
> - return mic_request_card_irq(func, NULL, name, data, intr_src);
> -}
> -
> -static void __mic_free_irq(struct vop_device *vpdev,
> - struct mic_irq *cookie, void *data)
> -{
> - return mic_free_card_irq(cookie, data);
> -}
> -
> -static void __mic_ack_interrupt(struct vop_device *vpdev, int num)
> -{
> - struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
> -
> - mic_ack_interrupt(&mdrv->mdev);
> -}
> -
> -static int __mic_next_db(struct vop_device *vpdev)
> -{
> - return mic_next_card_db();
> -}
> -
> -static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev)
> -{
> - struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
> -
> - return mdrv->dp;
> -}
> -
> -static void __mic_send_intr(struct vop_device *vpdev, int db)
> -{
> - struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
> -
> - mic_send_intr(&mdrv->mdev, db);
> -}
> -
> -static void __iomem *__mic_ioremap(struct vop_device *vpdev,
> - dma_addr_t pa, size_t len)
> -{
> - struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
> -
> - return mic_card_map(&mdrv->mdev, pa, len);
> -}
> -
> -static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va)
> -{
> - struct mic_driver *mdrv = vpdev_to_mdrv(vpdev);
> -
> - mic_card_unmap(&mdrv->mdev, va);
> -}
> -
> -static struct vop_hw_ops vop_hw_ops = {
> - .request_irq = __mic_request_irq,
> - .free_irq = __mic_free_irq,
> - .ack_interrupt = __mic_ack_interrupt,
> - .next_db = __mic_next_db,
> - .get_remote_dp = __mic_get_remote_dp,
> - .send_intr = __mic_send_intr,
> - .remap = __mic_ioremap,
> - .unmap = __mic_iounmap,
> -};
> -
> -static int mic_request_dma_chans(struct mic_driver *mdrv)
> -{
> - dma_cap_mask_t mask;
> - struct dma_chan *chan;
> -
> - dma_cap_zero(mask);
> - dma_cap_set(DMA_MEMCPY, mask);
> -
> - do {
> - chan = dma_request_channel(mask, NULL, NULL);
> - if (chan) {
> - mdrv->dma_ch[mdrv->num_dma_ch++] = chan;
> - if (mdrv->num_dma_ch >= MIC_MAX_DMA_CHAN)
> - break;
> - }
> - } while (chan);
> - dev_info(mdrv->dev, "DMA channels # %d\n", mdrv->num_dma_ch);
> - return mdrv->num_dma_ch;
> -}
> -
> -static void mic_free_dma_chans(struct mic_driver *mdrv)
> -{
> - int i = 0;
> -
> - for (i = 0; i < mdrv->num_dma_ch; i++) {
> - dma_release_channel(mdrv->dma_ch[i]);
> - mdrv->dma_ch[i] = NULL;
> - }
> - mdrv->num_dma_ch = 0;
> -}
> -
> -/*
> - * mic_driver_init - MIC driver initialization tasks.
> - *
> - * Returns 0 in success. Appropriate error code on failure.
> - */
> -int __init mic_driver_init(struct mic_driver *mdrv)
> -{
> - int rc;
> - struct mic_bootparam __iomem *bootparam;
> - u8 node_id;
> -
> - g_drv = mdrv;
> - /* Unloading the card module is not supported. */
> - if (!try_module_get(mdrv->dev->driver->owner)) {
> - rc = -ENODEV;
> - goto done;
> - }
> - rc = mic_dp_init();
> - if (rc)
> - goto put;
> - rc = mic_init_irq();
> - if (rc)
> - goto dp_uninit;
> - if (!mic_request_dma_chans(mdrv)) {
> - rc = -ENODEV;
> - goto irq_uninit;
> - }
> - mdrv->vpdev = vop_register_device(mdrv->dev, VOP_DEV_TRNSP,
> - NULL, &vop_hw_ops, 0,
> - NULL, mdrv->dma_ch[0]);
> - if (IS_ERR(mdrv->vpdev)) {
> - rc = PTR_ERR(mdrv->vpdev);
> - goto dma_free;
> - }
> - bootparam = mdrv->dp;
> - node_id = ioread8(&bootparam->node_id);
> - mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV,
> - NULL, &scif_hw_ops,
> - 0, node_id, &mdrv->mdev.mmio,
> NULL,
> - NULL, mdrv->dp, mdrv->dma_ch,
> - mdrv->num_dma_ch, true);
> - if (IS_ERR(mdrv->scdev)) {
> - rc = PTR_ERR(mdrv->scdev);
> - goto vop_remove;
> - }
> - mic_create_card_debug_dir(mdrv);
> -done:
> - return rc;
> -vop_remove:
> - vop_unregister_device(mdrv->vpdev);
> -dma_free:
> - mic_free_dma_chans(mdrv);
> -irq_uninit:
> - mic_uninit_irq();
> -dp_uninit:
> - mic_dp_uninit();
> -put:
> - module_put(mdrv->dev->driver->owner);
> - return rc;
> -}
> -
> -/*
> - * mic_driver_uninit - MIC driver uninitialization tasks.
> - *
> - * Returns None
> - */
> -void mic_driver_uninit(struct mic_driver *mdrv)
> -{
> - mic_delete_card_debug_dir(mdrv);
> - scif_unregister_device(mdrv->scdev);
> - vop_unregister_device(mdrv->vpdev);
> - mic_free_dma_chans(mdrv);
> - mic_uninit_irq();
> - mic_dp_uninit();
> - module_put(mdrv->dev->driver->owner);
> -}
> diff --git a/drivers/misc/mic/card/mic_device.h
> b/drivers/misc/mic/card/mic_device.h
> deleted file mode 100644
> index d6cc69a235a3..000000000000
> --- a/drivers/misc/mic/card/mic_device.h
> +++ /dev/null
> @@ -1,137 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Disclaimer: The codes contained in these modules may be specific to
> - * the Intel Software Development Platform codenamed: Knights Ferry, and
> - * the Intel product codenamed: Knights Corner, and are not backward
> - * compatible with other Intel products. Additionally, Intel will NOT
> - * support the codes or instruction set in future products.
> - *
> - * Intel MIC Card driver.
> - */
> -#ifndef _MIC_CARD_DEVICE_H_
> -#define _MIC_CARD_DEVICE_H_
> -
> -#include <linux/workqueue.h>
> -#include <linux/io.h>
> -#include <linux/interrupt.h>
> -#include <linux/mic_bus.h>
> -#include "../bus/scif_bus.h"
> -#include "../bus/vop_bus.h"
> -
> -/**
> - * struct mic_intr_info - Contains h/w specific interrupt sources info
> - *
> - * @num_intr: The number of irqs available
> - */
> -struct mic_intr_info {
> - u32 num_intr;
> -};
> -
> -/**
> - * struct mic_irq_info - OS specific irq information
> - *
> - * @irq_usage_count: usage count array tracking the number of sources
> - * assigned for each irq.
> - */
> -struct mic_irq_info {
> - int *irq_usage_count;
> -};
> -
> -/**
> - * struct mic_device - MIC device information.
> - *
> - * @mmio: MMIO bar information.
> - */
> -struct mic_device {
> - struct mic_mw mmio;
> -};
> -
> -/**
> - * struct mic_driver - MIC card driver information.
> - *
> - * @name: Name for MIC driver.
> - * @dbg_dir: debugfs directory of this MIC device.
> - * @dev: The device backing this MIC.
> - * @dp: The pointer to the virtio device page.
> - * @mdev: MIC device information for the host.
> - * @hotplug_work: Hot plug work for adding/removing virtio devices.
> - * @irq_info: The OS specific irq information
> - * @intr_info: H/W specific interrupt information.
> - * @dma_mbdev: dma device on the MIC virtual bus.
> - * @dma_ch - Array of DMA channels
> - * @num_dma_ch - Number of DMA channels available
> - * @scdev: SCIF device on the SCIF virtual bus.
> - * @vpdev: Virtio over PCIe device on the VOP virtual bus.
> - */
> -struct mic_driver {
> - char name[20];
> - struct dentry *dbg_dir;
> - struct device *dev;
> - void __iomem *dp;
> - struct mic_device mdev;
> - struct work_struct hotplug_work;
> - struct mic_irq_info irq_info;
> - struct mic_intr_info intr_info;
> - struct mbus_device *dma_mbdev;
> - struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
> - int num_dma_ch;
> - struct scif_hw_dev *scdev;
> - struct vop_device *vpdev;
> -};
> -
> -/**
> - * struct mic_irq - opaque pointer used as cookie
> - */
> -struct mic_irq;
> -
> -/**
> - * mic_mmio_read - read from an MMIO register.
> - * @mw: MMIO register base virtual address.
> - * @offset: register offset.
> - *
> - * RETURNS: register value.
> - */
> -static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
> -{
> - return ioread32(mw->va + offset);
> -}
> -
> -/**
> - * mic_mmio_write - write to an MMIO register.
> - * @mw: MMIO register base virtual address.
> - * @val: the data value to put into the register
> - * @offset: register offset.
> - *
> - * RETURNS: none.
> - */
> -static inline void
> -mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
> -{
> - iowrite32(val, mw->va + offset);
> -}
> -
> -int mic_driver_init(struct mic_driver *mdrv);
> -void mic_driver_uninit(struct mic_driver *mdrv);
> -int mic_next_card_db(void);
> -struct mic_irq *
> -mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn,
> - const char *name, void *data, int db);
> -void mic_free_card_irq(struct mic_irq *cookie, void *data);
> -u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
> -void mic_send_intr(struct mic_device *mdev, int doorbell);
> -void mic_send_p2p_intr(int doorbell, struct mic_mw *mw);
> -int mic_db_to_irq(struct mic_driver *mdrv, int db);
> -u32 mic_ack_interrupt(struct mic_device *mdev);
> -void mic_hw_intr_init(struct mic_driver *mdrv);
> -void __iomem *
> -mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size);
> -void mic_card_unmap(struct mic_device *mdev, void __iomem *addr);
> -void __init mic_create_card_debug_dir(struct mic_driver *mdrv);
> -void mic_delete_card_debug_dir(struct mic_driver *mdrv);
> -void __init mic_init_card_debugfs(void);
> -void mic_exit_card_debugfs(void);
> -#endif
> diff --git a/drivers/misc/mic/card/mic_x100.c
> b/drivers/misc/mic/card/mic_x100.c
> deleted file mode 100644
> index c8bff2916d3d..000000000000
> --- a/drivers/misc/mic/card/mic_x100.c
> +++ /dev/null
> @@ -1,347 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Disclaimer: The codes contained in these modules may be specific to
> - * the Intel Software Development Platform codenamed: Knights Ferry, and
> - * the Intel product codenamed: Knights Corner, and are not backward
> - * compatible with other Intel products. Additionally, Intel will NOT
> - * support the codes or instruction set in future products.
> - *
> - * Intel MIC Card driver.
> - */
> -#include <linux/module.h>
> -#include <linux/pci.h>
> -#include <linux/platform_device.h>
> -
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_x100.h"
> -
> -static const char mic_driver_name[] = "mic";
> -
> -static struct mic_driver g_drv;
> -
> -/**
> - * mic_read_spad - read from the scratchpad register
> - * @mdev: pointer to mic_device instance
> - * @idx: index to scratchpad register, 0 based
> - *
> - * This function allows reading of the 32bit scratchpad register.
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
> -{
> - return mic_mmio_read(&mdev->mmio,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_SPAD0 + idx * 4);
> -}
> -
> -/**
> - * __mic_send_intr - Send interrupt to Host.
> - * @mdev: pointer to mic_device instance
> - * @doorbell: Doorbell number.
> - */
> -void mic_send_intr(struct mic_device *mdev, int doorbell)
> -{
> - struct mic_mw *mw = &mdev->mmio;
> -
> - if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
> - return;
> - /* Ensure that the interrupt is ordered w.r.t previous stores. */
> - wmb();
> - mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
> -}
> -
> -/*
> - * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
> - */
> -static void mic_x100_send_sbox_intr(struct mic_mw *mw, int doorbell)
> -{
> - u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
> - u32 apicicr_low = mic_mmio_read(mw,
> MIC_X100_SBOX_BASE_ADDRESS +
> - apic_icr_offset);
> -
> - /* for MIC we need to make sure we "hit" the send_icr bit (13) */
> - apicicr_low = (apicicr_low | (1 << 13));
> - /*
> - * Ensure that the interrupt is ordered w.r.t. previous stores
> - * to main memory. Fence instructions are not implemented in X100
> - * since execution is in order but a compiler barrier is still
> - * required.
> - */
> - wmb();
> - mic_mmio_write(mw, apicicr_low,
> - MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
> -}
> -
> -static void mic_x100_send_rdmasr_intr(struct mic_mw *mw, int doorbell)
> -{
> - int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
> - /*
> - * Ensure that the interrupt is ordered w.r.t. previous stores
> - * to main memory. Fence instructions are not implemented in X100
> - * since execution is in order but a compiler barrier is still
> - * required.
> - */
> - wmb();
> - mic_mmio_write(mw, 0, MIC_X100_SBOX_BASE_ADDRESS +
> rdmasr_offset);
> -}
> -
> -/**
> - * mic_ack_interrupt - Device specific interrupt handling.
> - * @mdev: pointer to mic_device instance
> - *
> - * Returns: bitmask of doorbell events triggered.
> - */
> -u32 mic_ack_interrupt(struct mic_device *mdev)
> -{
> - return 0;
> -}
> -
> -static inline int mic_get_sbox_irq(int db)
> -{
> - return MIC_X100_IRQ_BASE + db;
> -}
> -
> -static inline int mic_get_rdmasr_irq(int index)
> -{
> - return MIC_X100_RDMASR_IRQ_BASE + index;
> -}
> -
> -void mic_send_p2p_intr(int db, struct mic_mw *mw)
> -{
> - int rdmasr_index;
> -
> - if (db < MIC_X100_NUM_SBOX_IRQ) {
> - mic_x100_send_sbox_intr(mw, db);
> - } else {
> - rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ;
> - mic_x100_send_rdmasr_intr(mw, rdmasr_index);
> - }
> -}
> -
> -/**
> - * mic_hw_intr_init - Initialize h/w specific interrupt
> - * information.
> - * @mdrv: pointer to mic_driver
> - */
> -void mic_hw_intr_init(struct mic_driver *mdrv)
> -{
> - mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ +
> - MIC_X100_NUM_RDMASR_IRQ;
> -}
> -
> -/**
> - * mic_db_to_irq - Retrieve irq number corresponding to a doorbell.
> - * @mdrv: pointer to mic_driver
> - * @db: The doorbell obtained for which the irq is needed. Doorbell
> - * may correspond to an sbox doorbell or an rdmasr index.
> - *
> - * Returns the irq corresponding to the doorbell.
> - */
> -int mic_db_to_irq(struct mic_driver *mdrv, int db)
> -{
> - int rdmasr_index;
> -
> - /*
> - * The total number of doorbell interrupts on the card are 16. Indices
> - * 0-8 falls in the SBOX category and 8-15 fall in the RDMASR category.
> - */
> - if (db < MIC_X100_NUM_SBOX_IRQ) {
> - return mic_get_sbox_irq(db);
> - } else {
> - rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ;
> - return mic_get_rdmasr_irq(rdmasr_index);
> - }
> -}
> -
> -/*
> - * mic_card_map - Allocate virtual address for a remote memory region.
> - * @mdev: pointer to mic_device instance.
> - * @addr: Remote DMA address.
> - * @size: Size of the region.
> - *
> - * Returns: Virtual address backing the remote memory region.
> - */
> -void __iomem *
> -mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size)
> -{
> - return ioremap(addr, size);
> -}
> -
> -/*
> - * mic_card_unmap - Unmap the virtual address for a remote memory
> region.
> - * @mdev: pointer to mic_device instance.
> - * @addr: Virtual address for remote memory region.
> - *
> - * Returns: None.
> - */
> -void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
> -{
> - iounmap(addr);
> -}
> -
> -static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev)
> -{
> - return dev_get_drvdata(mbdev->dev.parent);
> -}
> -
> -static struct mic_irq *
> -_mic_request_threaded_irq(struct mbus_device *mbdev,
> - irq_handler_t handler, irq_handler_t thread_fn,
> - const char *name, void *data, int intr_src)
> -{
> - int rc = 0;
> - unsigned int irq = intr_src;
> - unsigned long cookie = irq;
> -
> - rc = request_threaded_irq(irq, handler, thread_fn, 0, name, data);
> - if (rc) {
> - dev_err(mbdev_to_mdrv(mbdev)->dev,
> - "request_threaded_irq failed rc = %d\n", rc);
> - return ERR_PTR(rc);
> - }
> - return (struct mic_irq *)cookie;
> -}
> -
> -static void _mic_free_irq(struct mbus_device *mbdev,
> - struct mic_irq *cookie, void *data)
> -{
> - unsigned long irq = (unsigned long)cookie;
> - free_irq(irq, data);
> -}
> -
> -static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
> -{
> - mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev);
> -}
> -
> -static struct mbus_hw_ops mbus_hw_ops = {
> - .request_threaded_irq = _mic_request_threaded_irq,
> - .free_irq = _mic_free_irq,
> - .ack_interrupt = _mic_ack_interrupt,
> -};
> -
> -static int __init mic_probe(struct platform_device *pdev)
> -{
> - struct mic_driver *mdrv = &g_drv;
> - struct mic_device *mdev = &mdrv->mdev;
> - int rc = 0;
> -
> - mdrv->dev = &pdev->dev;
> - snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name);
> -
> - /* FIXME: use dma_set_mask_and_coherent() and check result */
> - dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> -
> - mdev->mmio.pa = MIC_X100_MMIO_BASE;
> - mdev->mmio.len = MIC_X100_MMIO_LEN;
> - mdev->mmio.va = devm_ioremap(&pdev->dev,
> MIC_X100_MMIO_BASE,
> - MIC_X100_MMIO_LEN);
> - if (!mdev->mmio.va) {
> - dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
> - rc = -EIO;
> - goto done;
> - }
> - mic_hw_intr_init(mdrv);
> - platform_set_drvdata(pdev, mdrv);
> - mdrv->dma_mbdev = mbus_register_device(mdrv->dev,
> MBUS_DEV_DMA_MIC,
> - NULL, &mbus_hw_ops, 0,
> - mdrv->mdev.mmio.va);
> - if (IS_ERR(mdrv->dma_mbdev)) {
> - rc = PTR_ERR(mdrv->dma_mbdev);
> - dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc);
> - goto done;
> - }
> - rc = mic_driver_init(mdrv);
> - if (rc) {
> - dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
> - goto remove_dma;
> - }
> -done:
> - return rc;
> -remove_dma:
> - mbus_unregister_device(mdrv->dma_mbdev);
> - return rc;
> -}
> -
> -static int mic_remove(struct platform_device *pdev)
> -{
> - struct mic_driver *mdrv = &g_drv;
> -
> - mic_driver_uninit(mdrv);
> - mbus_unregister_device(mdrv->dma_mbdev);
> - return 0;
> -}
> -
> -static void mic_platform_shutdown(struct platform_device *pdev)
> -{
> - mic_remove(pdev);
> -}
> -
> -static struct platform_driver __refdata mic_platform_driver = {
> - .probe = mic_probe,
> - .remove = mic_remove,
> - .shutdown = mic_platform_shutdown,
> - .driver = {
> - .name = mic_driver_name,
> - },
> -};
> -
> -static struct platform_device *mic_platform_dev;
> -
> -static int __init mic_init(void)
> -{
> - int ret;
> - struct cpuinfo_x86 *c = &cpu_data(0);
> -
> - if (!(c->x86 == 11 && c->x86_model == 1)) {
> - ret = -ENODEV;
> - pr_err("%s not running on X100 ret %d\n", __func__, ret);
> - goto done;
> - }
> -
> - request_module("mic_x100_dma");
> - mic_init_card_debugfs();
> -
> - mic_platform_dev =
> platform_device_register_simple(mic_driver_name,
> - 0, NULL, 0);
> - ret = PTR_ERR_OR_ZERO(mic_platform_dev);
> - if (ret) {
> - pr_err("platform_device_register_full ret %d\n", ret);
> - goto cleanup_debugfs;
> - }
> - ret = platform_driver_register(&mic_platform_driver);
> - if (ret) {
> - pr_err("platform_driver_register ret %d\n", ret);
> - goto device_unregister;
> - }
> - return ret;
> -
> -device_unregister:
> - platform_device_unregister(mic_platform_dev);
> -cleanup_debugfs:
> - mic_exit_card_debugfs();
> -done:
> - return ret;
> -}
> -
> -static void __exit mic_exit(void)
> -{
> - platform_driver_unregister(&mic_platform_driver);
> - platform_device_unregister(mic_platform_dev);
> - mic_exit_card_debugfs();
> -}
> -
> -module_init(mic_init);
> -module_exit(mic_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/card/mic_x100.h
> b/drivers/misc/mic/card/mic_x100.h
> deleted file mode 100644
> index 46644dde0c07..000000000000
> --- a/drivers/misc/mic/card/mic_x100.h
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Disclaimer: The codes contained in these modules may be specific to
> - * the Intel Software Development Platform codenamed: Knights Ferry, and
> - * the Intel product codenamed: Knights Corner, and are not backward
> - * compatible with other Intel products. Additionally, Intel will NOT
> - * support the codes or instruction set in future products.
> - *
> - * Intel MIC Card driver.
> - */
> -#ifndef _MIC_X100_CARD_H_
> -#define _MIC_X100_CARD_H_
> -
> -#define MIC_X100_MMIO_BASE 0x08007C0000ULL
> -#define MIC_X100_MMIO_LEN 0x00020000ULL
> -#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000ULL
> -
> -#define MIC_X100_SBOX_SPAD0 0x0000AB20
> -#define MIC_X100_SBOX_SDBIC0 0x0000CC90
> -#define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000
> -#define MIC_X100_SBOX_RDMASR0 0x0000B180
> -#define MIC_X100_SBOX_APICICR0 0x0000A9D0
> -
> -#define MIC_X100_MAX_DOORBELL_IDX 8
> -
> -#define MIC_X100_NUM_SBOX_IRQ 8
> -#define MIC_X100_NUM_RDMASR_IRQ 8
> -#define MIC_X100_SBOX_IRQ_BASE 0
> -#define MIC_X100_RDMASR_IRQ_BASE 17
> -
> -#define MIC_X100_IRQ_BASE 26
> -
> -#endif
> diff --git a/drivers/misc/mic/common/mic_dev.h
> b/drivers/misc/mic/common/mic_dev.h
> deleted file mode 100644
> index f94f08df0260..000000000000
> --- a/drivers/misc/mic/common/mic_dev.h
> +++ /dev/null
> @@ -1,55 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC driver.
> - */
> -#ifndef __MIC_DEV_H__
> -#define __MIC_DEV_H__
> -
> -/* The maximum number of MIC devices supported in a single host system.
> */
> -#define MIC_MAX_NUM_DEVS 128
> -
> -/**
> - * enum mic_hw_family - The hardware family to which a device belongs.
> - */
> -enum mic_hw_family {
> - MIC_FAMILY_X100 = 0,
> - MIC_FAMILY_X200,
> - MIC_FAMILY_UNKNOWN,
> - MIC_FAMILY_LAST
> -};
> -
> -/**
> - * struct mic_mw - MIC memory window
> - *
> - * @pa: Base physical address.
> - * @va: Base ioremap'd virtual address.
> - * @len: Size of the memory window.
> - */
> -struct mic_mw {
> - phys_addr_t pa;
> - void __iomem *va;
> - resource_size_t len;
> -};
> -
> -/*
> - * Scratch pad register offsets used by the host to communicate
> - * device page DMA address to the card.
> - */
> -#define MIC_DPLO_SPAD 14
> -#define MIC_DPHI_SPAD 15
> -
> -/*
> - * These values are supposed to be in the config_change field of the
> - * device page when the host sends a config change interrupt to the card.
> - */
> -#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1
> -#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2
> -
> -/* Maximum number of DMA channels */
> -#define MIC_MAX_DMA_CHAN 4
> -
> -#endif
> diff --git a/drivers/misc/mic/cosm/Makefile
> b/drivers/misc/mic/cosm/Makefile
> deleted file mode 100644
> index 97d74cb12030..000000000000
> --- a/drivers/misc/mic/cosm/Makefile
> +++ /dev/null
> @@ -1,11 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -#
> -# Makefile - Intel MIC Coprocessor State Management (COSM) Driver
> -# Copyright(c) 2015, Intel Corporation.
> -#
> -obj-$(CONFIG_MIC_COSM) += mic_cosm.o
> -
> -mic_cosm-objs := cosm_main.o
> -mic_cosm-objs += cosm_debugfs.o
> -mic_cosm-objs += cosm_sysfs.o
> -mic_cosm-objs += cosm_scif_server.o
> diff --git a/drivers/misc/mic/cosm/cosm_debugfs.c
> b/drivers/misc/mic/cosm/cosm_debugfs.c
> deleted file mode 100644
> index cb55653cf1f9..000000000000
> --- a/drivers/misc/mic/cosm/cosm_debugfs.c
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC Coprocessor State Management (COSM) Driver
> - */
> -
> -#include <linux/debugfs.h>
> -#include <linux/slab.h>
> -#include <linux/io.h>
> -#include "cosm_main.h"
> -
> -/* Debugfs parent dir */
> -static struct dentry *cosm_dbg;
> -
> -/*
> - * log_buf_show - Display MIC kernel log buffer
> - *
> - * log_buf addr/len is read from System.map by user space
> - * and populated in sysfs entries.
> - */
> -static int log_buf_show(struct seq_file *s, void *unused)
> -{
> - void __iomem *log_buf_va;
> - int __iomem *log_buf_len_va;
> - struct cosm_device *cdev = s->private;
> - void *kva;
> - int size;
> - u64 aper_offset;
> -
> - if (!cdev || !cdev->log_buf_addr || !cdev->log_buf_len)
> - goto done;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - switch (cdev->state) {
> - case MIC_BOOTING:
> - case MIC_ONLINE:
> - case MIC_SHUTTING_DOWN:
> - break;
> - default:
> - goto unlock;
> - }
> -
> - /*
> - * Card kernel will never be relocated and any kernel text/data
> mapping
> - * can be translated to phys address by subtracting
> __START_KERNEL_map.
> - */
> - aper_offset = (u64)cdev->log_buf_len - __START_KERNEL_map;
> - log_buf_len_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
> - aper_offset = (u64)cdev->log_buf_addr - __START_KERNEL_map;
> - log_buf_va = cdev->hw_ops->aper(cdev)->va + aper_offset;
> -
> - size = ioread32(log_buf_len_va);
> - kva = kmalloc(size, GFP_KERNEL);
> - if (!kva)
> - goto unlock;
> -
> - memcpy_fromio(kva, log_buf_va, size);
> - seq_write(s, kva, size);
> - kfree(kva);
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> -done:
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(log_buf);
> -
> -/*
> - * force_reset_show - Force MIC reset
> - *
> - * Invokes the force_reset COSM bus op instead of the standard reset
> - * op in case a force reset of the MIC device is required
> - */
> -static int force_reset_show(struct seq_file *s, void *pos)
> -{
> - struct cosm_device *cdev = s->private;
> -
> - cosm_stop(cdev, true);
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(force_reset);
> -
> -void cosm_create_debug_dir(struct cosm_device *cdev)
> -{
> - char name[16];
> -
> - if (!cosm_dbg)
> - return;
> -
> - scnprintf(name, sizeof(name), "mic%d", cdev->index);
> - cdev->dbg_dir = debugfs_create_dir(name, cosm_dbg);
> -
> - debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev,
> - &log_buf_fops);
> - debugfs_create_file("force_reset", 0444, cdev->dbg_dir, cdev,
> - &force_reset_fops);
> -}
> -
> -void cosm_delete_debug_dir(struct cosm_device *cdev)
> -{
> - debugfs_remove_recursive(cdev->dbg_dir);
> -}
> -
> -void cosm_init_debugfs(void)
> -{
> - cosm_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
> -}
> -
> -void cosm_exit_debugfs(void)
> -{
> - debugfs_remove(cosm_dbg);
> -}
> diff --git a/drivers/misc/mic/cosm/cosm_main.c
> b/drivers/misc/mic/cosm/cosm_main.c
> deleted file mode 100644
> index ebb0eac43754..000000000000
> --- a/drivers/misc/mic/cosm/cosm_main.c
> +++ /dev/null
> @@ -1,382 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC Coprocessor State Management (COSM) Driver
> - */
> -
> -#include <linux/module.h>
> -#include <linux/delay.h>
> -#include <linux/idr.h>
> -#include <linux/slab.h>
> -#include <linux/cred.h>
> -#include "cosm_main.h"
> -
> -static const char cosm_driver_name[] = "mic";
> -
> -/* COSM ID allocator */
> -static struct ida g_cosm_ida;
> -/* Class of MIC devices for sysfs accessibility. */
> -static struct class *g_cosm_class;
> -/* Number of MIC devices */
> -static atomic_t g_num_dev;
> -
> -/**
> - * cosm_hw_reset - Issue a HW reset for the MIC device
> - * @cdev: pointer to cosm_device instance
> - * @force: force a MIC to reset even if it is already reset and ready
> - */
> -static void cosm_hw_reset(struct cosm_device *cdev, bool force)
> -{
> - int i;
> -
> -#define MIC_RESET_TO (45)
> - if (force && cdev->hw_ops->force_reset)
> - cdev->hw_ops->force_reset(cdev);
> - else
> - cdev->hw_ops->reset(cdev);
> -
> - for (i = 0; i < MIC_RESET_TO; i++) {
> - if (cdev->hw_ops->ready(cdev)) {
> - cosm_set_state(cdev, MIC_READY);
> - return;
> - }
> - /*
> - * Resets typically take 10s of seconds to complete.
> - * Since an MMIO read is required to check if the
> - * firmware is ready or not, a 1 second delay works nicely.
> - */
> - msleep(1000);
> - }
> - cosm_set_state(cdev, MIC_RESET_FAILED);
> -}
> -
> -/**
> - * cosm_start - Start the MIC
> - * @cdev: pointer to cosm_device instance
> - *
> - * This function prepares an MIC for boot and initiates boot.
> - * RETURNS: An appropriate -ERRNO error value on error, or 0 for success.
> - */
> -int cosm_start(struct cosm_device *cdev)
> -{
> - const struct cred *orig_cred;
> - struct cred *override_cred;
> - int rc;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - if (!cdev->bootmode) {
> - dev_err(&cdev->dev, "%s %d bootmode not set\n",
> - __func__, __LINE__);
> - rc = -EINVAL;
> - goto unlock_ret;
> - }
> -retry:
> - if (cdev->state != MIC_READY) {
> - dev_err(&cdev->dev, "%s %d MIC state not READY\n",
> - __func__, __LINE__);
> - rc = -EINVAL;
> - goto unlock_ret;
> - }
> - if (!cdev->hw_ops->ready(cdev)) {
> - cosm_hw_reset(cdev, false);
> - /*
> - * The state will either be MIC_READY if the reset succeeded
> - * or MIC_RESET_FAILED if the firmware reset failed.
> - */
> - goto retry;
> - }
> -
> - /*
> - * Set credentials to root to allow non-root user to download
> initramsfs
> - * with 600 permissions
> - */
> - override_cred = prepare_creds();
> - if (!override_cred) {
> - dev_err(&cdev->dev, "%s %d prepare_creds failed\n",
> - __func__, __LINE__);
> - rc = -ENOMEM;
> - goto unlock_ret;
> - }
> - override_cred->fsuid = GLOBAL_ROOT_UID;
> - orig_cred = override_creds(override_cred);
> -
> - rc = cdev->hw_ops->start(cdev, cdev->index);
> -
> - revert_creds(orig_cred);
> - put_cred(override_cred);
> - if (rc)
> - goto unlock_ret;
> -
> - /*
> - * If linux is being booted, card is treated 'online' only
> - * when the scif interface in the card is up. If anything else
> - * is booted, we set card to 'online' immediately.
> - */
> - if (!strcmp(cdev->bootmode, "linux"))
> - cosm_set_state(cdev, MIC_BOOTING);
> - else
> - cosm_set_state(cdev, MIC_ONLINE);
> -unlock_ret:
> - mutex_unlock(&cdev->cosm_mutex);
> - if (rc)
> - dev_err(&cdev->dev, "cosm_start failed rc %d\n", rc);
> - return rc;
> -}
> -
> -/**
> - * cosm_stop - Prepare the MIC for reset and trigger reset
> - * @cdev: pointer to cosm_device instance
> - * @force: force a MIC to reset even if it is already reset and ready.
> - *
> - * RETURNS: None
> - */
> -void cosm_stop(struct cosm_device *cdev, bool force)
> -{
> - mutex_lock(&cdev->cosm_mutex);
> - if (cdev->state != MIC_READY || force) {
> - /*
> - * Don't call hw_ops if they have been called previously.
> - * stop(..) calls device_unregister and will crash the system if
> - * called multiple times.
> - */
> - u8 state = cdev->state == MIC_RESETTING ?
> - cdev->prev_state : cdev->state;
> - bool call_hw_ops = state != MIC_RESET_FAILED &&
> - state != MIC_READY;
> -
> - if (cdev->state != MIC_RESETTING)
> - cosm_set_state(cdev, MIC_RESETTING);
> - cdev->heartbeat_watchdog_enable = false;
> - if (call_hw_ops)
> - cdev->hw_ops->stop(cdev, force);
> - cosm_hw_reset(cdev, force);
> - cosm_set_shutdown_status(cdev, MIC_NOP);
> - if (call_hw_ops && cdev->hw_ops->post_reset)
> - cdev->hw_ops->post_reset(cdev, cdev->state);
> - }
> - mutex_unlock(&cdev->cosm_mutex);
> - flush_work(&cdev->scif_work);
> -}
> -
> -/**
> - * cosm_reset_trigger_work - Trigger MIC reset
> - * @work: The work structure
> - *
> - * This work is scheduled whenever the host wants to reset the MIC.
> - */
> -static void cosm_reset_trigger_work(struct work_struct *work)
> -{
> - struct cosm_device *cdev = container_of(work, struct cosm_device,
> - reset_trigger_work);
> - cosm_stop(cdev, false);
> -}
> -
> -/**
> - * cosm_reset - Schedule MIC reset
> - * @cdev: pointer to cosm_device instance
> - *
> - * RETURNS: An -EINVAL if the card is already READY or 0 for success.
> - */
> -int cosm_reset(struct cosm_device *cdev)
> -{
> - int rc = 0;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - if (cdev->state != MIC_READY) {
> - if (cdev->state != MIC_RESETTING) {
> - cdev->prev_state = cdev->state;
> - cosm_set_state(cdev, MIC_RESETTING);
> - schedule_work(&cdev->reset_trigger_work);
> - }
> - } else {
> - dev_err(&cdev->dev, "%s %d MIC is READY\n", __func__,
> __LINE__);
> - rc = -EINVAL;
> - }
> - mutex_unlock(&cdev->cosm_mutex);
> - return rc;
> -}
> -
> -/**
> - * cosm_shutdown - Initiate MIC shutdown.
> - * @cdev: pointer to cosm_device instance
> - *
> - * RETURNS: None
> - */
> -int cosm_shutdown(struct cosm_device *cdev)
> -{
> - struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN };
> - int rc = 0;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - if (cdev->state != MIC_ONLINE) {
> - rc = -EINVAL;
> - dev_err(&cdev->dev, "%s %d skipping shutdown in
> state: %s\n",
> - __func__, __LINE__, cosm_state_string[cdev->state]);
> - goto err;
> - }
> -
> - if (!cdev->epd) {
> - rc = -ENOTCONN;
> - dev_err(&cdev->dev, "%s %d scif endpoint not connected
> rc %d\n",
> - __func__, __LINE__, rc);
> - goto err;
> - }
> -
> - rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
> - if (rc < 0) {
> - dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
> - __func__, __LINE__, rc);
> - goto err;
> - }
> - cdev->heartbeat_watchdog_enable = false;
> - cosm_set_state(cdev, MIC_SHUTTING_DOWN);
> - rc = 0;
> -err:
> - mutex_unlock(&cdev->cosm_mutex);
> - return rc;
> -}
> -
> -static int cosm_driver_probe(struct cosm_device *cdev)
> -{
> - int rc;
> -
> - /* Initialize SCIF server at first probe */
> - if (atomic_add_return(1, &g_num_dev) == 1) {
> - rc = cosm_scif_init();
> - if (rc)
> - goto scif_exit;
> - }
> - mutex_init(&cdev->cosm_mutex);
> - INIT_WORK(&cdev->reset_trigger_work, cosm_reset_trigger_work);
> - INIT_WORK(&cdev->scif_work, cosm_scif_work);
> - cdev->sysfs_heartbeat_enable = true;
> - cosm_sysfs_init(cdev);
> - cdev->sdev = device_create_with_groups(g_cosm_class, cdev-
> >dev.parent,
> - MKDEV(0, cdev->index), cdev, cdev->attr_group,
> - "mic%d", cdev->index);
> - if (IS_ERR(cdev->sdev)) {
> - rc = PTR_ERR(cdev->sdev);
> - dev_err(&cdev->dev, "device_create_with_groups failed
> rc %d\n",
> - rc);
> - goto scif_exit;
> - }
> -
> - cdev->state_sysfs = sysfs_get_dirent(cdev->sdev->kobj.sd,
> - "state");
> - if (!cdev->state_sysfs) {
> - rc = -ENODEV;
> - dev_err(&cdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
> - goto destroy_device;
> - }
> - cosm_create_debug_dir(cdev);
> - return 0;
> -destroy_device:
> - device_destroy(g_cosm_class, MKDEV(0, cdev->index));
> -scif_exit:
> - if (atomic_dec_and_test(&g_num_dev))
> - cosm_scif_exit();
> - return rc;
> -}
> -
> -static void cosm_driver_remove(struct cosm_device *cdev)
> -{
> - cosm_delete_debug_dir(cdev);
> - sysfs_put(cdev->state_sysfs);
> - device_destroy(g_cosm_class, MKDEV(0, cdev->index));
> - flush_work(&cdev->reset_trigger_work);
> - cosm_stop(cdev, false);
> - if (atomic_dec_and_test(&g_num_dev))
> - cosm_scif_exit();
> -
> - /* These sysfs entries might have allocated */
> - kfree(cdev->cmdline);
> - kfree(cdev->firmware);
> - kfree(cdev->ramdisk);
> - kfree(cdev->bootmode);
> -}
> -
> -static int cosm_suspend(struct device *dev)
> -{
> - struct cosm_device *cdev = dev_to_cosm(dev);
> -
> - mutex_lock(&cdev->cosm_mutex);
> - switch (cdev->state) {
> - /**
> - * Suspend/freeze hooks in userspace have already shutdown the
> card.
> - * Card should be 'ready' in most cases. It is however possible that
> - * some userspace application initiated a boot. In those cases, we
> - * simply reset the card.
> - */
> - case MIC_ONLINE:
> - case MIC_BOOTING:
> - case MIC_SHUTTING_DOWN:
> - mutex_unlock(&cdev->cosm_mutex);
> - cosm_stop(cdev, false);
> - break;
> - default:
> - mutex_unlock(&cdev->cosm_mutex);
> - break;
> - }
> - return 0;
> -}
> -
> -static const struct dev_pm_ops cosm_pm_ops = {
> - .suspend = cosm_suspend,
> - .freeze = cosm_suspend
> -};
> -
> -static struct cosm_driver cosm_driver = {
> - .driver = {
> - .name = KBUILD_MODNAME,
> - .owner = THIS_MODULE,
> - .pm = &cosm_pm_ops,
> - },
> - .probe = cosm_driver_probe,
> - .remove = cosm_driver_remove
> -};
> -
> -static int __init cosm_init(void)
> -{
> - int ret;
> -
> - cosm_init_debugfs();
> -
> - g_cosm_class = class_create(THIS_MODULE, cosm_driver_name);
> - if (IS_ERR(g_cosm_class)) {
> - ret = PTR_ERR(g_cosm_class);
> - pr_err("class_create failed ret %d\n", ret);
> - goto cleanup_debugfs;
> - }
> -
> - ida_init(&g_cosm_ida);
> - ret = cosm_register_driver(&cosm_driver);
> - if (ret) {
> - pr_err("cosm_register_driver failed ret %d\n", ret);
> - goto ida_destroy;
> - }
> - return 0;
> -ida_destroy:
> - ida_destroy(&g_cosm_ida);
> - class_destroy(g_cosm_class);
> -cleanup_debugfs:
> - cosm_exit_debugfs();
> - return ret;
> -}
> -
> -static void __exit cosm_exit(void)
> -{
> - cosm_unregister_driver(&cosm_driver);
> - ida_destroy(&g_cosm_ida);
> - class_destroy(g_cosm_class);
> - cosm_exit_debugfs();
> -}
> -
> -module_init(cosm_init);
> -module_exit(cosm_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC Coprocessor State Management
> (COSM) Driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/cosm/cosm_main.h
> b/drivers/misc/mic/cosm/cosm_main.h
> deleted file mode 100644
> index 5188ad245814..000000000000
> --- a/drivers/misc/mic/cosm/cosm_main.h
> +++ /dev/null
> @@ -1,61 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC Coprocessor State Management (COSM) Driver
> - */
> -#ifndef _COSM_COSM_H_
> -#define _COSM_COSM_H_
> -
> -#include <linux/scif.h>
> -#include "../bus/cosm_bus.h"
> -
> -#define COSM_HEARTBEAT_SEND_SEC 30
> -#define SCIF_COSM_LISTEN_PORT 201
> -
> -/**
> - * enum COSM msg id's
> - * @COSM_MSG_SHUTDOWN: host->card trigger shutdown
> - * @COSM_MSG_SYNC_TIME: host->card send host time to card to sync
> time
> - * @COSM_MSG_HEARTBEAT: card->host heartbeat
> - * @COSM_MSG_SHUTDOWN_STATUS: card->host with shutdown status as
> payload
> - */
> -enum cosm_msg_id {
> - COSM_MSG_SHUTDOWN,
> - COSM_MSG_SYNC_TIME,
> - COSM_MSG_HEARTBEAT,
> - COSM_MSG_SHUTDOWN_STATUS,
> -};
> -
> -struct cosm_msg {
> - u64 id;
> - union {
> - u64 shutdown_status;
> - struct {
> - u64 tv_sec;
> - u64 tv_nsec;
> - } timespec;
> - };
> -};
> -
> -extern const char * const cosm_state_string[];
> -extern const char * const cosm_shutdown_status_string[];
> -
> -void cosm_sysfs_init(struct cosm_device *cdev);
> -int cosm_start(struct cosm_device *cdev);
> -void cosm_stop(struct cosm_device *cdev, bool force);
> -int cosm_reset(struct cosm_device *cdev);
> -int cosm_shutdown(struct cosm_device *cdev);
> -void cosm_set_state(struct cosm_device *cdev, u8 state);
> -void cosm_set_shutdown_status(struct cosm_device *cdev, u8 status);
> -void cosm_init_debugfs(void);
> -void cosm_exit_debugfs(void);
> -void cosm_create_debug_dir(struct cosm_device *cdev);
> -void cosm_delete_debug_dir(struct cosm_device *cdev);
> -int cosm_scif_init(void);
> -void cosm_scif_exit(void);
> -void cosm_scif_work(struct work_struct *work);
> -
> -#endif
> diff --git a/drivers/misc/mic/cosm/cosm_scif_server.c
> b/drivers/misc/mic/cosm/cosm_scif_server.c
> deleted file mode 100644
> index 7baec9fd8756..000000000000
> --- a/drivers/misc/mic/cosm/cosm_scif_server.c
> +++ /dev/null
> @@ -1,399 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC Coprocessor State Management (COSM) Driver
> - */
> -#include <linux/kthread.h>
> -#include <linux/sched/signal.h>
> -
> -#include "cosm_main.h"
> -
> -/*
> - * The COSM driver uses SCIF to communicate between the management
> node and the
> - * MIC cards. SCIF is used to (a) Send a shutdown command to the card (b)
> - * receive a shutdown status back from the card upon completion of
> shutdown and
> - * (c) receive periodic heartbeat messages from the card used to deduce if
> the
> - * card has crashed.
> - *
> - * A COSM server consisting of a SCIF listening endpoint waits for incoming
> - * connections from the card. Upon acceptance of the connection, a
> separate
> - * work-item is scheduled to handle SCIF message processing for that card.
> The
> - * life-time of this work-item is therefore the time from which the
> connection
> - * from a card is accepted to the time at which the connection is closed. A
> new
> - * work-item starts each time the card boots and is alive till the card (a)
> - * shuts down (b) is reset (c) crashes (d) cosm_client driver on the card is
> - * unloaded.
> - *
> - * From the point of view of COSM interactions with SCIF during card
> - * shutdown, reset and crash are as follows:
> - *
> - * Card shutdown
> - * -------------
> - * 1. COSM client on the card invokes orderly_poweroff() in response to
> SHUTDOWN
> - * message from the host.
> - * 2. Card driver shutdown callback invokes scif_unregister_device(..)
> resulting
> - * in scif_remove(..) getting called on the card
> - * 3. scif_remove -> scif_stop -> scif_handle_remove_node ->
> - * scif_peer_unregister_device -> device_unregister for the host peer
> device
> - * 4. During device_unregister remove(..) method of cosm_client is invoked
> which
> - * closes the COSM SCIF endpoint on the card. This results in a
> SCIF_DISCNCT
> - * message being sent to host SCIF. SCIF_DISCNCT message processing on
> the
> - * host SCIF sets the host COSM SCIF endpoint state to DISCONNECTED and
> wakes
> - * up the host COSM thread blocked in scif_poll(..) resulting in
> - * scif_poll(..) returning EPOLLHUP.
> - * 5. On the card, scif_peer_release_dev is next called which results in an
> - * SCIF_EXIT message being sent to the host and after receiving the
> - * SCIF_EXIT_ACK from the host the peer device teardown on the card is
> - * complete.
> - * 6. As part of the SCIF_EXIT message processing on the host, host sends a
> - * SCIF_REMOVE_NODE to itself corresponding to the card being removed.
> This
> - * starts a similar SCIF peer device teardown sequence on the host
> - * corresponding to the card being shut down.
> - *
> - * Card reset
> - * ----------
> - * The case of interest here is when the card has not been previously shut
> down
> - * since most of the steps below are skipped in that case:
> -
> - * 1. cosm_stop(..) invokes hw_ops->stop(..) method of the base PCIe driver
> - * which unregisters the SCIF HW device resulting in scif_remove(..) being
> - * called on the host.
> - * 2. scif_remove(..) calls scif_disconnect_node(..) which results in a
> - * SCIF_EXIT message being sent to the card.
> - * 3. The card executes scif_stop() as part of SCIF_EXIT message
> - * processing. This results in the COSM endpoint on the card being closed
> and
> - * the SCIF host peer device on the card getting unregistered similar to
> - * steps 3, 4 and 5 for the card shutdown case above. scif_poll(..) on the
> - * host returns EPOLLHUP as a result.
> - * 4. On the host, card peer device unregister and SCIF HW remove(..) also
> - * subsequently complete.
> - *
> - * Card crash
> - * ----------
> - * If a reset is issued after the card has crashed, there is no SCIF_DISCNT
> - * message from the card which would result in scif_poll(..) returning
> - * EPOLLHUP. In this case when the host SCIF driver sends a
> SCIF_REMOVE_NODE
> - * message to itself resulting in the card SCIF peer device being unregistered,
> - * this results in a scif_peer_release_dev -> scif_cleanup_scifdev->
> - * scif_invalidate_ep call sequence which sets the endpoint state to
> - * DISCONNECTED and results in scif_poll(..) returning EPOLLHUP.
> - */
> -
> -#define COSM_SCIF_BACKLOG 16
> -#define COSM_HEARTBEAT_CHECK_DELTA_SEC 10
> -#define COSM_HEARTBEAT_TIMEOUT_SEC \
> - (COSM_HEARTBEAT_SEND_SEC +
> COSM_HEARTBEAT_CHECK_DELTA_SEC)
> -#define COSM_HEARTBEAT_TIMEOUT_MSEC
> (COSM_HEARTBEAT_TIMEOUT_SEC * MSEC_PER_SEC)
> -
> -static struct task_struct *server_thread;
> -static scif_epd_t listen_epd;
> -
> -/* Publish MIC card's shutdown status to user space MIC daemon */
> -static void cosm_update_mic_status(struct cosm_device *cdev)
> -{
> - if (cdev->shutdown_status_int != MIC_NOP) {
> - cosm_set_shutdown_status(cdev, cdev-
> >shutdown_status_int);
> - cdev->shutdown_status_int = MIC_NOP;
> - }
> -}
> -
> -/* Store MIC card's shutdown status internally when it is received */
> -static void cosm_shutdown_status_int(struct cosm_device *cdev,
> - enum mic_status shutdown_status)
> -{
> - switch (shutdown_status) {
> - case MIC_HALTED:
> - case MIC_POWER_OFF:
> - case MIC_RESTART:
> - case MIC_CRASHED:
> - break;
> - default:
> - dev_err(&cdev->dev, "%s %d Unexpected
> shutdown_status %d\n",
> - __func__, __LINE__, shutdown_status);
> - return;
> - };
> - cdev->shutdown_status_int = shutdown_status;
> - cdev->heartbeat_watchdog_enable = false;
> -
> - if (cdev->state != MIC_SHUTTING_DOWN)
> - cosm_set_state(cdev, MIC_SHUTTING_DOWN);
> -}
> -
> -/* Non-blocking recv. Read and process all available messages */
> -static void cosm_scif_recv(struct cosm_device *cdev)
> -{
> - struct cosm_msg msg;
> - int rc;
> -
> - while (1) {
> - rc = scif_recv(cdev->epd, &msg, sizeof(msg), 0);
> - if (!rc) {
> - break;
> - } else if (rc < 0) {
> - dev_dbg(&cdev->dev, "%s: %d rc %d\n",
> - __func__, __LINE__, rc);
> - break;
> - }
> - dev_dbg(&cdev->dev, "%s: %d rc %d id 0x%llx\n",
> - __func__, __LINE__, rc, msg.id);
> -
> - switch (msg.id) {
> - case COSM_MSG_SHUTDOWN_STATUS:
> - cosm_shutdown_status_int(cdev,
> msg.shutdown_status);
> - break;
> - case COSM_MSG_HEARTBEAT:
> - /* Nothing to do, heartbeat only unblocks scif_poll */
> - break;
> - default:
> - dev_err(&cdev->dev, "%s: %d unknown
> msg.id %lld\n",
> - __func__, __LINE__, msg.id);
> - break;
> - }
> - }
> -}
> -
> -/* Publish crashed status for this MIC card */
> -static void cosm_set_crashed(struct cosm_device *cdev)
> -{
> - dev_err(&cdev->dev, "node alive timeout\n");
> - cosm_shutdown_status_int(cdev, MIC_CRASHED);
> - cosm_update_mic_status(cdev);
> -}
> -
> -/* Send host time to the MIC card to sync system time between host and
> MIC */
> -static void cosm_send_time(struct cosm_device *cdev)
> -{
> - struct cosm_msg msg = { .id = COSM_MSG_SYNC_TIME };
> - struct timespec64 ts;
> - int rc;
> -
> - ktime_get_real_ts64(&ts);
> - msg.timespec.tv_sec = ts.tv_sec;
> - msg.timespec.tv_nsec = ts.tv_nsec;
> -
> - rc = scif_send(cdev->epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
> - if (rc < 0)
> - dev_err(&cdev->dev, "%s %d scif_send failed rc %d\n",
> - __func__, __LINE__, rc);
> -}
> -
> -/*
> - * Close this cosm_device's endpoint after its peer endpoint on the card has
> - * been closed. In all cases except MIC card crash EPOLLHUP on the host is
> - * triggered by the client's endpoint being closed.
> - */
> -static void cosm_scif_close(struct cosm_device *cdev)
> -{
> - /*
> - * Because SHUTDOWN_STATUS message is sent by the MIC cards in
> the
> - * reboot notifier when shutdown is still not complete, we notify
> mpssd
> - * to reset the card when SCIF endpoint is closed.
> - */
> - cosm_update_mic_status(cdev);
> - scif_close(cdev->epd);
> - cdev->epd = NULL;
> - dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
> -}
> -
> -/*
> - * Set card state to ONLINE when a new SCIF connection from a MIC card is
> - * received. Normally the state is BOOTING when the connection comes in,
> but can
> - * be ONLINE if cosm_client driver on the card was unloaded and then
> reloaded.
> - */
> -static int cosm_set_online(struct cosm_device *cdev)
> -{
> - int rc = 0;
> -
> - if (MIC_BOOTING == cdev->state || MIC_ONLINE == cdev->state) {
> - cdev->heartbeat_watchdog_enable = cdev-
> >sysfs_heartbeat_enable;
> - cdev->epd = cdev->newepd;
> - if (cdev->state == MIC_BOOTING)
> - cosm_set_state(cdev, MIC_ONLINE);
> - cosm_send_time(cdev);
> - dev_dbg(&cdev->dev, "%s %d\n", __func__, __LINE__);
> - } else {
> - dev_warn(&cdev->dev, "%s %d not going online in
> state: %s\n",
> - __func__, __LINE__, cosm_state_string[cdev->state]);
> - rc = -EINVAL;
> - }
> - /* Drop reference acquired by bus_find_device in the server thread
> */
> - put_device(&cdev->dev);
> - return rc;
> -}
> -
> -/*
> - * Work function for handling work for a SCIF connection from a particular
> MIC
> - * card. It first sets the card state to ONLINE and then calls scif_poll to
> - * block on activity such as incoming messages on the SCIF endpoint. When
> the
> - * endpoint is closed, the work function exits, completing its life cycle, from
> - * MIC card boot to card shutdown/reset/crash.
> - */
> -void cosm_scif_work(struct work_struct *work)
> -{
> - struct cosm_device *cdev = container_of(work, struct cosm_device,
> - scif_work);
> - struct scif_pollepd pollepd;
> - int rc;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - if (cosm_set_online(cdev))
> - goto exit;
> -
> - while (1) {
> - pollepd.epd = cdev->epd;
> - pollepd.events = EPOLLIN;
> -
> - /* Drop the mutex before blocking in scif_poll(..) */
> - mutex_unlock(&cdev->cosm_mutex);
> - /* poll(..) with timeout on our endpoint */
> - rc = scif_poll(&pollepd, 1,
> COSM_HEARTBEAT_TIMEOUT_MSEC);
> - mutex_lock(&cdev->cosm_mutex);
> - if (rc < 0) {
> - dev_err(&cdev->dev, "%s %d scif_poll rc %d\n",
> - __func__, __LINE__, rc);
> - continue;
> - }
> -
> - /* There is a message from the card */
> - if (pollepd.revents & EPOLLIN)
> - cosm_scif_recv(cdev);
> -
> - /* The peer endpoint is closed or this endpoint disconnected
> */
> - if (pollepd.revents & EPOLLHUP) {
> - cosm_scif_close(cdev);
> - break;
> - }
> -
> - /* Did we timeout from poll? */
> - if (!rc && cdev->heartbeat_watchdog_enable)
> - cosm_set_crashed(cdev);
> - }
> -exit:
> - dev_dbg(&cdev->dev, "%s %d exiting\n", __func__, __LINE__);
> - mutex_unlock(&cdev->cosm_mutex);
> -}
> -
> -/*
> - * COSM SCIF server thread function. Accepts incoming SCIF connections
> from MIC
> - * cards, finds the correct cosm_device to associate that connection with and
> - * schedules individual work items for each MIC card.
> - */
> -static int cosm_scif_server(void *unused)
> -{
> - struct cosm_device *cdev;
> - scif_epd_t newepd;
> - struct scif_port_id port_id;
> - int rc;
> -
> - allow_signal(SIGKILL);
> -
> - while (!kthread_should_stop()) {
> - rc = scif_accept(listen_epd, &port_id, &newepd,
> - SCIF_ACCEPT_SYNC);
> - if (rc < 0) {
> - if (-ERESTARTSYS != rc)
> - pr_err("%s %d rc %d\n", __func__, __LINE__,
> rc);
> - continue;
> - }
> -
> - /*
> - * Associate the incoming connection with a particular
> - * cosm_device, COSM device ID == SCIF node ID - 1
> - */
> - cdev = cosm_find_cdev_by_id(port_id.node - 1);
> - if (!cdev)
> - continue;
> - cdev->newepd = newepd;
> - schedule_work(&cdev->scif_work);
> - }
> -
> - pr_debug("%s %d Server thread stopped\n", __func__, __LINE__);
> - return 0;
> -}
> -
> -static int cosm_scif_listen(void)
> -{
> - int rc;
> -
> - listen_epd = scif_open();
> - if (!listen_epd) {
> - pr_err("%s %d scif_open failed\n", __func__, __LINE__);
> - return -ENOMEM;
> - }
> -
> - rc = scif_bind(listen_epd, SCIF_COSM_LISTEN_PORT);
> - if (rc < 0) {
> - pr_err("%s %d scif_bind failed rc %d\n",
> - __func__, __LINE__, rc);
> - goto err;
> - }
> -
> - rc = scif_listen(listen_epd, COSM_SCIF_BACKLOG);
> - if (rc < 0) {
> - pr_err("%s %d scif_listen rc %d\n", __func__, __LINE__, rc);
> - goto err;
> - }
> - pr_debug("%s %d listen_epd set up\n", __func__, __LINE__);
> - return 0;
> -err:
> - scif_close(listen_epd);
> - listen_epd = NULL;
> - return rc;
> -}
> -
> -static void cosm_scif_listen_exit(void)
> -{
> - pr_debug("%s %d closing listen_epd\n", __func__, __LINE__);
> - if (listen_epd) {
> - scif_close(listen_epd);
> - listen_epd = NULL;
> - }
> -}
> -
> -/*
> - * Create a listening SCIF endpoint and a server kthread which accepts
> incoming
> - * SCIF connections from MIC cards
> - */
> -int cosm_scif_init(void)
> -{
> - int rc = cosm_scif_listen();
> -
> - if (rc) {
> - pr_err("%s %d cosm_scif_listen rc %d\n",
> - __func__, __LINE__, rc);
> - goto err;
> - }
> -
> - server_thread = kthread_run(cosm_scif_server, NULL,
> "cosm_server");
> - if (IS_ERR(server_thread)) {
> - rc = PTR_ERR(server_thread);
> - pr_err("%s %d kthread_run rc %d\n", __func__, __LINE__, rc);
> - goto listen_exit;
> - }
> - return 0;
> -listen_exit:
> - cosm_scif_listen_exit();
> -err:
> - return rc;
> -}
> -
> -/* Stop the running server thread and close the listening SCIF endpoint */
> -void cosm_scif_exit(void)
> -{
> - int rc;
> -
> - if (!IS_ERR_OR_NULL(server_thread)) {
> - rc = send_sig(SIGKILL, server_thread, 0);
> - if (rc) {
> - pr_err("%s %d send_sig rc %d\n",
> - __func__, __LINE__, rc);
> - return;
> - }
> - kthread_stop(server_thread);
> - }
> -
> - cosm_scif_listen_exit();
> -}
> diff --git a/drivers/misc/mic/cosm/cosm_sysfs.c
> b/drivers/misc/mic/cosm/cosm_sysfs.c
> deleted file mode 100644
> index e6dac967c1af..000000000000
> --- a/drivers/misc/mic/cosm/cosm_sysfs.c
> +++ /dev/null
> @@ -1,449 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC Coprocessor State Management (COSM) Driver
> - */
> -#include <linux/slab.h>
> -#include "cosm_main.h"
> -
> -/*
> - * A state-to-string lookup table, for exposing a human readable state
> - * via sysfs. Always keep in sync with enum cosm_states
> - */
> -const char * const cosm_state_string[] = {
> - [MIC_READY] = "ready",
> - [MIC_BOOTING] = "booting",
> - [MIC_ONLINE] = "online",
> - [MIC_SHUTTING_DOWN] = "shutting_down",
> - [MIC_RESETTING] = "resetting",
> - [MIC_RESET_FAILED] = "reset_failed",
> -};
> -
> -/*
> - * A shutdown-status-to-string lookup table, for exposing a human
> - * readable state via sysfs. Always keep in sync with enum
> cosm_shutdown_status
> - */
> -const char * const cosm_shutdown_status_string[] = {
> - [MIC_NOP] = "nop",
> - [MIC_CRASHED] = "crashed",
> - [MIC_HALTED] = "halted",
> - [MIC_POWER_OFF] = "poweroff",
> - [MIC_RESTART] = "restart",
> -};
> -
> -void cosm_set_shutdown_status(struct cosm_device *cdev, u8
> shutdown_status)
> -{
> - dev_dbg(&cdev->dev, "Shutdown Status %s -> %s\n",
> - cosm_shutdown_status_string[cdev->shutdown_status],
> - cosm_shutdown_status_string[shutdown_status]);
> - cdev->shutdown_status = shutdown_status;
> -}
> -
> -void cosm_set_state(struct cosm_device *cdev, u8 state)
> -{
> - dev_dbg(&cdev->dev, "State %s -> %s\n",
> - cosm_state_string[cdev->state],
> - cosm_state_string[state]);
> - cdev->state = state;
> - sysfs_notify_dirent(cdev->state_sysfs);
> -}
> -
> -static ssize_t
> -family_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - return cdev->hw_ops->family(cdev, buf);
> -}
> -static DEVICE_ATTR_RO(family);
> -
> -static ssize_t
> -stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - return cdev->hw_ops->stepping(cdev, buf);
> -}
> -static DEVICE_ATTR_RO(stepping);
> -
> -static ssize_t
> -state_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev || cdev->state >= MIC_LAST)
> - return -EINVAL;
> -
> - return scnprintf(buf, PAGE_SIZE, "%s\n",
> - cosm_state_string[cdev->state]);
> -}
> -
> -static ssize_t
> -state_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - int rc;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - if (sysfs_streq(buf, "boot")) {
> - rc = cosm_start(cdev);
> - goto done;
> - }
> - if (sysfs_streq(buf, "reset")) {
> - rc = cosm_reset(cdev);
> - goto done;
> - }
> -
> - if (sysfs_streq(buf, "shutdown")) {
> - rc = cosm_shutdown(cdev);
> - goto done;
> - }
> - rc = -EINVAL;
> -done:
> - if (rc)
> - count = rc;
> - return count;
> -}
> -static DEVICE_ATTR_RW(state);
> -
> -static ssize_t shutdown_status_show(struct device *dev,
> - struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev || cdev->shutdown_status >= MIC_STATUS_LAST)
> - return -EINVAL;
> -
> - return scnprintf(buf, PAGE_SIZE, "%s\n",
> - cosm_shutdown_status_string[cdev->shutdown_status]);
> -}
> -static DEVICE_ATTR_RO(shutdown_status);
> -
> -static ssize_t
> -heartbeat_enable_show(struct device *dev,
> - struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - return scnprintf(buf, PAGE_SIZE, "%d\n", cdev-
> >sysfs_heartbeat_enable);
> -}
> -
> -static ssize_t
> -heartbeat_enable_store(struct device *dev,
> - struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - int enable;
> - int ret;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - ret = kstrtoint(buf, 10, &enable);
> - if (ret)
> - goto unlock;
> -
> - cdev->sysfs_heartbeat_enable = enable;
> - /* if state is not online, cdev->heartbeat_watchdog_enable is 0 */
> - if (cdev->state == MIC_ONLINE)
> - cdev->heartbeat_watchdog_enable = enable;
> - ret = count;
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> - return ret;
> -}
> -static DEVICE_ATTR_RW(heartbeat_enable);
> -
> -static ssize_t
> -cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - char *cmdline;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - cmdline = cdev->cmdline;
> -
> - if (cmdline)
> - return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
> - return 0;
> -}
> -
> -static ssize_t
> -cmdline_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - kfree(cdev->cmdline);
> -
> - cdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
> - if (!cdev->cmdline) {
> - count = -ENOMEM;
> - goto unlock;
> - }
> -
> - strncpy(cdev->cmdline, buf, count);
> -
> - if (cdev->cmdline[count - 1] == '\n')
> - cdev->cmdline[count - 1] = '\0';
> - else
> - cdev->cmdline[count] = '\0';
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> - return count;
> -}
> -static DEVICE_ATTR_RW(cmdline);
> -
> -static ssize_t
> -firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - char *firmware;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - firmware = cdev->firmware;
> -
> - if (firmware)
> - return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
> - return 0;
> -}
> -
> -static ssize_t
> -firmware_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - kfree(cdev->firmware);
> -
> - cdev->firmware = kmalloc(count + 1, GFP_KERNEL);
> - if (!cdev->firmware) {
> - count = -ENOMEM;
> - goto unlock;
> - }
> - strncpy(cdev->firmware, buf, count);
> -
> - if (cdev->firmware[count - 1] == '\n')
> - cdev->firmware[count - 1] = '\0';
> - else
> - cdev->firmware[count] = '\0';
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> - return count;
> -}
> -static DEVICE_ATTR_RW(firmware);
> -
> -static ssize_t
> -ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - char *ramdisk;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - ramdisk = cdev->ramdisk;
> -
> - if (ramdisk)
> - return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
> - return 0;
> -}
> -
> -static ssize_t
> -ramdisk_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - kfree(cdev->ramdisk);
> -
> - cdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
> - if (!cdev->ramdisk) {
> - count = -ENOMEM;
> - goto unlock;
> - }
> -
> - strncpy(cdev->ramdisk, buf, count);
> -
> - if (cdev->ramdisk[count - 1] == '\n')
> - cdev->ramdisk[count - 1] = '\0';
> - else
> - cdev->ramdisk[count] = '\0';
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> - return count;
> -}
> -static DEVICE_ATTR_RW(ramdisk);
> -
> -static ssize_t
> -bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - char *bootmode;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - bootmode = cdev->bootmode;
> -
> - if (bootmode)
> - return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
> - return 0;
> -}
> -
> -static ssize_t
> -bootmode_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "flash"))
> - return -EINVAL;
> -
> - mutex_lock(&cdev->cosm_mutex);
> - kfree(cdev->bootmode);
> -
> - cdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
> - if (!cdev->bootmode) {
> - count = -ENOMEM;
> - goto unlock;
> - }
> -
> - strncpy(cdev->bootmode, buf, count);
> -
> - if (cdev->bootmode[count - 1] == '\n')
> - cdev->bootmode[count - 1] = '\0';
> - else
> - cdev->bootmode[count] = '\0';
> -unlock:
> - mutex_unlock(&cdev->cosm_mutex);
> - return count;
> -}
> -static DEVICE_ATTR_RW(bootmode);
> -
> -static ssize_t
> -log_buf_addr_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_addr);
> -}
> -
> -static ssize_t
> -log_buf_addr_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - int ret;
> - unsigned long addr;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - ret = kstrtoul(buf, 16, &addr);
> - if (ret)
> - goto exit;
> -
> - cdev->log_buf_addr = (void *)addr;
> - ret = count;
> -exit:
> - return ret;
> -}
> -static DEVICE_ATTR_RW(log_buf_addr);
> -
> -static ssize_t
> -log_buf_len_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - return scnprintf(buf, PAGE_SIZE, "%p\n", cdev->log_buf_len);
> -}
> -
> -static ssize_t
> -log_buf_len_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> -{
> - struct cosm_device *cdev = dev_get_drvdata(dev);
> - int ret;
> - unsigned long addr;
> -
> - if (!cdev)
> - return -EINVAL;
> -
> - ret = kstrtoul(buf, 16, &addr);
> - if (ret)
> - goto exit;
> -
> - cdev->log_buf_len = (int *)addr;
> - ret = count;
> -exit:
> - return ret;
> -}
> -static DEVICE_ATTR_RW(log_buf_len);
> -
> -static struct attribute *cosm_default_attrs[] = {
> - &dev_attr_family.attr,
> - &dev_attr_stepping.attr,
> - &dev_attr_state.attr,
> - &dev_attr_shutdown_status.attr,
> - &dev_attr_heartbeat_enable.attr,
> - &dev_attr_cmdline.attr,
> - &dev_attr_firmware.attr,
> - &dev_attr_ramdisk.attr,
> - &dev_attr_bootmode.attr,
> - &dev_attr_log_buf_addr.attr,
> - &dev_attr_log_buf_len.attr,
> -
> - NULL
> -};
> -
> -ATTRIBUTE_GROUPS(cosm_default);
> -
> -void cosm_sysfs_init(struct cosm_device *cdev)
> -{
> - cdev->attr_group = cosm_default_groups;
> -}
> diff --git a/drivers/misc/mic/cosm_client/Makefile
> b/drivers/misc/mic/cosm_client/Makefile
> deleted file mode 100644
> index 5b62270bc2ab..000000000000
> --- a/drivers/misc/mic/cosm_client/Makefile
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -# Makefile - Intel MIC COSM Client Driver
> -# Copyright(c) 2015, Intel Corporation.
> -#
> -obj-$(CONFIG_MIC_COSM) += cosm_client.o
> -
> -cosm_client-objs += cosm_scif_client.o
> diff --git a/drivers/misc/mic/cosm_client/cosm_scif_client.c
> b/drivers/misc/mic/cosm_client/cosm_scif_client.c
> deleted file mode 100644
> index a03213dd9319..000000000000
> --- a/drivers/misc/mic/cosm_client/cosm_scif_client.c
> +++ /dev/null
> @@ -1,269 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel MIC COSM Client Driver
> - */
> -#include <linux/module.h>
> -#include <linux/delay.h>
> -#include <linux/reboot.h>
> -#include <linux/kthread.h>
> -#include <linux/sched/signal.h>
> -
> -#include "../cosm/cosm_main.h"
> -
> -#define COSM_SCIF_MAX_RETRIES 10
> -#define COSM_HEARTBEAT_SEND_MSEC (COSM_HEARTBEAT_SEND_SEC *
> MSEC_PER_SEC)
> -
> -static struct task_struct *client_thread;
> -static scif_epd_t client_epd;
> -static struct scif_peer_dev *client_spdev;
> -
> -/*
> - * Reboot notifier: receives shutdown status from the OS and communicates
> it
> - * back to the COSM process on the host
> - */
> -static int cosm_reboot_event(struct notifier_block *this, unsigned long event,
> - void *ptr)
> -{
> - struct cosm_msg msg = { .id = COSM_MSG_SHUTDOWN_STATUS };
> - int rc;
> -
> - event = (event == SYS_RESTART) ? SYSTEM_RESTART : event;
> - dev_info(&client_spdev->dev, "%s %d received event %ld\n",
> - __func__, __LINE__, event);
> -
> - msg.shutdown_status = event;
> - rc = scif_send(client_epd, &msg, sizeof(msg), SCIF_SEND_BLOCK);
> - if (rc < 0)
> - dev_err(&client_spdev->dev, "%s %d scif_send rc %d\n",
> - __func__, __LINE__, rc);
> -
> - return NOTIFY_DONE;
> -}
> -
> -static struct notifier_block cosm_reboot = {
> - .notifier_call = cosm_reboot_event,
> -};
> -
> -/* Set system time from timespec value received from the host */
> -static void cosm_set_time(struct cosm_msg *msg)
> -{
> - struct timespec64 ts = {
> - .tv_sec = msg->timespec.tv_sec,
> - .tv_nsec = msg->timespec.tv_nsec,
> - };
> - int rc = do_settimeofday64(&ts);
> -
> - if (rc)
> - dev_err(&client_spdev->dev, "%s: %d settimeofday rc %d\n",
> - __func__, __LINE__, rc);
> -}
> -
> -/* COSM client receive message processing */
> -static void cosm_client_recv(void)
> -{
> - struct cosm_msg msg;
> - int rc;
> -
> - while (1) {
> - rc = scif_recv(client_epd, &msg, sizeof(msg), 0);
> - if (!rc) {
> - return;
> - } else if (rc < 0) {
> - dev_err(&client_spdev->dev, "%s: %d rc %d\n",
> - __func__, __LINE__, rc);
> - return;
> - }
> -
> - dev_dbg(&client_spdev->dev, "%s: %d rc %d id 0x%llx\n",
> - __func__, __LINE__, rc, msg.id);
> -
> - switch (msg.id) {
> - case COSM_MSG_SYNC_TIME:
> - cosm_set_time(&msg);
> - break;
> - case COSM_MSG_SHUTDOWN:
> - orderly_poweroff(true);
> - break;
> - default:
> - dev_err(&client_spdev->dev, "%s: %d unknown
> id %lld\n",
> - __func__, __LINE__, msg.id);
> - break;
> - }
> - }
> -}
> -
> -/* Initiate connection to the COSM server on the host */
> -static int cosm_scif_connect(void)
> -{
> - struct scif_port_id port_id;
> - int i, rc;
> -
> - client_epd = scif_open();
> - if (!client_epd) {
> - dev_err(&client_spdev->dev, "%s %d scif_open failed\n",
> - __func__, __LINE__);
> - return -ENOMEM;
> - }
> -
> - port_id.node = 0;
> - port_id.port = SCIF_COSM_LISTEN_PORT;
> -
> - for (i = 0; i < COSM_SCIF_MAX_RETRIES; i++) {
> - rc = scif_connect(client_epd, &port_id);
> - if (rc < 0)
> - msleep(1000);
> - else
> - break;
> - }
> -
> - if (rc < 0) {
> - dev_err(&client_spdev->dev, "%s %d scif_connect rc %d\n",
> - __func__, __LINE__, rc);
> - scif_close(client_epd);
> - client_epd = NULL;
> - }
> - return rc < 0 ? rc : 0;
> -}
> -
> -/* Close host SCIF connection */
> -static void cosm_scif_connect_exit(void)
> -{
> - if (client_epd) {
> - scif_close(client_epd);
> - client_epd = NULL;
> - }
> -}
> -
> -/*
> - * COSM SCIF client thread function: waits for messages from the host and
> sends
> - * a heartbeat to the host
> - */
> -static int cosm_scif_client(void *unused)
> -{
> - struct cosm_msg msg = { .id = COSM_MSG_HEARTBEAT };
> - struct scif_pollepd pollepd;
> - int rc;
> -
> - allow_signal(SIGKILL);
> -
> - while (!kthread_should_stop()) {
> - pollepd.epd = client_epd;
> - pollepd.events = EPOLLIN;
> -
> - rc = scif_poll(&pollepd, 1, COSM_HEARTBEAT_SEND_MSEC);
> - if (rc < 0) {
> - if (-EINTR != rc)
> - dev_err(&client_spdev->dev,
> - "%s %d scif_poll rc %d\n",
> - __func__, __LINE__, rc);
> - continue;
> - }
> -
> - if (pollepd.revents & EPOLLIN)
> - cosm_client_recv();
> -
> - msg.id = COSM_MSG_HEARTBEAT;
> - rc = scif_send(client_epd, &msg, sizeof(msg),
> SCIF_SEND_BLOCK);
> - if (rc < 0)
> - dev_err(&client_spdev->dev, "%s %d scif_send
> rc %d\n",
> - __func__, __LINE__, rc);
> - }
> -
> - dev_dbg(&client_spdev->dev, "%s %d Client thread stopped\n",
> - __func__, __LINE__);
> - return 0;
> -}
> -
> -static void cosm_scif_probe(struct scif_peer_dev *spdev)
> -{
> - int rc;
> -
> - dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
> - __func__, __LINE__, spdev->dnode);
> -
> - /* We are only interested in the host with spdev->dnode == 0 */
> - if (spdev->dnode)
> - return;
> -
> - client_spdev = spdev;
> - rc = cosm_scif_connect();
> - if (rc)
> - goto exit;
> -
> - rc = register_reboot_notifier(&cosm_reboot);
> - if (rc) {
> - dev_err(&spdev->dev,
> - "reboot notifier registration failed rc %d\n", rc);
> - goto connect_exit;
> - }
> -
> - client_thread = kthread_run(cosm_scif_client, NULL, "cosm_client");
> - if (IS_ERR(client_thread)) {
> - rc = PTR_ERR(client_thread);
> - dev_err(&spdev->dev, "%s %d kthread_run rc %d\n",
> - __func__, __LINE__, rc);
> - goto unreg_reboot;
> - }
> - return;
> -unreg_reboot:
> - unregister_reboot_notifier(&cosm_reboot);
> -connect_exit:
> - cosm_scif_connect_exit();
> -exit:
> - client_spdev = NULL;
> -}
> -
> -static void cosm_scif_remove(struct scif_peer_dev *spdev)
> -{
> - int rc;
> -
> - dev_dbg(&spdev->dev, "%s %d: dnode %d\n",
> - __func__, __LINE__, spdev->dnode);
> -
> - if (spdev->dnode)
> - return;
> -
> - if (!IS_ERR_OR_NULL(client_thread)) {
> - rc = send_sig(SIGKILL, client_thread, 0);
> - if (rc) {
> - pr_err("%s %d send_sig rc %d\n",
> - __func__, __LINE__, rc);
> - return;
> - }
> - kthread_stop(client_thread);
> - }
> - unregister_reboot_notifier(&cosm_reboot);
> - cosm_scif_connect_exit();
> - client_spdev = NULL;
> -}
> -
> -static struct scif_client scif_client_cosm = {
> - .name = KBUILD_MODNAME,
> - .probe = cosm_scif_probe,
> - .remove = cosm_scif_remove,
> -};
> -
> -static int __init cosm_client_init(void)
> -{
> - int rc = scif_client_register(&scif_client_cosm);
> -
> - if (rc)
> - pr_err("scif_client_register failed rc %d\n", rc);
> - return rc;
> -}
> -
> -static void __exit cosm_client_exit(void)
> -{
> - scif_client_unregister(&scif_client_cosm);
> -}
> -
> -module_init(cosm_client_init);
> -module_exit(cosm_client_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC card OS state management client
> driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
> deleted file mode 100644
> index 25f153367980..000000000000
> --- a/drivers/misc/mic/host/Makefile
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -#
> -# Makefile - Intel MIC Linux driver.
> -# Copyright(c) 2013, Intel Corporation.
> -#
> -obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
> -mic_host-objs := mic_main.o
> -mic_host-objs += mic_x100.o
> -mic_host-objs += mic_smpt.o
> -mic_host-objs += mic_intr.o
> -mic_host-objs += mic_boot.o
> -mic_host-objs += mic_debugfs.o
> diff --git a/drivers/misc/mic/host/mic_boot.c
> b/drivers/misc/mic/host/mic_boot.c
> deleted file mode 100644
> index 8cb85b8b3e19..000000000000
> --- a/drivers/misc/mic/host/mic_boot.c
> +++ /dev/null
> @@ -1,588 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/delay.h>
> -#include <linux/firmware.h>
> -#include <linux/pci.h>
> -#include <linux/kmod.h>
> -#include <linux/dma-map-ops.h>
> -#include <linux/mic_common.h>
> -#include <linux/mic_bus.h>
> -#include "../bus/scif_bus.h"
> -#include "../bus/vop_bus.h"
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_smpt.h"
> -
> -static inline struct mic_device *vpdev_to_mdev(struct device *dev)
> -{
> - return dev_get_drvdata(dev->parent);
> -}
> -
> -static dma_addr_t
> -_mic_dma_map_page(struct device *dev, struct page *page,
> - unsigned long offset, size_t size,
> - enum dma_data_direction dir, unsigned long attrs)
> -{
> - void *va = phys_to_virt(page_to_phys(page)) + offset;
> - struct mic_device *mdev = vpdev_to_mdev(dev);
> -
> - return mic_map_single(mdev, va, size);
> -}
> -
> -static void _mic_dma_unmap_page(struct device *dev, dma_addr_t
> dma_addr,
> - size_t size, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(dev);
> -
> - mic_unmap_single(mdev, dma_addr, size);
> -}
> -
> -static const struct dma_map_ops _mic_dma_ops = {
> - .map_page = _mic_dma_map_page,
> - .unmap_page = _mic_dma_unmap_page,
> -};
> -
> -static struct mic_irq *
> -__mic_request_irq(struct vop_device *vpdev,
> - irqreturn_t (*func)(int irq, void *data),
> - const char *name, void *data, int intr_src)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - return mic_request_threaded_irq(mdev, func, NULL, name, data,
> - intr_src, MIC_INTR_DB);
> -}
> -
> -static void __mic_free_irq(struct vop_device *vpdev,
> - struct mic_irq *cookie, void *data)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - mic_free_irq(mdev, cookie, data);
> -}
> -
> -static void __mic_ack_interrupt(struct vop_device *vpdev, int num)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - mdev->ops->intr_workarounds(mdev);
> -}
> -
> -static int __mic_next_db(struct vop_device *vpdev)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - return mic_next_db(mdev);
> -}
> -
> -static void *__mic_get_dp(struct vop_device *vpdev)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - return mdev->dp;
> -}
> -
> -static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev)
> -{
> - return NULL;
> -}
> -
> -static void __mic_send_intr(struct vop_device *vpdev, int db)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - mdev->ops->send_intr(mdev, db);
> -}
> -
> -static void __iomem *__mic_ioremap(struct vop_device *vpdev,
> - dma_addr_t pa, size_t len)
> -{
> - struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
> -
> - return mdev->aper.va + pa;
> -}
> -
> -static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va)
> -{
> - /* nothing to do */
> -}
> -
> -static struct vop_hw_ops vop_hw_ops = {
> - .request_irq = __mic_request_irq,
> - .free_irq = __mic_free_irq,
> - .ack_interrupt = __mic_ack_interrupt,
> - .next_db = __mic_next_db,
> - .get_dp = __mic_get_dp,
> - .get_remote_dp = __mic_get_remote_dp,
> - .send_intr = __mic_send_intr,
> - .remap = __mic_ioremap,
> - .unmap = __mic_iounmap,
> -};
> -
> -static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
> -{
> - return dev_get_drvdata(scdev->dev.parent);
> -}
> -
> -static void *__mic_dma_alloc(struct device *dev, size_t size,
> - dma_addr_t *dma_handle, gfp_t gfp,
> - unsigned long attrs)
> -{
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> - dma_addr_t tmp;
> - void *va = kzalloc(size, gfp);
> -
> - if (va) {
> - tmp = mic_map_single(mdev, va, size);
> - if (dma_mapping_error(dev, tmp)) {
> - kfree(va);
> - va = NULL;
> - } else {
> - *dma_handle = tmp;
> - }
> - }
> - return va;
> -}
> -
> -static void __mic_dma_free(struct device *dev, size_t size, void *vaddr,
> - dma_addr_t dma_handle, unsigned long attrs)
> -{
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - mic_unmap_single(mdev, dma_handle, size);
> - kfree(vaddr);
> -}
> -
> -static dma_addr_t
> -__mic_dma_map_page(struct device *dev, struct page *page, unsigned long
> offset,
> - size_t size, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - void *va = phys_to_virt(page_to_phys(page)) + offset;
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - return mic_map_single(mdev, va, size);
> -}
> -
> -static void
> -__mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
> - size_t size, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - mic_unmap_single(mdev, dma_addr, size);
> -}
> -
> -static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
> - int nents, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> - struct scatterlist *s;
> - int i, j, ret;
> - dma_addr_t da;
> -
> - ret = dma_map_sg(&mdev->pdev->dev, sg, nents, dir);
> - if (ret <= 0)
> - return 0;
> -
> - for_each_sg(sg, s, nents, i) {
> - da = mic_map(mdev, sg_dma_address(s) + s->offset, s-
> >length);
> - if (!da)
> - goto err;
> - sg_dma_address(s) = da;
> - }
> - return nents;
> -err:
> - for_each_sg(sg, s, i, j) {
> - mic_unmap(mdev, sg_dma_address(s), s->length);
> - sg_dma_address(s) = mic_to_dma_addr(mdev,
> sg_dma_address(s));
> - }
> - dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
> - return 0;
> -}
> -
> -static void __mic_dma_unmap_sg(struct device *dev,
> - struct scatterlist *sg, int nents,
> - enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - struct scif_hw_dev *scdev = dev_get_drvdata(dev);
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> - struct scatterlist *s;
> - dma_addr_t da;
> - int i;
> -
> - for_each_sg(sg, s, nents, i) {
> - da = mic_to_dma_addr(mdev, sg_dma_address(s));
> - mic_unmap(mdev, sg_dma_address(s), s->length);
> - sg_dma_address(s) = da;
> - }
> - dma_unmap_sg(&mdev->pdev->dev, sg, nents, dir);
> -}
> -
> -static const struct dma_map_ops __mic_dma_ops = {
> - .alloc = __mic_dma_alloc,
> - .free = __mic_dma_free,
> - .map_page = __mic_dma_map_page,
> - .unmap_page = __mic_dma_unmap_page,
> - .map_sg = __mic_dma_map_sg,
> - .unmap_sg = __mic_dma_unmap_sg,
> -};
> -
> -static struct mic_irq *
> -___mic_request_irq(struct scif_hw_dev *scdev,
> - irqreturn_t (*func)(int irq, void *data),
> - const char *name,
> - void *data, int db)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - return mic_request_threaded_irq(mdev, func, NULL, name, data,
> - db, MIC_INTR_DB);
> -}
> -
> -static void
> -___mic_free_irq(struct scif_hw_dev *scdev,
> - struct mic_irq *cookie, void *data)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - mic_free_irq(mdev, cookie, data);
> -}
> -
> -static void ___mic_ack_interrupt(struct scif_hw_dev *scdev, int num)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - mdev->ops->intr_workarounds(mdev);
> -}
> -
> -static int ___mic_next_db(struct scif_hw_dev *scdev)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - return mic_next_db(mdev);
> -}
> -
> -static void ___mic_send_intr(struct scif_hw_dev *scdev, int db)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - mdev->ops->send_intr(mdev, db);
> -}
> -
> -static void __iomem *___mic_ioremap(struct scif_hw_dev *scdev,
> - phys_addr_t pa, size_t len)
> -{
> - struct mic_device *mdev = scdev_to_mdev(scdev);
> -
> - return mdev->aper.va + pa;
> -}
> -
> -static void ___mic_iounmap(struct scif_hw_dev *scdev, void __iomem *va)
> -{
> - /* nothing to do */
> -}
> -
> -static struct scif_hw_ops scif_hw_ops = {
> - .request_irq = ___mic_request_irq,
> - .free_irq = ___mic_free_irq,
> - .ack_interrupt = ___mic_ack_interrupt,
> - .next_db = ___mic_next_db,
> - .send_intr = ___mic_send_intr,
> - .remap = ___mic_ioremap,
> - .unmap = ___mic_iounmap,
> -};
> -
> -static inline struct mic_device *mbdev_to_mdev(struct mbus_device
> *mbdev)
> -{
> - return dev_get_drvdata(mbdev->dev.parent);
> -}
> -
> -static dma_addr_t
> -mic_dma_map_page(struct device *dev, struct page *page,
> - unsigned long offset, size_t size, enum dma_data_direction
> dir,
> - unsigned long attrs)
> -{
> - void *va = phys_to_virt(page_to_phys(page)) + offset;
> - struct mic_device *mdev = dev_get_drvdata(dev->parent);
> -
> - return mic_map_single(mdev, va, size);
> -}
> -
> -static void
> -mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
> - size_t size, enum dma_data_direction dir,
> - unsigned long attrs)
> -{
> - struct mic_device *mdev = dev_get_drvdata(dev->parent);
> - mic_unmap_single(mdev, dma_addr, size);
> -}
> -
> -static const struct dma_map_ops mic_dma_ops = {
> - .map_page = mic_dma_map_page,
> - .unmap_page = mic_dma_unmap_page,
> -};
> -
> -static struct mic_irq *
> -_mic_request_threaded_irq(struct mbus_device *mbdev,
> - irq_handler_t handler, irq_handler_t thread_fn,
> - const char *name, void *data, int intr_src)
> -{
> - return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
> - thread_fn, name, data,
> - intr_src, MIC_INTR_DMA);
> -}
> -
> -static void _mic_free_irq(struct mbus_device *mbdev,
> - struct mic_irq *cookie, void *data)
> -{
> - mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
> -}
> -
> -static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
> -{
> - struct mic_device *mdev = mbdev_to_mdev(mbdev);
> - mdev->ops->intr_workarounds(mdev);
> -}
> -
> -static struct mbus_hw_ops mbus_hw_ops = {
> - .request_threaded_irq = _mic_request_threaded_irq,
> - .free_irq = _mic_free_irq,
> - .ack_interrupt = _mic_ack_interrupt,
> -};
> -
> -/* Initialize the MIC bootparams */
> -void mic_bootparam_init(struct mic_device *mdev)
> -{
> - struct mic_bootparam *bootparam = mdev->dp;
> -
> - bootparam->magic = cpu_to_le32(MIC_MAGIC);
> - bootparam->h2c_config_db = -1;
> - bootparam->node_id = mdev->id + 1;
> - bootparam->scif_host_dma_addr = 0x0;
> - bootparam->scif_card_dma_addr = 0x0;
> - bootparam->c2h_scif_db = -1;
> - bootparam->h2c_scif_db = -1;
> -}
> -
> -static inline struct mic_device *cosmdev_to_mdev(struct cosm_device *cdev)
> -{
> - return dev_get_drvdata(cdev->dev.parent);
> -}
> -
> -static void _mic_reset(struct cosm_device *cdev)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> -
> - mdev->ops->reset_fw_ready(mdev);
> - mdev->ops->reset(mdev);
> -}
> -
> -static bool _mic_ready(struct cosm_device *cdev)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> -
> - return mdev->ops->is_fw_ready(mdev);
> -}
> -
> -/**
> - * mic_request_dma_chans - Request DMA channels
> - * @mdev: pointer to mic_device instance
> - *
> - * returns number of DMA channels acquired
> - */
> -static int mic_request_dma_chans(struct mic_device *mdev)
> -{
> - dma_cap_mask_t mask;
> - struct dma_chan *chan;
> -
> - dma_cap_zero(mask);
> - dma_cap_set(DMA_MEMCPY, mask);
> -
> - do {
> - chan = dma_request_channel(mask, mdev->ops->dma_filter,
> - &mdev->pdev->dev);
> - if (chan) {
> - mdev->dma_ch[mdev->num_dma_ch++] = chan;
> - if (mdev->num_dma_ch >= MIC_MAX_DMA_CHAN)
> - break;
> - }
> - } while (chan);
> - dev_info(&mdev->pdev->dev, "DMA channels # %d\n", mdev-
> >num_dma_ch);
> - return mdev->num_dma_ch;
> -}
> -
> -/**
> - * mic_free_dma_chans - release DMA channels
> - * @mdev: pointer to mic_device instance
> - *
> - * returns none
> - */
> -static void mic_free_dma_chans(struct mic_device *mdev)
> -{
> - int i = 0;
> -
> - for (i = 0; i < mdev->num_dma_ch; i++) {
> - dma_release_channel(mdev->dma_ch[i]);
> - mdev->dma_ch[i] = NULL;
> - }
> - mdev->num_dma_ch = 0;
> -}
> -
> -/**
> - * _mic_start - Start the MIC.
> - * @cdev: pointer to cosm_device instance
> - * @id: MIC device id/index provided by COSM used in other drivers like SCIF
> - *
> - * This function prepares an MIC for boot and initiates boot.
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - *
> - * For all cosm_hw_ops the caller holds a mutex to ensure serialization.
> - */
> -static int _mic_start(struct cosm_device *cdev, int id)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> - int rc;
> -
> - mic_bootparam_init(mdev);
> - mdev->dma_mbdev = mbus_register_device(&mdev->pdev->dev,
> - MBUS_DEV_DMA_HOST,
> &mic_dma_ops,
> - &mbus_hw_ops, id, mdev-
> >mmio.va);
> - if (IS_ERR(mdev->dma_mbdev)) {
> - rc = PTR_ERR(mdev->dma_mbdev);
> - goto unlock_ret;
> - }
> - if (!mic_request_dma_chans(mdev)) {
> - rc = -ENODEV;
> - goto dma_remove;
> - }
> - mdev->scdev = scif_register_device(&mdev->pdev->dev,
> MIC_SCIF_DEV,
> - &__mic_dma_ops, &scif_hw_ops,
> - id + 1, 0, &mdev->mmio,
> - &mdev->aper, mdev->dp, NULL,
> - mdev->dma_ch, mdev-
> >num_dma_ch,
> - true);
> - if (IS_ERR(mdev->scdev)) {
> - rc = PTR_ERR(mdev->scdev);
> - goto dma_free;
> - }
> -
> - mdev->vpdev = vop_register_device(&mdev->pdev->dev,
> - VOP_DEV_TRNSP, &_mic_dma_ops,
> - &vop_hw_ops, id + 1, &mdev->aper,
> - mdev->dma_ch[0]);
> - if (IS_ERR(mdev->vpdev)) {
> - rc = PTR_ERR(mdev->vpdev);
> - goto scif_remove;
> - }
> -
> - rc = mdev->ops->load_mic_fw(mdev, NULL);
> - if (rc)
> - goto vop_remove;
> - mic_smpt_restore(mdev);
> - mic_intr_restore(mdev);
> - mdev->intr_ops->enable_interrupts(mdev);
> - mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev-
> >dp_dma_addr);
> - mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev-
> >dp_dma_addr >> 32);
> - mdev->ops->send_firmware_intr(mdev);
> - goto unlock_ret;
> -vop_remove:
> - vop_unregister_device(mdev->vpdev);
> -scif_remove:
> - scif_unregister_device(mdev->scdev);
> -dma_free:
> - mic_free_dma_chans(mdev);
> -dma_remove:
> - mbus_unregister_device(mdev->dma_mbdev);
> -unlock_ret:
> - return rc;
> -}
> -
> -/**
> - * _mic_stop - Prepare the MIC for reset and trigger reset.
> - * @cdev: pointer to cosm_device instance
> - * @force: force a MIC to reset even if it is already offline.
> - *
> - * RETURNS: None.
> - */
> -static void _mic_stop(struct cosm_device *cdev, bool force)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> -
> - /*
> - * Since SCIF handles card shutdown and reset (using COSM), it will
> - * will be the first to be registered and the last to be
> - * unregistered.
> - */
> - vop_unregister_device(mdev->vpdev);
> - scif_unregister_device(mdev->scdev);
> - mic_free_dma_chans(mdev);
> - mbus_unregister_device(mdev->dma_mbdev);
> - mic_bootparam_init(mdev);
> -}
> -
> -static ssize_t _mic_family(struct cosm_device *cdev, char *buf)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> - static const char *family[MIC_FAMILY_LAST] = { "x100", "Unknown" };
> -
> - return scnprintf(buf, PAGE_SIZE, "%s\n", family[mdev->family]);
> -}
> -
> -static ssize_t _mic_stepping(struct cosm_device *cdev, char *buf)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> - const char *string = "??";
> -
> - switch (mdev->stepping) {
> - case MIC_A0_STEP:
> - string = "A0";
> - break;
> - case MIC_B0_STEP:
> - string = "B0";
> - break;
> - case MIC_B1_STEP:
> - string = "B1";
> - break;
> - case MIC_C0_STEP:
> - string = "C0";
> - break;
> - default:
> - break;
> - }
> - return scnprintf(buf, PAGE_SIZE, "%s\n", string);
> -}
> -
> -static struct mic_mw *_mic_aper(struct cosm_device *cdev)
> -{
> - struct mic_device *mdev = cosmdev_to_mdev(cdev);
> -
> - return &mdev->aper;
> -}
> -
> -struct cosm_hw_ops cosm_hw_ops = {
> - .reset = _mic_reset,
> - .force_reset = _mic_reset,
> - .post_reset = NULL,
> - .ready = _mic_ready,
> - .start = _mic_start,
> - .stop = _mic_stop,
> - .family = _mic_family,
> - .stepping = _mic_stepping,
> - .aper = _mic_aper,
> -};
> diff --git a/drivers/misc/mic/host/mic_debugfs.c
> b/drivers/misc/mic/host/mic_debugfs.c
> deleted file mode 100644
> index ffda740e20d5..000000000000
> --- a/drivers/misc/mic/host/mic_debugfs.c
> +++ /dev/null
> @@ -1,149 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/debugfs.h>
> -#include <linux/pci.h>
> -#include <linux/seq_file.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_smpt.h"
> -
> -/* Debugfs parent dir */
> -static struct dentry *mic_dbg;
> -
> -static int mic_smpt_show(struct seq_file *s, void *pos)
> -{
> - int i;
> - struct mic_device *mdev = s->private;
> - unsigned long flags;
> -
> - seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
> - mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
> - seq_puts(s,
> "====================================================\n");
> -
> - if (mdev->smpt) {
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> - spin_lock_irqsave(&smpt_info->smpt_lock, flags);
> - for (i = 0; i < smpt_info->info.num_reg; i++) {
> - seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
> - " ", i, smpt_info->entry[i].dma_addr,
> - smpt_info->entry[i].ref_count);
> - }
> - spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
> - }
> - seq_puts(s,
> "====================================================\n");
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(mic_smpt);
> -
> -static int mic_post_code_show(struct seq_file *s, void *pos)
> -{
> - struct mic_device *mdev = s->private;
> - u32 reg = mdev->ops->get_postcode(mdev);
> -
> - seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(mic_post_code);
> -
> -static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
> -{
> - struct mic_device *mdev = s->private;
> - int reg;
> - int i, j;
> - u16 entry;
> - u16 vector;
> - struct pci_dev *pdev = mdev->pdev;
> -
> - if (pci_dev_msi_enabled(pdev)) {
> - for (i = 0; i < mdev->irq_info.num_vectors; i++) {
> - if (pdev->msix_enabled) {
> - entry = mdev->irq_info.msix_entries[i].entry;
> - vector = mdev-
> >irq_info.msix_entries[i].vector;
> - } else {
> - entry = 0;
> - vector = pdev->irq;
> - }
> -
> - reg = mdev->intr_ops->read_msi_to_src_map(mdev,
> entry);
> -
> - seq_printf(s, "%s %-10d %s %-10d
> MXAR[%d]: %08X\n",
> - "IRQ:", vector, "Entry:", entry, i, reg);
> -
> - seq_printf(s, "%-10s", "offset:");
> - for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
> - seq_printf(s, "%4d ", j);
> - seq_puts(s, "\n");
> -
> -
> - seq_printf(s, "%-10s", "count:");
> - for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
> - seq_printf(s, "%4d ",
> - (mdev->irq_info.mic_msi_map[i] &
> - BIT(j)) ? 1 : 0);
> - seq_puts(s, "\n\n");
> - }
> - } else {
> - seq_puts(s, "MSI/MSIx interrupts not enabled\n");
> - }
> -
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(mic_msi_irq_info);
> -
> -/*
> - * mic_create_debug_dir - Initialize MIC debugfs entries.
> - */
> -void mic_create_debug_dir(struct mic_device *mdev)
> -{
> - char name[16];
> -
> - if (!mic_dbg)
> - return;
> -
> - scnprintf(name, sizeof(name), "mic%d", mdev->id);
> - mdev->dbg_dir = debugfs_create_dir(name, mic_dbg);
> -
> - debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev,
> - &mic_smpt_fops);
> -
> - debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
> - &mic_post_code_fops);
> -
> - debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
> - &mic_msi_irq_info_fops);
> -}
> -
> -/*
> - * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
> - */
> -void mic_delete_debug_dir(struct mic_device *mdev)
> -{
> - debugfs_remove_recursive(mdev->dbg_dir);
> -}
> -
> -/*
> - * mic_init_debugfs - Initialize global debugfs entry.
> - */
> -void __init mic_init_debugfs(void)
> -{
> - mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
> -}
> -
> -/*
> - * mic_exit_debugfs - Uninitialize global debugfs entry
> - */
> -void mic_exit_debugfs(void)
> -{
> - debugfs_remove(mic_dbg);
> -}
> diff --git a/drivers/misc/mic/host/mic_device.h
> b/drivers/misc/mic/host/mic_device.h
> deleted file mode 100644
> index 41bcd308ae59..000000000000
> --- a/drivers/misc/mic/host/mic_device.h
> +++ /dev/null
> @@ -1,157 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#ifndef _MIC_DEVICE_H_
> -#define _MIC_DEVICE_H_
> -
> -#include <linux/cdev.h>
> -#include <linux/idr.h>
> -#include <linux/notifier.h>
> -#include <linux/irqreturn.h>
> -#include <linux/dmaengine.h>
> -#include <linux/miscdevice.h>
> -#include <linux/mic_bus.h>
> -#include "../bus/scif_bus.h"
> -#include "../bus/vop_bus.h"
> -#include "../bus/cosm_bus.h"
> -#include "mic_intr.h"
> -
> -/**
> - * enum mic_stepping - MIC stepping ids.
> - */
> -enum mic_stepping {
> - MIC_A0_STEP = 0x0,
> - MIC_B0_STEP = 0x10,
> - MIC_B1_STEP = 0x11,
> - MIC_C0_STEP = 0x20,
> -};
> -
> -extern struct cosm_hw_ops cosm_hw_ops;
> -
> -/**
> - * struct mic_device - MIC device information for each card.
> - *
> - * @mmio: MMIO bar information.
> - * @aper: Aperture bar information.
> - * @family: The MIC family to which this device belongs.
> - * @ops: MIC HW specific operations.
> - * @id: The unique device id for this MIC device.
> - * @stepping: Stepping ID.
> - * @pdev: Underlying PCI device.
> - * @mic_mutex: Mutex for synchronizing access to mic_device.
> - * @intr_ops: HW specific interrupt operations.
> - * @smpt_ops: Hardware specific SMPT operations.
> - * @smpt: MIC SMPT information.
> - * @intr_info: H/W specific interrupt information.
> - * @irq_info: The OS specific irq information
> - * @dbg_dir: debugfs directory of this MIC device.
> - * @bootaddr: MIC boot address.
> - * @dp: virtio device page
> - * @dp_dma_addr: virtio device page DMA address.
> - * @dma_mbdev: MIC BUS DMA device.
> - * @dma_ch - Array of DMA channels
> - * @num_dma_ch - Number of DMA channels available
> - * @scdev: SCIF device on the SCIF virtual bus.
> - * @vpdev: Virtio over PCIe device on the VOP virtual bus.
> - * @cosm_dev: COSM device
> - */
> -struct mic_device {
> - struct mic_mw mmio;
> - struct mic_mw aper;
> - enum mic_hw_family family;
> - struct mic_hw_ops *ops;
> - int id;
> - enum mic_stepping stepping;
> - struct pci_dev *pdev;
> - struct mutex mic_mutex;
> - struct mic_hw_intr_ops *intr_ops;
> - struct mic_smpt_ops *smpt_ops;
> - struct mic_smpt_info *smpt;
> - struct mic_intr_info *intr_info;
> - struct mic_irq_info irq_info;
> - struct dentry *dbg_dir;
> - u32 bootaddr;
> - void *dp;
> - dma_addr_t dp_dma_addr;
> - struct mbus_device *dma_mbdev;
> - struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
> - int num_dma_ch;
> - struct scif_hw_dev *scdev;
> - struct vop_device *vpdev;
> - struct cosm_device *cosm_dev;
> -};
> -
> -/**
> - * struct mic_hw_ops - MIC HW specific operations.
> - * @aper_bar: Aperture bar resource number.
> - * @mmio_bar: MMIO bar resource number.
> - * @read_spad: Read from scratch pad register.
> - * @write_spad: Write to scratch pad register.
> - * @send_intr: Send an interrupt for a particular doorbell on the card.
> - * @ack_interrupt: Hardware specific operations to ack the h/w on
> - * receipt of an interrupt.
> - * @intr_workarounds: Hardware specific workarounds needed after
> - * handling an interrupt.
> - * @reset: Reset the remote processor.
> - * @reset_fw_ready: Reset firmware ready field.
> - * @is_fw_ready: Check if firmware is ready for OS download.
> - * @send_firmware_intr: Send an interrupt to the card firmware.
> - * @load_mic_fw: Load firmware segments required to boot the card
> - * into card memory. This includes the kernel, command line, ramdisk etc.
> - * @get_postcode: Get post code status from firmware.
> - * @dma_filter: DMA filter function to be used.
> - */
> -struct mic_hw_ops {
> - u8 aper_bar;
> - u8 mmio_bar;
> - u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
> - void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32
> val);
> - void (*send_intr)(struct mic_device *mdev, int doorbell);
> - u32 (*ack_interrupt)(struct mic_device *mdev);
> - void (*intr_workarounds)(struct mic_device *mdev);
> - void (*reset)(struct mic_device *mdev);
> - void (*reset_fw_ready)(struct mic_device *mdev);
> - bool (*is_fw_ready)(struct mic_device *mdev);
> - void (*send_firmware_intr)(struct mic_device *mdev);
> - int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
> - u32 (*get_postcode)(struct mic_device *mdev);
> - bool (*dma_filter)(struct dma_chan *chan, void *param);
> -};
> -
> -/**
> - * mic_mmio_read - read from an MMIO register.
> - * @mw: MMIO register base virtual address.
> - * @offset: register offset.
> - *
> - * RETURNS: register value.
> - */
> -static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
> -{
> - return ioread32(mw->va + offset);
> -}
> -
> -/**
> - * mic_mmio_write - write to an MMIO register.
> - * @mw: MMIO register base virtual address.
> - * @val: the data value to put into the register
> - * @offset: register offset.
> - *
> - * RETURNS: none.
> - */
> -static inline void
> -mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
> -{
> - iowrite32(val, mw->va + offset);
> -}
> -
> -void mic_bootparam_init(struct mic_device *mdev);
> -void mic_create_debug_dir(struct mic_device *dev);
> -void mic_delete_debug_dir(struct mic_device *dev);
> -void __init mic_init_debugfs(void);
> -void mic_exit_debugfs(void);
> -#endif
> diff --git a/drivers/misc/mic/host/mic_intr.c
> b/drivers/misc/mic/host/mic_intr.c
> deleted file mode 100644
> index 85b3221b5d40..000000000000
> --- a/drivers/misc/mic/host/mic_intr.c
> +++ /dev/null
> @@ -1,635 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/pci.h>
> -#include <linux/interrupt.h>
> -
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -
> -static irqreturn_t mic_thread_fn(int irq, void *dev)
> -{
> - struct mic_device *mdev = dev;
> - struct mic_intr_info *intr_info = mdev->intr_info;
> - struct mic_irq_info *irq_info = &mdev->irq_info;
> - struct mic_intr_cb *intr_cb;
> - struct pci_dev *pdev = mdev->pdev;
> - int i;
> -
> - spin_lock(&irq_info->mic_thread_lock);
> - for (i = intr_info->intr_start_idx[MIC_INTR_DB];
> - i < intr_info->intr_len[MIC_INTR_DB]; i++)
> - if (test_and_clear_bit(i, &irq_info->mask)) {
> - list_for_each_entry(intr_cb, &irq_info->cb_list[i],
> - list)
> - if (intr_cb->thread_fn)
> - intr_cb->thread_fn(pdev->irq,
> - intr_cb->data);
> - }
> - spin_unlock(&irq_info->mic_thread_lock);
> - return IRQ_HANDLED;
> -}
> -/**
> - * mic_interrupt - Generic interrupt handler for
> - * MSI and INTx based interrupts.
> - * @irq: interrupt to handle (unused)
> - * @dev: pointer to the mic_device instance
> - */
> -static irqreturn_t mic_interrupt(int irq, void *dev)
> -{
> - struct mic_device *mdev = dev;
> - struct mic_intr_info *intr_info = mdev->intr_info;
> - struct mic_irq_info *irq_info = &mdev->irq_info;
> - struct mic_intr_cb *intr_cb;
> - struct pci_dev *pdev = mdev->pdev;
> - u32 mask;
> - int i;
> -
> - mask = mdev->ops->ack_interrupt(mdev);
> - if (!mask)
> - return IRQ_NONE;
> -
> - spin_lock(&irq_info->mic_intr_lock);
> - for (i = intr_info->intr_start_idx[MIC_INTR_DB];
> - i < intr_info->intr_len[MIC_INTR_DB]; i++)
> - if (mask & BIT(i)) {
> - list_for_each_entry(intr_cb, &irq_info->cb_list[i],
> - list)
> - if (intr_cb->handler)
> - intr_cb->handler(pdev->irq,
> - intr_cb->data);
> - set_bit(i, &irq_info->mask);
> - }
> - spin_unlock(&irq_info->mic_intr_lock);
> - return IRQ_WAKE_THREAD;
> -}
> -
> -/* Return the interrupt offset from the index. Index is 0 based. */
> -static u16 mic_map_src_to_offset(struct mic_device *mdev,
> - int intr_src, enum mic_intr_type type)
> -{
> - if (type >= MIC_NUM_INTR_TYPES)
> - return MIC_NUM_OFFSETS;
> - if (intr_src >= mdev->intr_info->intr_len[type])
> - return MIC_NUM_OFFSETS;
> -
> - return mdev->intr_info->intr_start_idx[type] + intr_src;
> -}
> -
> -/* Return next available msix_entry. */
> -static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
> -{
> - int i;
> - struct mic_irq_info *info = &mdev->irq_info;
> -
> - for (i = 0; i < info->num_vectors; i++)
> - if (!info->mic_msi_map[i])
> - return &info->msix_entries[i];
> - return NULL;
> -}
> -
> -/**
> - * mic_register_intr_callback - Register a callback handler for the
> - * given source id.
> - *
> - * @mdev: pointer to the mic_device instance
> - * @idx: The source id to be registered.
> - * @handler: The function to be called when the source id receives
> - * the interrupt.
> - * @thread_fn: thread fn. corresponding to the handler
> - * @data: Private data of the requester.
> - * Return the callback structure that was registered or an
> - * appropriate error on failure.
> - */
> -static struct mic_intr_cb *mic_register_intr_callback(struct mic_device
> *mdev,
> - u8 idx, irq_handler_t handler, irq_handler_t
> thread_fn,
> - void *data)
> -{
> - struct mic_intr_cb *intr_cb;
> - unsigned long flags;
> - int rc;
> - intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
> -
> - if (!intr_cb)
> - return ERR_PTR(-ENOMEM);
> -
> - intr_cb->handler = handler;
> - intr_cb->thread_fn = thread_fn;
> - intr_cb->data = data;
> - intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
> - 0, 0, GFP_KERNEL);
> - if (intr_cb->cb_id < 0) {
> - rc = intr_cb->cb_id;
> - goto ida_fail;
> - }
> -
> - spin_lock(&mdev->irq_info.mic_thread_lock);
> - spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
> - list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
> - spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
> - spin_unlock(&mdev->irq_info.mic_thread_lock);
> -
> - return intr_cb;
> -ida_fail:
> - kfree(intr_cb);
> - return ERR_PTR(rc);
> -}
> -
> -/**
> - * mic_unregister_intr_callback - Unregister the callback handler
> - * identified by its callback id.
> - *
> - * @mdev: pointer to the mic_device instance
> - * @idx: The callback structure id to be unregistered.
> - * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
> - * such callback handler was found.
> - */
> -static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
> -{
> - struct list_head *pos, *tmp;
> - struct mic_intr_cb *intr_cb;
> - unsigned long flags;
> - int i;
> -
> - spin_lock(&mdev->irq_info.mic_thread_lock);
> - spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
> - for (i = 0; i < MIC_NUM_OFFSETS; i++) {
> - list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
> - intr_cb = list_entry(pos, struct mic_intr_cb, list);
> - if (intr_cb->cb_id == idx) {
> - list_del(pos);
> - ida_simple_remove(&mdev->irq_info.cb_ida,
> - intr_cb->cb_id);
> - kfree(intr_cb);
> - spin_unlock_irqrestore(
> - &mdev->irq_info.mic_intr_lock, flags);
> - spin_unlock(&mdev-
> >irq_info.mic_thread_lock);
> - return i;
> - }
> - }
> - }
> - spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
> - spin_unlock(&mdev->irq_info.mic_thread_lock);
> - return MIC_NUM_OFFSETS;
> -}
> -
> -/**
> - * mic_setup_msix - Initializes MSIx interrupts.
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: PCI device structure
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - int rc, i;
> - int entry_size = sizeof(*mdev->irq_info.msix_entries);
> -
> - mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
> - entry_size, GFP_KERNEL);
> - if (!mdev->irq_info.msix_entries) {
> - rc = -ENOMEM;
> - goto err_nomem1;
> - }
> -
> - for (i = 0; i < MIC_MIN_MSIX; i++)
> - mdev->irq_info.msix_entries[i].entry = i;
> -
> - rc = pci_enable_msix_exact(pdev, mdev->irq_info.msix_entries,
> - MIC_MIN_MSIX);
> - if (rc) {
> - dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
> - goto err_enable_msix;
> - }
> -
> - mdev->irq_info.num_vectors = MIC_MIN_MSIX;
> - mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
> - mdev->irq_info.num_vectors), GFP_KERNEL);
> -
> - if (!mdev->irq_info.mic_msi_map) {
> - rc = -ENOMEM;
> - goto err_nomem2;
> - }
> -
> - dev_dbg(&mdev->pdev->dev,
> - "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
> - return 0;
> -err_nomem2:
> - pci_disable_msix(pdev);
> -err_enable_msix:
> - kfree(mdev->irq_info.msix_entries);
> -err_nomem1:
> - mdev->irq_info.num_vectors = 0;
> - return rc;
> -}
> -
> -/**
> - * mic_setup_callbacks - Initialize data structures needed
> - * to handle callbacks.
> - *
> - * @mdev: pointer to mic_device instance
> - */
> -static int mic_setup_callbacks(struct mic_device *mdev)
> -{
> - int i;
> -
> - mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
> - sizeof(*mdev->irq_info.cb_list),
> - GFP_KERNEL);
> - if (!mdev->irq_info.cb_list)
> - return -ENOMEM;
> -
> - for (i = 0; i < MIC_NUM_OFFSETS; i++)
> - INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
> - ida_init(&mdev->irq_info.cb_ida);
> - spin_lock_init(&mdev->irq_info.mic_intr_lock);
> - spin_lock_init(&mdev->irq_info.mic_thread_lock);
> - return 0;
> -}
> -
> -/**
> - * mic_release_callbacks - Uninitialize data structures needed
> - * to handle callbacks.
> - *
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_release_callbacks(struct mic_device *mdev)
> -{
> - unsigned long flags;
> - struct list_head *pos, *tmp;
> - struct mic_intr_cb *intr_cb;
> - int i;
> -
> - spin_lock(&mdev->irq_info.mic_thread_lock);
> - spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
> - for (i = 0; i < MIC_NUM_OFFSETS; i++) {
> - if (list_empty(&mdev->irq_info.cb_list[i]))
> - break;
> -
> - list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
> - intr_cb = list_entry(pos, struct mic_intr_cb, list);
> - list_del(pos);
> - ida_simple_remove(&mdev->irq_info.cb_ida,
> - intr_cb->cb_id);
> - kfree(intr_cb);
> - }
> - }
> - spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
> - spin_unlock(&mdev->irq_info.mic_thread_lock);
> - ida_destroy(&mdev->irq_info.cb_ida);
> - kfree(mdev->irq_info.cb_list);
> -}
> -
> -/**
> - * mic_setup_msi - Initializes MSI interrupts.
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: PCI device structure
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - int rc;
> -
> - rc = pci_enable_msi(pdev);
> - if (rc) {
> - dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
> - return rc;
> - }
> -
> - mdev->irq_info.num_vectors = 1;
> - mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
> - mdev->irq_info.num_vectors), GFP_KERNEL);
> -
> - if (!mdev->irq_info.mic_msi_map) {
> - rc = -ENOMEM;
> - goto err_nomem1;
> - }
> -
> - rc = mic_setup_callbacks(mdev);
> - if (rc) {
> - dev_err(&pdev->dev, "Error setting up callbacks\n");
> - goto err_nomem2;
> - }
> -
> - rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
> - 0, "mic-msi", mdev);
> - if (rc) {
> - dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
> - goto err_irq_req_fail;
> - }
> -
> - dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev-
> >irq_info.num_vectors);
> - return 0;
> -err_irq_req_fail:
> - mic_release_callbacks(mdev);
> -err_nomem2:
> - kfree(mdev->irq_info.mic_msi_map);
> -err_nomem1:
> - pci_disable_msi(pdev);
> - mdev->irq_info.num_vectors = 0;
> - return rc;
> -}
> -
> -/**
> - * mic_setup_intx - Initializes legacy interrupts.
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: PCI device structure
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - int rc;
> -
> - /* Enable intx */
> - pci_intx(pdev, 1);
> - rc = mic_setup_callbacks(mdev);
> - if (rc) {
> - dev_err(&pdev->dev, "Error setting up callbacks\n");
> - goto err_nomem;
> - }
> -
> - rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
> - IRQF_SHARED, "mic-intx", mdev);
> - if (rc)
> - goto err;
> -
> - dev_dbg(&pdev->dev, "intx irq setup\n");
> - return 0;
> -err:
> - mic_release_callbacks(mdev);
> -err_nomem:
> - return rc;
> -}
> -
> -/**
> - * mic_next_db - Retrieve the next doorbell interrupt source id.
> - * The id is picked sequentially from the available pool of
> - * doorlbell ids.
> - *
> - * @mdev: pointer to the mic_device instance.
> - *
> - * Returns the next doorbell interrupt source.
> - */
> -int mic_next_db(struct mic_device *mdev)
> -{
> - int next_db;
> -
> - next_db = mdev->irq_info.next_avail_src %
> - mdev->intr_info->intr_len[MIC_INTR_DB];
> - mdev->irq_info.next_avail_src++;
> - return next_db;
> -}
> -
> -#define COOKIE_ID_SHIFT 16
> -#define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
> -#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
> -#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
> -
> -/**
> - * mic_request_threaded_irq - request an irq. mic_mutex needs
> - * to be held before calling this function.
> - *
> - * @mdev: pointer to mic_device instance
> - * @handler: The callback function that handles the interrupt.
> - * The function needs to call ack_interrupts
> - * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
> - * @thread_fn: thread fn required by request_threaded_irq.
> - * @name: The ASCII name of the callee requesting the irq.
> - * @data: private data that is returned back when calling the
> - * function handler.
> - * @intr_src: The source id of the requester. Its the doorbell id
> - * for Doorbell interrupts and DMA channel id for DMA interrupts.
> - * @type: The type of interrupt. Values defined in mic_intr_type
> - *
> - * returns: The cookie that is transparent to the caller. Passed
> - * back when calling mic_free_irq. An appropriate error code
> - * is returned on failure. Caller needs to use IS_ERR(return_val)
> - * to check for failure and PTR_ERR(return_val) to obtained the
> - * error code.
> - *
> - */
> -struct mic_irq *
> -mic_request_threaded_irq(struct mic_device *mdev,
> - irq_handler_t handler, irq_handler_t thread_fn,
> - const char *name, void *data, int intr_src,
> - enum mic_intr_type type)
> -{
> - u16 offset;
> - int rc = 0;
> - struct msix_entry *msix = NULL;
> - unsigned long cookie = 0;
> - u16 entry;
> - struct mic_intr_cb *intr_cb;
> - struct pci_dev *pdev = mdev->pdev;
> -
> - offset = mic_map_src_to_offset(mdev, intr_src, type);
> - if (offset >= MIC_NUM_OFFSETS) {
> - dev_err(&mdev->pdev->dev,
> - "Error mapping index %d to a valid source id.\n",
> - intr_src);
> - rc = -EINVAL;
> - goto err;
> - }
> -
> - if (mdev->irq_info.num_vectors > 1) {
> - msix = mic_get_available_vector(mdev);
> - if (!msix) {
> - dev_err(&mdev->pdev->dev,
> - "No MSIx vectors available for use.\n");
> - rc = -ENOSPC;
> - goto err;
> - }
> -
> - rc = request_threaded_irq(msix->vector, handler, thread_fn,
> - 0, name, data);
> - if (rc) {
> - dev_dbg(&mdev->pdev->dev,
> - "request irq failed rc = %d\n", rc);
> - goto err;
> - }
> - entry = msix->entry;
> - mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
> - mdev->intr_ops->program_msi_to_src_map(mdev,
> - entry, offset, true);
> - cookie = MK_COOKIE(entry, offset);
> - dev_dbg(&mdev->pdev->dev, "irq: %d assigned for
> src: %d\n",
> - msix->vector, intr_src);
> - } else {
> - intr_cb = mic_register_intr_callback(mdev, offset, handler,
> - thread_fn, data);
> - if (IS_ERR(intr_cb)) {
> - dev_err(&mdev->pdev->dev,
> - "No available callback entries for use\n");
> - rc = PTR_ERR(intr_cb);
> - goto err;
> - }
> -
> - entry = 0;
> - if (pci_dev_msi_enabled(pdev)) {
> - mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
> - mdev->intr_ops->program_msi_to_src_map(mdev,
> - entry, offset, true);
> - }
> - cookie = MK_COOKIE(entry, intr_cb->cb_id);
> - dev_dbg(&mdev->pdev->dev, "callback %d registered for
> src: %d\n",
> - intr_cb->cb_id, intr_src);
> - }
> - return (struct mic_irq *)cookie;
> -err:
> - return ERR_PTR(rc);
> -}
> -
> -/**
> - * mic_free_irq - free irq. mic_mutex
> - * needs to be held before calling this function.
> - *
> - * @mdev: pointer to mic_device instance
> - * @cookie: cookie obtained during a successful call to
> mic_request_threaded_irq
> - * @data: private data specified by the calling function during the
> - * mic_request_threaded_irq
> - *
> - * returns: none.
> - */
> -void mic_free_irq(struct mic_device *mdev,
> - struct mic_irq *cookie, void *data)
> -{
> - u32 offset;
> - u32 entry;
> - u8 src_id;
> - unsigned int irq;
> - struct pci_dev *pdev = mdev->pdev;
> -
> - entry = GET_ENTRY((unsigned long)cookie);
> - offset = GET_OFFSET((unsigned long)cookie);
> - if (mdev->irq_info.num_vectors > 1) {
> - if (entry >= mdev->irq_info.num_vectors) {
> - dev_warn(&mdev->pdev->dev,
> - "entry %d should be < num_irq %d\n",
> - entry, mdev->irq_info.num_vectors);
> - return;
> - }
> - irq = mdev->irq_info.msix_entries[entry].vector;
> - free_irq(irq, data);
> - mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
> - mdev->intr_ops->program_msi_to_src_map(mdev,
> - entry, offset, false);
> -
> - dev_dbg(&mdev->pdev->dev, "irq: %d freed\n", irq);
> - } else {
> - irq = pdev->irq;
> - src_id = mic_unregister_intr_callback(mdev, offset);
> - if (src_id >= MIC_NUM_OFFSETS) {
> - dev_warn(&mdev->pdev->dev, "Error unregistering
> callback\n");
> - return;
> - }
> - if (pci_dev_msi_enabled(pdev)) {
> - mdev->irq_info.mic_msi_map[entry] &=
> ~(BIT(src_id));
> - mdev->intr_ops->program_msi_to_src_map(mdev,
> - entry, src_id, false);
> - }
> - dev_dbg(&mdev->pdev->dev, "callback %d unregistered for
> src: %d\n",
> - offset, src_id);
> - }
> -}
> -
> -/**
> - * mic_setup_interrupts - Initializes interrupts.
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: PCI device structure
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - int rc;
> -
> - rc = mic_setup_msix(mdev, pdev);
> - if (!rc)
> - goto done;
> -
> - rc = mic_setup_msi(mdev, pdev);
> - if (!rc)
> - goto done;
> -
> - rc = mic_setup_intx(mdev, pdev);
> - if (rc) {
> - dev_err(&mdev->pdev->dev, "no usable interrupts\n");
> - return rc;
> - }
> -done:
> - mdev->intr_ops->enable_interrupts(mdev);
> - return 0;
> -}
> -
> -/**
> - * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: PCI device structure
> - *
> - * returns none.
> - */
> -void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - int i;
> -
> - mdev->intr_ops->disable_interrupts(mdev);
> - if (mdev->irq_info.num_vectors > 1) {
> - for (i = 0; i < mdev->irq_info.num_vectors; i++) {
> - if (mdev->irq_info.mic_msi_map[i])
> - dev_warn(&pdev->dev, "irq %d may still be in
> use.\n",
> - mdev-
> >irq_info.msix_entries[i].vector);
> - }
> - kfree(mdev->irq_info.mic_msi_map);
> - kfree(mdev->irq_info.msix_entries);
> - pci_disable_msix(pdev);
> - } else {
> - if (pci_dev_msi_enabled(pdev)) {
> - free_irq(pdev->irq, mdev);
> - kfree(mdev->irq_info.mic_msi_map);
> - pci_disable_msi(pdev);
> - } else {
> - free_irq(pdev->irq, mdev);
> - }
> - mic_release_callbacks(mdev);
> - }
> -}
> -
> -/**
> - * mic_intr_restore - Restore MIC interrupt registers.
> - *
> - * @mdev: pointer to mic_device instance.
> - *
> - * Restore the interrupt registers to values previously
> - * stored in the SW data structures. mic_mutex needs to
> - * be held before calling this function.
> - *
> - * returns None.
> - */
> -void mic_intr_restore(struct mic_device *mdev)
> -{
> - int entry, offset;
> - struct pci_dev *pdev = mdev->pdev;
> -
> - if (!pci_dev_msi_enabled(pdev))
> - return;
> -
> - for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
> - for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
> - if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
> - mdev->intr_ops-
> >program_msi_to_src_map(mdev,
> - entry, offset, true);
> - }
> - }
> -}
> diff --git a/drivers/misc/mic/host/mic_intr.h
> b/drivers/misc/mic/host/mic_intr.h
> deleted file mode 100644
> index b14ba818006f..000000000000
> --- a/drivers/misc/mic/host/mic_intr.h
> +++ /dev/null
> @@ -1,137 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#ifndef _MIC_INTR_H_
> -#define _MIC_INTR_H_
> -
> -#include <linux/bitops.h>
> -#include <linux/interrupt.h>
> -/*
> - * The minimum number of msix vectors required for normal operation.
> - * 3 for virtio network, console and block devices.
> - * 1 for card shutdown notifications.
> - * 4 for host owned DMA channels.
> - * 1 for SCIF
> - */
> -#define MIC_MIN_MSIX 9
> -#define MIC_NUM_OFFSETS 32
> -
> -/**
> - * mic_intr_source - The type of source that will generate
> - * the interrupt.The number of types needs to be in sync with
> - * MIC_NUM_INTR_TYPES
> - *
> - * MIC_INTR_DB: The source is a doorbell
> - * MIC_INTR_DMA: The source is a DMA channel
> - * MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
> - * MIC_NUM_INTR_TYPES: Total number of interrupt sources.
> - */
> -enum mic_intr_type {
> - MIC_INTR_DB = 0,
> - MIC_INTR_DMA,
> - MIC_INTR_ERR,
> - MIC_NUM_INTR_TYPES
> -};
> -
> -/**
> - * struct mic_intr_info - Contains h/w specific interrupt sources
> - * information.
> - *
> - * @intr_start_idx: Contains the starting indexes of the
> - * interrupt types.
> - * @intr_len: Contains the length of the interrupt types.
> - */
> -struct mic_intr_info {
> - u16 intr_start_idx[MIC_NUM_INTR_TYPES];
> - u16 intr_len[MIC_NUM_INTR_TYPES];
> -};
> -
> -/**
> - * struct mic_irq_info - OS specific irq information
> - *
> - * @next_avail_src: next available doorbell that can be assigned.
> - * @msix_entries: msix entries allocated while setting up MSI-x
> - * @mic_msi_map: The MSI/MSI-x mapping information.
> - * @num_vectors: The number of MSI/MSI-x vectors that have been
> allocated.
> - * @cb_ida: callback ID allocator to track the callbacks registered.
> - * @mic_intr_lock: spinlock to protect the interrupt callback list.
> - * @mic_thread_lock: spinlock to protect the thread callback list.
> - * This lock is used to protect against thread_fn while
> - * mic_intr_lock is used to protect against interrupt handler.
> - * @cb_list: Array of callback lists one for each source.
> - * @mask: Mask used by the main thread fn to call the underlying thread fns.
> - */
> -struct mic_irq_info {
> - int next_avail_src;
> - struct msix_entry *msix_entries;
> - u32 *mic_msi_map;
> - u16 num_vectors;
> - struct ida cb_ida;
> - spinlock_t mic_intr_lock;
> - spinlock_t mic_thread_lock;
> - struct list_head *cb_list;
> - unsigned long mask;
> -};
> -
> -/**
> - * struct mic_intr_cb - Interrupt callback structure.
> - *
> - * @handler: The callback function
> - * @thread_fn: The thread_fn.
> - * @data: Private data of the requester.
> - * @cb_id: The callback id. Identifies this callback.
> - * @list: list head pointing to the next callback structure.
> - */
> -struct mic_intr_cb {
> - irq_handler_t handler;
> - irq_handler_t thread_fn;
> - void *data;
> - int cb_id;
> - struct list_head list;
> -};
> -
> -/**
> - * struct mic_irq - opaque pointer used as cookie
> - */
> -struct mic_irq;
> -
> -/* Forward declaration */
> -struct mic_device;
> -
> -/**
> - * struct mic_hw_intr_ops: MIC HW specific interrupt operations
> - * @intr_init: Initialize H/W specific interrupt information.
> - * @enable_interrupts: Enable interrupts from the hardware.
> - * @disable_interrupts: Disable interrupts from the hardware.
> - * @program_msi_to_src_map: Update MSI mapping registers with
> - * irq information.
> - * @read_msi_to_src_map: Read MSI mapping registers containing
> - * irq information.
> - */
> -struct mic_hw_intr_ops {
> - void (*intr_init)(struct mic_device *mdev);
> - void (*enable_interrupts)(struct mic_device *mdev);
> - void (*disable_interrupts)(struct mic_device *mdev);
> - void (*program_msi_to_src_map) (struct mic_device *mdev,
> - int idx, int intr_src, bool set);
> - u32 (*read_msi_to_src_map) (struct mic_device *mdev,
> - int idx);
> -};
> -
> -int mic_next_db(struct mic_device *mdev);
> -struct mic_irq *
> -mic_request_threaded_irq(struct mic_device *mdev,
> - irq_handler_t handler, irq_handler_t thread_fn,
> - const char *name, void *data, int intr_src,
> - enum mic_intr_type type);
> -void mic_free_irq(struct mic_device *mdev,
> - struct mic_irq *cookie, void *data);
> -int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
> -void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
> -void mic_intr_restore(struct mic_device *mdev);
> -#endif
> diff --git a/drivers/misc/mic/host/mic_main.c
> b/drivers/misc/mic/host/mic_main.c
> deleted file mode 100644
> index ea4608527ea0..000000000000
> --- a/drivers/misc/mic/host/mic_main.c
> +++ /dev/null
> @@ -1,335 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/fs.h>
> -#include <linux/module.h>
> -#include <linux/pci.h>
> -#include <linux/poll.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_x100.h"
> -#include "mic_smpt.h"
> -
> -static const char mic_driver_name[] = "mic";
> -
> -static const struct pci_device_id mic_pci_tbl[] = {
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
> - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
> -
> - /* required last entry */
> - { 0, }
> -};
> -
> -MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
> -
> -/* ID allocator for MIC devices */
> -static struct ida g_mic_ida;
> -
> -/* Initialize the device page */
> -static int mic_dp_init(struct mic_device *mdev)
> -{
> - mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
> - if (!mdev->dp)
> - return -ENOMEM;
> -
> - mdev->dp_dma_addr = mic_map_single(mdev,
> - mdev->dp, MIC_DP_SIZE);
> - if (mic_map_error(mdev->dp_dma_addr)) {
> - kfree(mdev->dp);
> - dev_err(&mdev->pdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, -ENOMEM);
> - return -ENOMEM;
> - }
> - mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev-
> >dp_dma_addr);
> - mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev-
> >dp_dma_addr >> 32);
> - return 0;
> -}
> -
> -/* Uninitialize the device page */
> -static void mic_dp_uninit(struct mic_device *mdev)
> -{
> - mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
> - kfree(mdev->dp);
> -}
> -
> -/**
> - * mic_ops_init: Initialize HW specific operation tables.
> - *
> - * @mdev: pointer to mic_device instance
> - *
> - * returns none.
> - */
> -static void mic_ops_init(struct mic_device *mdev)
> -{
> - switch (mdev->family) {
> - case MIC_FAMILY_X100:
> - mdev->ops = &mic_x100_ops;
> - mdev->intr_ops = &mic_x100_intr_ops;
> - mdev->smpt_ops = &mic_x100_smpt_ops;
> - break;
> - default:
> - break;
> - }
> -}
> -
> -/**
> - * mic_get_family - Determine hardware family to which this MIC belongs.
> - *
> - * @pdev: The pci device structure
> - *
> - * returns family.
> - */
> -static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
> -{
> - enum mic_hw_family family;
> -
> - switch (pdev->device) {
> - case MIC_X100_PCI_DEVICE_2250:
> - case MIC_X100_PCI_DEVICE_2251:
> - case MIC_X100_PCI_DEVICE_2252:
> - case MIC_X100_PCI_DEVICE_2253:
> - case MIC_X100_PCI_DEVICE_2254:
> - case MIC_X100_PCI_DEVICE_2255:
> - case MIC_X100_PCI_DEVICE_2256:
> - case MIC_X100_PCI_DEVICE_2257:
> - case MIC_X100_PCI_DEVICE_2258:
> - case MIC_X100_PCI_DEVICE_2259:
> - case MIC_X100_PCI_DEVICE_225a:
> - case MIC_X100_PCI_DEVICE_225b:
> - case MIC_X100_PCI_DEVICE_225c:
> - case MIC_X100_PCI_DEVICE_225d:
> - case MIC_X100_PCI_DEVICE_225e:
> - family = MIC_FAMILY_X100;
> - break;
> - default:
> - family = MIC_FAMILY_UNKNOWN;
> - break;
> - }
> - return family;
> -}
> -
> -/**
> - * mic_device_init - Allocates and initializes the MIC device structure
> - *
> - * @mdev: pointer to mic_device instance
> - * @pdev: The pci device structure
> - *
> - * returns none.
> - */
> -static void
> -mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
> -{
> - mdev->pdev = pdev;
> - mdev->family = mic_get_family(pdev);
> - mdev->stepping = pdev->revision;
> - mic_ops_init(mdev);
> - mutex_init(&mdev->mic_mutex);
> - mdev->irq_info.next_avail_src = 0;
> -}
> -
> -/**
> - * mic_probe - Device Initialization Routine
> - *
> - * @pdev: PCI device structure
> - * @ent: entry in mic_pci_tbl
> - *
> - * returns 0 on success, < 0 on failure.
> - */
> -static int mic_probe(struct pci_dev *pdev,
> - const struct pci_device_id *ent)
> -{
> - int rc;
> - struct mic_device *mdev;
> -
> - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
> - if (!mdev) {
> - rc = -ENOMEM;
> - goto mdev_alloc_fail;
> - }
> - mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS,
> GFP_KERNEL);
> - if (mdev->id < 0) {
> - rc = mdev->id;
> - dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
> - goto ida_fail;
> - }
> -
> - mic_device_init(mdev, pdev);
> -
> - rc = pci_enable_device(pdev);
> - if (rc) {
> - dev_err(&pdev->dev, "failed to enable pci device.\n");
> - goto ida_remove;
> - }
> -
> - pci_set_master(pdev);
> -
> - rc = pci_request_regions(pdev, mic_driver_name);
> - if (rc) {
> - dev_err(&pdev->dev, "failed to get pci regions.\n");
> - goto disable_device;
> - }
> -
> - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
> - if (rc) {
> - dev_err(&pdev->dev, "Cannot set DMA mask\n");
> - goto release_regions;
> - }
> -
> - mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
> - mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
> - mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
> - if (!mdev->mmio.va) {
> - dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
> - rc = -EIO;
> - goto release_regions;
> - }
> -
> - mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
> - mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
> - mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
> - if (!mdev->aper.va) {
> - dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
> - rc = -EIO;
> - goto unmap_mmio;
> - }
> -
> - mdev->intr_ops->intr_init(mdev);
> - rc = mic_setup_interrupts(mdev, pdev);
> - if (rc) {
> - dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
> - goto unmap_aper;
> - }
> - rc = mic_smpt_init(mdev);
> - if (rc) {
> - dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
> - goto free_interrupts;
> - }
> -
> - pci_set_drvdata(pdev, mdev);
> -
> - rc = mic_dp_init(mdev);
> - if (rc) {
> - dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
> - goto smpt_uninit;
> - }
> - mic_bootparam_init(mdev);
> - mic_create_debug_dir(mdev);
> -
> - mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev,
> &cosm_hw_ops);
> - if (IS_ERR(mdev->cosm_dev)) {
> - rc = PTR_ERR(mdev->cosm_dev);
> - dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
> - goto cleanup_debug_dir;
> - }
> - return 0;
> -cleanup_debug_dir:
> - mic_delete_debug_dir(mdev);
> - mic_dp_uninit(mdev);
> -smpt_uninit:
> - mic_smpt_uninit(mdev);
> -free_interrupts:
> - mic_free_interrupts(mdev, pdev);
> -unmap_aper:
> - iounmap(mdev->aper.va);
> -unmap_mmio:
> - iounmap(mdev->mmio.va);
> -release_regions:
> - pci_release_regions(pdev);
> -disable_device:
> - pci_disable_device(pdev);
> -ida_remove:
> - ida_simple_remove(&g_mic_ida, mdev->id);
> -ida_fail:
> - kfree(mdev);
> -mdev_alloc_fail:
> - dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
> - return rc;
> -}
> -
> -/**
> - * mic_remove - Device Removal Routine
> - * mic_remove is called by the PCI subsystem to alert the driver
> - * that it should release a PCI device.
> - *
> - * @pdev: PCI device structure
> - */
> -static void mic_remove(struct pci_dev *pdev)
> -{
> - struct mic_device *mdev;
> -
> - mdev = pci_get_drvdata(pdev);
> - if (!mdev)
> - return;
> -
> - cosm_unregister_device(mdev->cosm_dev);
> - mic_delete_debug_dir(mdev);
> - mic_dp_uninit(mdev);
> - mic_smpt_uninit(mdev);
> - mic_free_interrupts(mdev, pdev);
> - iounmap(mdev->aper.va);
> - iounmap(mdev->mmio.va);
> - pci_release_regions(pdev);
> - pci_disable_device(pdev);
> - ida_simple_remove(&g_mic_ida, mdev->id);
> - kfree(mdev);
> -}
> -
> -static struct pci_driver mic_driver = {
> - .name = mic_driver_name,
> - .id_table = mic_pci_tbl,
> - .probe = mic_probe,
> - .remove = mic_remove
> -};
> -
> -static int __init mic_init(void)
> -{
> - int ret;
> -
> - request_module("mic_x100_dma");
> - mic_init_debugfs();
> - ida_init(&g_mic_ida);
> - ret = pci_register_driver(&mic_driver);
> - if (ret) {
> - pr_err("pci_register_driver failed ret %d\n", ret);
> - goto cleanup_debugfs;
> - }
> - return 0;
> -cleanup_debugfs:
> - ida_destroy(&g_mic_ida);
> - mic_exit_debugfs();
> - return ret;
> -}
> -
> -static void __exit mic_exit(void)
> -{
> - pci_unregister_driver(&mic_driver);
> - ida_destroy(&g_mic_ida);
> - mic_exit_debugfs();
> -}
> -
> -module_init(mic_init);
> -module_exit(mic_exit);
> -
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/host/mic_smpt.c
> b/drivers/misc/mic/host/mic_smpt.c
> deleted file mode 100644
> index 50d1bebecd54..000000000000
> --- a/drivers/misc/mic/host/mic_smpt.c
> +++ /dev/null
> @@ -1,427 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/pci.h>
> -
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_smpt.h"
> -
> -static inline u64 mic_system_page_mask(struct mic_device *mdev)
> -{
> - return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
> -}
> -
> -static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev,
> dma_addr_t pa)
> -{
> - return (pa - mdev->smpt->info.base) >> mdev->smpt-
> >info.page_shift;
> -}
> -
> -static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
> -{
> - return mdev->smpt->info.base + (index * mdev->smpt-
> >info.page_size);
> -}
> -
> -static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
> -{
> - return pa & mic_system_page_mask(mdev);
> -}
> -
> -static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t
> pa)
> -{
> - return ALIGN(pa - mic_system_page_mask(mdev),
> - mdev->smpt->info.page_size);
> -}
> -
> -static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t
> pa)
> -{
> - return ALIGN(pa, mdev->smpt->info.page_size);
> -}
> -
> -/* Total Cumulative system memory accessible by MIC across all SMPT
> entries */
> -static inline u64 mic_max_system_memory(struct mic_device *mdev)
> -{
> - return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
> -}
> -
> -/* Maximum system memory address accessible by MIC */
> -static inline u64 mic_max_system_addr(struct mic_device *mdev)
> -{
> - return mdev->smpt->info.base + mic_max_system_memory(mdev) -
> 1ULL;
> -}
> -
> -/* Check if the DMA address is a MIC system memory address */
> -static inline bool
> -mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
> -{
> - return pa >= mdev->smpt->info.base && pa <=
> mic_max_system_addr(mdev);
> -}
> -
> -/* Populate an SMPT entry and update the reference counts. */
> -static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
> - int entries, struct mic_device *mdev)
> -{
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> - int i;
> -
> - for (i = spt; i < spt + entries; i++,
> - addr += smpt_info->info.page_size) {
> - if (!smpt_info->entry[i].ref_count &&
> - (smpt_info->entry[i].dma_addr != addr)) {
> - mdev->smpt_ops->set(mdev, addr, i);
> - smpt_info->entry[i].dma_addr = addr;
> - }
> - smpt_info->entry[i].ref_count += ref[i - spt];
> - }
> -}
> -
> -/*
> - * Find an available MIC address in MIC SMPT address space
> - * for a given DMA address and size.
> - */
> -static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
> - int entries, s64 *ref, size_t size)
> -{
> - int spt;
> - int ae = 0;
> - int i;
> - unsigned long flags;
> - dma_addr_t mic_addr = 0;
> - dma_addr_t addr = dma_addr;
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> -
> - spin_lock_irqsave(&smpt_info->smpt_lock, flags);
> -
> - /* find existing entries */
> - for (i = 0; i < smpt_info->info.num_reg; i++) {
> - if (smpt_info->entry[i].dma_addr == addr) {
> - ae++;
> - addr += smpt_info->info.page_size;
> - } else if (ae) /* cannot find contiguous entries */
> - goto not_found;
> -
> - if (ae == entries)
> - goto found;
> - }
> -
> - /* find free entry */
> - for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
> - ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
> - if (ae == entries)
> - goto found;
> - }
> -
> -not_found:
> - spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
> - return mic_addr;
> -
> -found:
> - spt = i - entries + 1;
> - mic_addr = mic_smpt_to_pa(mdev, spt);
> - mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
> - smpt_info->map_count++;
> - smpt_info->ref_count += (s64)size;
> - spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
> - return mic_addr;
> -}
> -
> -/*
> - * Returns number of smpt entries needed for dma_addr to dma_addr + size
> - * also returns the reference count array for each of those entries
> - * and the starting smpt address
> - */
> -static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t
> dma_addr,
> - size_t size, s64 *ref, u64 *smpt_start)
> -{
> - u64 start = dma_addr;
> - u64 end = dma_addr + size;
> - int i = 0;
> -
> - while (start < end) {
> - ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
> - end) - start;
> - start = mic_smpt_align_high(mdev, start + 1);
> - }
> -
> - if (smpt_start)
> - *smpt_start = mic_smpt_align_low(mdev, dma_addr);
> -
> - return i;
> -}
> -
> -/*
> - * mic_to_dma_addr - Converts a MIC address to a DMA address.
> - *
> - * @mdev: pointer to mic_device instance.
> - * @mic_addr: MIC address.
> - *
> - * returns a DMA address.
> - */
> -dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t
> mic_addr)
> -{
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> - int spt;
> - dma_addr_t dma_addr;
> -
> - if (!mic_is_system_addr(mdev, mic_addr)) {
> - dev_err(&mdev->pdev->dev,
> - "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
> - return -EINVAL;
> - }
> - spt = mic_sys_addr_to_smpt(mdev, mic_addr);
> - dma_addr = smpt_info->entry[spt].dma_addr +
> - mic_smpt_offset(mdev, mic_addr);
> - return dma_addr;
> -}
> -
> -/**
> - * mic_map - Maps a DMA address to a MIC physical address.
> - *
> - * @mdev: pointer to mic_device instance.
> - * @dma_addr: DMA address.
> - * @size: Size of the region to be mapped.
> - *
> - * This API converts the DMA address provided to a DMA address
> understood
> - * by MIC. Caller should check for errors by calling mic_map_error(..).
> - *
> - * returns DMA address as required by MIC.
> - */
> -dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr,
> size_t size)
> -{
> - dma_addr_t mic_addr = 0;
> - int num_entries;
> - s64 *ref;
> - u64 smpt_start;
> -
> - if (!size || size > mic_max_system_memory(mdev))
> - return mic_addr;
> -
> - ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64),
> GFP_ATOMIC);
> - if (!ref)
> - return mic_addr;
> -
> - num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
> - ref, &smpt_start);
> -
> - /* Set the smpt table appropriately and get 16G aligned mic address
> */
> - mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
> -
> - kfree(ref);
> -
> - /*
> - * If mic_addr is zero then its an error case
> - * since mic_addr can never be zero.
> - * else generate mic_addr by adding the 16G offset in dma_addr
> - */
> - if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
> - dev_err(&mdev->pdev->dev,
> - "mic_map failed dma_addr 0x%llx size 0x%lx\n",
> - dma_addr, size);
> - return mic_addr;
> - } else {
> - return mic_addr + mic_smpt_offset(mdev, dma_addr);
> - }
> -}
> -
> -/**
> - * mic_unmap - Unmaps a MIC physical address.
> - *
> - * @mdev: pointer to mic_device instance.
> - * @mic_addr: MIC physical address.
> - * @size: Size of the region to be unmapped.
> - *
> - * This API unmaps the mappings created by mic_map(..).
> - *
> - * returns None.
> - */
> -void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t
> size)
> -{
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> - s64 *ref;
> - int num_smpt;
> - int spt;
> - int i;
> - unsigned long flags;
> -
> - if (!size)
> - return;
> -
> - if (!mic_is_system_addr(mdev, mic_addr)) {
> - dev_err(&mdev->pdev->dev,
> - "invalid address: 0x%llx\n", mic_addr);
> - return;
> - }
> -
> - spt = mic_sys_addr_to_smpt(mdev, mic_addr);
> - ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64),
> GFP_ATOMIC);
> - if (!ref)
> - return;
> -
> - /* Get number of smpt entries to be mapped, ref count array */
> - num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref,
> NULL);
> -
> - spin_lock_irqsave(&smpt_info->smpt_lock, flags);
> - smpt_info->unmap_count++;
> - smpt_info->ref_count -= (s64)size;
> -
> - for (i = spt; i < spt + num_smpt; i++) {
> - smpt_info->entry[i].ref_count -= ref[i - spt];
> - if (smpt_info->entry[i].ref_count < 0)
> - dev_warn(&mdev->pdev->dev,
> - "ref count for entry %d is negative\n", i);
> - }
> - spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
> - kfree(ref);
> -}
> -
> -/**
> - * mic_map_single - Maps a virtual address to a MIC physical address.
> - *
> - * @mdev: pointer to mic_device instance.
> - * @va: Kernel direct mapped virtual address.
> - * @size: Size of the region to be mapped.
> - *
> - * This API calls pci_map_single(..) for the direct mapped virtual address
> - * and then converts the DMA address provided to a DMA address
> understood
> - * by MIC. Caller should check for errors by calling mic_map_error(..).
> - *
> - * returns DMA address as required by MIC.
> - */
> -dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
> -{
> - dma_addr_t mic_addr = 0;
> - struct pci_dev *pdev = mdev->pdev;
> - dma_addr_t dma_addr =
> - pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
> -
> - if (!pci_dma_mapping_error(pdev, dma_addr)) {
> - mic_addr = mic_map(mdev, dma_addr, size);
> - if (!mic_addr) {
> - dev_err(&mdev->pdev->dev,
> - "mic_map failed dma_addr 0x%llx size
> 0x%lx\n",
> - dma_addr, size);
> - pci_unmap_single(pdev, dma_addr,
> - size, PCI_DMA_BIDIRECTIONAL);
> - }
> - }
> - return mic_addr;
> -}
> -
> -/**
> - * mic_unmap_single - Unmaps a MIC physical address.
> - *
> - * @mdev: pointer to mic_device instance.
> - * @mic_addr: MIC physical address.
> - * @size: Size of the region to be unmapped.
> - *
> - * This API unmaps the mappings created by mic_map_single(..).
> - *
> - * returns None.
> - */
> -void
> -mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t
> size)
> -{
> - struct pci_dev *pdev = mdev->pdev;
> - dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
> - mic_unmap(mdev, mic_addr, size);
> - pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
> -}
> -
> -/**
> - * mic_smpt_init - Initialize MIC System Memory Page Tables.
> - *
> - * @mdev: pointer to mic_device instance.
> - *
> - * returns 0 for success and -errno for error.
> - */
> -int mic_smpt_init(struct mic_device *mdev)
> -{
> - int i, err = 0;
> - dma_addr_t dma_addr;
> - struct mic_smpt_info *smpt_info;
> -
> - mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
> - if (!mdev->smpt)
> - return -ENOMEM;
> -
> - smpt_info = mdev->smpt;
> - mdev->smpt_ops->init(mdev);
> - smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
> - sizeof(*smpt_info->entry),
> GFP_KERNEL);
> - if (!smpt_info->entry) {
> - err = -ENOMEM;
> - goto free_smpt;
> - }
> - spin_lock_init(&smpt_info->smpt_lock);
> - for (i = 0; i < smpt_info->info.num_reg; i++) {
> - dma_addr = i * smpt_info->info.page_size;
> - smpt_info->entry[i].dma_addr = dma_addr;
> - smpt_info->entry[i].ref_count = 0;
> - mdev->smpt_ops->set(mdev, dma_addr, i);
> - }
> - smpt_info->ref_count = 0;
> - smpt_info->map_count = 0;
> - smpt_info->unmap_count = 0;
> - return 0;
> -free_smpt:
> - kfree(smpt_info);
> - return err;
> -}
> -
> -/**
> - * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
> - *
> - * @mdev: pointer to mic_device instance.
> - *
> - * returns None.
> - */
> -void mic_smpt_uninit(struct mic_device *mdev)
> -{
> - struct mic_smpt_info *smpt_info = mdev->smpt;
> - int i;
> -
> - dev_dbg(&mdev->pdev->dev,
> - "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
> - mdev->id, smpt_info->ref_count,
> - smpt_info->map_count, smpt_info->unmap_count);
> -
> - for (i = 0; i < smpt_info->info.num_reg; i++) {
> - dev_dbg(&mdev->pdev->dev,
> - "SMPT entry[%d] dma_addr = 0x%llx ref_count
> = %lld\n",
> - i, smpt_info->entry[i].dma_addr,
> - smpt_info->entry[i].ref_count);
> - if (smpt_info->entry[i].ref_count)
> - dev_warn(&mdev->pdev->dev,
> - "ref count for entry %d is not zero\n", i);
> - }
> - kfree(smpt_info->entry);
> - kfree(smpt_info);
> -}
> -
> -/**
> - * mic_smpt_restore - Restore MIC System Memory Page Tables.
> - *
> - * @mdev: pointer to mic_device instance.
> - *
> - * Restore the SMPT registers to values previously stored in the
> - * SW data structures. Some MIC steppings lose register state
> - * across resets and this API should be called for performing
> - * a restore operation if required.
> - *
> - * returns None.
> - */
> -void mic_smpt_restore(struct mic_device *mdev)
> -{
> - int i;
> - dma_addr_t dma_addr;
> -
> - for (i = 0; i < mdev->smpt->info.num_reg; i++) {
> - dma_addr = mdev->smpt->entry[i].dma_addr;
> - mdev->smpt_ops->set(mdev, dma_addr, i);
> - }
> -}
> diff --git a/drivers/misc/mic/host/mic_smpt.h
> b/drivers/misc/mic/host/mic_smpt.h
> deleted file mode 100644
> index 3b1ec14a9d81..000000000000
> --- a/drivers/misc/mic/host/mic_smpt.h
> +++ /dev/null
> @@ -1,87 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#ifndef MIC_SMPT_H
> -#define MIC_SMPT_H
> -/**
> - * struct mic_smpt_ops - MIC HW specific SMPT operations.
> - * @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
> - * @set: Set the value for a particular SMPT entry.
> - */
> -struct mic_smpt_ops {
> - void (*init)(struct mic_device *mdev);
> - void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8
> index);
> -};
> -
> -/**
> - * struct mic_smpt - MIC SMPT entry information.
> - * @dma_addr: Base DMA address for this SMPT entry.
> - * @ref_count: Number of active mappings for this SMPT entry in bytes.
> - */
> -struct mic_smpt {
> - dma_addr_t dma_addr;
> - s64 ref_count;
> -};
> -
> -/**
> - * struct mic_smpt_hw_info - MIC SMPT hardware specific information.
> - * @num_reg: Number of SMPT registers.
> - * @page_shift: System memory page shift.
> - * @page_size: System memory page size.
> - * @base: System address base.
> - */
> -struct mic_smpt_hw_info {
> - u8 num_reg;
> - u8 page_shift;
> - u64 page_size;
> - u64 base;
> -};
> -
> -/**
> - * struct mic_smpt_info - MIC SMPT information.
> - * @entry: Array of SMPT entries.
> - * @smpt_lock: Spin lock protecting access to SMPT data structures.
> - * @info: Hardware specific SMPT information.
> - * @ref_count: Number of active SMPT mappings (for debug).
> - * @map_count: Number of SMPT mappings created (for debug).
> - * @unmap_count: Number of SMPT mappings destroyed (for debug).
> - */
> -struct mic_smpt_info {
> - struct mic_smpt *entry;
> - spinlock_t smpt_lock;
> - struct mic_smpt_hw_info info;
> - s64 ref_count;
> - s64 map_count;
> - s64 unmap_count;
> -};
> -
> -dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
> -void mic_unmap_single(struct mic_device *mdev,
> - dma_addr_t mic_addr, size_t size);
> -dma_addr_t mic_map(struct mic_device *mdev,
> - dma_addr_t dma_addr, size_t size);
> -void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t
> size);
> -dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t
> mic_addr);
> -
> -/**
> - * mic_map_error - Check a MIC address for errors.
> - *
> - * @mdev: pointer to mic_device instance.
> - *
> - * returns Whether there was an error during mic_map..(..) APIs.
> - */
> -static inline bool mic_map_error(dma_addr_t mic_addr)
> -{
> - return !mic_addr;
> -}
> -
> -int mic_smpt_init(struct mic_device *mdev);
> -void mic_smpt_uninit(struct mic_device *mdev);
> -void mic_smpt_restore(struct mic_device *mdev);
> -
> -#endif
> diff --git a/drivers/misc/mic/host/mic_x100.c
> b/drivers/misc/mic/host/mic_x100.c
> deleted file mode 100644
> index f5536c1ad607..000000000000
> --- a/drivers/misc/mic/host/mic_x100.c
> +++ /dev/null
> @@ -1,585 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#include <linux/fs.h>
> -#include <linux/pci.h>
> -#include <linux/sched.h>
> -#include <linux/firmware.h>
> -#include <linux/delay.h>
> -
> -#include "../common/mic_dev.h"
> -#include "mic_device.h"
> -#include "mic_x100.h"
> -#include "mic_smpt.h"
> -
> -static const u16 mic_x100_intr_init[] = {
> - MIC_X100_DOORBELL_IDX_START,
> - MIC_X100_DMA_IDX_START,
> - MIC_X100_ERR_IDX_START,
> - MIC_X100_NUM_DOORBELL,
> - MIC_X100_NUM_DMA,
> - MIC_X100_NUM_ERR,
> -};
> -
> -/**
> - * mic_x100_write_spad - write to the scratchpad register
> - * @mdev: pointer to mic_device instance
> - * @idx: index to the scratchpad register, 0 based
> - * @val: the data value to put into the register
> - *
> - * This function allows writing of a 32bit value to the indexed scratchpad
> - * register.
> - *
> - * RETURNS: none.
> - */
> -static void
> -mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
> -{
> - dev_dbg(&mdev->pdev->dev, "Writing 0x%x to scratch pad
> index %d\n",
> - val, idx);
> - mic_mmio_write(&mdev->mmio, val,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_SPAD0 + idx * 4);
> -}
> -
> -/**
> - * mic_x100_read_spad - read from the scratchpad register
> - * @mdev: pointer to mic_device instance
> - * @idx: index to scratchpad register, 0 based
> - *
> - * This function allows reading of the 32bit scratchpad register.
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static u32
> -mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
> -{
> - u32 val = mic_mmio_read(&mdev->mmio,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_SPAD0 + idx * 4);
> -
> - dev_dbg(&mdev->pdev->dev,
> - "Reading 0x%x from scratch pad index %d\n", val, idx);
> - return val;
> -}
> -
> -/**
> - * mic_x100_enable_interrupts - Enable interrupts.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_enable_interrupts(struct mic_device *mdev)
> -{
> - u32 reg;
> - struct mic_mw *mw = &mdev->mmio;
> - u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SICE0;
> - u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SIAC0;
> -
> - reg = mic_mmio_read(mw, sice0);
> - reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
> MIC_X100_SBOX_DMA_BITS(0xff);
> - mic_mmio_write(mw, reg, sice0);
> -
> - /*
> - * Enable auto-clear when enabling interrupts. Applicable only for
> - * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
> - */
> - if (mdev->irq_info.num_vectors > 1) {
> - reg = mic_mmio_read(mw, siac0);
> - reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
> - MIC_X100_SBOX_DMA_BITS(0xff);
> - mic_mmio_write(mw, reg, siac0);
> - }
> -}
> -
> -/**
> - * mic_x100_disable_interrupts - Disable interrupts.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_disable_interrupts(struct mic_device *mdev)
> -{
> - u32 reg;
> - struct mic_mw *mw = &mdev->mmio;
> - u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SICE0;
> - u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SIAC0;
> - u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SICC0;
> -
> - reg = mic_mmio_read(mw, sice0);
> - mic_mmio_write(mw, reg, sicc0);
> -
> - if (mdev->irq_info.num_vectors > 1) {
> - reg = mic_mmio_read(mw, siac0);
> - reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
> - MIC_X100_SBOX_DMA_BITS(0xff));
> - mic_mmio_write(mw, reg, siac0);
> - }
> -}
> -
> -/**
> - * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
> - * @mdev: pointer to mic_device instance
> - * @doorbell: doorbell number
> - */
> -static void mic_x100_send_sbox_intr(struct mic_device *mdev,
> - int doorbell)
> -{
> - struct mic_mw *mw = &mdev->mmio;
> - u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
> - u32 apicicr_low = mic_mmio_read(mw,
> MIC_X100_SBOX_BASE_ADDRESS +
> - apic_icr_offset);
> -
> - /* for MIC we need to make sure we "hit" the send_icr bit (13) */
> - apicicr_low = (apicicr_low | (1 << 13));
> -
> - /* Ensure that the interrupt is ordered w.r.t. previous stores. */
> - wmb();
> - mic_mmio_write(mw, apicicr_low,
> - MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
> -}
> -
> -/**
> - * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
> - * @mdev: pointer to mic_device instance
> - * @doorbell: doorbell number
> - */
> -static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
> - int doorbell)
> -{
> - int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
> - /* Ensure that the interrupt is ordered w.r.t. previous stores. */
> - wmb();
> - mic_mmio_write(&mdev->mmio, 0,
> - MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
> -}
> -
> -/**
> - * __mic_x100_send_intr - Send interrupt to MIC.
> - * @mdev: pointer to mic_device instance
> - * @doorbell: doorbell number.
> - */
> -static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
> -{
> - int rdmasr_db;
> - if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
> - mic_x100_send_sbox_intr(mdev, doorbell);
> - } else {
> - rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ;
> - mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
> - }
> -}
> -
> -/**
> - * mic_x100_ack_interrupt - Read the interrupt sources register and
> - * clear it. This function will be called in the MSI/INTx case.
> - * @mdev: Pointer to mic_device instance.
> - *
> - * Returns: bitmask of interrupt sources triggered.
> - */
> -static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
> -{
> - u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS +
> MIC_X100_SBOX_SICR0;
> - u32 reg = mic_mmio_read(&mdev->mmio, sicr0);
> - mic_mmio_write(&mdev->mmio, reg, sicr0);
> - return reg;
> -}
> -
> -/**
> - * mic_x100_intr_workarounds - These hardware specific workarounds are
> - * to be invoked everytime an interrupt is handled.
> - * @mdev: Pointer to mic_device instance.
> - *
> - * Returns: none
> - */
> -static void mic_x100_intr_workarounds(struct mic_device *mdev)
> -{
> - struct mic_mw *mw = &mdev->mmio;
> -
> - /* Clear pending bit array. */
> - if (MIC_A0_STEP == mdev->stepping)
> - mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_MSIXPBACR);
> -
> - if (mdev->stepping >= MIC_B0_STEP)
> - mdev->intr_ops->enable_interrupts(mdev);
> -}
> -
> -/**
> - * mic_x100_hw_intr_init - Initialize h/w specific interrupt
> - * information.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_hw_intr_init(struct mic_device *mdev)
> -{
> - mdev->intr_info = (struct mic_intr_info *)mic_x100_intr_init;
> -}
> -
> -/**
> - * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
> - * @mdev: pointer to mic_device instance
> - * @idx: index to the mapping register, 0 based
> - *
> - * This function allows reading of the 32bit MSI mapping register.
> - *
> - * RETURNS: The value in the register.
> - */
> -static u32
> -mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
> -{
> - return mic_mmio_read(&mdev->mmio,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_MXAR0 + idx * 4);
> -}
> -
> -/**
> - * mic_x100_program_msi_to_src_map - program the MSI mapping registers
> - * @mdev: pointer to mic_device instance
> - * @idx: index to the mapping register, 0 based
> - * @offset: The bit offset in the register that needs to be updated.
> - * @set: boolean specifying if the bit in the specified offset needs
> - * to be set or cleared.
> - *
> - * RETURNS: None.
> - */
> -static void
> -mic_x100_program_msi_to_src_map(struct mic_device *mdev,
> - int idx, int offset, bool set)
> -{
> - unsigned long reg;
> - struct mic_mw *mw = &mdev->mmio;
> - u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_MXAR0 + idx * 4;
> -
> - reg = mic_mmio_read(mw, mxar);
> - if (set)
> - __set_bit(offset, &reg);
> - else
> - __clear_bit(offset, &reg);
> - mic_mmio_write(mw, reg, mxar);
> -}
> -
> -/*
> - * mic_x100_reset_fw_ready - Reset Firmware ready status field.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_reset_fw_ready(struct mic_device *mdev)
> -{
> - mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0);
> -}
> -
> -/*
> - * mic_x100_is_fw_ready - Check if firmware is ready.
> - * @mdev: pointer to mic_device instance
> - */
> -static bool mic_x100_is_fw_ready(struct mic_device *mdev)
> -{
> - u32 scratch2 = mdev->ops->read_spad(mdev,
> MIC_X100_DOWNLOAD_INFO);
> - return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true :
> false;
> -}
> -
> -/**
> - * mic_x100_get_apic_id - Get bootstrap APIC ID.
> - * @mdev: pointer to mic_device instance
> - */
> -static u32 mic_x100_get_apic_id(struct mic_device *mdev)
> -{
> - u32 scratch2 = 0;
> -
> - scratch2 = mdev->ops->read_spad(mdev,
> MIC_X100_DOWNLOAD_INFO);
> - return MIC_X100_SPAD2_APIC_ID(scratch2);
> -}
> -
> -/**
> - * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_send_firmware_intr(struct mic_device *mdev)
> -{
> - u32 apicicr_low;
> - u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
> - int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
> - struct mic_mw *mw = &mdev->mmio;
> -
> - /*
> - * For MIC we need to make sure we "hit"
> - * the send_icr bit (13).
> - */
> - apicicr_low = (vector | (1 << 13));
> -
> - mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
> - MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);
> -
> - /* Ensure that the interrupt is ordered w.r.t. previous stores. */
> - wmb();
> - mic_mmio_write(mw, apicicr_low,
> - MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
> -}
> -
> -/**
> - * mic_x100_hw_reset - Reset the MIC device.
> - * @mdev: pointer to mic_device instance
> - */
> -static void mic_x100_hw_reset(struct mic_device *mdev)
> -{
> - u32 reset_reg;
> - u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
> - struct mic_mw *mw = &mdev->mmio;
> -
> - /* Ensure that the reset is ordered w.r.t. previous loads and stores */
> - mb();
> - /* Trigger reset */
> - reset_reg = mic_mmio_read(mw, rgcr);
> - reset_reg |= 0x1;
> - mic_mmio_write(mw, reset_reg, rgcr);
> - /*
> - * It seems we really want to delay at least 1 second
> - * after touching reset to prevent a lot of problems.
> - */
> - msleep(1000);
> -}
> -
> -/**
> - * mic_x100_load_command_line - Load command line to MIC.
> - * @mdev: pointer to mic_device instance
> - * @fw: the firmware image
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int
> -mic_x100_load_command_line(struct mic_device *mdev, const struct
> firmware *fw)
> -{
> - u32 len = 0;
> - u32 boot_mem;
> - char *buf;
> - void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr +
> fw->size;
> -#define CMDLINE_SIZE 2048
> -
> - boot_mem = mdev->aper.len >> 20;
> - buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
> - if (!buf)
> - return -ENOMEM;
> -
> - len += scnprintf(buf, CMDLINE_SIZE - len,
> - " mem=%dM", boot_mem);
> - if (mdev->cosm_dev->cmdline)
> - scnprintf(buf + len, CMDLINE_SIZE - len, " %s",
> - mdev->cosm_dev->cmdline);
> - memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
> - kfree(buf);
> - return 0;
> -}
> -
> -/**
> - * mic_x100_load_ramdisk - Load ramdisk to MIC.
> - * @mdev: pointer to mic_device instance
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int
> -mic_x100_load_ramdisk(struct mic_device *mdev)
> -{
> - const struct firmware *fw;
> - int rc;
> - struct boot_params __iomem *bp = mdev->aper.va + mdev-
> >bootaddr;
> -
> - rc = request_firmware(&fw, mdev->cosm_dev->ramdisk, &mdev-
> >pdev->dev);
> - if (rc < 0) {
> - dev_err(&mdev->pdev->dev,
> - "ramdisk request_firmware failed: %d %s\n",
> - rc, mdev->cosm_dev->ramdisk);
> - goto error;
> - }
> - /*
> - * Typically the bootaddr for card OS is 64M
> - * so copy over the ramdisk @ 128M.
> - */
> - memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data,
> fw->size);
> - iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image);
> - iowrite32(fw->size, &bp->hdr.ramdisk_size);
> - release_firmware(fw);
> -error:
> - return rc;
> -}
> -
> -/**
> - * mic_x100_get_boot_addr - Get MIC boot address.
> - * @mdev: pointer to mic_device instance
> - *
> - * This function is called during firmware load to determine
> - * the address at which the OS should be downloaded in card
> - * memory i.e. GDDR.
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int
> -mic_x100_get_boot_addr(struct mic_device *mdev)
> -{
> - u32 scratch2, boot_addr;
> - int rc = 0;
> -
> - scratch2 = mdev->ops->read_spad(mdev,
> MIC_X100_DOWNLOAD_INFO);
> - boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
> - dev_dbg(&mdev->pdev->dev, "%s %d boot_addr 0x%x\n",
> - __func__, __LINE__, boot_addr);
> - if (boot_addr > (1 << 31)) {
> - dev_err(&mdev->pdev->dev,
> - "incorrect bootaddr 0x%x\n",
> - boot_addr);
> - rc = -EINVAL;
> - goto error;
> - }
> - mdev->bootaddr = boot_addr;
> -error:
> - return rc;
> -}
> -
> -/**
> - * mic_x100_load_firmware - Load firmware to MIC.
> - * @mdev: pointer to mic_device instance
> - * @buf: buffer containing boot string including firmware/ramdisk path.
> - *
> - * RETURNS: An appropriate -ERRNO error value on error, or zero for
> success.
> - */
> -static int
> -mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
> -{
> - int rc;
> - const struct firmware *fw;
> -
> - rc = mic_x100_get_boot_addr(mdev);
> - if (rc)
> - return rc;
> - /* load OS */
> - rc = request_firmware(&fw, mdev->cosm_dev->firmware, &mdev-
> >pdev->dev);
> - if (rc < 0) {
> - dev_err(&mdev->pdev->dev,
> - "ramdisk request_firmware failed: %d %s\n",
> - rc, mdev->cosm_dev->firmware);
> - return rc;
> - }
> - if (mdev->bootaddr > mdev->aper.len - fw->size) {
> - rc = -EINVAL;
> - dev_err(&mdev->pdev->dev, "%s %d rc %d bootaddr
> 0x%x\n",
> - __func__, __LINE__, rc, mdev->bootaddr);
> - goto error;
> - }
> - memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
> - mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
> - if (!strcmp(mdev->cosm_dev->bootmode, "flash")) {
> - rc = -EINVAL;
> - dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
> - __func__, __LINE__, rc);
> - goto error;
> - }
> - /* load command line */
> - rc = mic_x100_load_command_line(mdev, fw);
> - if (rc) {
> - dev_err(&mdev->pdev->dev, "%s %d rc %d\n",
> - __func__, __LINE__, rc);
> - goto error;
> - }
> - release_firmware(fw);
> - /* load ramdisk */
> - if (mdev->cosm_dev->ramdisk)
> - rc = mic_x100_load_ramdisk(mdev);
> -
> - return rc;
> -
> -error:
> - release_firmware(fw);
> - return rc;
> -}
> -
> -/**
> - * mic_x100_get_postcode - Get postcode status from firmware.
> - * @mdev: pointer to mic_device instance
> - *
> - * RETURNS: postcode.
> - */
> -static u32 mic_x100_get_postcode(struct mic_device *mdev)
> -{
> - return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
> -}
> -
> -/**
> - * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
> - * @mdev: pointer to mic_device instance
> - * @dma_addr: DMA address to use
> - * @index: entry to write to
> - *
> - * RETURNS: none.
> - */
> -static void
> -mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8
> index)
> -{
> -#define SNOOP_ON (0 << 0)
> -#define SNOOP_OFF (1 << 0)
> -/*
> - * Sbox Smpt Reg Bits:
> - * Bits 31:2 Host address
> - * Bits 1 RSVD
> - * Bits 0 No snoop
> - */
> -#define BUILD_SMPT(NO_SNOOP, HOST_ADDR) \
> - (u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
> -
> - uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
> - dma_addr >> mdev->smpt->info.page_shift);
> - mic_mmio_write(&mdev->mmio, smpt_reg_val,
> - MIC_X100_SBOX_BASE_ADDRESS +
> - MIC_X100_SBOX_SMPT00 + (4 * index));
> -}
> -
> -/**
> - * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
> - * @mdev: pointer to mic_device instance
> - *
> - * RETURNS: none.
> - */
> -static void mic_x100_smpt_hw_init(struct mic_device *mdev)
> -{
> - struct mic_smpt_hw_info *info = &mdev->smpt->info;
> -
> - info->num_reg = 32;
> - info->page_shift = 34;
> - info->page_size = (1ULL << info->page_shift);
> - info->base = 0x8000000000ULL;
> -}
> -
> -struct mic_smpt_ops mic_x100_smpt_ops = {
> - .init = mic_x100_smpt_hw_init,
> - .set = mic_x100_smpt_set,
> -};
> -
> -static bool mic_x100_dma_filter(struct dma_chan *chan, void *param)
> -{
> - if (chan->device->dev->parent == (struct device *)param)
> - return true;
> - return false;
> -}
> -
> -struct mic_hw_ops mic_x100_ops = {
> - .aper_bar = MIC_X100_APER_BAR,
> - .mmio_bar = MIC_X100_MMIO_BAR,
> - .read_spad = mic_x100_read_spad,
> - .write_spad = mic_x100_write_spad,
> - .send_intr = mic_x100_send_intr,
> - .ack_interrupt = mic_x100_ack_interrupt,
> - .intr_workarounds = mic_x100_intr_workarounds,
> - .reset = mic_x100_hw_reset,
> - .reset_fw_ready = mic_x100_reset_fw_ready,
> - .is_fw_ready = mic_x100_is_fw_ready,
> - .send_firmware_intr = mic_x100_send_firmware_intr,
> - .load_mic_fw = mic_x100_load_firmware,
> - .get_postcode = mic_x100_get_postcode,
> - .dma_filter = mic_x100_dma_filter,
> -};
> -
> -struct mic_hw_intr_ops mic_x100_intr_ops = {
> - .intr_init = mic_x100_hw_intr_init,
> - .enable_interrupts = mic_x100_enable_interrupts,
> - .disable_interrupts = mic_x100_disable_interrupts,
> - .program_msi_to_src_map = mic_x100_program_msi_to_src_map,
> - .read_msi_to_src_map = mic_x100_read_msi_to_src_map,
> -};
> diff --git a/drivers/misc/mic/host/mic_x100.h
> b/drivers/misc/mic/host/mic_x100.h
> deleted file mode 100644
> index aebcaed6fa72..000000000000
> --- a/drivers/misc/mic/host/mic_x100.h
> +++ /dev/null
> @@ -1,77 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC Host driver.
> - */
> -#ifndef _MIC_X100_HW_H_
> -#define _MIC_X100_HW_H_
> -
> -#define MIC_X100_PCI_DEVICE_2250 0x2250
> -#define MIC_X100_PCI_DEVICE_2251 0x2251
> -#define MIC_X100_PCI_DEVICE_2252 0x2252
> -#define MIC_X100_PCI_DEVICE_2253 0x2253
> -#define MIC_X100_PCI_DEVICE_2254 0x2254
> -#define MIC_X100_PCI_DEVICE_2255 0x2255
> -#define MIC_X100_PCI_DEVICE_2256 0x2256
> -#define MIC_X100_PCI_DEVICE_2257 0x2257
> -#define MIC_X100_PCI_DEVICE_2258 0x2258
> -#define MIC_X100_PCI_DEVICE_2259 0x2259
> -#define MIC_X100_PCI_DEVICE_225a 0x225a
> -#define MIC_X100_PCI_DEVICE_225b 0x225b
> -#define MIC_X100_PCI_DEVICE_225c 0x225c
> -#define MIC_X100_PCI_DEVICE_225d 0x225d
> -#define MIC_X100_PCI_DEVICE_225e 0x225e
> -
> -#define MIC_X100_APER_BAR 0
> -#define MIC_X100_MMIO_BAR 4
> -
> -#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
> -#define MIC_X100_SBOX_SPAD0 0x0000AB20
> -#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
> -#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
> -#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
> -#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
> -#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
> -#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
> -
> -#define MIC_X100_SBOX_APICICR0 0x0000A9D0
> -#define MIC_X100_SBOX_SICR0 0x00009004
> -#define MIC_X100_SBOX_SICE0 0x0000900C
> -#define MIC_X100_SBOX_SICC0 0x00009010
> -#define MIC_X100_SBOX_SIAC0 0x00009014
> -#define MIC_X100_SBOX_MSIXPBACR 0x00009084
> -#define MIC_X100_SBOX_MXAR0 0x00009044
> -#define MIC_X100_SBOX_SMPT00 0x00003100
> -#define MIC_X100_SBOX_RDMASR0 0x0000B180
> -
> -#define MIC_X100_DOORBELL_IDX_START 0
> -#define MIC_X100_NUM_DOORBELL 4
> -#define MIC_X100_DMA_IDX_START 8
> -#define MIC_X100_NUM_DMA 8
> -#define MIC_X100_ERR_IDX_START 30
> -#define MIC_X100_NUM_ERR 1
> -
> -#define MIC_X100_NUM_SBOX_IRQ 8
> -#define MIC_X100_NUM_RDMASR_IRQ 8
> -#define MIC_X100_RDMASR_IRQ_BASE 17
> -#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1)
> -#define MIC_X100_SPAD2_APIC_ID(x) (((x) >> 1) & 0x1ff)
> -#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000)
> -#define MIC_X100_SBOX_APICICR7 0x0000AA08
> -#define MIC_X100_SBOX_RGCR 0x00004010
> -#define MIC_X100_SBOX_SDBIC0 0x0000CC90
> -#define MIC_X100_DOWNLOAD_INFO 2
> -#define MIC_X100_FW_SIZE 5
> -#define MIC_X100_POSTCODE 0x242c
> -
> -/* Host->Card(bootstrap) Interrupt Vector */
> -#define MIC_X100_BSP_INTERRUPT_VECTOR 229
> -
> -extern struct mic_hw_ops mic_x100_ops;
> -extern struct mic_smpt_ops mic_x100_smpt_ops;
> -extern struct mic_hw_intr_ops mic_x100_intr_ops;
> -
> -#endif
> diff --git a/drivers/misc/mic/scif/Makefile b/drivers/misc/mic/scif/Makefile
> deleted file mode 100644
> index ff372555d118..000000000000
> --- a/drivers/misc/mic/scif/Makefile
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -#
> -# Makefile - SCIF driver.
> -# Copyright(c) 2014, Intel Corporation.
> -#
> -obj-$(CONFIG_SCIF) += scif.o
> -scif-objs := scif_main.o
> -scif-objs += scif_peer_bus.o
> -scif-objs += scif_ports.o
> -scif-objs += scif_debugfs.o
> -scif-objs += scif_fd.o
> -scif-objs += scif_api.o
> -scif-objs += scif_epd.o
> -scif-objs += scif_rb.o
> -scif-objs += scif_nodeqp.o
> -scif-objs += scif_nm.o
> -scif-objs += scif_dma.o
> -scif-objs += scif_fence.o
> -scif-objs += scif_mmap.o
> -scif-objs += scif_rma.o
> -scif-objs += scif_rma_list.o
> diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c
> deleted file mode 100644
> index 304d6c833712..000000000000
> --- a/drivers/misc/mic/scif/scif_api.c
> +++ /dev/null
> @@ -1,1485 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/scif.h>
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -static const char * const scif_ep_states[] = {
> - "Unbound",
> - "Bound",
> - "Listening",
> - "Connected",
> - "Connecting",
> - "Mapping",
> - "Closing",
> - "Close Listening",
> - "Disconnected",
> - "Zombie"};
> -
> -enum conn_async_state {
> - ASYNC_CONN_IDLE = 1, /* ep setup for async connect */
> - ASYNC_CONN_INPROGRESS, /* async connect in progress */
> - ASYNC_CONN_FLUSH_WORK /* async work flush in progress */
> -};
> -
> -/*
> - * File operations for anonymous inode file associated with a SCIF endpoint,
> - * used in kernel mode SCIF poll. Kernel mode SCIF poll calls portions of the
> - * poll API in the kernel and these take in a struct file *. Since a struct
> - * file is not available to kernel mode SCIF, it uses an anonymous file for
> - * this purpose.
> - */
> -const struct file_operations scif_anon_fops = {
> - .owner = THIS_MODULE,
> -};
> -
> -scif_epd_t scif_open(void)
> -{
> - struct scif_endpt *ep;
> - int err;
> -
> - might_sleep();
> - ep = kzalloc(sizeof(*ep), GFP_KERNEL);
> - if (!ep)
> - goto err_ep_alloc;
> -
> - ep->qp_info.qp = kzalloc(sizeof(*ep->qp_info.qp), GFP_KERNEL);
> - if (!ep->qp_info.qp)
> - goto err_qp_alloc;
> -
> - err = scif_anon_inode_getfile(ep);
> - if (err)
> - goto err_anon_inode;
> -
> - spin_lock_init(&ep->lock);
> - mutex_init(&ep->sendlock);
> - mutex_init(&ep->recvlock);
> -
> - scif_rma_ep_init(ep);
> - ep->state = SCIFEP_UNBOUND;
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI open: ep %p success\n", ep);
> - return ep;
> -
> -err_anon_inode:
> - kfree(ep->qp_info.qp);
> -err_qp_alloc:
> - kfree(ep);
> -err_ep_alloc:
> - return NULL;
> -}
> -EXPORT_SYMBOL_GPL(scif_open);
> -
> -/*
> - * scif_disconnect_ep - Disconnects the endpoint if found
> - * @epd: The end point returned from scif_open()
> - */
> -static struct scif_endpt *scif_disconnect_ep(struct scif_endpt *ep)
> -{
> - struct scifmsg msg;
> - struct scif_endpt *fep = NULL;
> - struct scif_endpt *tmpep;
> - struct list_head *pos, *tmpq;
> - int err;
> -
> - /*
> - * Wake up any threads blocked in send()/recv() before closing
> - * out the connection. Grabbing and releasing the send/recv lock
> - * will ensure that any blocked senders/receivers have exited for
> - * Ring 0 endpoints. It is a Ring 0 bug to call send/recv after
> - * close. Ring 3 endpoints are not affected since close will not
> - * be called while there are IOCTLs executing.
> - */
> - wake_up_interruptible(&ep->sendwq);
> - wake_up_interruptible(&ep->recvwq);
> - mutex_lock(&ep->sendlock);
> - mutex_unlock(&ep->sendlock);
> - mutex_lock(&ep->recvlock);
> - mutex_unlock(&ep->recvlock);
> -
> - /* Remove from the connected list */
> - mutex_lock(&scif_info.connlock);
> - list_for_each_safe(pos, tmpq, &scif_info.connected) {
> - tmpep = list_entry(pos, struct scif_endpt, list);
> - if (tmpep == ep) {
> - list_del(pos);
> - fep = tmpep;
> - spin_lock(&ep->lock);
> - break;
> - }
> - }
> -
> - if (!fep) {
> - /*
> - * The other side has completed the disconnect before
> - * the end point can be removed from the list. Therefore
> - * the ep lock is not locked, traverse the disconnected
> - * list to find the endpoint and release the conn lock.
> - */
> - list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
> - tmpep = list_entry(pos, struct scif_endpt, list);
> - if (tmpep == ep) {
> - list_del(pos);
> - break;
> - }
> - }
> - mutex_unlock(&scif_info.connlock);
> - return NULL;
> - }
> -
> - init_completion(&ep->discon);
> - msg.uop = SCIF_DISCNCT;
> - msg.src = ep->port;
> - msg.dst = ep->peer;
> - msg.payload[0] = (u64)ep;
> - msg.payload[1] = ep->remote_ep;
> -
> - err = scif_nodeqp_send(ep->remote_dev, &msg);
> - spin_unlock(&ep->lock);
> - mutex_unlock(&scif_info.connlock);
> -
> - if (!err)
> - /* Wait for the remote node to respond with
> SCIF_DISCNT_ACK */
> - wait_for_completion_timeout(&ep->discon,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - return ep;
> -}
> -
> -int scif_close(scif_epd_t epd)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scif_endpt *tmpep;
> - struct list_head *pos, *tmpq;
> - enum scif_epd_state oldstate;
> - bool flush_conn;
> -
> - dev_dbg(scif_info.mdev.this_device, "SCIFAPI close: ep %p %s\n",
> - ep, scif_ep_states[ep->state]);
> - might_sleep();
> - spin_lock(&ep->lock);
> - flush_conn = (ep->conn_async_state == ASYNC_CONN_INPROGRESS);
> - spin_unlock(&ep->lock);
> -
> - if (flush_conn)
> - flush_work(&scif_info.conn_work);
> -
> - spin_lock(&ep->lock);
> - oldstate = ep->state;
> -
> - ep->state = SCIFEP_CLOSING;
> -
> - switch (oldstate) {
> - case SCIFEP_ZOMBIE:
> - dev_err(scif_info.mdev.this_device,
> - "SCIFAPI close: zombie state unexpected\n");
> - fallthrough;
> - case SCIFEP_DISCONNECTED:
> - spin_unlock(&ep->lock);
> - scif_unregister_all_windows(epd);
> - /* Remove from the disconnected list */
> - mutex_lock(&scif_info.connlock);
> - list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
> - tmpep = list_entry(pos, struct scif_endpt, list);
> - if (tmpep == ep) {
> - list_del(pos);
> - break;
> - }
> - }
> - mutex_unlock(&scif_info.connlock);
> - break;
> - case SCIFEP_UNBOUND:
> - case SCIFEP_BOUND:
> - case SCIFEP_CONNECTING:
> - spin_unlock(&ep->lock);
> - break;
> - case SCIFEP_MAPPING:
> - case SCIFEP_CONNECTED:
> - case SCIFEP_CLOSING:
> - {
> - spin_unlock(&ep->lock);
> - scif_unregister_all_windows(epd);
> - scif_disconnect_ep(ep);
> - break;
> - }
> - case SCIFEP_LISTENING:
> - case SCIFEP_CLLISTEN:
> - {
> - struct scif_conreq *conreq;
> - struct scifmsg msg;
> - struct scif_endpt *aep;
> -
> - spin_unlock(&ep->lock);
> - mutex_lock(&scif_info.eplock);
> -
> - /* remove from listen list */
> - list_for_each_safe(pos, tmpq, &scif_info.listen) {
> - tmpep = list_entry(pos, struct scif_endpt, list);
> - if (tmpep == ep)
> - list_del(pos);
> - }
> - /* Remove any dangling accepts */
> - while (ep->acceptcnt) {
> - aep = list_first_entry(&ep->li_accept,
> - struct scif_endpt, liacceptlist);
> - list_del(&aep->liacceptlist);
> - scif_put_port(aep->port.port);
> - list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
> - tmpep = list_entry(pos, struct scif_endpt,
> - miacceptlist);
> - if (tmpep == aep) {
> - list_del(pos);
> - break;
> - }
> - }
> - mutex_unlock(&scif_info.eplock);
> - mutex_lock(&scif_info.connlock);
> - list_for_each_safe(pos, tmpq, &scif_info.connected)
> {
> - tmpep = list_entry(pos,
> - struct scif_endpt, list);
> - if (tmpep == aep) {
> - list_del(pos);
> - break;
> - }
> - }
> - list_for_each_safe(pos, tmpq,
> &scif_info.disconnected) {
> - tmpep = list_entry(pos,
> - struct scif_endpt, list);
> - if (tmpep == aep) {
> - list_del(pos);
> - break;
> - }
> - }
> - mutex_unlock(&scif_info.connlock);
> - scif_teardown_ep(aep);
> - mutex_lock(&scif_info.eplock);
> - scif_add_epd_to_zombie_list(aep,
> SCIF_EPLOCK_HELD);
> - ep->acceptcnt--;
> - }
> -
> - spin_lock(&ep->lock);
> - mutex_unlock(&scif_info.eplock);
> -
> - /* Remove and reject any pending connection requests. */
> - while (ep->conreqcnt) {
> - conreq = list_first_entry(&ep->conlist,
> - struct scif_conreq, list);
> - list_del(&conreq->list);
> -
> - msg.uop = SCIF_CNCT_REJ;
> - msg.dst.node = conreq->msg.src.node;
> - msg.dst.port = conreq->msg.src.port;
> - msg.payload[0] = conreq->msg.payload[0];
> - msg.payload[1] = conreq->msg.payload[1];
> - /*
> - * No Error Handling on purpose for
> scif_nodeqp_send().
> - * If the remote node is lost we still want free the
> - * connection requests on the self node.
> - */
> - scif_nodeqp_send(&scif_dev[conreq->msg.src.node],
> - &msg);
> - ep->conreqcnt--;
> - kfree(conreq);
> - }
> -
> - spin_unlock(&ep->lock);
> - /* If a kSCIF accept is waiting wake it up */
> - wake_up_interruptible(&ep->conwq);
> - break;
> - }
> - }
> - scif_put_port(ep->port.port);
> - scif_anon_inode_fput(ep);
> - scif_teardown_ep(ep);
> - scif_add_epd_to_zombie_list(ep, !SCIF_EPLOCK_HELD);
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(scif_close);
> -
> -/**
> - * scif_flush() - Wakes up any blocking accepts. The endpoint will no longer
> - * accept new connections.
> - * @epd: The end point returned from scif_open()
> - */
> -int __scif_flush(scif_epd_t epd)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> -
> - switch (ep->state) {
> - case SCIFEP_LISTENING:
> - {
> - ep->state = SCIFEP_CLLISTEN;
> -
> - /* If an accept is waiting wake it up */
> - wake_up_interruptible(&ep->conwq);
> - break;
> - }
> - default:
> - break;
> - }
> - return 0;
> -}
> -
> -int scif_bind(scif_epd_t epd, u16 pn)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int ret = 0;
> - int tmp;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI bind: ep %p %s requested port number %d\n",
> - ep, scif_ep_states[ep->state], pn);
> - if (pn) {
> - /*
> - * Similar to IETF RFC 1700, SCIF ports below
> - * SCIF_ADMIN_PORT_END can only be bound by system (or
> root)
> - * processes or by processes executed by privileged users.
> - */
> - if (pn < SCIF_ADMIN_PORT_END
> && !capable(CAP_SYS_ADMIN)) {
> - ret = -EACCES;
> - goto scif_bind_admin_exit;
> - }
> - }
> -
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_BOUND) {
> - ret = -EINVAL;
> - goto scif_bind_exit;
> - } else if (ep->state != SCIFEP_UNBOUND) {
> - ret = -EISCONN;
> - goto scif_bind_exit;
> - }
> -
> - if (pn) {
> - tmp = scif_rsrv_port(pn);
> - if (tmp != pn) {
> - ret = -EINVAL;
> - goto scif_bind_exit;
> - }
> - } else {
> - ret = scif_get_new_port();
> - if (ret < 0)
> - goto scif_bind_exit;
> - pn = ret;
> - }
> -
> - ep->state = SCIFEP_BOUND;
> - ep->port.node = scif_info.nodeid;
> - ep->port.port = pn;
> - ep->conn_async_state = ASYNC_CONN_IDLE;
> - ret = pn;
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI bind: bound to port number %d\n", pn);
> -scif_bind_exit:
> - spin_unlock(&ep->lock);
> -scif_bind_admin_exit:
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(scif_bind);
> -
> -int scif_listen(scif_epd_t epd, int backlog)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI listen: ep %p %s\n", ep, scif_ep_states[ep->state]);
> - spin_lock(&ep->lock);
> - switch (ep->state) {
> - case SCIFEP_ZOMBIE:
> - case SCIFEP_CLOSING:
> - case SCIFEP_CLLISTEN:
> - case SCIFEP_UNBOUND:
> - case SCIFEP_DISCONNECTED:
> - spin_unlock(&ep->lock);
> - return -EINVAL;
> - case SCIFEP_LISTENING:
> - case SCIFEP_CONNECTED:
> - case SCIFEP_CONNECTING:
> - case SCIFEP_MAPPING:
> - spin_unlock(&ep->lock);
> - return -EISCONN;
> - case SCIFEP_BOUND:
> - break;
> - }
> -
> - ep->state = SCIFEP_LISTENING;
> - ep->backlog = backlog;
> -
> - ep->conreqcnt = 0;
> - ep->acceptcnt = 0;
> - INIT_LIST_HEAD(&ep->conlist);
> - init_waitqueue_head(&ep->conwq);
> - INIT_LIST_HEAD(&ep->li_accept);
> - spin_unlock(&ep->lock);
> -
> - /*
> - * Listen status is complete so delete the qp information not needed
> - * on a listen before placing on the list of listening ep's
> - */
> - scif_teardown_ep(ep);
> - ep->qp_info.qp = NULL;
> -
> - mutex_lock(&scif_info.eplock);
> - list_add_tail(&ep->list, &scif_info.listen);
> - mutex_unlock(&scif_info.eplock);
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(scif_listen);
> -
> -/*
> -
> ****************************************************************
> ********
> - * SCIF connection flow:
> - *
> - * 1) A SCIF listening endpoint can call scif_accept(..) to wait for SCIF
> - * connections via a SCIF_CNCT_REQ message
> - * 2) A SCIF endpoint can initiate a SCIF connection by calling
> - * scif_connect(..) which calls scif_setup_qp_connect(..) which
> - * allocates the local qp for the endpoint ring buffer and then sends
> - * a SCIF_CNCT_REQ to the remote node and waits for a
> SCIF_CNCT_GNT or
> - * a SCIF_CNCT_REJ message
> - * 3) The peer node handles a SCIF_CNCT_REQ via scif_cnctreq_resp(..)
> which
> - * wakes up any threads blocked in step 1 or sends a SCIF_CNCT_REJ
> - * message otherwise
> - * 4) A thread blocked waiting for incoming connections allocates its local
> - * endpoint QP and ring buffer following which it sends a
> SCIF_CNCT_GNT
> - * and waits for a SCIF_CNCT_GNT(N)ACK. If the allocation fails then
> - * the node sends a SCIF_CNCT_REJ message
> - * 5) Upon receipt of a SCIF_CNCT_GNT or a SCIF_CNCT_REJ message the
> - * connecting endpoint is woken up as part of handling
> - * scif_cnctgnt_resp(..) following which it maps the remote endpoints'
> - * QP, updates its outbound QP and sends a SCIF_CNCT_GNTACK
> message on
> - * success or a SCIF_CNCT_GNTNACK message on failure and completes
> - * the scif_connect(..) API
> - * 6) Upon receipt of a SCIF_CNCT_GNT(N)ACK the accepting endpoint
> blocked
> - * in step 4 is woken up and completes the scif_accept(..) API
> - * 7) The SCIF connection is now established between the two SCIF
> endpoints.
> - */
> -static int scif_conn_func(struct scif_endpt *ep)
> -{
> - int err = 0;
> - struct scifmsg msg;
> - struct device *spdev;
> -
> - err = scif_reserve_dma_chan(ep);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - ep->state = SCIFEP_BOUND;
> - goto connect_error_simple;
> - }
> - /* Initiate the first part of the endpoint QP setup */
> - err = scif_setup_qp_connect(ep->qp_info.qp, &ep-
> >qp_info.qp_offset,
> - SCIF_ENDPT_QP_SIZE, ep->remote_dev);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s err %d qp_offset 0x%llx\n",
> - __func__, err, ep->qp_info.qp_offset);
> - ep->state = SCIFEP_BOUND;
> - goto connect_error_simple;
> - }
> -
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - goto cleanup_qp;
> - }
> - /* Format connect message and send it */
> - msg.src = ep->port;
> - msg.dst = ep->conn_port;
> - msg.uop = SCIF_CNCT_REQ;
> - msg.payload[0] = (u64)ep;
> - msg.payload[1] = ep->qp_info.qp_offset;
> - err = _scif_nodeqp_send(ep->remote_dev, &msg);
> - if (err)
> - goto connect_error_dec;
> - scif_put_peer_dev(spdev);
> - /*
> - * Wait for the remote node to respond with SCIF_CNCT_GNT or
> - * SCIF_CNCT_REJ message.
> - */
> - err = wait_event_timeout(ep->conwq, ep->state !=
> SCIFEP_CONNECTING,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d timeout\n", __func__, __LINE__);
> - ep->state = SCIFEP_BOUND;
> - }
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - goto cleanup_qp;
> - }
> - if (ep->state == SCIFEP_MAPPING) {
> - err = scif_setup_qp_connect_response(ep->remote_dev,
> - ep->qp_info.qp,
> - ep->qp_info.gnt_pld);
> - /*
> - * If the resource to map the queue are not available then
> - * we need to tell the other side to terminate the accept
> - */
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - msg.uop = SCIF_CNCT_GNTNACK;
> - msg.payload[0] = ep->remote_ep;
> - _scif_nodeqp_send(ep->remote_dev, &msg);
> - ep->state = SCIFEP_BOUND;
> - goto connect_error_dec;
> - }
> -
> - msg.uop = SCIF_CNCT_GNTACK;
> - msg.payload[0] = ep->remote_ep;
> - err = _scif_nodeqp_send(ep->remote_dev, &msg);
> - if (err) {
> - ep->state = SCIFEP_BOUND;
> - goto connect_error_dec;
> - }
> - ep->state = SCIFEP_CONNECTED;
> - mutex_lock(&scif_info.connlock);
> - list_add_tail(&ep->list, &scif_info.connected);
> - mutex_unlock(&scif_info.connlock);
> - dev_dbg(&ep->remote_dev->sdev->dev,
> - "SCIFAPI connect: ep %p connected\n", ep);
> - } else if (ep->state == SCIFEP_BOUND) {
> - dev_dbg(&ep->remote_dev->sdev->dev,
> - "SCIFAPI connect: ep %p connection refused\n", ep);
> - err = -ECONNREFUSED;
> - goto connect_error_dec;
> - }
> - scif_put_peer_dev(spdev);
> - return err;
> -connect_error_dec:
> - scif_put_peer_dev(spdev);
> -cleanup_qp:
> - scif_cleanup_ep_qp(ep);
> -connect_error_simple:
> - return err;
> -}
> -
> -/*
> - * scif_conn_handler:
> - *
> - * Workqueue handler for servicing non-blocking SCIF connect
> - *
> - */
> -void scif_conn_handler(struct work_struct *work)
> -{
> - struct scif_endpt *ep;
> -
> - do {
> - ep = NULL;
> - spin_lock(&scif_info.nb_connect_lock);
> - if (!list_empty(&scif_info.nb_connect_list)) {
> - ep = list_first_entry(&scif_info.nb_connect_list,
> - struct scif_endpt, conn_list);
> - list_del(&ep->conn_list);
> - }
> - spin_unlock(&scif_info.nb_connect_lock);
> - if (ep) {
> - ep->conn_err = scif_conn_func(ep);
> - wake_up_interruptible(&ep->conn_pend_wq);
> - }
> - } while (ep);
> -}
> -
> -int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> - struct scif_dev *remote_dev;
> - struct device *spdev;
> -
> - dev_dbg(scif_info.mdev.this_device, "SCIFAPI connect: ep %p %s\n",
> ep,
> - scif_ep_states[ep->state]);
> -
> - if (!scif_dev || dst->node > scif_info.maxid)
> - return -ENODEV;
> -
> - might_sleep();
> -
> - remote_dev = &scif_dev[dst->node];
> - spdev = scif_get_peer_dev(remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - return err;
> - }
> -
> - spin_lock(&ep->lock);
> - switch (ep->state) {
> - case SCIFEP_ZOMBIE:
> - case SCIFEP_CLOSING:
> - err = -EINVAL;
> - break;
> - case SCIFEP_DISCONNECTED:
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
> - ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
> - else
> - err = -EINVAL;
> - break;
> - case SCIFEP_LISTENING:
> - case SCIFEP_CLLISTEN:
> - err = -EOPNOTSUPP;
> - break;
> - case SCIFEP_CONNECTING:
> - case SCIFEP_MAPPING:
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
> - err = -EINPROGRESS;
> - else
> - err = -EISCONN;
> - break;
> - case SCIFEP_CONNECTED:
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
> - ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
> - else
> - err = -EISCONN;
> - break;
> - case SCIFEP_UNBOUND:
> - err = scif_get_new_port();
> - if (err < 0)
> - break;
> - ep->port.port = err;
> - ep->port.node = scif_info.nodeid;
> - ep->conn_async_state = ASYNC_CONN_IDLE;
> - fallthrough;
> - case SCIFEP_BOUND:
> - /*
> - * If a non-blocking connect has been already initiated
> - * (conn_async_state is either ASYNC_CONN_INPROGRESS or
> - * ASYNC_CONN_FLUSH_WORK), the end point could end up
> in
> - * SCIF_BOUND due an error in the connection process
> - * (e.g., connection refused) If conn_async_state is
> - * ASYNC_CONN_INPROGRESS - transition to
> ASYNC_CONN_FLUSH_WORK
> - * so that the error status can be collected. If the state is
> - * already ASYNC_CONN_FLUSH_WORK - then set the error to
> - * EINPROGRESS since some other thread is waiting to collect
> - * error status.
> - */
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
> - ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
> - } else if (ep->conn_async_state ==
> ASYNC_CONN_FLUSH_WORK) {
> - err = -EINPROGRESS;
> - } else {
> - ep->conn_port = *dst;
> - init_waitqueue_head(&ep->sendwq);
> - init_waitqueue_head(&ep->recvwq);
> - init_waitqueue_head(&ep->conwq);
> - ep->conn_async_state = 0;
> -
> - if (unlikely(non_block))
> - ep->conn_async_state =
> ASYNC_CONN_INPROGRESS;
> - }
> - break;
> - }
> -
> - if (err || ep->conn_async_state == ASYNC_CONN_FLUSH_WORK)
> - goto connect_simple_unlock1;
> -
> - ep->state = SCIFEP_CONNECTING;
> - ep->remote_dev = &scif_dev[dst->node];
> - ep->qp_info.qp->magic = SCIFEP_MAGIC;
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
> - init_waitqueue_head(&ep->conn_pend_wq);
> - spin_lock(&scif_info.nb_connect_lock);
> - list_add_tail(&ep->conn_list, &scif_info.nb_connect_list);
> - spin_unlock(&scif_info.nb_connect_lock);
> - err = -EINPROGRESS;
> - schedule_work(&scif_info.conn_work);
> - }
> -connect_simple_unlock1:
> - spin_unlock(&ep->lock);
> - scif_put_peer_dev(spdev);
> - if (err) {
> - return err;
> - } else if (ep->conn_async_state == ASYNC_CONN_FLUSH_WORK) {
> - flush_work(&scif_info.conn_work);
> - err = ep->conn_err;
> - spin_lock(&ep->lock);
> - ep->conn_async_state = ASYNC_CONN_IDLE;
> - spin_unlock(&ep->lock);
> - } else {
> - err = scif_conn_func(ep);
> - }
> - return err;
> -}
> -
> -int scif_connect(scif_epd_t epd, struct scif_port_id *dst)
> -{
> - return __scif_connect(epd, dst, false);
> -}
> -EXPORT_SYMBOL_GPL(scif_connect);
> -
> -/*
> - * scif_accept() - Accept a connection request from the remote node
> - *
> - * The function accepts a connection request from the remote node.
> Successful
> - * complete is indicate by a new end point being created and passed back
> - * to the caller for future reference.
> - *
> - * Upon successful complete a zero will be returned and the peer
> information
> - * will be filled in.
> - *
> - * If the end point is not in the listening state -EINVAL will be returned.
> - *
> - * If during the connection sequence resource allocation fails the -ENOMEM
> - * will be returned.
> - *
> - * If the function is called with the ASYNC flag set and no connection
> requests
> - * are pending it will return -EAGAIN.
> - *
> - * If the remote side is not sending any connection requests the caller may
> - * terminate this function with a signal. If so a -EINTR will be returned.
> - */
> -int scif_accept(scif_epd_t epd, struct scif_port_id *peer,
> - scif_epd_t *newepd, int flags)
> -{
> - struct scif_endpt *lep = (struct scif_endpt *)epd;
> - struct scif_endpt *cep;
> - struct scif_conreq *conreq;
> - struct scifmsg msg;
> - int err;
> - struct device *spdev;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI accept: ep %p %s\n", lep, scif_ep_states[lep->state]);
> -
> - if (flags & ~SCIF_ACCEPT_SYNC)
> - return -EINVAL;
> -
> - if (!peer || !newepd)
> - return -EINVAL;
> -
> - might_sleep();
> - spin_lock(&lep->lock);
> - if (lep->state != SCIFEP_LISTENING) {
> - spin_unlock(&lep->lock);
> - return -EINVAL;
> - }
> -
> - if (!lep->conreqcnt && !(flags & SCIF_ACCEPT_SYNC)) {
> - /* No connection request present and we do not want to
> wait */
> - spin_unlock(&lep->lock);
> - return -EAGAIN;
> - }
> -
> - lep->files = current->files;
> -retry_connection:
> - spin_unlock(&lep->lock);
> - /* Wait for the remote node to send us a SCIF_CNCT_REQ */
> - err = wait_event_interruptible(lep->conwq,
> - (lep->conreqcnt ||
> - (lep->state != SCIFEP_LISTENING)));
> - if (err)
> - return err;
> -
> - if (lep->state != SCIFEP_LISTENING)
> - return -EINTR;
> -
> - spin_lock(&lep->lock);
> -
> - if (!lep->conreqcnt)
> - goto retry_connection;
> -
> - /* Get the first connect request off the list */
> - conreq = list_first_entry(&lep->conlist, struct scif_conreq, list);
> - list_del(&conreq->list);
> - lep->conreqcnt--;
> - spin_unlock(&lep->lock);
> -
> - /* Fill in the peer information */
> - peer->node = conreq->msg.src.node;
> - peer->port = conreq->msg.src.port;
> -
> - cep = kzalloc(sizeof(*cep), GFP_KERNEL);
> - if (!cep) {
> - err = -ENOMEM;
> - goto scif_accept_error_epalloc;
> - }
> - spin_lock_init(&cep->lock);
> - mutex_init(&cep->sendlock);
> - mutex_init(&cep->recvlock);
> - cep->state = SCIFEP_CONNECTING;
> - cep->remote_dev = &scif_dev[peer->node];
> - cep->remote_ep = conreq->msg.payload[0];
> -
> - scif_rma_ep_init(cep);
> -
> - err = scif_reserve_dma_chan(cep);
> - if (err) {
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto scif_accept_error_qpalloc;
> - }
> -
> - cep->qp_info.qp = kzalloc(sizeof(*cep->qp_info.qp), GFP_KERNEL);
> - if (!cep->qp_info.qp) {
> - err = -ENOMEM;
> - goto scif_accept_error_qpalloc;
> - }
> -
> - err = scif_anon_inode_getfile(cep);
> - if (err)
> - goto scif_accept_error_anon_inode;
> -
> - cep->qp_info.qp->magic = SCIFEP_MAGIC;
> - spdev = scif_get_peer_dev(cep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - goto scif_accept_error_map;
> - }
> - err = scif_setup_qp_accept(cep->qp_info.qp, &cep-
> >qp_info.qp_offset,
> - conreq->msg.payload[1],
> SCIF_ENDPT_QP_SIZE,
> - cep->remote_dev);
> - if (err) {
> - dev_dbg(&cep->remote_dev->sdev->dev,
> - "SCIFAPI accept: ep %p new %p
> scif_setup_qp_accept %d qp_offset 0x%llx\n",
> - lep, cep, err, cep->qp_info.qp_offset);
> - scif_put_peer_dev(spdev);
> - goto scif_accept_error_map;
> - }
> -
> - cep->port.node = lep->port.node;
> - cep->port.port = lep->port.port;
> - cep->peer.node = peer->node;
> - cep->peer.port = peer->port;
> - init_waitqueue_head(&cep->sendwq);
> - init_waitqueue_head(&cep->recvwq);
> - init_waitqueue_head(&cep->conwq);
> -
> - msg.uop = SCIF_CNCT_GNT;
> - msg.src = cep->port;
> - msg.payload[0] = cep->remote_ep;
> - msg.payload[1] = cep->qp_info.qp_offset;
> - msg.payload[2] = (u64)cep;
> -
> - err = _scif_nodeqp_send(cep->remote_dev, &msg);
> - scif_put_peer_dev(spdev);
> - if (err)
> - goto scif_accept_error_map;
> -retry:
> - /* Wait for the remote node to respond with SCIF_CNCT_GNT(N)ACK
> */
> - err = wait_event_timeout(cep->conwq, cep->state !=
> SCIFEP_CONNECTING,
> - SCIF_NODE_ACCEPT_TIMEOUT);
> - if (!err && scifdev_alive(cep))
> - goto retry;
> - err = !err ? -ENODEV : 0;
> - if (err)
> - goto scif_accept_error_map;
> - kfree(conreq);
> -
> - spin_lock(&cep->lock);
> -
> - if (cep->state == SCIFEP_CLOSING) {
> - /*
> - * Remote failed to allocate resources and NAKed the grant.
> - * There is at this point nothing referencing the new end
> point.
> - */
> - spin_unlock(&cep->lock);
> - scif_teardown_ep(cep);
> - kfree(cep);
> -
> - /* If call with sync flag then go back and wait. */
> - if (flags & SCIF_ACCEPT_SYNC) {
> - spin_lock(&lep->lock);
> - goto retry_connection;
> - }
> - return -EAGAIN;
> - }
> -
> - scif_get_port(cep->port.port);
> - *newepd = (scif_epd_t)cep;
> - spin_unlock(&cep->lock);
> - return 0;
> -scif_accept_error_map:
> - scif_anon_inode_fput(cep);
> -scif_accept_error_anon_inode:
> - scif_teardown_ep(cep);
> -scif_accept_error_qpalloc:
> - kfree(cep);
> -scif_accept_error_epalloc:
> - msg.uop = SCIF_CNCT_REJ;
> - msg.dst.node = conreq->msg.src.node;
> - msg.dst.port = conreq->msg.src.port;
> - msg.payload[0] = conreq->msg.payload[0];
> - msg.payload[1] = conreq->msg.payload[1];
> - scif_nodeqp_send(&scif_dev[conreq->msg.src.node], &msg);
> - kfree(conreq);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_accept);
> -
> -/*
> - * scif_msg_param_check:
> - * @epd: The end point returned from scif_open()
> - * @len: Length to receive
> - * @flags: blocking or non blocking
> - *
> - * Validate parameters for messaging APIs scif_send(..)/scif_recv(..).
> - */
> -static inline int scif_msg_param_check(scif_epd_t epd, int len, int flags)
> -{
> - int ret = -EINVAL;
> -
> - if (len < 0)
> - goto err_ret;
> - if (flags && (!(flags & SCIF_RECV_BLOCK)))
> - goto err_ret;
> - ret = 0;
> -err_ret:
> - return ret;
> -}
> -
> -static int _scif_send(scif_epd_t epd, void *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scifmsg notif_msg;
> - int curr_xfer_len = 0, sent_len = 0, write_count;
> - int ret = 0;
> - struct scif_qp *qp = ep->qp_info.qp;
> -
> - if (flags & SCIF_SEND_BLOCK)
> - might_sleep();
> -
> - spin_lock(&ep->lock);
> - while (sent_len != len && SCIFEP_CONNECTED == ep->state) {
> - write_count = scif_rb_space(&qp->outbound_q);
> - if (write_count) {
> - /* Best effort to send as much data as possible */
> - curr_xfer_len = min(len - sent_len, write_count);
> - ret = scif_rb_write(&qp->outbound_q, msg,
> - curr_xfer_len);
> - if (ret < 0)
> - break;
> - /* Success. Update write pointer */
> - scif_rb_commit(&qp->outbound_q);
> - /*
> - * Send a notification to the peer about the
> - * produced data message.
> - */
> - notif_msg.src = ep->port;
> - notif_msg.uop = SCIF_CLIENT_SENT;
> - notif_msg.payload[0] = ep->remote_ep;
> - ret = _scif_nodeqp_send(ep->remote_dev,
> &notif_msg);
> - if (ret)
> - break;
> - sent_len += curr_xfer_len;
> - msg = msg + curr_xfer_len;
> - continue;
> - }
> - curr_xfer_len = min(len - sent_len, SCIF_ENDPT_QP_SIZE - 1);
> - /* Not enough RB space. return for the Non Blocking case */
> - if (!(flags & SCIF_SEND_BLOCK))
> - break;
> -
> - spin_unlock(&ep->lock);
> - /* Wait for a SCIF_CLIENT_RCVD message in the Blocking case
> */
> - ret =
> - wait_event_interruptible(ep->sendwq,
> - (SCIFEP_CONNECTED != ep->state) ||
> - (scif_rb_space(&qp-
> >outbound_q) >=
> - curr_xfer_len));
> - spin_lock(&ep->lock);
> - if (ret)
> - break;
> - }
> - if (sent_len)
> - ret = sent_len;
> - else if (!ret && SCIFEP_CONNECTED != ep->state)
> - ret = SCIFEP_DISCONNECTED == ep->state ?
> - -ECONNRESET : -ENOTCONN;
> - spin_unlock(&ep->lock);
> - return ret;
> -}
> -
> -static int _scif_recv(scif_epd_t epd, void *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scifmsg notif_msg;
> - int curr_recv_len = 0, remaining_len = len, read_count;
> - int ret = 0;
> - struct scif_qp *qp = ep->qp_info.qp;
> -
> - if (flags & SCIF_RECV_BLOCK)
> - might_sleep();
> - spin_lock(&ep->lock);
> - while (remaining_len && (SCIFEP_CONNECTED == ep->state ||
> - SCIFEP_DISCONNECTED == ep->state)) {
> - read_count = scif_rb_count(&qp->inbound_q,
> remaining_len);
> - if (read_count) {
> - /*
> - * Best effort to recv as much data as there
> - * are bytes to read in the RB particularly
> - * important for the Non Blocking case.
> - */
> - curr_recv_len = min(remaining_len, read_count);
> - scif_rb_get_next(&qp->inbound_q, msg,
> curr_recv_len);
> - if (ep->state == SCIFEP_CONNECTED) {
> - /*
> - * Update the read pointer only if the
> endpoint
> - * is still connected else the read pointer
> - * might no longer exist since the peer has
> - * freed resources!
> - */
> - scif_rb_update_read_ptr(&qp->inbound_q);
> - /*
> - * Send a notification to the peer about the
> - * consumed data message only if the EP is in
> - * SCIFEP_CONNECTED state.
> - */
> - notif_msg.src = ep->port;
> - notif_msg.uop = SCIF_CLIENT_RCVD;
> - notif_msg.payload[0] = ep->remote_ep;
> - ret = _scif_nodeqp_send(ep->remote_dev,
> - &notif_msg);
> - if (ret)
> - break;
> - }
> - remaining_len -= curr_recv_len;
> - msg = msg + curr_recv_len;
> - continue;
> - }
> - /*
> - * Bail out now if the EP is in SCIFEP_DISCONNECTED state
> else
> - * we will keep looping forever.
> - */
> - if (ep->state == SCIFEP_DISCONNECTED)
> - break;
> - /*
> - * Return in the Non Blocking case if there is no data
> - * to read in this iteration.
> - */
> - if (!(flags & SCIF_RECV_BLOCK))
> - break;
> - curr_recv_len = min(remaining_len, SCIF_ENDPT_QP_SIZE - 1);
> - spin_unlock(&ep->lock);
> - /*
> - * Wait for a SCIF_CLIENT_SEND message in the blocking case
> - * or until other side disconnects.
> - */
> - ret =
> - wait_event_interruptible(ep->recvwq,
> - SCIFEP_CONNECTED != ep->state ||
> - scif_rb_count(&qp->inbound_q,
> - curr_recv_len)
> - >= curr_recv_len);
> - spin_lock(&ep->lock);
> - if (ret)
> - break;
> - }
> - if (len - remaining_len)
> - ret = len - remaining_len;
> - else if (!ret && ep->state != SCIFEP_CONNECTED)
> - ret = ep->state == SCIFEP_DISCONNECTED ?
> - -ECONNRESET : -ENOTCONN;
> - spin_unlock(&ep->lock);
> - return ret;
> -}
> -
> -/**
> - * scif_user_send() - Send data to connection queue
> - * @epd: The end point returned from scif_open()
> - * @msg: Address to place data
> - * @len: Length to receive
> - * @flags: blocking or non blocking
> - *
> - * This function is called from the driver IOCTL entry point
> - * only and is a wrapper for _scif_send().
> - */
> -int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> - int sent_len = 0;
> - char *tmp;
> - int loop_len;
> - int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI send (U): ep %p %s\n", ep, scif_ep_states[ep-
> >state]);
> - if (!len)
> - return 0;
> -
> - err = scif_msg_param_check(epd, len, flags);
> - if (err)
> - goto send_err;
> -
> - tmp = kmalloc(chunk_len, GFP_KERNEL);
> - if (!tmp) {
> - err = -ENOMEM;
> - goto send_err;
> - }
> - /*
> - * Grabbing the lock before breaking up the transfer in
> - * multiple chunks is required to ensure that messages do
> - * not get fragmented and reordered.
> - */
> - mutex_lock(&ep->sendlock);
> - while (sent_len != len) {
> - loop_len = len - sent_len;
> - loop_len = min(chunk_len, loop_len);
> - if (copy_from_user(tmp, msg, loop_len)) {
> - err = -EFAULT;
> - goto send_free_err;
> - }
> - err = _scif_send(epd, tmp, loop_len, flags);
> - if (err < 0)
> - goto send_free_err;
> - sent_len += err;
> - msg += err;
> - if (err != loop_len)
> - goto send_free_err;
> - }
> -send_free_err:
> - mutex_unlock(&ep->sendlock);
> - kfree(tmp);
> -send_err:
> - return err < 0 ? err : sent_len;
> -}
> -
> -/**
> - * scif_user_recv() - Receive data from connection queue
> - * @epd: The end point returned from scif_open()
> - * @msg: Address to place data
> - * @len: Length to receive
> - * @flags: blocking or non blocking
> - *
> - * This function is called from the driver IOCTL entry point
> - * only and is a wrapper for _scif_recv().
> - */
> -int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> - int recv_len = 0;
> - char *tmp;
> - int loop_len;
> - int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI recv (U): ep %p %s\n", ep, scif_ep_states[ep->state]);
> - if (!len)
> - return 0;
> -
> - err = scif_msg_param_check(epd, len, flags);
> - if (err)
> - goto recv_err;
> -
> - tmp = kmalloc(chunk_len, GFP_KERNEL);
> - if (!tmp) {
> - err = -ENOMEM;
> - goto recv_err;
> - }
> - /*
> - * Grabbing the lock before breaking up the transfer in
> - * multiple chunks is required to ensure that messages do
> - * not get fragmented and reordered.
> - */
> - mutex_lock(&ep->recvlock);
> - while (recv_len != len) {
> - loop_len = len - recv_len;
> - loop_len = min(chunk_len, loop_len);
> - err = _scif_recv(epd, tmp, loop_len, flags);
> - if (err < 0)
> - goto recv_free_err;
> - if (copy_to_user(msg, tmp, err)) {
> - err = -EFAULT;
> - goto recv_free_err;
> - }
> - recv_len += err;
> - msg += err;
> - if (err != loop_len)
> - goto recv_free_err;
> - }
> -recv_free_err:
> - mutex_unlock(&ep->recvlock);
> - kfree(tmp);
> -recv_err:
> - return err < 0 ? err : recv_len;
> -}
> -
> -/**
> - * scif_send() - Send data to connection queue
> - * @epd: The end point returned from scif_open()
> - * @msg: Address to place data
> - * @len: Length to receive
> - * @flags: blocking or non blocking
> - *
> - * This function is called from the kernel mode only and is
> - * a wrapper for _scif_send().
> - */
> -int scif_send(scif_epd_t epd, void *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int ret;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI send (K): ep %p %s\n", ep, scif_ep_states[ep-
> >state]);
> - if (!len)
> - return 0;
> -
> - ret = scif_msg_param_check(epd, len, flags);
> - if (ret)
> - return ret;
> - if (!ep->remote_dev)
> - return -ENOTCONN;
> - /*
> - * Grab the mutex lock in the blocking case only
> - * to ensure messages do not get fragmented/reordered.
> - * The non blocking mode is protected using spin locks
> - * in _scif_send().
> - */
> - if (flags & SCIF_SEND_BLOCK)
> - mutex_lock(&ep->sendlock);
> -
> - ret = _scif_send(epd, msg, len, flags);
> -
> - if (flags & SCIF_SEND_BLOCK)
> - mutex_unlock(&ep->sendlock);
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(scif_send);
> -
> -/**
> - * scif_recv() - Receive data from connection queue
> - * @epd: The end point returned from scif_open()
> - * @msg: Address to place data
> - * @len: Length to receive
> - * @flags: blocking or non blocking
> - *
> - * This function is called from the kernel mode only and is
> - * a wrapper for _scif_recv().
> - */
> -int scif_recv(scif_epd_t epd, void *msg, int len, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int ret;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI recv (K): ep %p %s\n", ep, scif_ep_states[ep->state]);
> - if (!len)
> - return 0;
> -
> - ret = scif_msg_param_check(epd, len, flags);
> - if (ret)
> - return ret;
> - /*
> - * Grab the mutex lock in the blocking case only
> - * to ensure messages do not get fragmented/reordered.
> - * The non blocking mode is protected using spin locks
> - * in _scif_send().
> - */
> - if (flags & SCIF_RECV_BLOCK)
> - mutex_lock(&ep->recvlock);
> -
> - ret = _scif_recv(epd, msg, len, flags);
> -
> - if (flags & SCIF_RECV_BLOCK)
> - mutex_unlock(&ep->recvlock);
> -
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(scif_recv);
> -
> -static inline void _scif_poll_wait(struct file *f, wait_queue_head_t *wq,
> - poll_table *p, struct scif_endpt *ep)
> -{
> - /*
> - * Because poll_wait makes a GFP_KERNEL allocation, give up the lock
> - * and regrab it afterwards. Because the endpoint state might have
> - * changed while the lock was given up, the state must be checked
> - * again after re-acquiring the lock. The code in __scif_pollfd(..)
> - * does this.
> - */
> - spin_unlock(&ep->lock);
> - poll_wait(f, wq, p);
> - spin_lock(&ep->lock);
> -}
> -
> -__poll_t
> -__scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep)
> -{
> - __poll_t mask = 0;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI pollfd: ep %p %s\n", ep, scif_ep_states[ep->state]);
> -
> - spin_lock(&ep->lock);
> -
> - /* Endpoint is waiting for a non-blocking connect to complete */
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
> - _scif_poll_wait(f, &ep->conn_pend_wq, wait, ep);
> - if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
> - if (ep->state == SCIFEP_CONNECTED ||
> - ep->state == SCIFEP_DISCONNECTED ||
> - ep->conn_err)
> - mask |= EPOLLOUT;
> - goto exit;
> - }
> - }
> -
> - /* Endpoint is listening for incoming connection requests */
> - if (ep->state == SCIFEP_LISTENING) {
> - _scif_poll_wait(f, &ep->conwq, wait, ep);
> - if (ep->state == SCIFEP_LISTENING) {
> - if (ep->conreqcnt)
> - mask |= EPOLLIN;
> - goto exit;
> - }
> - }
> -
> - /* Endpoint is connected or disconnected */
> - if (ep->state == SCIFEP_CONNECTED || ep->state ==
> SCIFEP_DISCONNECTED) {
> - if (poll_requested_events(wait) & EPOLLIN)
> - _scif_poll_wait(f, &ep->recvwq, wait, ep);
> - if (poll_requested_events(wait) & EPOLLOUT)
> - _scif_poll_wait(f, &ep->sendwq, wait, ep);
> - if (ep->state == SCIFEP_CONNECTED ||
> - ep->state == SCIFEP_DISCONNECTED) {
> - /* Data can be read without blocking */
> - if (scif_rb_count(&ep->qp_info.qp->inbound_q, 1))
> - mask |= EPOLLIN;
> - /* Data can be written without blocking */
> - if (scif_rb_space(&ep->qp_info.qp->outbound_q))
> - mask |= EPOLLOUT;
> - /* Return EPOLLHUP if endpoint is disconnected */
> - if (ep->state == SCIFEP_DISCONNECTED)
> - mask |= EPOLLHUP;
> - goto exit;
> - }
> - }
> -
> - /* Return EPOLLERR if the endpoint is in none of the above states */
> - mask |= EPOLLERR;
> -exit:
> - spin_unlock(&ep->lock);
> - return mask;
> -}
> -
> -/**
> - * scif_poll() - Kernel mode SCIF poll
> - * @ufds: Array of scif_pollepd structures containing the end points
> - * and events to poll on
> - * @nfds: Size of the ufds array
> - * @timeout_msecs: Timeout in msecs, -ve implies infinite timeout
> - *
> - * The code flow in this function is based on do_poll(..) in select.c
> - *
> - * Returns the number of endpoints which have pending events or 0 in
> - * the event of a timeout. If a signal is used for wake up, -EINTR is
> - * returned.
> - */
> -int
> -scif_poll(struct scif_pollepd *ufds, unsigned int nfds, long timeout_msecs)
> -{
> - struct poll_wqueues table;
> - poll_table *pt;
> - int i, count = 0, timed_out = timeout_msecs == 0;
> - __poll_t mask;
> - u64 timeout = timeout_msecs < 0 ? MAX_SCHEDULE_TIMEOUT
> - : msecs_to_jiffies(timeout_msecs);
> -
> - poll_initwait(&table);
> - pt = &table.pt;
> - while (1) {
> - for (i = 0; i < nfds; i++) {
> - pt->_key = ufds[i].events | EPOLLERR | EPOLLHUP;
> - mask = __scif_pollfd(ufds[i].epd->anon,
> - pt, ufds[i].epd);
> - mask &= ufds[i].events | EPOLLERR | EPOLLHUP;
> - if (mask) {
> - count++;
> - pt->_qproc = NULL;
> - }
> - ufds[i].revents = mask;
> - }
> - pt->_qproc = NULL;
> - if (!count) {
> - count = table.error;
> - if (signal_pending(current))
> - count = -EINTR;
> - }
> - if (count || timed_out)
> - break;
> -
> - if (!schedule_timeout_interruptible(timeout))
> - timed_out = 1;
> - }
> - poll_freewait(&table);
> - return count;
> -}
> -EXPORT_SYMBOL_GPL(scif_poll);
> -
> -int scif_get_node_ids(u16 *nodes, int len, u16 *self)
> -{
> - int online = 0;
> - int offset = 0;
> - int node;
> -
> - if (!scif_is_mgmt_node())
> - scif_get_node_info();
> -
> - *self = scif_info.nodeid;
> - mutex_lock(&scif_info.conflock);
> - len = min_t(int, len, scif_info.total);
> - for (node = 0; node <= scif_info.maxid; node++) {
> - if (_scifdev_alive(&scif_dev[node])) {
> - online++;
> - if (offset < len)
> - nodes[offset++] = node;
> - }
> - }
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI get_node_ids total %d online %d filled in %d
> nodes\n",
> - scif_info.total, online, offset);
> - mutex_unlock(&scif_info.conflock);
> -
> - return online;
> -}
> -EXPORT_SYMBOL_GPL(scif_get_node_ids);
> -
> -static int scif_add_client_dev(struct device *dev, struct subsys_interface *si)
> -{
> - struct scif_client *client =
> - container_of(si, struct scif_client, si);
> - struct scif_peer_dev *spdev =
> - container_of(dev, struct scif_peer_dev, dev);
> -
> - if (client->probe)
> - client->probe(spdev);
> - return 0;
> -}
> -
> -static void scif_remove_client_dev(struct device *dev,
> - struct subsys_interface *si)
> -{
> - struct scif_client *client =
> - container_of(si, struct scif_client, si);
> - struct scif_peer_dev *spdev =
> - container_of(dev, struct scif_peer_dev, dev);
> -
> - if (client->remove)
> - client->remove(spdev);
> -}
> -
> -void scif_client_unregister(struct scif_client *client)
> -{
> - subsys_interface_unregister(&client->si);
> -}
> -EXPORT_SYMBOL_GPL(scif_client_unregister);
> -
> -int scif_client_register(struct scif_client *client)
> -{
> - struct subsys_interface *si = &client->si;
> -
> - si->name = client->name;
> - si->subsys = &scif_peer_bus;
> - si->add_dev = scif_add_client_dev;
> - si->remove_dev = scif_remove_client_dev;
> -
> - return subsys_interface_register(&client->si);
> -}
> -EXPORT_SYMBOL_GPL(scif_client_register);
> diff --git a/drivers/misc/mic/scif/scif_debugfs.c
> b/drivers/misc/mic/scif/scif_debugfs.c
> deleted file mode 100644
> index 8fe38e7ca6e6..000000000000
> --- a/drivers/misc/mic/scif/scif_debugfs.c
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/debugfs.h>
> -#include <linux/seq_file.h>
> -
> -#include "../common/mic_dev.h"
> -#include "scif_main.h"
> -
> -/* Debugfs parent dir */
> -static struct dentry *scif_dbg;
> -
> -static int scif_dev_show(struct seq_file *s, void *unused)
> -{
> - int node;
> -
> - seq_printf(s, "Total Nodes %d Self Node Id %d Maxid %d\n",
> - scif_info.total, scif_info.nodeid,
> - scif_info.maxid);
> -
> - if (!scif_dev)
> - return 0;
> -
> - seq_printf(s, "%-16s\t%-16s\n", "node_id", "state");
> -
> - for (node = 0; node <= scif_info.maxid; node++)
> - seq_printf(s, "%-16d\t%-16s\n", scif_dev[node].node,
> - _scifdev_alive(&scif_dev[node]) ?
> - "Running" : "Offline");
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(scif_dev);
> -
> -static void scif_display_window(struct scif_window *window, struct seq_file
> *s)
> -{
> - int j;
> - struct scatterlist *sg;
> - scif_pinned_pages_t pin = window->pinned_pages;
> -
> - seq_printf(s, "window %p type %d temp %d offset 0x%llx ",
> - window, window->type, window->temp, window->offset);
> - seq_printf(s, "nr_pages 0x%llx nr_contig_chunks 0x%x prot %d ",
> - window->nr_pages, window->nr_contig_chunks, window-
> >prot);
> - seq_printf(s, "ref_count %d magic 0x%llx peer_window 0x%llx ",
> - window->ref_count, window->magic, window-
> >peer_window);
> - seq_printf(s, "unreg_state 0x%x va_for_temp 0x%lx\n",
> - window->unreg_state, window->va_for_temp);
> -
> - for (j = 0; j < window->nr_contig_chunks; j++)
> - seq_printf(s, "page[%d] dma_addr 0x%llx num_pages
> 0x%llx\n", j,
> - window->dma_addr[j], window->num_pages[j]);
> -
> - if (window->type == SCIF_WINDOW_SELF && pin)
> - for (j = 0; j < window->nr_pages; j++)
> - seq_printf(s, "page[%d] = pinned_pages %p
> address %p\n",
> - j, pin->pages[j],
> - page_address(pin->pages[j]));
> -
> - if (window->st)
> - for_each_sg(window->st->sgl, sg, window->st->nents, j)
> - seq_printf(s, "sg[%d] dma addr 0x%llx length
> 0x%x\n",
> - j, sg_dma_address(sg), sg_dma_len(sg));
> -}
> -
> -static void scif_display_all_windows(struct list_head *head, struct seq_file
> *s)
> -{
> - struct list_head *item;
> - struct scif_window *window;
> -
> - list_for_each(item, head) {
> - window = list_entry(item, struct scif_window, list);
> - scif_display_window(window, s);
> - }
> -}
> -
> -static int scif_rma_show(struct seq_file *s, void *unused)
> -{
> - struct scif_endpt *ep;
> - struct list_head *pos;
> -
> - mutex_lock(&scif_info.connlock);
> - list_for_each(pos, &scif_info.connected) {
> - ep = list_entry(pos, struct scif_endpt, list);
> - seq_printf(s, "ep %p self windows\n", ep);
> - mutex_lock(&ep->rma_info.rma_lock);
> - scif_display_all_windows(&ep->rma_info.reg_list, s);
> - seq_printf(s, "ep %p remote windows\n", ep);
> - scif_display_all_windows(&ep->rma_info.remote_reg_list, s);
> - mutex_unlock(&ep->rma_info.rma_lock);
> - }
> - mutex_unlock(&scif_info.connlock);
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(scif_rma);
> -
> -void __init scif_init_debugfs(void)
> -{
> - scif_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
> -
> - debugfs_create_file("scif_dev", 0444, scif_dbg, NULL,
> &scif_dev_fops);
> - debugfs_create_file("scif_rma", 0444, scif_dbg, NULL,
> &scif_rma_fops);
> - debugfs_create_u8("en_msg_log", 0666, scif_dbg,
> &scif_info.en_msg_log);
> - debugfs_create_u8("p2p_enable", 0666, scif_dbg,
> &scif_info.p2p_enable);
> -}
> -
> -void scif_exit_debugfs(void)
> -{
> - debugfs_remove_recursive(scif_dbg);
> -}
> diff --git a/drivers/misc/mic/scif/scif_dma.c
> b/drivers/misc/mic/scif/scif_dma.c
> deleted file mode 100644
> index 401b98e5ad79..000000000000
> --- a/drivers/misc/mic/scif/scif_dma.c
> +++ /dev/null
> @@ -1,1940 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -/*
> - * struct scif_dma_comp_cb - SCIF DMA completion callback
> - *
> - * @dma_completion_func: DMA completion callback
> - * @cb_cookie: DMA completion callback cookie
> - * @temp_buf: Temporary buffer
> - * @temp_buf_to_free: Temporary buffer to be freed
> - * @is_cache: Is a kmem_cache allocated buffer
> - * @dst_offset: Destination registration offset
> - * @dst_window: Destination registration window
> - * @len: Length of the temp buffer
> - * @temp_phys: DMA address of the temp buffer
> - * @sdev: The SCIF device
> - * @header_padding: padding for cache line alignment
> - */
> -struct scif_dma_comp_cb {
> - void (*dma_completion_func)(void *cookie);
> - void *cb_cookie;
> - u8 *temp_buf;
> - u8 *temp_buf_to_free;
> - bool is_cache;
> - s64 dst_offset;
> - struct scif_window *dst_window;
> - size_t len;
> - dma_addr_t temp_phys;
> - struct scif_dev *sdev;
> - int header_padding;
> -};
> -
> -/**
> - * struct scif_copy_work - Work for DMA copy
> - *
> - * @src_offset: Starting source offset
> - * @dst_offset: Starting destination offset
> - * @src_window: Starting src registered window
> - * @dst_window: Starting dst registered window
> - * @loopback: true if this is a loopback DMA transfer
> - * @len: Length of the transfer
> - * @comp_cb: DMA copy completion callback
> - * @remote_dev: The remote SCIF peer device
> - * @fence_type: polling or interrupt based
> - * @ordered: is this a tail byte ordered DMA transfer
> - */
> -struct scif_copy_work {
> - s64 src_offset;
> - s64 dst_offset;
> - struct scif_window *src_window;
> - struct scif_window *dst_window;
> - int loopback;
> - size_t len;
> - struct scif_dma_comp_cb *comp_cb;
> - struct scif_dev *remote_dev;
> - int fence_type;
> - bool ordered;
> -};
> -
> -/**
> - * scif_reserve_dma_chan:
> - * @ep: Endpoint Descriptor.
> - *
> - * This routine reserves a DMA channel for a particular
> - * endpoint. All DMA transfers for an endpoint are always
> - * programmed on the same DMA channel.
> - */
> -int scif_reserve_dma_chan(struct scif_endpt *ep)
> -{
> - int err = 0;
> - struct scif_dev *scifdev;
> - struct scif_hw_dev *sdev;
> - struct dma_chan *chan;
> -
> - /* Loopback DMAs are not supported on the management node */
> - if (!scif_info.nodeid && scifdev_self(ep->remote_dev))
> - return 0;
> - if (scif_info.nodeid)
> - scifdev = &scif_dev[0];
> - else
> - scifdev = ep->remote_dev;
> - sdev = scifdev->sdev;
> - if (!sdev->num_dma_ch)
> - return -ENODEV;
> - chan = sdev->dma_ch[scifdev->dma_ch_idx];
> - scifdev->dma_ch_idx = (scifdev->dma_ch_idx + 1) % sdev-
> >num_dma_ch;
> - mutex_lock(&ep->rma_info.rma_lock);
> - ep->rma_info.dma_chan = chan;
> - mutex_unlock(&ep->rma_info.rma_lock);
> - return err;
> -}
> -
> -#ifdef CONFIG_MMU_NOTIFIER
> -/*
> - * scif_rma_destroy_tcw:
> - *
> - * This routine destroys temporary cached windows
> - */
> -static
> -void __scif_rma_destroy_tcw(struct scif_mmu_notif *mmn,
> - u64 start, u64 len)
> -{
> - struct list_head *item, *tmp;
> - struct scif_window *window;
> - u64 start_va, end_va;
> - u64 end = start + len;
> -
> - if (end <= start)
> - return;
> -
> - list_for_each_safe(item, tmp, &mmn->tc_reg_list) {
> - window = list_entry(item, struct scif_window, list);
> - if (!len)
> - break;
> - start_va = window->va_for_temp;
> - end_va = start_va + (window->nr_pages << PAGE_SHIFT);
> - if (start < start_va && end <= start_va)
> - break;
> - if (start >= end_va)
> - continue;
> - __scif_rma_destroy_tcw_helper(window);
> - }
> -}
> -
> -static void scif_rma_destroy_tcw(struct scif_mmu_notif *mmn, u64 start,
> u64 len)
> -{
> - struct scif_endpt *ep = mmn->ep;
> -
> - spin_lock(&ep->rma_info.tc_lock);
> - __scif_rma_destroy_tcw(mmn, start, len);
> - spin_unlock(&ep->rma_info.tc_lock);
> -}
> -
> -static void scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
> -{
> - struct list_head *item, *tmp;
> - struct scif_mmu_notif *mmn;
> -
> - list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
> - mmn = list_entry(item, struct scif_mmu_notif, list);
> - scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
> - }
> -}
> -
> -static void __scif_rma_destroy_tcw_ep(struct scif_endpt *ep)
> -{
> - struct list_head *item, *tmp;
> - struct scif_mmu_notif *mmn;
> -
> - spin_lock(&ep->rma_info.tc_lock);
> - list_for_each_safe(item, tmp, &ep->rma_info.mmn_list) {
> - mmn = list_entry(item, struct scif_mmu_notif, list);
> - __scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
> - }
> - spin_unlock(&ep->rma_info.tc_lock);
> -}
> -
> -static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
> -{
> - if ((cur_bytes >> PAGE_SHIFT) > scif_info.rma_tc_limit)
> - return false;
> - if ((atomic_read(&ep->rma_info.tcw_total_pages)
> - + (cur_bytes >> PAGE_SHIFT)) >
> - scif_info.rma_tc_limit) {
> - dev_info(scif_info.mdev.this_device,
> - "%s %d total=%d, current=%zu reached max\n",
> - __func__, __LINE__,
> - atomic_read(&ep->rma_info.tcw_total_pages),
> - (1 + (cur_bytes >> PAGE_SHIFT)));
> - scif_rma_destroy_tcw_invalid();
> - __scif_rma_destroy_tcw_ep(ep);
> - }
> - return true;
> -}
> -
> -static void scif_mmu_notifier_release(struct mmu_notifier *mn,
> - struct mm_struct *mm)
> -{
> - struct scif_mmu_notif *mmn;
> -
> - mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
> - scif_rma_destroy_tcw(mmn, 0, ULONG_MAX);
> - schedule_work(&scif_info.misc_work);
> -}
> -
> -static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier
> *mn,
> - const struct mmu_notifier_range
> *range)
> -{
> - struct scif_mmu_notif *mmn;
> -
> - mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
> - scif_rma_destroy_tcw(mmn, range->start, range->end - range->start);
> -
> - return 0;
> -}
> -
> -static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier
> *mn,
> - const struct mmu_notifier_range *range)
> -{
> - /*
> - * Nothing to do here, everything needed was done in
> - * invalidate_range_start.
> - */
> -}
> -
> -static const struct mmu_notifier_ops scif_mmu_notifier_ops = {
> - .release = scif_mmu_notifier_release,
> - .clear_flush_young = NULL,
> - .invalidate_range_start = scif_mmu_notifier_invalidate_range_start,
> - .invalidate_range_end = scif_mmu_notifier_invalidate_range_end};
> -
> -static void scif_ep_unregister_mmu_notifier(struct scif_endpt *ep)
> -{
> - struct scif_endpt_rma_info *rma = &ep->rma_info;
> - struct scif_mmu_notif *mmn = NULL;
> - struct list_head *item, *tmp;
> -
> - mutex_lock(&ep->rma_info.mmn_lock);
> - list_for_each_safe(item, tmp, &rma->mmn_list) {
> - mmn = list_entry(item, struct scif_mmu_notif, list);
> - mmu_notifier_unregister(&mmn->ep_mmu_notifier, mmn-
> >mm);
> - list_del(item);
> - kfree(mmn);
> - }
> - mutex_unlock(&ep->rma_info.mmn_lock);
> -}
> -
> -static void scif_init_mmu_notifier(struct scif_mmu_notif *mmn,
> - struct mm_struct *mm, struct scif_endpt
> *ep)
> -{
> - mmn->ep = ep;
> - mmn->mm = mm;
> - mmn->ep_mmu_notifier.ops = &scif_mmu_notifier_ops;
> - INIT_LIST_HEAD(&mmn->list);
> - INIT_LIST_HEAD(&mmn->tc_reg_list);
> -}
> -
> -static struct scif_mmu_notif *
> -scif_find_mmu_notifier(struct mm_struct *mm, struct scif_endpt_rma_info
> *rma)
> -{
> - struct scif_mmu_notif *mmn;
> -
> - list_for_each_entry(mmn, &rma->mmn_list, list)
> - if (mmn->mm == mm)
> - return mmn;
> - return NULL;
> -}
> -
> -static struct scif_mmu_notif *
> -scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
> -{
> - struct scif_mmu_notif *mmn
> - = kzalloc(sizeof(*mmn), GFP_KERNEL);
> -
> - if (!mmn)
> - return ERR_PTR(-ENOMEM);
> -
> - scif_init_mmu_notifier(mmn, current->mm, ep);
> - if (mmu_notifier_register(&mmn->ep_mmu_notifier, current->mm))
> {
> - kfree(mmn);
> - return ERR_PTR(-EBUSY);
> - }
> - list_add(&mmn->list, &ep->rma_info.mmn_list);
> - return mmn;
> -}
> -
> -/*
> - * Called from the misc thread to destroy temporary cached windows and
> - * unregister the MMU notifier for the SCIF endpoint.
> - */
> -void scif_mmu_notif_handler(struct work_struct *work)
> -{
> - struct list_head *pos, *tmpq;
> - struct scif_endpt *ep;
> -restart:
> - scif_rma_destroy_tcw_invalid();
> - spin_lock(&scif_info.rmalock);
> - list_for_each_safe(pos, tmpq, &scif_info.mmu_notif_cleanup) {
> - ep = list_entry(pos, struct scif_endpt, mmu_list);
> - list_del(&ep->mmu_list);
> - spin_unlock(&scif_info.rmalock);
> - scif_rma_destroy_tcw_ep(ep);
> - scif_ep_unregister_mmu_notifier(ep);
> - goto restart;
> - }
> - spin_unlock(&scif_info.rmalock);
> -}
> -
> -static bool scif_is_set_reg_cache(int flags)
> -{
> - return !!(flags & SCIF_RMA_USECACHE);
> -}
> -#else
> -static struct scif_mmu_notif *
> -scif_find_mmu_notifier(struct mm_struct *mm,
> - struct scif_endpt_rma_info *rma)
> -{
> - return NULL;
> -}
> -
> -static struct scif_mmu_notif *
> -scif_add_mmu_notifier(struct mm_struct *mm, struct scif_endpt *ep)
> -{
> - return NULL;
> -}
> -
> -void scif_mmu_notif_handler(struct work_struct *work)
> -{
> -}
> -
> -static bool scif_is_set_reg_cache(int flags)
> -{
> - return false;
> -}
> -
> -static bool scif_rma_tc_can_cache(struct scif_endpt *ep, size_t cur_bytes)
> -{
> - return false;
> -}
> -#endif
> -
> -/**
> - * scif_register_temp:
> - * @epd: End Point Descriptor.
> - * @addr: virtual address to/from which to copy
> - * @len: length of range to copy
> - * @prot: read/write protection
> - * @out_offset: computed offset returned by reference.
> - * @out_window: allocated registered window returned by reference.
> - *
> - * Create a temporary registered window. The peer will not know about this
> - * window. This API is used for scif_vreadfrom()/scif_vwriteto() API's.
> - */
> -static int
> -scif_register_temp(scif_epd_t epd, unsigned long addr, size_t len, int prot,
> - off_t *out_offset, struct scif_window **out_window)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err;
> - scif_pinned_pages_t pinned_pages;
> - size_t aligned_len;
> -
> - aligned_len = ALIGN(len, PAGE_SIZE);
> -
> - err = __scif_pin_pages((void *)(addr & PAGE_MASK),
> - aligned_len, &prot, 0, &pinned_pages);
> - if (err)
> - return err;
> -
> - pinned_pages->prot = prot;
> -
> - /* Compute the offset for this registration */
> - err = scif_get_window_offset(ep, 0, 0,
> - aligned_len >> PAGE_SHIFT,
> - (s64 *)out_offset);
> - if (err)
> - goto error_unpin;
> -
> - /* Allocate and prepare self registration window */
> - *out_window = scif_create_window(ep, aligned_len >> PAGE_SHIFT,
> - *out_offset, true);
> - if (!*out_window) {
> - scif_free_window_offset(ep, NULL, *out_offset);
> - err = -ENOMEM;
> - goto error_unpin;
> - }
> -
> - (*out_window)->pinned_pages = pinned_pages;
> - (*out_window)->nr_pages = pinned_pages->nr_pages;
> - (*out_window)->prot = pinned_pages->prot;
> -
> - (*out_window)->va_for_temp = addr & PAGE_MASK;
> - err = scif_map_window(ep->remote_dev, *out_window);
> - if (err) {
> - /* Something went wrong! Rollback */
> - scif_destroy_window(ep, *out_window);
> - *out_window = NULL;
> - } else {
> - *out_offset |= (addr - (*out_window)->va_for_temp);
> - }
> - return err;
> -error_unpin:
> - if (err)
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - scif_unpin_pages(pinned_pages);
> - return err;
> -}
> -
> -#define SCIF_DMA_TO (3 * HZ)
> -
> -/*
> - * scif_sync_dma - Program a DMA without an interrupt descriptor
> - *
> - * @dev - The address of the pointer to the device instance used
> - * for DMA registration.
> - * @chan - DMA channel to be used.
> - * @sync_wait: Wait for DMA to complete?
> - *
> - * Return 0 on success and -errno on error.
> - */
> -static int scif_sync_dma(struct scif_hw_dev *sdev, struct dma_chan *chan,
> - bool sync_wait)
> -{
> - int err = 0;
> - struct dma_async_tx_descriptor *tx = NULL;
> - enum dma_ctrl_flags flags = DMA_PREP_FENCE;
> - dma_cookie_t cookie;
> - struct dma_device *ddev;
> -
> - if (!chan) {
> - err = -EIO;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - ddev = chan->device;
> -
> - tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> - cookie = tx->tx_submit(tx);
> -
> - if (dma_submit_error(cookie)) {
> - err = -ENOMEM;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> - if (!sync_wait) {
> - dma_async_issue_pending(chan);
> - } else {
> - if (dma_sync_wait(chan, cookie) == DMA_COMPLETE) {
> - err = 0;
> - } else {
> - err = -EIO;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - }
> - }
> -release:
> - return err;
> -}
> -
> -static void scif_dma_callback(void *arg)
> -{
> - struct completion *done = (struct completion *)arg;
> -
> - complete(done);
> -}
> -
> -#define SCIF_DMA_SYNC_WAIT true
> -#define SCIF_DMA_POLL BIT(0)
> -#define SCIF_DMA_INTR BIT(1)
> -
> -/*
> - * scif_async_dma - Program a DMA with an interrupt descriptor
> - *
> - * @dev - The address of the pointer to the device instance used
> - * for DMA registration.
> - * @chan - DMA channel to be used.
> - * Return 0 on success and -errno on error.
> - */
> -static int scif_async_dma(struct scif_hw_dev *sdev, struct dma_chan *chan)
> -{
> - int err = 0;
> - struct dma_device *ddev;
> - struct dma_async_tx_descriptor *tx = NULL;
> - enum dma_ctrl_flags flags = DMA_PREP_INTERRUPT |
> DMA_PREP_FENCE;
> - DECLARE_COMPLETION_ONSTACK(done_wait);
> - dma_cookie_t cookie;
> - enum dma_status status;
> -
> - if (!chan) {
> - err = -EIO;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - ddev = chan->device;
> -
> - tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, flags);
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> - reinit_completion(&done_wait);
> - tx->callback = scif_dma_callback;
> - tx->callback_param = &done_wait;
> - cookie = tx->tx_submit(tx);
> -
> - if (dma_submit_error(cookie)) {
> - err = -ENOMEM;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> - dma_async_issue_pending(chan);
> -
> - err = wait_for_completion_timeout(&done_wait, SCIF_DMA_TO);
> - if (!err) {
> - err = -EIO;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> - err = 0;
> - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
> - if (status != DMA_COMPLETE) {
> - err = -EIO;
> - dev_err(&sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto release;
> - }
> -release:
> - return err;
> -}
> -
> -/*
> - * scif_drain_dma_poll - Drain all outstanding DMA operations for a
> particular
> - * DMA channel via polling.
> - *
> - * @sdev - The SCIF device
> - * @chan - DMA channel
> - * Return 0 on success and -errno on error.
> - */
> -static int scif_drain_dma_poll(struct scif_hw_dev *sdev, struct dma_chan
> *chan)
> -{
> - if (!chan)
> - return -EINVAL;
> - return scif_sync_dma(sdev, chan, SCIF_DMA_SYNC_WAIT);
> -}
> -
> -/*
> - * scif_drain_dma_intr - Drain all outstanding DMA operations for a
> particular
> - * DMA channel via interrupt based blocking wait.
> - *
> - * @sdev - The SCIF device
> - * @chan - DMA channel
> - * Return 0 on success and -errno on error.
> - */
> -int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan)
> -{
> - if (!chan)
> - return -EINVAL;
> - return scif_async_dma(sdev, chan);
> -}
> -
> -/**
> - * scif_rma_destroy_windows:
> - *
> - * This routine destroys all windows queued for cleanup
> - */
> -void scif_rma_destroy_windows(void)
> -{
> - struct list_head *item, *tmp;
> - struct scif_window *window;
> - struct scif_endpt *ep;
> - struct dma_chan *chan;
> -
> - might_sleep();
> -restart:
> - spin_lock(&scif_info.rmalock);
> - list_for_each_safe(item, tmp, &scif_info.rma) {
> - window = list_entry(item, struct scif_window,
> - list);
> - ep = (struct scif_endpt *)window->ep;
> - chan = ep->rma_info.dma_chan;
> -
> - list_del_init(&window->list);
> - spin_unlock(&scif_info.rmalock);
> - if (!chan || !scifdev_alive(ep) ||
> - !scif_drain_dma_intr(ep->remote_dev->sdev,
> - ep->rma_info.dma_chan))
> - /* Remove window from global list */
> - window->unreg_state = OP_COMPLETED;
> - else
> - dev_warn(&ep->remote_dev->sdev->dev,
> - "DMA engine hung?\n");
> - if (window->unreg_state == OP_COMPLETED) {
> - if (window->type == SCIF_WINDOW_SELF)
> - scif_destroy_window(ep, window);
> - else
> - scif_destroy_remote_window(window);
> - atomic_dec(&ep->rma_info.tw_refcount);
> - }
> - goto restart;
> - }
> - spin_unlock(&scif_info.rmalock);
> -}
> -
> -/**
> - * scif_rma_destroy_tcw:
> - *
> - * This routine destroys temporary cached registered windows
> - * which have been queued for cleanup.
> - */
> -void scif_rma_destroy_tcw_invalid(void)
> -{
> - struct list_head *item, *tmp;
> - struct scif_window *window;
> - struct scif_endpt *ep;
> - struct dma_chan *chan;
> -
> - might_sleep();
> -restart:
> - spin_lock(&scif_info.rmalock);
> - list_for_each_safe(item, tmp, &scif_info.rma_tc) {
> - window = list_entry(item, struct scif_window, list);
> - ep = (struct scif_endpt *)window->ep;
> - chan = ep->rma_info.dma_chan;
> - list_del_init(&window->list);
> - spin_unlock(&scif_info.rmalock);
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (!chan || !scifdev_alive(ep) ||
> - !scif_drain_dma_intr(ep->remote_dev->sdev,
> - ep->rma_info.dma_chan)) {
> - atomic_sub(window->nr_pages,
> - &ep->rma_info.tcw_total_pages);
> - scif_destroy_window(ep, window);
> - atomic_dec(&ep->rma_info.tcw_refcount);
> - } else {
> - dev_warn(&ep->remote_dev->sdev->dev,
> - "DMA engine hung?\n");
> - }
> - mutex_unlock(&ep->rma_info.rma_lock);
> - goto restart;
> - }
> - spin_unlock(&scif_info.rmalock);
> -}
> -
> -static inline
> -void *_get_local_va(off_t off, struct scif_window *window, size_t len)
> -{
> - int page_nr = (off - window->offset) >> PAGE_SHIFT;
> - off_t page_off = off & ~PAGE_MASK;
> - void *va = NULL;
> -
> - if (window->type == SCIF_WINDOW_SELF) {
> - struct page **pages = window->pinned_pages->pages;
> -
> - va = page_address(pages[page_nr]) + page_off;
> - }
> - return va;
> -}
> -
> -static inline
> -void *ioremap_remote(off_t off, struct scif_window *window,
> - size_t len, struct scif_dev *dev,
> - struct scif_window_iter *iter)
> -{
> - dma_addr_t phys = scif_off_to_dma_addr(window, off, NULL, iter);
> -
> - /*
> - * If the DMA address is not card relative then we need the DMA
> - * addresses to be an offset into the bar. The aperture base was
> already
> - * added so subtract it here since scif_ioremap is going to add it again
> - */
> - if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
> - dev->sdev->aper && !dev->sdev->card_rel_da)
> - phys = phys - dev->sdev->aper->pa;
> - return scif_ioremap(phys, len, dev);
> -}
> -
> -static inline void
> -iounmap_remote(void *virt, size_t size, struct scif_copy_work *work)
> -{
> - scif_iounmap(virt, size, work->remote_dev);
> -}
> -
> -/*
> - * Takes care of ordering issue caused by
> - * 1. Hardware: Only in the case of cpu copy from mgmt node to card
> - * because of WC memory.
> - * 2. Software: If memcpy reorders copy instructions for optimization.
> - * This could happen at both mgmt node and card.
> - */
> -static inline void
> -scif_ordered_memcpy_toio(char *dst, const char *src, size_t count)
> -{
> - if (!count)
> - return;
> -
> - memcpy_toio((void __iomem __force *)dst, src, --count);
> - /* Order the last byte with the previous stores */
> - wmb();
> - *(dst + count) = *(src + count);
> -}
> -
> -static inline void scif_unaligned_cpy_toio(char *dst, const char *src,
> - size_t count, bool ordered)
> -{
> - if (ordered)
> - scif_ordered_memcpy_toio(dst, src, count);
> - else
> - memcpy_toio((void __iomem __force *)dst, src, count);
> -}
> -
> -static inline
> -void scif_ordered_memcpy_fromio(char *dst, const char *src, size_t count)
> -{
> - if (!count)
> - return;
> -
> - memcpy_fromio(dst, (void __iomem __force *)src, --count);
> - /* Order the last byte with the previous loads */
> - rmb();
> - *(dst + count) = *(src + count);
> -}
> -
> -static inline void scif_unaligned_cpy_fromio(char *dst, const char *src,
> - size_t count, bool ordered)
> -{
> - if (ordered)
> - scif_ordered_memcpy_fromio(dst, src, count);
> - else
> - memcpy_fromio(dst, (void __iomem __force *)src, count);
> -}
> -
> -#define SCIF_RMA_ERROR_CODE (~(dma_addr_t)0x0)
> -
> -/*
> - * scif_off_to_dma_addr:
> - * Obtain the dma_addr given the window and the offset.
> - * @window: Registered window.
> - * @off: Window offset.
> - * @nr_bytes: Return the number of contiguous bytes till next DMA addr
> index.
> - * @index: Return the index of the dma_addr array found.
> - * @start_off: start offset of index of the dma addr array found.
> - * The nr_bytes provides the callee an estimate of the maximum possible
> - * DMA xfer possible while the index/start_off provide faster lookups
> - * for the next iteration.
> - */
> -dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
> - size_t *nr_bytes, struct scif_window_iter
> *iter)
> -{
> - int i, page_nr;
> - s64 start, end;
> - off_t page_off;
> -
> - if (window->nr_pages == window->nr_contig_chunks) {
> - page_nr = (off - window->offset) >> PAGE_SHIFT;
> - page_off = off & ~PAGE_MASK;
> -
> - if (nr_bytes)
> - *nr_bytes = PAGE_SIZE - page_off;
> - return window->dma_addr[page_nr] | page_off;
> - }
> - if (iter) {
> - i = iter->index;
> - start = iter->offset;
> - } else {
> - i = 0;
> - start = window->offset;
> - }
> - for (; i < window->nr_contig_chunks; i++) {
> - end = start + (window->num_pages[i] << PAGE_SHIFT);
> - if (off >= start && off < end) {
> - if (iter) {
> - iter->index = i;
> - iter->offset = start;
> - }
> - if (nr_bytes)
> - *nr_bytes = end - off;
> - return (window->dma_addr[i] + (off - start));
> - }
> - start += (window->num_pages[i] << PAGE_SHIFT);
> - }
> - dev_err(scif_info.mdev.this_device,
> - "%s %d BUG. Addr not found? window %p off 0x%llx\n",
> - __func__, __LINE__, window, off);
> - return SCIF_RMA_ERROR_CODE;
> -}
> -
> -/*
> - * Copy between rma window and temporary buffer
> - */
> -static void scif_rma_local_cpu_copy(s64 offset, struct scif_window *window,
> - u8 *temp, size_t rem_len, bool to_temp)
> -{
> - void *window_virt;
> - size_t loop_len;
> - int offset_in_page;
> - s64 end_offset;
> -
> - offset_in_page = offset & ~PAGE_MASK;
> - loop_len = PAGE_SIZE - offset_in_page;
> -
> - if (rem_len < loop_len)
> - loop_len = rem_len;
> -
> - window_virt = _get_local_va(offset, window, loop_len);
> - if (!window_virt)
> - return;
> - if (to_temp)
> - memcpy(temp, window_virt, loop_len);
> - else
> - memcpy(window_virt, temp, loop_len);
> -
> - offset += loop_len;
> - temp += loop_len;
> - rem_len -= loop_len;
> -
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - while (rem_len) {
> - if (offset == end_offset) {
> - window = list_next_entry(window, list);
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - }
> - loop_len = min(PAGE_SIZE, rem_len);
> - window_virt = _get_local_va(offset, window, loop_len);
> - if (!window_virt)
> - return;
> - if (to_temp)
> - memcpy(temp, window_virt, loop_len);
> - else
> - memcpy(window_virt, temp, loop_len);
> - offset += loop_len;
> - temp += loop_len;
> - rem_len -= loop_len;
> - }
> -}
> -
> -/**
> - * scif_rma_completion_cb:
> - * @data: RMA cookie
> - *
> - * RMA interrupt completion callback.
> - */
> -static void scif_rma_completion_cb(void *data)
> -{
> - struct scif_dma_comp_cb *comp_cb = data;
> -
> - /* Free DMA Completion CB. */
> - if (comp_cb->dst_window)
> - scif_rma_local_cpu_copy(comp_cb->dst_offset,
> - comp_cb->dst_window,
> - comp_cb->temp_buf +
> - comp_cb->header_padding,
> - comp_cb->len, false);
> - scif_unmap_single(comp_cb->temp_phys, comp_cb->sdev,
> - SCIF_KMEM_UNALIGNED_BUF_SIZE);
> - if (comp_cb->is_cache)
> - kmem_cache_free(unaligned_cache,
> - comp_cb->temp_buf_to_free);
> - else
> - kfree(comp_cb->temp_buf_to_free);
> -}
> -
> -/* Copies between temporary buffer and offsets provided in work */
> -static int
> -scif_rma_list_dma_copy_unaligned(struct scif_copy_work *work,
> - u8 *temp, struct dma_chan *chan,
> - bool src_local)
> -{
> - struct scif_dma_comp_cb *comp_cb = work->comp_cb;
> - dma_addr_t window_dma_addr, temp_dma_addr;
> - dma_addr_t temp_phys = comp_cb->temp_phys;
> - size_t loop_len, nr_contig_bytes = 0, remaining_len = work->len;
> - int offset_in_ca, ret = 0;
> - s64 end_offset, offset;
> - struct scif_window *window;
> - void *window_virt_addr;
> - size_t tail_len;
> - struct dma_async_tx_descriptor *tx;
> - struct dma_device *dev = chan->device;
> - dma_cookie_t cookie;
> -
> - if (src_local) {
> - offset = work->dst_offset;
> - window = work->dst_window;
> - } else {
> - offset = work->src_offset;
> - window = work->src_window;
> - }
> -
> - offset_in_ca = offset & (L1_CACHE_BYTES - 1);
> - if (offset_in_ca) {
> - loop_len = L1_CACHE_BYTES - offset_in_ca;
> - loop_len = min(loop_len, remaining_len);
> - window_virt_addr = ioremap_remote(offset, window,
> - loop_len,
> - work->remote_dev,
> - NULL);
> - if (!window_virt_addr)
> - return -ENOMEM;
> - if (src_local)
> - scif_unaligned_cpy_toio(window_virt_addr, temp,
> - loop_len,
> - work->ordered &&
> - !(remaining_len - loop_len));
> - else
> - scif_unaligned_cpy_fromio(temp, window_virt_addr,
> - loop_len, work->ordered
> &&
> - !(remaining_len - loop_len));
> - iounmap_remote(window_virt_addr, loop_len, work);
> -
> - offset += loop_len;
> - temp += loop_len;
> - temp_phys += loop_len;
> - remaining_len -= loop_len;
> - }
> -
> - offset_in_ca = offset & ~PAGE_MASK;
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> -
> - tail_len = remaining_len & (L1_CACHE_BYTES - 1);
> - remaining_len -= tail_len;
> - while (remaining_len) {
> - if (offset == end_offset) {
> - window = list_next_entry(window, list);
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - }
> - if (scif_is_mgmt_node())
> - temp_dma_addr = temp_phys;
> - else
> - /* Fix if we ever enable IOMMU on the card */
> - temp_dma_addr = (dma_addr_t)virt_to_phys(temp);
> - window_dma_addr = scif_off_to_dma_addr(window, offset,
> - &nr_contig_bytes,
> - NULL);
> - loop_len = min(nr_contig_bytes, remaining_len);
> - if (src_local) {
> - if (work->ordered && !tail_len &&
> - !(remaining_len - loop_len) &&
> - loop_len != L1_CACHE_BYTES) {
> - /*
> - * Break up the last chunk of the transfer into
> - * two steps. if there is no tail to guarantee
> - * DMA ordering. SCIF_DMA_POLLING inserts
> - * a status update descriptor in step 1 which
> - * acts as a double sided synchronization
> fence
> - * for the DMA engine to ensure that the last
> - * cache line in step 2 is updated last.
> - */
> - /* Step 1) DMA: Body Length -
> L1_CACHE_BYTES. */
> - tx =
> - dev->device_prep_dma_memcpy(chan,
> - window_dma_addr,
> - temp_dma_addr,
> - loop_len -
> - L1_CACHE_BYTES,
> - DMA_PREP_FENCE);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - offset += (loop_len - L1_CACHE_BYTES);
> - temp_dma_addr += (loop_len -
> L1_CACHE_BYTES);
> - window_dma_addr += (loop_len -
> L1_CACHE_BYTES);
> - remaining_len -= (loop_len -
> L1_CACHE_BYTES);
> - loop_len = remaining_len;
> -
> - /* Step 2) DMA: L1_CACHE_BYTES */
> - tx =
> - dev->device_prep_dma_memcpy(chan,
> - window_dma_addr,
> - temp_dma_addr,
> - loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - } else {
> - tx =
> - dev->device_prep_dma_memcpy(chan,
> - window_dma_addr,
> - temp_dma_addr,
> - loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - }
> - } else {
> - tx = dev->device_prep_dma_memcpy(chan,
> temp_dma_addr,
> - window_dma_addr, loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - }
> - offset += loop_len;
> - temp += loop_len;
> - temp_phys += loop_len;
> - remaining_len -= loop_len;
> - offset_in_ca = 0;
> - }
> - if (tail_len) {
> - if (offset == end_offset) {
> - window = list_next_entry(window, list);
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - }
> - window_virt_addr = ioremap_remote(offset, window,
> tail_len,
> - work->remote_dev,
> - NULL);
> - if (!window_virt_addr)
> - return -ENOMEM;
> - /*
> - * The CPU copy for the tail bytes must be initiated only once
> - * previous DMA transfers for this endpoint have completed
> - * to guarantee ordering.
> - */
> - if (work->ordered) {
> - struct scif_dev *rdev = work->remote_dev;
> -
> - ret = scif_drain_dma_intr(rdev->sdev, chan);
> - if (ret)
> - return ret;
> - }
> - if (src_local)
> - scif_unaligned_cpy_toio(window_virt_addr, temp,
> - tail_len, work->ordered);
> - else
> - scif_unaligned_cpy_fromio(temp, window_virt_addr,
> - tail_len, work->ordered);
> - iounmap_remote(window_virt_addr, tail_len, work);
> - }
> - tx = dev->device_prep_dma_memcpy(chan, 0, 0, 0,
> DMA_PREP_INTERRUPT);
> - if (!tx) {
> - ret = -ENOMEM;
> - return ret;
> - }
> - tx->callback = &scif_rma_completion_cb;
> - tx->callback_param = comp_cb;
> - cookie = tx->tx_submit(tx);
> -
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - return ret;
> - }
> - dma_async_issue_pending(chan);
> - return 0;
> -err:
> - dev_err(scif_info.mdev.this_device,
> - "%s %d Desc Prog Failed ret %d\n",
> - __func__, __LINE__, ret);
> - return ret;
> -}
> -
> -/*
> - * _scif_rma_list_dma_copy_aligned:
> - *
> - * Traverse all the windows and perform DMA copy.
> - */
> -static int _scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
> - struct dma_chan *chan)
> -{
> - dma_addr_t src_dma_addr, dst_dma_addr;
> - size_t loop_len, remaining_len, src_contig_bytes = 0;
> - size_t dst_contig_bytes = 0;
> - struct scif_window_iter src_win_iter;
> - struct scif_window_iter dst_win_iter;
> - s64 end_src_offset, end_dst_offset;
> - struct scif_window *src_window = work->src_window;
> - struct scif_window *dst_window = work->dst_window;
> - s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
> - int ret = 0;
> - struct dma_async_tx_descriptor *tx;
> - struct dma_device *dev = chan->device;
> - dma_cookie_t cookie;
> -
> - remaining_len = work->len;
> -
> - scif_init_window_iter(src_window, &src_win_iter);
> - scif_init_window_iter(dst_window, &dst_win_iter);
> - end_src_offset = src_window->offset +
> - (src_window->nr_pages << PAGE_SHIFT);
> - end_dst_offset = dst_window->offset +
> - (dst_window->nr_pages << PAGE_SHIFT);
> - while (remaining_len) {
> - if (src_offset == end_src_offset) {
> - src_window = list_next_entry(src_window, list);
> - end_src_offset = src_window->offset +
> - (src_window->nr_pages << PAGE_SHIFT);
> - scif_init_window_iter(src_window, &src_win_iter);
> - }
> - if (dst_offset == end_dst_offset) {
> - dst_window = list_next_entry(dst_window, list);
> - end_dst_offset = dst_window->offset +
> - (dst_window->nr_pages << PAGE_SHIFT);
> - scif_init_window_iter(dst_window, &dst_win_iter);
> - }
> -
> - /* compute dma addresses for transfer */
> - src_dma_addr = scif_off_to_dma_addr(src_window,
> src_offset,
> - &src_contig_bytes,
> - &src_win_iter);
> - dst_dma_addr = scif_off_to_dma_addr(dst_window,
> dst_offset,
> - &dst_contig_bytes,
> - &dst_win_iter);
> - loop_len = min(src_contig_bytes, dst_contig_bytes);
> - loop_len = min(loop_len, remaining_len);
> - if (work->ordered && !(remaining_len - loop_len)) {
> - /*
> - * Break up the last chunk of the transfer into two
> - * steps to ensure that the last byte in step 2 is
> - * updated last.
> - */
> - /* Step 1) DMA: Body Length - 1 */
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr,
> - loop_len - 1,
> - DMA_PREP_FENCE);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - src_offset += (loop_len - 1);
> - dst_offset += (loop_len - 1);
> - src_dma_addr += (loop_len - 1);
> - dst_dma_addr += (loop_len - 1);
> - remaining_len -= (loop_len - 1);
> - loop_len = remaining_len;
> -
> - /* Step 2) DMA: 1 BYTES */
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr, loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - } else {
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr, loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - }
> - src_offset += loop_len;
> - dst_offset += loop_len;
> - remaining_len -= loop_len;
> - }
> - return ret;
> -err:
> - dev_err(scif_info.mdev.this_device,
> - "%s %d Desc Prog Failed ret %d\n",
> - __func__, __LINE__, ret);
> - return ret;
> -}
> -
> -/*
> - * scif_rma_list_dma_copy_aligned:
> - *
> - * Traverse all the windows and perform DMA copy.
> - */
> -static int scif_rma_list_dma_copy_aligned(struct scif_copy_work *work,
> - struct dma_chan *chan)
> -{
> - dma_addr_t src_dma_addr, dst_dma_addr;
> - size_t loop_len, remaining_len, tail_len, src_contig_bytes = 0;
> - size_t dst_contig_bytes = 0;
> - int src_cache_off;
> - s64 end_src_offset, end_dst_offset;
> - struct scif_window_iter src_win_iter;
> - struct scif_window_iter dst_win_iter;
> - void *src_virt, *dst_virt;
> - struct scif_window *src_window = work->src_window;
> - struct scif_window *dst_window = work->dst_window;
> - s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
> - int ret = 0;
> - struct dma_async_tx_descriptor *tx;
> - struct dma_device *dev = chan->device;
> - dma_cookie_t cookie;
> -
> - remaining_len = work->len;
> - scif_init_window_iter(src_window, &src_win_iter);
> - scif_init_window_iter(dst_window, &dst_win_iter);
> -
> - src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
> - if (src_cache_off != 0) {
> - /* Head */
> - loop_len = L1_CACHE_BYTES - src_cache_off;
> - loop_len = min(loop_len, remaining_len);
> - src_dma_addr = __scif_off_to_dma_addr(src_window,
> src_offset);
> - dst_dma_addr = __scif_off_to_dma_addr(dst_window,
> dst_offset);
> - if (src_window->type == SCIF_WINDOW_SELF)
> - src_virt = _get_local_va(src_offset, src_window,
> - loop_len);
> - else
> - src_virt = ioremap_remote(src_offset, src_window,
> - loop_len,
> - work->remote_dev, NULL);
> - if (!src_virt)
> - return -ENOMEM;
> - if (dst_window->type == SCIF_WINDOW_SELF)
> - dst_virt = _get_local_va(dst_offset, dst_window,
> - loop_len);
> - else
> - dst_virt = ioremap_remote(dst_offset, dst_window,
> - loop_len,
> - work->remote_dev, NULL);
> - if (!dst_virt) {
> - if (src_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(src_virt, loop_len, work);
> - return -ENOMEM;
> - }
> - if (src_window->type == SCIF_WINDOW_SELF)
> - scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
> - remaining_len == loop_len ?
> - work->ordered : false);
> - else
> - scif_unaligned_cpy_fromio(dst_virt, src_virt,
> loop_len,
> - remaining_len == loop_len ?
> - work->ordered : false);
> - if (src_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(src_virt, loop_len, work);
> - if (dst_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(dst_virt, loop_len, work);
> - src_offset += loop_len;
> - dst_offset += loop_len;
> - remaining_len -= loop_len;
> - }
> -
> - end_src_offset = src_window->offset +
> - (src_window->nr_pages << PAGE_SHIFT);
> - end_dst_offset = dst_window->offset +
> - (dst_window->nr_pages << PAGE_SHIFT);
> - tail_len = remaining_len & (L1_CACHE_BYTES - 1);
> - remaining_len -= tail_len;
> - while (remaining_len) {
> - if (src_offset == end_src_offset) {
> - src_window = list_next_entry(src_window, list);
> - end_src_offset = src_window->offset +
> - (src_window->nr_pages << PAGE_SHIFT);
> - scif_init_window_iter(src_window, &src_win_iter);
> - }
> - if (dst_offset == end_dst_offset) {
> - dst_window = list_next_entry(dst_window, list);
> - end_dst_offset = dst_window->offset +
> - (dst_window->nr_pages << PAGE_SHIFT);
> - scif_init_window_iter(dst_window, &dst_win_iter);
> - }
> -
> - /* compute dma addresses for transfer */
> - src_dma_addr = scif_off_to_dma_addr(src_window,
> src_offset,
> - &src_contig_bytes,
> - &src_win_iter);
> - dst_dma_addr = scif_off_to_dma_addr(dst_window,
> dst_offset,
> - &dst_contig_bytes,
> - &dst_win_iter);
> - loop_len = min(src_contig_bytes, dst_contig_bytes);
> - loop_len = min(loop_len, remaining_len);
> - if (work->ordered && !tail_len &&
> - !(remaining_len - loop_len)) {
> - /*
> - * Break up the last chunk of the transfer into two
> - * steps. if there is no tail to gurantee DMA ordering.
> - * Passing SCIF_DMA_POLLING inserts a status update
> - * descriptor in step 1 which acts as a double sided
> - * synchronization fence for the DMA engine to
> ensure
> - * that the last cache line in step 2 is updated last.
> - */
> - /* Step 1) DMA: Body Length - L1_CACHE_BYTES. */
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr,
> - loop_len -
> - L1_CACHE_BYTES,
> - DMA_PREP_FENCE);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - src_offset += (loop_len - L1_CACHE_BYTES);
> - dst_offset += (loop_len - L1_CACHE_BYTES);
> - src_dma_addr += (loop_len - L1_CACHE_BYTES);
> - dst_dma_addr += (loop_len - L1_CACHE_BYTES);
> - remaining_len -= (loop_len - L1_CACHE_BYTES);
> - loop_len = remaining_len;
> -
> - /* Step 2) DMA: L1_CACHE_BYTES */
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr,
> - loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - } else {
> - tx = dev->device_prep_dma_memcpy(chan,
> dst_dma_addr,
> - src_dma_addr,
> - loop_len, 0);
> - if (!tx) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - ret = -ENOMEM;
> - goto err;
> - }
> - dma_async_issue_pending(chan);
> - }
> - src_offset += loop_len;
> - dst_offset += loop_len;
> - remaining_len -= loop_len;
> - }
> - remaining_len = tail_len;
> - if (remaining_len) {
> - loop_len = remaining_len;
> - if (src_offset == end_src_offset)
> - src_window = list_next_entry(src_window, list);
> - if (dst_offset == end_dst_offset)
> - dst_window = list_next_entry(dst_window, list);
> -
> - src_dma_addr = __scif_off_to_dma_addr(src_window,
> src_offset);
> - dst_dma_addr = __scif_off_to_dma_addr(dst_window,
> dst_offset);
> - /*
> - * The CPU copy for the tail bytes must be initiated only once
> - * previous DMA transfers for this endpoint have completed
> to
> - * guarantee ordering.
> - */
> - if (work->ordered) {
> - struct scif_dev *rdev = work->remote_dev;
> -
> - ret = scif_drain_dma_poll(rdev->sdev, chan);
> - if (ret)
> - return ret;
> - }
> - if (src_window->type == SCIF_WINDOW_SELF)
> - src_virt = _get_local_va(src_offset, src_window,
> - loop_len);
> - else
> - src_virt = ioremap_remote(src_offset, src_window,
> - loop_len,
> - work->remote_dev, NULL);
> - if (!src_virt)
> - return -ENOMEM;
> -
> - if (dst_window->type == SCIF_WINDOW_SELF)
> - dst_virt = _get_local_va(dst_offset, dst_window,
> - loop_len);
> - else
> - dst_virt = ioremap_remote(dst_offset, dst_window,
> - loop_len,
> - work->remote_dev, NULL);
> - if (!dst_virt) {
> - if (src_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(src_virt, loop_len, work);
> - return -ENOMEM;
> - }
> -
> - if (src_window->type == SCIF_WINDOW_SELF)
> - scif_unaligned_cpy_toio(dst_virt, src_virt, loop_len,
> - work->ordered);
> - else
> - scif_unaligned_cpy_fromio(dst_virt, src_virt,
> - loop_len, work->ordered);
> - if (src_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(src_virt, loop_len, work);
> -
> - if (dst_window->type != SCIF_WINDOW_SELF)
> - iounmap_remote(dst_virt, loop_len, work);
> - remaining_len -= loop_len;
> - }
> - return ret;
> -err:
> - dev_err(scif_info.mdev.this_device,
> - "%s %d Desc Prog Failed ret %d\n",
> - __func__, __LINE__, ret);
> - return ret;
> -}
> -
> -/*
> - * scif_rma_list_cpu_copy:
> - *
> - * Traverse all the windows and perform CPU copy.
> - */
> -static int scif_rma_list_cpu_copy(struct scif_copy_work *work)
> -{
> - void *src_virt, *dst_virt;
> - size_t loop_len, remaining_len;
> - int src_page_off, dst_page_off;
> - s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
> - struct scif_window *src_window = work->src_window;
> - struct scif_window *dst_window = work->dst_window;
> - s64 end_src_offset, end_dst_offset;
> - int ret = 0;
> - struct scif_window_iter src_win_iter;
> - struct scif_window_iter dst_win_iter;
> -
> - remaining_len = work->len;
> -
> - scif_init_window_iter(src_window, &src_win_iter);
> - scif_init_window_iter(dst_window, &dst_win_iter);
> - while (remaining_len) {
> - src_page_off = src_offset & ~PAGE_MASK;
> - dst_page_off = dst_offset & ~PAGE_MASK;
> - loop_len = min(PAGE_SIZE -
> - max(src_page_off, dst_page_off),
> - remaining_len);
> -
> - if (src_window->type == SCIF_WINDOW_SELF)
> - src_virt = _get_local_va(src_offset, src_window,
> - loop_len);
> - else
> - src_virt = ioremap_remote(src_offset, src_window,
> - loop_len,
> - work->remote_dev,
> - &src_win_iter);
> - if (!src_virt) {
> - ret = -ENOMEM;
> - goto error;
> - }
> -
> - if (dst_window->type == SCIF_WINDOW_SELF)
> - dst_virt = _get_local_va(dst_offset, dst_window,
> - loop_len);
> - else
> - dst_virt = ioremap_remote(dst_offset, dst_window,
> - loop_len,
> - work->remote_dev,
> - &dst_win_iter);
> - if (!dst_virt) {
> - if (src_window->type == SCIF_WINDOW_PEER)
> - iounmap_remote(src_virt, loop_len, work);
> - ret = -ENOMEM;
> - goto error;
> - }
> -
> - if (work->loopback) {
> - memcpy(dst_virt, src_virt, loop_len);
> - } else {
> - if (src_window->type == SCIF_WINDOW_SELF)
> - memcpy_toio((void __iomem __force
> *)dst_virt,
> - src_virt, loop_len);
> - else
> - memcpy_fromio(dst_virt,
> - (void __iomem __force *)src_virt,
> - loop_len);
> - }
> - if (src_window->type == SCIF_WINDOW_PEER)
> - iounmap_remote(src_virt, loop_len, work);
> -
> - if (dst_window->type == SCIF_WINDOW_PEER)
> - iounmap_remote(dst_virt, loop_len, work);
> -
> - src_offset += loop_len;
> - dst_offset += loop_len;
> - remaining_len -= loop_len;
> - if (remaining_len) {
> - end_src_offset = src_window->offset +
> - (src_window->nr_pages << PAGE_SHIFT);
> - end_dst_offset = dst_window->offset +
> - (dst_window->nr_pages << PAGE_SHIFT);
> - if (src_offset == end_src_offset) {
> - src_window = list_next_entry(src_window,
> list);
> - scif_init_window_iter(src_window,
> - &src_win_iter);
> - }
> - if (dst_offset == end_dst_offset) {
> - dst_window = list_next_entry(dst_window,
> list);
> - scif_init_window_iter(dst_window,
> - &dst_win_iter);
> - }
> - }
> - }
> -error:
> - return ret;
> -}
> -
> -static int scif_rma_list_dma_copy_wrapper(struct scif_endpt *epd,
> - struct scif_copy_work *work,
> - struct dma_chan *chan, off_t loffset)
> -{
> - int src_cache_off, dst_cache_off;
> - s64 src_offset = work->src_offset, dst_offset = work->dst_offset;
> - u8 *temp = NULL;
> - bool src_local = true;
> - struct scif_dma_comp_cb *comp_cb;
> - int err;
> -
> - if (is_dma_copy_aligned(chan->device, 1, 1, 1))
> - return _scif_rma_list_dma_copy_aligned(work, chan);
> -
> - src_cache_off = src_offset & (L1_CACHE_BYTES - 1);
> - dst_cache_off = dst_offset & (L1_CACHE_BYTES - 1);
> -
> - if (dst_cache_off == src_cache_off)
> - return scif_rma_list_dma_copy_aligned(work, chan);
> -
> - if (work->loopback)
> - return scif_rma_list_cpu_copy(work);
> - src_local = work->src_window->type == SCIF_WINDOW_SELF;
> -
> - /* Allocate dma_completion cb */
> - comp_cb = kzalloc(sizeof(*comp_cb), GFP_KERNEL);
> - if (!comp_cb)
> - goto error;
> -
> - work->comp_cb = comp_cb;
> - comp_cb->cb_cookie = comp_cb;
> - comp_cb->dma_completion_func = &scif_rma_completion_cb;
> -
> - if (work->len + (L1_CACHE_BYTES << 1) <
> SCIF_KMEM_UNALIGNED_BUF_SIZE) {
> - comp_cb->is_cache = false;
> - /* Allocate padding bytes to align to a cache line */
> - temp = kmalloc(work->len + (L1_CACHE_BYTES << 1),
> - GFP_KERNEL);
> - if (!temp)
> - goto free_comp_cb;
> - comp_cb->temp_buf_to_free = temp;
> - /* kmalloc(..) does not guarantee cache line alignment */
> - if (!IS_ALIGNED((u64)temp, L1_CACHE_BYTES))
> - temp = PTR_ALIGN(temp, L1_CACHE_BYTES);
> - } else {
> - comp_cb->is_cache = true;
> - temp = kmem_cache_alloc(unaligned_cache, GFP_KERNEL);
> - if (!temp)
> - goto free_comp_cb;
> - comp_cb->temp_buf_to_free = temp;
> - }
> -
> - if (src_local) {
> - temp += dst_cache_off;
> - scif_rma_local_cpu_copy(work->src_offset, work-
> >src_window,
> - temp, work->len, true);
> - } else {
> - comp_cb->dst_window = work->dst_window;
> - comp_cb->dst_offset = work->dst_offset;
> - work->src_offset = work->src_offset - src_cache_off;
> - comp_cb->len = work->len;
> - work->len = ALIGN(work->len + src_cache_off,
> L1_CACHE_BYTES);
> - comp_cb->header_padding = src_cache_off;
> - }
> - comp_cb->temp_buf = temp;
> -
> - err = scif_map_single(&comp_cb->temp_phys, temp,
> - work->remote_dev,
> SCIF_KMEM_UNALIGNED_BUF_SIZE);
> - if (err)
> - goto free_temp_buf;
> - comp_cb->sdev = work->remote_dev;
> - if (scif_rma_list_dma_copy_unaligned(work, temp, chan, src_local) <
> 0)
> - goto free_temp_buf;
> - if (!src_local)
> - work->fence_type = SCIF_DMA_INTR;
> - return 0;
> -free_temp_buf:
> - if (comp_cb->is_cache)
> - kmem_cache_free(unaligned_cache, comp_cb-
> >temp_buf_to_free);
> - else
> - kfree(comp_cb->temp_buf_to_free);
> -free_comp_cb:
> - kfree(comp_cb);
> -error:
> - return -ENOMEM;
> -}
> -
> -/**
> - * scif_rma_copy:
> - * @epd: end point descriptor.
> - * @loffset: offset in local registered address space to/from which to copy
> - * @addr: user virtual address to/from which to copy
> - * @len: length of range to copy
> - * @roffset: offset in remote registered address space to/from which to
> copy
> - * @flags: flags
> - * @dir: LOCAL->REMOTE or vice versa.
> - * @last_chunk: true if this is the last chunk of a larger transfer
> - *
> - * Validate parameters, check if src/dst registered ranges requested for copy
> - * are valid and initiate either CPU or DMA copy.
> - */
> -static int scif_rma_copy(scif_epd_t epd, off_t loffset, unsigned long addr,
> - size_t len, off_t roffset, int flags,
> - enum scif_rma_dir dir, bool last_chunk)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scif_rma_req remote_req;
> - struct scif_rma_req req;
> - struct scif_window *local_window = NULL;
> - struct scif_window *remote_window = NULL;
> - struct scif_copy_work copy_work;
> - bool loopback;
> - int err = 0;
> - struct dma_chan *chan;
> - struct scif_mmu_notif *mmn = NULL;
> - bool cache = false;
> - struct device *spdev;
> -
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - if (flags && !(flags & (SCIF_RMA_USECPU | SCIF_RMA_USECACHE |
> - SCIF_RMA_SYNC | SCIF_RMA_ORDERED)))
> - return -EINVAL;
> -
> - loopback = scifdev_self(ep->remote_dev) ? true : false;
> - copy_work.fence_type = ((flags & SCIF_RMA_SYNC) && last_chunk) ?
> - SCIF_DMA_POLL : 0;
> - copy_work.ordered = !!((flags & SCIF_RMA_ORDERED) &&
> last_chunk);
> -
> - /* Use CPU for Mgmt node <-> Mgmt node copies */
> - if (loopback && scif_is_mgmt_node()) {
> - flags |= SCIF_RMA_USECPU;
> - copy_work.fence_type = 0x0;
> - }
> -
> - cache = scif_is_set_reg_cache(flags);
> -
> - remote_req.out_window = &remote_window;
> - remote_req.offset = roffset;
> - remote_req.nr_bytes = len;
> - /*
> - * If transfer is from local to remote then the remote window
> - * must be writeable and vice versa.
> - */
> - remote_req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_WRITE :
> VM_READ;
> - remote_req.type = SCIF_WINDOW_PARTIAL;
> - remote_req.head = &ep->rma_info.remote_reg_list;
> -
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - return err;
> - }
> -
> - if (addr && cache) {
> - mutex_lock(&ep->rma_info.mmn_lock);
> - mmn = scif_find_mmu_notifier(current->mm, &ep-
> >rma_info);
> - if (!mmn)
> - mmn = scif_add_mmu_notifier(current->mm, ep);
> - mutex_unlock(&ep->rma_info.mmn_lock);
> - if (IS_ERR(mmn)) {
> - scif_put_peer_dev(spdev);
> - return PTR_ERR(mmn);
> - }
> - cache = cache && !scif_rma_tc_can_cache(ep, len);
> - }
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (addr) {
> - req.out_window = &local_window;
> - req.nr_bytes = ALIGN(len + (addr & ~PAGE_MASK),
> - PAGE_SIZE);
> - req.va_for_temp = addr & PAGE_MASK;
> - req.prot = (dir == SCIF_LOCAL_TO_REMOTE ?
> - VM_READ : VM_WRITE | VM_READ);
> - /* Does a valid local window exist? */
> - if (mmn) {
> - spin_lock(&ep->rma_info.tc_lock);
> - req.head = &mmn->tc_reg_list;
> - err = scif_query_tcw(ep, &req);
> - spin_unlock(&ep->rma_info.tc_lock);
> - }
> - if (!mmn || err) {
> - err = scif_register_temp(epd, req.va_for_temp,
> - req.nr_bytes, req.prot,
> - &loffset, &local_window);
> - if (err) {
> - mutex_unlock(&ep->rma_info.rma_lock);
> - goto error;
> - }
> - if (!cache)
> - goto skip_cache;
> - atomic_inc(&ep->rma_info.tcw_refcount);
> - atomic_add_return(local_window->nr_pages,
> - &ep->rma_info.tcw_total_pages);
> - if (mmn) {
> - spin_lock(&ep->rma_info.tc_lock);
> - scif_insert_tcw(local_window,
> - &mmn->tc_reg_list);
> - spin_unlock(&ep->rma_info.tc_lock);
> - }
> - }
> -skip_cache:
> - loffset = local_window->offset +
> - (addr - local_window->va_for_temp);
> - } else {
> - req.out_window = &local_window;
> - req.offset = loffset;
> - /*
> - * If transfer is from local to remote then the self window
> - * must be readable and vice versa.
> - */
> - req.prot = dir == SCIF_LOCAL_TO_REMOTE ? VM_READ :
> VM_WRITE;
> - req.nr_bytes = len;
> - req.type = SCIF_WINDOW_PARTIAL;
> - req.head = &ep->rma_info.reg_list;
> - /* Does a valid local window exist? */
> - err = scif_query_window(&req);
> - if (err) {
> - mutex_unlock(&ep->rma_info.rma_lock);
> - goto error;
> - }
> - }
> -
> - /* Does a valid remote window exist? */
> - err = scif_query_window(&remote_req);
> - if (err) {
> - mutex_unlock(&ep->rma_info.rma_lock);
> - goto error;
> - }
> -
> - /*
> - * Prepare copy_work for submitting work to the DMA kernel thread
> - * or CPU copy routine.
> - */
> - copy_work.len = len;
> - copy_work.loopback = loopback;
> - copy_work.remote_dev = ep->remote_dev;
> - if (dir == SCIF_LOCAL_TO_REMOTE) {
> - copy_work.src_offset = loffset;
> - copy_work.src_window = local_window;
> - copy_work.dst_offset = roffset;
> - copy_work.dst_window = remote_window;
> - } else {
> - copy_work.src_offset = roffset;
> - copy_work.src_window = remote_window;
> - copy_work.dst_offset = loffset;
> - copy_work.dst_window = local_window;
> - }
> -
> - if (flags & SCIF_RMA_USECPU) {
> - scif_rma_list_cpu_copy(&copy_work);
> - } else {
> - chan = ep->rma_info.dma_chan;
> - err = scif_rma_list_dma_copy_wrapper(epd, &copy_work,
> - chan, loffset);
> - }
> - if (addr && !cache)
> - atomic_inc(&ep->rma_info.tw_refcount);
> -
> - mutex_unlock(&ep->rma_info.rma_lock);
> -
> - if (last_chunk) {
> - struct scif_dev *rdev = ep->remote_dev;
> -
> - if (copy_work.fence_type == SCIF_DMA_POLL)
> - err = scif_drain_dma_poll(rdev->sdev,
> - ep->rma_info.dma_chan);
> - else if (copy_work.fence_type == SCIF_DMA_INTR)
> - err = scif_drain_dma_intr(rdev->sdev,
> - ep->rma_info.dma_chan);
> - }
> -
> - if (addr && !cache)
> - scif_queue_for_cleanup(local_window, &scif_info.rma);
> - scif_put_peer_dev(spdev);
> - return err;
> -error:
> - if (err) {
> - if (addr && local_window && !cache)
> - scif_destroy_window(ep, local_window);
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d len 0x%lx\n",
> - __func__, __LINE__, err, len);
> - }
> - scif_put_peer_dev(spdev);
> - return err;
> -}
> -
> -int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len,
> - off_t roffset, int flags)
> -{
> - int err;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI readfrom: ep %p loffset 0x%lx len 0x%lx offset 0x%lx
> flags 0x%x\n",
> - epd, loffset, len, roffset, flags);
> - if (scif_unaligned(loffset, roffset)) {
> - while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
> - err = scif_rma_copy(epd, loffset, 0x0,
> - SCIF_MAX_UNALIGNED_BUF_SIZE,
> - roffset, flags,
> - SCIF_REMOTE_TO_LOCAL, false);
> - if (err)
> - goto readfrom_err;
> - loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
> - }
> - }
> - err = scif_rma_copy(epd, loffset, 0x0, len,
> - roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
> -readfrom_err:
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_readfrom);
> -
> -int scif_writeto(scif_epd_t epd, off_t loffset, size_t len,
> - off_t roffset, int flags)
> -{
> - int err;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI writeto: ep %p loffset 0x%lx len 0x%lx roffset 0x%lx
> flags 0x%x\n",
> - epd, loffset, len, roffset, flags);
> - if (scif_unaligned(loffset, roffset)) {
> - while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
> - err = scif_rma_copy(epd, loffset, 0x0,
> - SCIF_MAX_UNALIGNED_BUF_SIZE,
> - roffset, flags,
> - SCIF_LOCAL_TO_REMOTE, false);
> - if (err)
> - goto writeto_err;
> - loffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
> - }
> - }
> - err = scif_rma_copy(epd, loffset, 0x0, len,
> - roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
> -writeto_err:
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_writeto);
> -
> -int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len,
> - off_t roffset, int flags)
> -{
> - int err;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI vreadfrom: ep %p addr %p len 0x%lx roffset 0x%lx
> flags 0x%x\n",
> - epd, addr, len, roffset, flags);
> - if (scif_unaligned((off_t __force)addr, roffset)) {
> - if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
> - flags &= ~SCIF_RMA_USECACHE;
> -
> - while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
> - err = scif_rma_copy(epd, 0, (u64)addr,
> - SCIF_MAX_UNALIGNED_BUF_SIZE,
> - roffset, flags,
> - SCIF_REMOTE_TO_LOCAL, false);
> - if (err)
> - goto vreadfrom_err;
> - addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
> - }
> - }
> - err = scif_rma_copy(epd, 0, (u64)addr, len,
> - roffset, flags, SCIF_REMOTE_TO_LOCAL, true);
> -vreadfrom_err:
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_vreadfrom);
> -
> -int scif_vwriteto(scif_epd_t epd, void *addr, size_t len,
> - off_t roffset, int flags)
> -{
> - int err;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI vwriteto: ep %p addr %p len 0x%lx roffset 0x%lx
> flags 0x%x\n",
> - epd, addr, len, roffset, flags);
> - if (scif_unaligned((off_t __force)addr, roffset)) {
> - if (len > SCIF_MAX_UNALIGNED_BUF_SIZE)
> - flags &= ~SCIF_RMA_USECACHE;
> -
> - while (len > SCIF_MAX_UNALIGNED_BUF_SIZE) {
> - err = scif_rma_copy(epd, 0, (u64)addr,
> - SCIF_MAX_UNALIGNED_BUF_SIZE,
> - roffset, flags,
> - SCIF_LOCAL_TO_REMOTE, false);
> - if (err)
> - goto vwriteto_err;
> - addr += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - roffset += SCIF_MAX_UNALIGNED_BUF_SIZE;
> - len -= SCIF_MAX_UNALIGNED_BUF_SIZE;
> - }
> - }
> - err = scif_rma_copy(epd, 0, (u64)addr, len,
> - roffset, flags, SCIF_LOCAL_TO_REMOTE, true);
> -vwriteto_err:
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_vwriteto);
> diff --git a/drivers/misc/mic/scif/scif_epd.c
> b/drivers/misc/mic/scif/scif_epd.c
> deleted file mode 100644
> index 426687f6696b..000000000000
> --- a/drivers/misc/mic/scif/scif_epd.c
> +++ /dev/null
> @@ -1,357 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -void scif_cleanup_ep_qp(struct scif_endpt *ep)
> -{
> - struct scif_qp *qp = ep->qp_info.qp;
> -
> - if (qp->outbound_q.rb_base) {
> - scif_iounmap((void *)qp->outbound_q.rb_base,
> - qp->outbound_q.size, ep->remote_dev);
> - qp->outbound_q.rb_base = NULL;
> - }
> - if (qp->remote_qp) {
> - scif_iounmap((void *)qp->remote_qp,
> - sizeof(struct scif_qp), ep->remote_dev);
> - qp->remote_qp = NULL;
> - }
> - if (qp->local_qp) {
> - scif_unmap_single(qp->local_qp, ep->remote_dev,
> - sizeof(struct scif_qp));
> - qp->local_qp = 0x0;
> - }
> - if (qp->local_buf) {
> - scif_unmap_single(qp->local_buf, ep->remote_dev,
> - SCIF_ENDPT_QP_SIZE);
> - qp->local_buf = 0;
> - }
> -}
> -
> -void scif_teardown_ep(void *endpt)
> -{
> - struct scif_endpt *ep = endpt;
> - struct scif_qp *qp = ep->qp_info.qp;
> -
> - if (qp) {
> - spin_lock(&ep->lock);
> - scif_cleanup_ep_qp(ep);
> - spin_unlock(&ep->lock);
> - kfree(qp->inbound_q.rb_base);
> - kfree(qp);
> - }
> -}
> -
> -/*
> - * Enqueue the endpoint to the zombie list for cleanup.
> - * The endpoint should not be accessed once this API returns.
> - */
> -void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held)
> -{
> - if (!eplock_held)
> - mutex_lock(&scif_info.eplock);
> - spin_lock(&ep->lock);
> - ep->state = SCIFEP_ZOMBIE;
> - spin_unlock(&ep->lock);
> - list_add_tail(&ep->list, &scif_info.zombie);
> - scif_info.nr_zombies++;
> - if (!eplock_held)
> - mutex_unlock(&scif_info.eplock);
> - schedule_work(&scif_info.misc_work);
> -}
> -
> -static struct scif_endpt *scif_find_listen_ep(u16 port)
> -{
> - struct scif_endpt *ep = NULL;
> - struct list_head *pos, *tmpq;
> -
> - mutex_lock(&scif_info.eplock);
> - list_for_each_safe(pos, tmpq, &scif_info.listen) {
> - ep = list_entry(pos, struct scif_endpt, list);
> - if (ep->port.port == port) {
> - mutex_unlock(&scif_info.eplock);
> - return ep;
> - }
> - }
> - mutex_unlock(&scif_info.eplock);
> - return NULL;
> -}
> -
> -void scif_cleanup_zombie_epd(void)
> -{
> - struct list_head *pos, *tmpq;
> - struct scif_endpt *ep;
> -
> - mutex_lock(&scif_info.eplock);
> - list_for_each_safe(pos, tmpq, &scif_info.zombie) {
> - ep = list_entry(pos, struct scif_endpt, list);
> - if (scif_rma_ep_can_uninit(ep)) {
> - list_del(pos);
> - scif_info.nr_zombies--;
> - put_iova_domain(&ep->rma_info.iovad);
> - kfree(ep);
> - }
> - }
> - mutex_unlock(&scif_info.eplock);
> -}
> -
> -/**
> - * scif_cnctreq() - Respond to SCIF_CNCT_REQ interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * This message is initiated by the remote node to request a connection
> - * to the local node. This function looks for an end point in the
> - * listen state on the requested port id.
> - *
> - * If it finds a listening port it places the connect request on the
> - * listening end points queue and wakes up any pending accept calls.
> - *
> - * If it does not find a listening end point it sends a connection
> - * reject message to the remote node.
> - */
> -void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = NULL;
> - struct scif_conreq *conreq;
> -
> - conreq = kmalloc(sizeof(*conreq), GFP_KERNEL);
> - if (!conreq)
> - /* Lack of resources so reject the request. */
> - goto conreq_sendrej;
> -
> - ep = scif_find_listen_ep(msg->dst.port);
> - if (!ep)
> - /* Send reject due to no listening ports */
> - goto conreq_sendrej_free;
> - else
> - spin_lock(&ep->lock);
> -
> - if (ep->backlog <= ep->conreqcnt) {
> - /* Send reject due to too many pending requests */
> - spin_unlock(&ep->lock);
> - goto conreq_sendrej_free;
> - }
> -
> - conreq->msg = *msg;
> - list_add_tail(&conreq->list, &ep->conlist);
> - ep->conreqcnt++;
> - wake_up_interruptible(&ep->conwq);
> - spin_unlock(&ep->lock);
> - return;
> -
> -conreq_sendrej_free:
> - kfree(conreq);
> -conreq_sendrej:
> - msg->uop = SCIF_CNCT_REJ;
> - scif_nodeqp_send(&scif_dev[msg->src.node], msg);
> -}
> -
> -/**
> - * scif_cnctgnt() - Respond to SCIF_CNCT_GNT interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * An accept() on the remote node has occurred and sent this message
> - * to indicate success. Place the end point in the MAPPING state and
> - * save the remote nodes memory information. Then wake up the connect
> - * request so it can finish.
> - */
> -void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - if (SCIFEP_CONNECTING == ep->state) {
> - ep->peer.node = msg->src.node;
> - ep->peer.port = msg->src.port;
> - ep->qp_info.gnt_pld = msg->payload[1];
> - ep->remote_ep = msg->payload[2];
> - ep->state = SCIFEP_MAPPING;
> -
> - wake_up(&ep->conwq);
> - }
> - spin_unlock(&ep->lock);
> -}
> -
> -/**
> - * scif_cnctgnt_ack() - Respond to SCIF_CNCT_GNTACK interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The remote connection request has finished mapping the local memory.
> - * Place the connection in the connected state and wake up the pending
> - * accept() call.
> - */
> -void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - mutex_lock(&scif_info.connlock);
> - spin_lock(&ep->lock);
> - /* New ep is now connected with all resources set. */
> - ep->state = SCIFEP_CONNECTED;
> - list_add_tail(&ep->list, &scif_info.connected);
> - wake_up(&ep->conwq);
> - spin_unlock(&ep->lock);
> - mutex_unlock(&scif_info.connlock);
> -}
> -
> -/**
> - * scif_cnctgnt_nack() - Respond to SCIF_CNCT_GNTNACK interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The remote connection request failed to map the local memory it was
> sent.
> - * Place the end point in the CLOSING state to indicate it and wake up
> - * the pending accept();
> - */
> -void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - ep->state = SCIFEP_CLOSING;
> - wake_up(&ep->conwq);
> - spin_unlock(&ep->lock);
> -}
> -
> -/**
> - * scif_cnctrej() - Respond to SCIF_CNCT_REJ interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The remote end has rejected the connection request. Set the end
> - * point back to the bound state and wake up the pending connect().
> - */
> -void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - if (SCIFEP_CONNECTING == ep->state) {
> - ep->state = SCIFEP_BOUND;
> - wake_up(&ep->conwq);
> - }
> - spin_unlock(&ep->lock);
> -}
> -
> -/**
> - * scif_discnct() - Respond to SCIF_DISCNCT interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The remote node has indicated close() has been called on its end
> - * point. Remove the local end point from the connected list, set its
> - * state to disconnected and ensure accesses to the remote node are
> - * shutdown.
> - *
> - * When all accesses to the remote end have completed then send a
> - * DISCNT_ACK to indicate it can remove its resources and complete
> - * the close routine.
> - */
> -void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = NULL;
> - struct scif_endpt *tmpep;
> - struct list_head *pos, *tmpq;
> -
> - mutex_lock(&scif_info.connlock);
> - list_for_each_safe(pos, tmpq, &scif_info.connected) {
> - tmpep = list_entry(pos, struct scif_endpt, list);
> - /*
> - * The local ep may have sent a disconnect and and been
> closed
> - * due to a message response time out. It may have been
> - * allocated again and formed a new connection so we want
> to
> - * check if the remote ep matches
> - */
> - if (((u64)tmpep == msg->payload[1]) &&
> - ((u64)tmpep->remote_ep == msg->payload[0])) {
> - list_del(pos);
> - ep = tmpep;
> - spin_lock(&ep->lock);
> - break;
> - }
> - }
> -
> - /*
> - * If the terminated end is not found then this side started closing
> - * before the other side sent the disconnect. If so the ep will no
> - * longer be on the connected list. Regardless the other side
> - * needs to be acked to let it know close is complete.
> - */
> - if (!ep) {
> - mutex_unlock(&scif_info.connlock);
> - goto discnct_ack;
> - }
> -
> - ep->state = SCIFEP_DISCONNECTED;
> - list_add_tail(&ep->list, &scif_info.disconnected);
> -
> - wake_up_interruptible(&ep->sendwq);
> - wake_up_interruptible(&ep->recvwq);
> - spin_unlock(&ep->lock);
> - mutex_unlock(&scif_info.connlock);
> -
> -discnct_ack:
> - msg->uop = SCIF_DISCNT_ACK;
> - scif_nodeqp_send(&scif_dev[msg->src.node], msg);
> -}
> -
> -/**
> - * scif_discnct_ack() - Respond to SCIF_DISCNT_ACK interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remote side has indicated it has not more references to local resources
> - */
> -void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - ep->state = SCIFEP_DISCONNECTED;
> - spin_unlock(&ep->lock);
> - complete(&ep->discon);
> -}
> -
> -/**
> - * scif_clientsend() - Respond to SCIF_CLIENT_SEND interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remote side is confirming send or receive interrupt handling is complete.
> - */
> -void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - if (SCIFEP_CONNECTED == ep->state)
> - wake_up_interruptible(&ep->recvwq);
> - spin_unlock(&ep->lock);
> -}
> -
> -/**
> - * scif_clientrcvd() - Respond to SCIF_CLIENT_RCVD interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remote side is confirming send or receive interrupt handling is complete.
> - */
> -void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> -
> - spin_lock(&ep->lock);
> - if (SCIFEP_CONNECTED == ep->state)
> - wake_up_interruptible(&ep->sendwq);
> - spin_unlock(&ep->lock);
> -}
> diff --git a/drivers/misc/mic/scif/scif_epd.h
> b/drivers/misc/mic/scif/scif_epd.h
> deleted file mode 100644
> index 0b9dfe1cc06c..000000000000
> --- a/drivers/misc/mic/scif/scif_epd.h
> +++ /dev/null
> @@ -1,200 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef SCIF_EPD_H
> -#define SCIF_EPD_H
> -
> -#include <linux/delay.h>
> -#include <linux/scif.h>
> -#include <linux/scif_ioctl.h>
> -
> -#define SCIF_EPLOCK_HELD true
> -
> -enum scif_epd_state {
> - SCIFEP_UNBOUND,
> - SCIFEP_BOUND,
> - SCIFEP_LISTENING,
> - SCIFEP_CONNECTED,
> - SCIFEP_CONNECTING,
> - SCIFEP_MAPPING,
> - SCIFEP_CLOSING,
> - SCIFEP_CLLISTEN,
> - SCIFEP_DISCONNECTED,
> - SCIFEP_ZOMBIE
> -};
> -
> -/*
> - * struct scif_conreq - Data structure added to the connection list.
> - *
> - * @msg: connection request message received
> - * @list: link to list of connection requests
> - */
> -struct scif_conreq {
> - struct scifmsg msg;
> - struct list_head list;
> -};
> -
> -/* Size of the RB for the Endpoint QP */
> -#define SCIF_ENDPT_QP_SIZE 0x1000
> -
> -/*
> - * scif_endpt_qp_info - SCIF endpoint queue pair
> - *
> - * @qp - Qpair for this endpoint
> - * @qp_offset - DMA address of the QP
> - * @gnt_pld - Payload in a SCIF_CNCT_GNT message containing the
> - * physical address of the remote_qp.
> - */
> -struct scif_endpt_qp_info {
> - struct scif_qp *qp;
> - dma_addr_t qp_offset;
> - dma_addr_t gnt_pld;
> -};
> -
> -/*
> - * struct scif_endpt - The SCIF endpoint data structure
> - *
> - * @state: end point state
> - * @lock: lock synchronizing access to endpoint fields like state etc
> - * @port: self port information
> - * @peer: peer port information
> - * @backlog: maximum pending connection requests
> - * @qp_info: Endpoint QP information for SCIF messaging
> - * @remote_dev: scifdev used by this endpt to communicate with remote
> node.
> - * @remote_ep: remote endpoint
> - * @conreqcnt: Keep track of number of connection requests.
> - * @files: Open file information used to match the id passed in with
> - * the flush routine.
> - * @conlist: list of connection requests
> - * @conwq: waitqueue for connection processing
> - * @discon: completion used during disconnection
> - * @sendwq: waitqueue used during sending messages
> - * @recvwq: waitqueue used during message receipt
> - * @sendlock: Synchronize ordering of messages sent
> - * @recvlock: Synchronize ordering of messages received
> - * @list: link to list of various endpoints like connected, listening etc
> - * @li_accept: pending ACCEPTREG
> - * @acceptcnt: pending ACCEPTREG cnt
> - * @liacceptlist: link to listen accept
> - * @miacceptlist: link to uaccept
> - * @listenep: associated listen ep
> - * @conn_work: Non blocking connect work
> - * @conn_port: Connection port
> - * @conn_err: Errors during connection
> - * @conn_async_state: Async connection
> - * @conn_pend_wq: Used by poll while waiting for incoming connections
> - * @conn_list: List of async connection requests
> - * @rma_info: Information for triggering SCIF RMA and DMA operations
> - * @mmu_list: link to list of MMU notifier cleanup work
> - * @anon: anonymous file for use in kernel mode scif poll
> - */
> -struct scif_endpt {
> - enum scif_epd_state state;
> - spinlock_t lock;
> - struct scif_port_id port;
> - struct scif_port_id peer;
> - int backlog;
> - struct scif_endpt_qp_info qp_info;
> - struct scif_dev *remote_dev;
> - u64 remote_ep;
> - int conreqcnt;
> - struct files_struct *files;
> - struct list_head conlist;
> - wait_queue_head_t conwq;
> - struct completion discon;
> - wait_queue_head_t sendwq;
> - wait_queue_head_t recvwq;
> - struct mutex sendlock;
> - struct mutex recvlock;
> - struct list_head list;
> - struct list_head li_accept;
> - int acceptcnt;
> - struct list_head liacceptlist;
> - struct list_head miacceptlist;
> - struct scif_endpt *listenep;
> - struct scif_port_id conn_port;
> - int conn_err;
> - int conn_async_state;
> - wait_queue_head_t conn_pend_wq;
> - struct list_head conn_list;
> - struct scif_endpt_rma_info rma_info;
> - struct list_head mmu_list;
> - struct file *anon;
> -};
> -
> -static inline int scifdev_alive(struct scif_endpt *ep)
> -{
> - return _scifdev_alive(ep->remote_dev);
> -}
> -
> -/*
> - * scif_verify_epd:
> - * ep: SCIF endpoint
> - *
> - * Checks several generic error conditions and returns the
> - * appropriate error.
> - */
> -static inline int scif_verify_epd(struct scif_endpt *ep)
> -{
> - if (ep->state == SCIFEP_DISCONNECTED)
> - return -ECONNRESET;
> -
> - if (ep->state != SCIFEP_CONNECTED)
> - return -ENOTCONN;
> -
> - if (!scifdev_alive(ep))
> - return -ENODEV;
> -
> - return 0;
> -}
> -
> -static inline int scif_anon_inode_getfile(scif_epd_t epd)
> -{
> - epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
> -
> - return PTR_ERR_OR_ZERO(epd->anon);
> -}
> -
> -static inline void scif_anon_inode_fput(scif_epd_t epd)
> -{
> - if (epd->anon) {
> - fput(epd->anon);
> - epd->anon = NULL;
> - }
> -}
> -
> -void scif_cleanup_zombie_epd(void);
> -void scif_teardown_ep(void *endpt);
> -void scif_cleanup_ep_qp(struct scif_endpt *ep);
> -void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held);
> -void scif_get_node_info(void);
> -void scif_send_acks(struct scif_dev *dev);
> -void scif_conn_handler(struct work_struct *work);
> -int scif_rsrv_port(u16 port);
> -void scif_get_port(u16 port);
> -int scif_get_new_port(void);
> -void scif_put_port(u16 port);
> -int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags);
> -int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags);
> -void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
> -int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
> -int __scif_flush(scif_epd_t epd);
> -int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
> -__poll_t __scif_pollfd(struct file *f, poll_table *wait,
> - struct scif_endpt *ep);
> -int __scif_pin_pages(void *addr, size_t len, int *out_prot,
> - int map_flags, scif_pinned_pages_t *pages);
> -#endif /* SCIF_EPD_H */
> diff --git a/drivers/misc/mic/scif/scif_fd.c b/drivers/misc/mic/scif/scif_fd.c
> deleted file mode 100644
> index 3f08646cd78a..000000000000
> --- a/drivers/misc/mic/scif/scif_fd.c
> +++ /dev/null
> @@ -1,462 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -
> -static int scif_fdopen(struct inode *inode, struct file *f)
> -{
> - struct scif_endpt *priv = scif_open();
> -
> - if (!priv)
> - return -ENOMEM;
> - f->private_data = priv;
> - return 0;
> -}
> -
> -static int scif_fdclose(struct inode *inode, struct file *f)
> -{
> - struct scif_endpt *priv = f->private_data;
> -
> - return scif_close(priv);
> -}
> -
> -static int scif_fdmmap(struct file *f, struct vm_area_struct *vma)
> -{
> - struct scif_endpt *priv = f->private_data;
> -
> - return scif_mmap(vma, priv);
> -}
> -
> -static __poll_t scif_fdpoll(struct file *f, poll_table *wait)
> -{
> - struct scif_endpt *priv = f->private_data;
> -
> - return __scif_pollfd(f, wait, priv);
> -}
> -
> -static int scif_fdflush(struct file *f, fl_owner_t id)
> -{
> - struct scif_endpt *ep = f->private_data;
> -
> - spin_lock(&ep->lock);
> - /*
> - * The listening endpoint stashes the open file information before
> - * waiting for incoming connections. The release callback would
> never be
> - * called if the application closed the endpoint, while waiting for
> - * incoming connections from a separate thread since the file
> descriptor
> - * reference count is bumped up in the accept IOCTL. Call the flush
> - * routine if the id matches the endpoint open file information so
> that
> - * the listening endpoint can be woken up and the fd released.
> - */
> - if (ep->files == id)
> - __scif_flush(ep);
> - spin_unlock(&ep->lock);
> - return 0;
> -}
> -
> -static __always_inline void scif_err_debug(int err, const char *str)
> -{
> - /*
> - * ENOTCONN is a common uninteresting error which is
> - * flooding debug messages to the console unnecessarily.
> - */
> - if (err < 0 && err != -ENOTCONN)
> - dev_dbg(scif_info.mdev.this_device, "%s err %d\n", str, err);
> -}
> -
> -static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
> -{
> - struct scif_endpt *priv = f->private_data;
> - void __user *argp = (void __user *)arg;
> - int err = 0;
> - struct scifioctl_msg request;
> - bool non_block = false;
> -
> - non_block = !!(f->f_flags & O_NONBLOCK);
> -
> - switch (cmd) {
> - case SCIF_BIND:
> - {
> - int pn;
> -
> - if (copy_from_user(&pn, argp, sizeof(pn)))
> - return -EFAULT;
> -
> - pn = scif_bind(priv, pn);
> - if (pn < 0)
> - return pn;
> -
> - if (copy_to_user(argp, &pn, sizeof(pn)))
> - return -EFAULT;
> -
> - return 0;
> - }
> - case SCIF_LISTEN:
> - return scif_listen(priv, arg);
> - case SCIF_CONNECT:
> - {
> - struct scifioctl_connect req;
> - struct scif_endpt *ep = (struct scif_endpt *)priv;
> -
> - if (copy_from_user(&req, argp, sizeof(req)))
> - return -EFAULT;
> -
> - err = __scif_connect(priv, &req.peer, non_block);
> - if (err < 0)
> - return err;
> -
> - req.self.node = ep->port.node;
> - req.self.port = ep->port.port;
> -
> - if (copy_to_user(argp, &req, sizeof(req)))
> - return -EFAULT;
> -
> - return 0;
> - }
> - /*
> - * Accept is done in two halves. The request ioctl does the basic
> - * functionality of accepting the request and returning the
> information
> - * about it including the internal ID of the end point. The register
> - * is done with the internal ID on a new file descriptor opened by the
> - * requesting process.
> - */
> - case SCIF_ACCEPTREQ:
> - {
> - struct scifioctl_accept request;
> - scif_epd_t *ep = (scif_epd_t *)&request.endpt;
> -
> - if (copy_from_user(&request, argp, sizeof(request)))
> - return -EFAULT;
> -
> - err = scif_accept(priv, &request.peer, ep, request.flags);
> - if (err < 0)
> - return err;
> -
> - if (copy_to_user(argp, &request, sizeof(request))) {
> - scif_close(*ep);
> - return -EFAULT;
> - }
> - /*
> - * Add to the list of user mode eps where the second half
> - * of the accept is not yet completed.
> - */
> - mutex_lock(&scif_info.eplock);
> - list_add_tail(&((*ep)->miacceptlist), &scif_info.uaccept);
> - list_add_tail(&((*ep)->liacceptlist), &priv->li_accept);
> - (*ep)->listenep = priv;
> - priv->acceptcnt++;
> - mutex_unlock(&scif_info.eplock);
> -
> - return 0;
> - }
> - case SCIF_ACCEPTREG:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scif_endpt *newep;
> - struct scif_endpt *lisep;
> - struct scif_endpt *fep = NULL;
> - struct scif_endpt *tmpep;
> - struct list_head *pos, *tmpq;
> -
> - /* Finally replace the pointer to the accepted endpoint */
> - if (copy_from_user(&newep, argp, sizeof(void *)))
> - return -EFAULT;
> -
> - /* Remove form the user accept queue */
> - mutex_lock(&scif_info.eplock);
> - list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
> - tmpep = list_entry(pos,
> - struct scif_endpt, miacceptlist);
> - if (tmpep == newep) {
> - list_del(pos);
> - fep = tmpep;
> - break;
> - }
> - }
> -
> - if (!fep) {
> - mutex_unlock(&scif_info.eplock);
> - return -ENOENT;
> - }
> -
> - lisep = newep->listenep;
> - list_for_each_safe(pos, tmpq, &lisep->li_accept) {
> - tmpep = list_entry(pos,
> - struct scif_endpt, liacceptlist);
> - if (tmpep == newep) {
> - list_del(pos);
> - lisep->acceptcnt--;
> - break;
> - }
> - }
> -
> - mutex_unlock(&scif_info.eplock);
> -
> - /* Free the resources automatically created from the open.
> */
> - scif_anon_inode_fput(priv);
> - scif_teardown_ep(priv);
> - scif_add_epd_to_zombie_list(priv, !SCIF_EPLOCK_HELD);
> - f->private_data = newep;
> - return 0;
> - }
> - case SCIF_SEND:
> - {
> - struct scif_endpt *priv = f->private_data;
> -
> - if (copy_from_user(&request, argp,
> - sizeof(struct scifioctl_msg))) {
> - err = -EFAULT;
> - goto send_err;
> - }
> - err = scif_user_send(priv, (void __user *)request.msg,
> - request.len, request.flags);
> - if (err < 0)
> - goto send_err;
> - if (copy_to_user(&
> - ((struct scifioctl_msg __user *)argp)-
> >out_len,
> - &err, sizeof(err))) {
> - err = -EFAULT;
> - goto send_err;
> - }
> - err = 0;
> -send_err:
> - scif_err_debug(err, "scif_send");
> - return err;
> - }
> - case SCIF_RECV:
> - {
> - struct scif_endpt *priv = f->private_data;
> -
> - if (copy_from_user(&request, argp,
> - sizeof(struct scifioctl_msg))) {
> - err = -EFAULT;
> - goto recv_err;
> - }
> -
> - err = scif_user_recv(priv, (void __user *)request.msg,
> - request.len, request.flags);
> - if (err < 0)
> - goto recv_err;
> -
> - if (copy_to_user(&
> - ((struct scifioctl_msg __user *)argp)-
> >out_len,
> - &err, sizeof(err))) {
> - err = -EFAULT;
> - goto recv_err;
> - }
> - err = 0;
> -recv_err:
> - scif_err_debug(err, "scif_recv");
> - return err;
> - }
> - case SCIF_GET_NODEIDS:
> - {
> - struct scifioctl_node_ids node_ids;
> - int entries;
> - u16 *nodes;
> - void __user *unodes, *uself;
> - u16 self;
> -
> - if (copy_from_user(&node_ids, argp, sizeof(node_ids))) {
> - err = -EFAULT;
> - goto getnodes_err2;
> - }
> -
> - entries = min_t(int, scif_info.maxid, node_ids.len);
> - nodes = kmalloc_array(entries, sizeof(u16), GFP_KERNEL);
> - if (entries && !nodes) {
> - err = -ENOMEM;
> - goto getnodes_err2;
> - }
> - node_ids.len = scif_get_node_ids(nodes, entries, &self);
> -
> - unodes = (void __user *)node_ids.nodes;
> - if (copy_to_user(unodes, nodes, sizeof(u16) * entries)) {
> - err = -EFAULT;
> - goto getnodes_err1;
> - }
> -
> - uself = (void __user *)node_ids.self;
> - if (copy_to_user(uself, &self, sizeof(u16))) {
> - err = -EFAULT;
> - goto getnodes_err1;
> - }
> -
> - if (copy_to_user(argp, &node_ids, sizeof(node_ids))) {
> - err = -EFAULT;
> - goto getnodes_err1;
> - }
> -getnodes_err1:
> - kfree(nodes);
> -getnodes_err2:
> - return err;
> - }
> - case SCIF_REG:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_reg reg;
> - off_t ret;
> -
> - if (copy_from_user(&reg, argp, sizeof(reg))) {
> - err = -EFAULT;
> - goto reg_err;
> - }
> - if (reg.flags & SCIF_MAP_KERNEL) {
> - err = -EINVAL;
> - goto reg_err;
> - }
> - ret = scif_register(priv, (void *)reg.addr, reg.len,
> - reg.offset, reg.prot, reg.flags);
> - if (ret < 0) {
> - err = (int)ret;
> - goto reg_err;
> - }
> -
> - if (copy_to_user(&((struct scifioctl_reg __user *)argp)
> - ->out_offset, &ret, sizeof(reg.out_offset))) {
> - err = -EFAULT;
> - goto reg_err;
> - }
> - err = 0;
> -reg_err:
> - scif_err_debug(err, "scif_register");
> - return err;
> - }
> - case SCIF_UNREG:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_unreg unreg;
> -
> - if (copy_from_user(&unreg, argp, sizeof(unreg))) {
> - err = -EFAULT;
> - goto unreg_err;
> - }
> - err = scif_unregister(priv, unreg.offset, unreg.len);
> -unreg_err:
> - scif_err_debug(err, "scif_unregister");
> - return err;
> - }
> - case SCIF_READFROM:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_copy copy;
> -
> - if (copy_from_user(&copy, argp, sizeof(copy))) {
> - err = -EFAULT;
> - goto readfrom_err;
> - }
> - err = scif_readfrom(priv, copy.loffset, copy.len, copy.roffset,
> - copy.flags);
> -readfrom_err:
> - scif_err_debug(err, "scif_readfrom");
> - return err;
> - }
> - case SCIF_WRITETO:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_copy copy;
> -
> - if (copy_from_user(&copy, argp, sizeof(copy))) {
> - err = -EFAULT;
> - goto writeto_err;
> - }
> - err = scif_writeto(priv, copy.loffset, copy.len, copy.roffset,
> - copy.flags);
> -writeto_err:
> - scif_err_debug(err, "scif_writeto");
> - return err;
> - }
> - case SCIF_VREADFROM:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_copy copy;
> -
> - if (copy_from_user(&copy, argp, sizeof(copy))) {
> - err = -EFAULT;
> - goto vreadfrom_err;
> - }
> - err = scif_vreadfrom(priv, (void __force *)copy.addr,
> copy.len,
> - copy.roffset, copy.flags);
> -vreadfrom_err:
> - scif_err_debug(err, "scif_vreadfrom");
> - return err;
> - }
> - case SCIF_VWRITETO:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_copy copy;
> -
> - if (copy_from_user(&copy, argp, sizeof(copy))) {
> - err = -EFAULT;
> - goto vwriteto_err;
> - }
> - err = scif_vwriteto(priv, (void __force *)copy.addr, copy.len,
> - copy.roffset, copy.flags);
> -vwriteto_err:
> - scif_err_debug(err, "scif_vwriteto");
> - return err;
> - }
> - case SCIF_FENCE_MARK:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_fence_mark mark;
> - int tmp_mark = 0;
> -
> - if (copy_from_user(&mark, argp, sizeof(mark))) {
> - err = -EFAULT;
> - goto fence_mark_err;
> - }
> - err = scif_fence_mark(priv, mark.flags, &tmp_mark);
> - if (err)
> - goto fence_mark_err;
> - if (copy_to_user((void __user *)mark.mark, &tmp_mark,
> - sizeof(tmp_mark))) {
> - err = -EFAULT;
> - goto fence_mark_err;
> - }
> -fence_mark_err:
> - scif_err_debug(err, "scif_fence_mark");
> - return err;
> - }
> - case SCIF_FENCE_WAIT:
> - {
> - struct scif_endpt *priv = f->private_data;
> -
> - err = scif_fence_wait(priv, arg);
> - scif_err_debug(err, "scif_fence_wait");
> - return err;
> - }
> - case SCIF_FENCE_SIGNAL:
> - {
> - struct scif_endpt *priv = f->private_data;
> - struct scifioctl_fence_signal signal;
> -
> - if (copy_from_user(&signal, argp, sizeof(signal))) {
> - err = -EFAULT;
> - goto fence_signal_err;
> - }
> -
> - err = scif_fence_signal(priv, signal.loff, signal.lval,
> - signal.roff, signal.rval, signal.flags);
> -fence_signal_err:
> - scif_err_debug(err, "scif_fence_signal");
> - return err;
> - }
> - }
> - return -EINVAL;
> -}
> -
> -const struct file_operations scif_fops = {
> - .open = scif_fdopen,
> - .release = scif_fdclose,
> - .unlocked_ioctl = scif_fdioctl,
> - .mmap = scif_fdmmap,
> - .poll = scif_fdpoll,
> - .flush = scif_fdflush,
> - .owner = THIS_MODULE,
> -};
> diff --git a/drivers/misc/mic/scif/scif_fence.c
> b/drivers/misc/mic/scif/scif_fence.c
> deleted file mode 100644
> index 4fedf6183951..000000000000
> --- a/drivers/misc/mic/scif/scif_fence.c
> +++ /dev/null
> @@ -1,783 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -
> -#include "scif_main.h"
> -
> -/**
> - * scif_recv_mark: Handle SCIF_MARK request
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has requested a mark.
> - */
> -void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - int mark = 0;
> - int err;
> -
> - err = _scif_fence_mark(ep, &mark);
> - if (err)
> - msg->uop = SCIF_MARK_NACK;
> - else
> - msg->uop = SCIF_MARK_ACK;
> - msg->payload[0] = ep->remote_ep;
> - msg->payload[2] = mark;
> - scif_nodeqp_send(ep->remote_dev, msg);
> -}
> -
> -/**
> - * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has responded to a SCIF_MARK message.
> - */
> -void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - struct scif_fence_info *fence_req =
> - (struct scif_fence_info *)msg->payload[1];
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (msg->uop == SCIF_MARK_ACK) {
> - fence_req->state = OP_COMPLETED;
> - fence_req->dma_mark = (int)msg->payload[2];
> - } else {
> - fence_req->state = OP_FAILED;
> - }
> - mutex_unlock(&ep->rma_info.rma_lock);
> - complete(&fence_req->comp);
> -}
> -
> -/**
> - * scif_recv_wait: Handle SCIF_WAIT request
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has requested waiting on a fence.
> - */
> -void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - struct scif_remote_fence_info *fence;
> -
> - /*
> - * Allocate structure for remote fence information and
> - * send a NACK if the allocation failed. The peer will
> - * return ENOMEM upon receiving a NACK.
> - */
> - fence = kmalloc(sizeof(*fence), GFP_KERNEL);
> - if (!fence) {
> - msg->payload[0] = ep->remote_ep;
> - msg->uop = SCIF_WAIT_NACK;
> - scif_nodeqp_send(ep->remote_dev, msg);
> - return;
> - }
> -
> - /* Prepare the fence request */
> - memcpy(&fence->msg, msg, sizeof(struct scifmsg));
> - INIT_LIST_HEAD(&fence->list);
> -
> - /* Insert to the global remote fence request list */
> - mutex_lock(&scif_info.fencelock);
> - atomic_inc(&ep->rma_info.fence_refcount);
> - list_add_tail(&fence->list, &scif_info.fence);
> - mutex_unlock(&scif_info.fencelock);
> -
> - schedule_work(&scif_info.misc_work);
> -}
> -
> -/**
> - * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has responded to a SCIF_WAIT message.
> - */
> -void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - struct scif_fence_info *fence_req =
> - (struct scif_fence_info *)msg->payload[1];
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (msg->uop == SCIF_WAIT_ACK)
> - fence_req->state = OP_COMPLETED;
> - else
> - fence_req->state = OP_FAILED;
> - mutex_unlock(&ep->rma_info.rma_lock);
> - complete(&fence_req->comp);
> -}
> -
> -/**
> - * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has requested a signal on a local offset.
> - */
> -void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - int err;
> -
> - err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
> - SCIF_WINDOW_SELF);
> - if (err)
> - msg->uop = SCIF_SIG_NACK;
> - else
> - msg->uop = SCIF_SIG_ACK;
> - msg->payload[0] = ep->remote_ep;
> - scif_nodeqp_send(ep->remote_dev, msg);
> -}
> -
> -/**
> - * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has requested a signal on a remote offset.
> - */
> -void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - int err;
> -
> - err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
> - SCIF_WINDOW_PEER);
> - if (err)
> - msg->uop = SCIF_SIG_NACK;
> - else
> - msg->uop = SCIF_SIG_ACK;
> - msg->payload[0] = ep->remote_ep;
> - scif_nodeqp_send(ep->remote_dev, msg);
> -}
> -
> -/**
> - * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * The peer has responded to a signal request.
> - */
> -void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - struct scif_fence_info *fence_req =
> - (struct scif_fence_info *)msg->payload[3];
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (msg->uop == SCIF_SIG_ACK)
> - fence_req->state = OP_COMPLETED;
> - else
> - fence_req->state = OP_FAILED;
> - mutex_unlock(&ep->rma_info.rma_lock);
> - complete(&fence_req->comp);
> -}
> -
> -static inline void *scif_get_local_va(off_t off, struct scif_window *window)
> -{
> - struct page **pages = window->pinned_pages->pages;
> - int page_nr = (off - window->offset) >> PAGE_SHIFT;
> - off_t page_off = off & ~PAGE_MASK;
> -
> - return page_address(pages[page_nr]) + page_off;
> -}
> -
> -static void scif_prog_signal_cb(void *arg)
> -{
> - struct scif_cb_arg *cb_arg = arg;
> -
> - dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg-
> >status,
> - cb_arg->src_dma_addr);
> - kfree(cb_arg);
> -}
> -
> -static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct dma_chan *chan = ep->rma_info.dma_chan;
> - struct dma_device *ddev = chan->device;
> - bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
> - struct dma_async_tx_descriptor *tx;
> - struct scif_status *status = NULL;
> - struct scif_cb_arg *cb_arg = NULL;
> - dma_addr_t src;
> - dma_cookie_t cookie;
> - int err;
> -
> - tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0,
> DMA_PREP_FENCE);
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto alloc_fail;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - err = (int)cookie;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto alloc_fail;
> - }
> - dma_async_issue_pending(chan);
> - if (x100) {
> - /*
> - * For X100 use the status descriptor to write the value to
> - * the destination.
> - */
> - tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0);
> - } else {
> - status = dma_pool_alloc(ep->remote_dev->signal_pool,
> GFP_KERNEL,
> - &src);
> - if (!status) {
> - err = -ENOMEM;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d
> err %d\n",
> - __func__, __LINE__, err);
> - goto alloc_fail;
> - }
> - status->val = val;
> - status->src_dma_addr = src;
> - status->ep = ep;
> - src += offsetof(struct scif_status, val);
> - tx = ddev->device_prep_dma_memcpy(chan, dst, src,
> sizeof(val),
> - DMA_PREP_INTERRUPT);
> - }
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto dma_fail;
> - }
> - if (!x100) {
> - cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL);
> - if (!cb_arg) {
> - err = -ENOMEM;
> - goto dma_fail;
> - }
> - cb_arg->src_dma_addr = src;
> - cb_arg->status = status;
> - cb_arg->ep = ep;
> - tx->callback = scif_prog_signal_cb;
> - tx->callback_param = cb_arg;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - err = -EIO;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto dma_fail;
> - }
> - dma_async_issue_pending(chan);
> - return 0;
> -dma_fail:
> - if (!x100) {
> - dma_pool_free(ep->remote_dev->signal_pool, status,
> - src - offsetof(struct scif_status, val));
> - kfree(cb_arg);
> - }
> -alloc_fail:
> - return err;
> -}
> -
> -/**
> - * scif_prog_signal:
> - * @epd: Endpoint Descriptor
> - * @offset: registered address to write @val to
> - * @val: Value to be written at @offset
> - * @type: Type of the window.
> - *
> - * Arrange to write a value to the registered offset after ensuring that the
> - * offset provided is indeed valid.
> - */
> -int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
> - enum scif_window_type type)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scif_window *window = NULL;
> - struct scif_rma_req req;
> - dma_addr_t dst_dma_addr;
> - int err;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - req.out_window = &window;
> - req.offset = offset;
> - req.nr_bytes = sizeof(u64);
> - req.prot = SCIF_PROT_WRITE;
> - req.type = SCIF_WINDOW_SINGLE;
> - if (type == SCIF_WINDOW_SELF)
> - req.head = &ep->rma_info.reg_list;
> - else
> - req.head = &ep->rma_info.remote_reg_list;
> - /* Does a valid window exist? */
> - err = scif_query_window(&req);
> - if (err) {
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto unlock_ret;
> - }
> -
> - if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
> - u64 *dst_virt;
> -
> - if (type == SCIF_WINDOW_SELF)
> - dst_virt = scif_get_local_va(offset, window);
> - else
> - dst_virt =
> - scif_get_local_va(offset, (struct scif_window *)
> - window->peer_window);
> - *dst_virt = val;
> - } else {
> - dst_dma_addr = __scif_off_to_dma_addr(window, offset);
> - err = _scif_prog_signal(epd, dst_dma_addr, val);
> - }
> -unlock_ret:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - return err;
> -}
> -
> -static int _scif_fence_wait(scif_epd_t epd, int mark)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
> - int err;
> -
> - /* Wait for DMA callback in scif_fence_mark_cb(..) */
> - err = wait_event_interruptible_timeout(ep->rma_info.markwq,
> - dma_async_is_tx_complete(
> - ep->rma_info.dma_chan,
> - cookie, NULL, NULL) ==
> - DMA_COMPLETE,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err)
> - err = -ETIMEDOUT;
> - else if (err > 0)
> - err = 0;
> - return err;
> -}
> -
> -/**
> - * scif_rma_handle_remote_fences:
> - *
> - * This routine services remote fence requests.
> - */
> -void scif_rma_handle_remote_fences(void)
> -{
> - struct list_head *item, *tmp;
> - struct scif_remote_fence_info *fence;
> - struct scif_endpt *ep;
> - int mark, err;
> -
> - might_sleep();
> - mutex_lock(&scif_info.fencelock);
> - list_for_each_safe(item, tmp, &scif_info.fence) {
> - fence = list_entry(item, struct scif_remote_fence_info,
> - list);
> - /* Remove fence from global list */
> - list_del(&fence->list);
> -
> - /* Initiate the fence operation */
> - ep = (struct scif_endpt *)fence->msg.payload[0];
> - mark = fence->msg.payload[2];
> - err = _scif_fence_wait(ep, mark);
> - if (err)
> - fence->msg.uop = SCIF_WAIT_NACK;
> - else
> - fence->msg.uop = SCIF_WAIT_ACK;
> - fence->msg.payload[0] = ep->remote_ep;
> - scif_nodeqp_send(ep->remote_dev, &fence->msg);
> - kfree(fence);
> - if (!atomic_sub_return(1, &ep->rma_info.fence_refcount))
> - schedule_work(&scif_info.misc_work);
> - }
> - mutex_unlock(&scif_info.fencelock);
> -}
> -
> -static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
> -{
> - int err;
> - struct scifmsg msg;
> - struct scif_fence_info *fence_req;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> -
> - fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
> - if (!fence_req) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - fence_req->state = OP_IN_PROGRESS;
> - init_completion(&fence_req->comp);
> -
> - msg.src = ep->port;
> - msg.uop = uop;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = (u64)fence_req;
> - if (uop == SCIF_WAIT)
> - msg.payload[2] = mark;
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED)
> - err = scif_nodeqp_send(ep->remote_dev, &msg);
> - else
> - err = -ENOTCONN;
> - spin_unlock(&ep->lock);
> - if (err)
> - goto error_free;
> -retry:
> - /* Wait for a SCIF_WAIT_(N)ACK message */
> - err = wait_for_completion_timeout(&fence_req->comp,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> - if (!err)
> - err = -ENODEV;
> - if (err > 0)
> - err = 0;
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (err < 0) {
> - if (fence_req->state == OP_IN_PROGRESS)
> - fence_req->state = OP_FAILED;
> - }
> - if (fence_req->state == OP_FAILED && !err)
> - err = -ENOMEM;
> - if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED)
> - *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark;
> - mutex_unlock(&ep->rma_info.rma_lock);
> -error_free:
> - kfree(fence_req);
> -error:
> - return err;
> -}
> -
> -/**
> - * scif_send_fence_mark:
> - * @epd: end point descriptor.
> - * @out_mark: Output DMA mark reported by peer.
> - *
> - * Send a remote fence mark request.
> - */
> -static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
> -{
> - return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
> -}
> -
> -/**
> - * scif_send_fence_wait:
> - * @epd: end point descriptor.
> - * @mark: DMA mark to wait for.
> - *
> - * Send a remote fence wait request.
> - */
> -static int scif_send_fence_wait(scif_epd_t epd, int mark)
> -{
> - return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
> -}
> -
> -static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
> - struct scif_fence_info *fence_req)
> -{
> - int err;
> -
> -retry:
> - /* Wait for a SCIF_SIG_(N)ACK message */
> - err = wait_for_completion_timeout(&fence_req->comp,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> - if (!err)
> - err = -ENODEV;
> - if (err > 0)
> - err = 0;
> - if (err < 0) {
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (fence_req->state == OP_IN_PROGRESS)
> - fence_req->state = OP_FAILED;
> - mutex_unlock(&ep->rma_info.rma_lock);
> - }
> - if (fence_req->state == OP_FAILED && !err)
> - err = -ENXIO;
> - return err;
> -}
> -
> -/**
> - * scif_send_fence_signal:
> - * @epd: endpoint descriptor
> - * @loff: local offset
> - * @lval: local value to write to loffset
> - * @roff: remote offset
> - * @rval: remote value to write to roffset
> - * @flags: flags
> - *
> - * Sends a remote fence signal request
> - */
> -static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
> - off_t loff, u64 lval, int flags)
> -{
> - int err = 0;
> - struct scifmsg msg;
> - struct scif_fence_info *fence_req;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> -
> - fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
> - if (!fence_req) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - fence_req->state = OP_IN_PROGRESS;
> - init_completion(&fence_req->comp);
> - msg.src = ep->port;
> - if (flags & SCIF_SIGNAL_LOCAL) {
> - msg.uop = SCIF_SIG_LOCAL;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = roff;
> - msg.payload[2] = rval;
> - msg.payload[3] = (u64)fence_req;
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED)
> - err = scif_nodeqp_send(ep->remote_dev, &msg);
> - else
> - err = -ENOTCONN;
> - spin_unlock(&ep->lock);
> - if (err)
> - goto error_free;
> - err = _scif_send_fence_signal_wait(ep, fence_req);
> - if (err)
> - goto error_free;
> - }
> - fence_req->state = OP_IN_PROGRESS;
> -
> - if (flags & SCIF_SIGNAL_REMOTE) {
> - msg.uop = SCIF_SIG_REMOTE;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = loff;
> - msg.payload[2] = lval;
> - msg.payload[3] = (u64)fence_req;
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED)
> - err = scif_nodeqp_send(ep->remote_dev, &msg);
> - else
> - err = -ENOTCONN;
> - spin_unlock(&ep->lock);
> - if (err)
> - goto error_free;
> - err = _scif_send_fence_signal_wait(ep, fence_req);
> - }
> -error_free:
> - kfree(fence_req);
> -error:
> - return err;
> -}
> -
> -static void scif_fence_mark_cb(void *arg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)arg;
> -
> - wake_up_interruptible(&ep->rma_info.markwq);
> - atomic_dec(&ep->rma_info.fence_refcount);
> -}
> -
> -/**
> - * _scif_fence_mark:
> - * @epd: endpoint descriptor
> - * @mark: DMA mark to set-up
> - *
> - * Set up a mark for this endpoint and return the value of the mark.
> - */
> -int _scif_fence_mark(scif_epd_t epd, int *mark)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct dma_chan *chan = ep->rma_info.dma_chan;
> - struct dma_device *ddev = chan->device;
> - struct dma_async_tx_descriptor *tx;
> - dma_cookie_t cookie;
> - int err;
> -
> - tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0,
> DMA_PREP_FENCE);
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - err = (int)cookie;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - dma_async_issue_pending(chan);
> - tx = ddev->device_prep_dma_interrupt(chan,
> DMA_PREP_INTERRUPT);
> - if (!tx) {
> - err = -ENOMEM;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - tx->callback = scif_fence_mark_cb;
> - tx->callback_param = ep;
> - *mark = cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - err = (int)cookie;
> - dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> - }
> - atomic_inc(&ep->rma_info.fence_refcount);
> - dma_async_issue_pending(chan);
> - return 0;
> -}
> -
> -#define SCIF_LOOPB_MAGIC_MARK 0xdead
> -
> -int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n",
> - ep, flags, *mark);
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - /* Invalid flags? */
> - if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
> - return -EINVAL;
> -
> - /* At least one of init self or peer RMA should be set */
> - if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
> - return -EINVAL;
> -
> - /* Exactly one of init self or peer RMA should be set but not both */
> - if ((flags & SCIF_FENCE_INIT_SELF) && (flags &
> SCIF_FENCE_INIT_PEER))
> - return -EINVAL;
> -
> - /*
> - * Management node loopback does not need to use DMA.
> - * Return a valid mark to be symmetric.
> - */
> - if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
> - *mark = SCIF_LOOPB_MAGIC_MARK;
> - return 0;
> - }
> -
> - if (flags & SCIF_FENCE_INIT_SELF)
> - err = _scif_fence_mark(epd, mark);
> - else
> - err = scif_send_fence_mark(ep, mark);
> -
> - if (err)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n",
> - ep, flags, *mark, err);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_fence_mark);
> -
> -int scif_fence_wait(scif_epd_t epd, int mark)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI fence_wait: ep %p mark 0x%x\n",
> - ep, mark);
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> - /*
> - * Management node loopback does not need to use DMA.
> - * The only valid mark provided is 0 so simply
> - * return success if the mark is valid.
> - */
> - if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
> - if (mark == SCIF_LOOPB_MAGIC_MARK)
> - return 0;
> - else
> - return -EINVAL;
> - }
> - if (mark & SCIF_REMOTE_FENCE)
> - err = scif_send_fence_wait(epd, mark);
> - else
> - err = _scif_fence_wait(epd, mark);
> - if (err < 0)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_fence_wait);
> -
> -int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
> - off_t roff, u64 rval, int flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - int err = 0;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx
> rval 0x%llx flags 0x%x\n",
> - ep, loff, lval, roff, rval, flags);
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - /* Invalid flags? */
> - if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
> - SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
> - return -EINVAL;
> -
> - /* At least one of init self or peer RMA should be set */
> - if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
> - return -EINVAL;
> -
> - /* Exactly one of init self or peer RMA should be set but not both */
> - if ((flags & SCIF_FENCE_INIT_SELF) && (flags &
> SCIF_FENCE_INIT_PEER))
> - return -EINVAL;
> -
> - /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE
> required */
> - if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)))
> - return -EINVAL;
> -
> - /* Only Dword offsets allowed */
> - if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
> - return -EINVAL;
> -
> - /* Only Dword aligned offsets allowed */
> - if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
> - return -EINVAL;
> -
> - if (flags & SCIF_FENCE_INIT_PEER) {
> - err = scif_send_fence_signal(epd, roff, rval, loff,
> - lval, flags);
> - } else {
> - /* Local Signal in Local RAS */
> - if (flags & SCIF_SIGNAL_LOCAL) {
> - err = scif_prog_signal(epd, loff, lval,
> - SCIF_WINDOW_SELF);
> - if (err)
> - goto error_ret;
> - }
> -
> - /* Signal in Remote RAS */
> - if (flags & SCIF_SIGNAL_REMOTE)
> - err = scif_prog_signal(epd, roff,
> - rval, SCIF_WINDOW_PEER);
> - }
> -error_ret:
> - if (err)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_fence_signal);
> diff --git a/drivers/misc/mic/scif/scif_main.c
> b/drivers/misc/mic/scif/scif_main.c
> deleted file mode 100644
> index e2278bf9f11d..000000000000
> --- a/drivers/misc/mic/scif/scif_main.c
> +++ /dev/null
> @@ -1,351 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/module.h>
> -#include <linux/idr.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -#include "../bus/scif_bus.h"
> -#include "scif_peer_bus.h"
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -struct scif_info scif_info = {
> - .mdev = {
> - .minor = MISC_DYNAMIC_MINOR,
> - .name = "scif",
> - .fops = &scif_fops,
> - }
> -};
> -
> -struct scif_dev *scif_dev;
> -struct kmem_cache *unaligned_cache;
> -static atomic_t g_loopb_cnt;
> -
> -/* Runs in the context of intr_wq */
> -static void scif_intr_bh_handler(struct work_struct *work)
> -{
> - struct scif_dev *scifdev =
> - container_of(work, struct scif_dev, intr_bh);
> -
> - if (scifdev_self(scifdev))
> - scif_loopb_msg_handler(scifdev, scifdev->qpairs);
> - else
> - scif_nodeqp_intrhandler(scifdev, scifdev->qpairs);
> -}
> -
> -int scif_setup_intr_wq(struct scif_dev *scifdev)
> -{
> - if (!scifdev->intr_wq) {
> - snprintf(scifdev->intr_wqname, sizeof(scifdev-
> >intr_wqname),
> - "SCIF INTR %d", scifdev->node);
> - scifdev->intr_wq =
> - alloc_ordered_workqueue(scifdev->intr_wqname, 0);
> - if (!scifdev->intr_wq)
> - return -ENOMEM;
> - INIT_WORK(&scifdev->intr_bh, scif_intr_bh_handler);
> - }
> - return 0;
> -}
> -
> -void scif_destroy_intr_wq(struct scif_dev *scifdev)
> -{
> - if (scifdev->intr_wq) {
> - destroy_workqueue(scifdev->intr_wq);
> - scifdev->intr_wq = NULL;
> - }
> -}
> -
> -irqreturn_t scif_intr_handler(int irq, void *data)
> -{
> - struct scif_dev *scifdev = data;
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - sdev->hw_ops->ack_interrupt(sdev, scifdev->db);
> - queue_work(scifdev->intr_wq, &scifdev->intr_bh);
> - return IRQ_HANDLED;
> -}
> -
> -static void scif_qp_setup_handler(struct work_struct *work)
> -{
> - struct scif_dev *scifdev = container_of(work, struct scif_dev,
> - qp_dwork.work);
> - struct scif_hw_dev *sdev = scifdev->sdev;
> - dma_addr_t da = 0;
> - int err;
> -
> - if (scif_is_mgmt_node()) {
> - struct mic_bootparam *bp = sdev->dp;
> -
> - da = bp->scif_card_dma_addr;
> - scifdev->rdb = bp->h2c_scif_db;
> - } else {
> - struct mic_bootparam __iomem *bp = sdev->rdp;
> -
> - da = readq(&bp->scif_host_dma_addr);
> - scifdev->rdb = ioread8(&bp->c2h_scif_db);
> - }
> - if (da) {
> - err = scif_qp_response(da, scifdev);
> - if (err)
> - dev_err(&scifdev->sdev->dev,
> - "scif_qp_response err %d\n", err);
> - } else {
> - schedule_delayed_work(&scifdev->qp_dwork,
> - msecs_to_jiffies(1000));
> - }
> -}
> -
> -static int scif_setup_scifdev(void)
> -{
> - /* We support a maximum of 129 SCIF nodes including the mgmt
> node */
> -#define MAX_SCIF_NODES 129
> - int i;
> - u8 num_nodes = MAX_SCIF_NODES;
> -
> - scif_dev = kcalloc(num_nodes, sizeof(*scif_dev), GFP_KERNEL);
> - if (!scif_dev)
> - return -ENOMEM;
> - for (i = 0; i < num_nodes; i++) {
> - struct scif_dev *scifdev = &scif_dev[i];
> -
> - scifdev->node = i;
> - scifdev->exit = OP_IDLE;
> - init_waitqueue_head(&scifdev->disconn_wq);
> - mutex_init(&scifdev->lock);
> - INIT_WORK(&scifdev->peer_add_work,
> scif_add_peer_device);
> - INIT_DELAYED_WORK(&scifdev->p2p_dwork,
> - scif_poll_qp_state);
> - INIT_DELAYED_WORK(&scifdev->qp_dwork,
> - scif_qp_setup_handler);
> - INIT_LIST_HEAD(&scifdev->p2p);
> - RCU_INIT_POINTER(scifdev->spdev, NULL);
> - }
> - return 0;
> -}
> -
> -static void scif_destroy_scifdev(void)
> -{
> - kfree(scif_dev);
> - scif_dev = NULL;
> -}
> -
> -static int scif_probe(struct scif_hw_dev *sdev)
> -{
> - struct scif_dev *scifdev = &scif_dev[sdev->dnode];
> - int rc;
> -
> - dev_set_drvdata(&sdev->dev, sdev);
> - scifdev->sdev = sdev;
> -
> - if (1 == atomic_add_return(1, &g_loopb_cnt)) {
> - struct scif_dev *loopb_dev = &scif_dev[sdev->snode];
> -
> - loopb_dev->sdev = sdev;
> - rc = scif_setup_loopback_qp(loopb_dev);
> - if (rc)
> - goto exit;
> - }
> -
> - rc = scif_setup_intr_wq(scifdev);
> - if (rc)
> - goto destroy_loopb;
> - rc = scif_setup_qp(scifdev);
> - if (rc)
> - goto destroy_intr;
> - scifdev->db = sdev->hw_ops->next_db(sdev);
> - scifdev->cookie = sdev->hw_ops->request_irq(sdev, scif_intr_handler,
> - "SCIF_INTR", scifdev,
> - scifdev->db);
> - if (IS_ERR(scifdev->cookie)) {
> - rc = PTR_ERR(scifdev->cookie);
> - goto free_qp;
> - }
> - if (scif_is_mgmt_node()) {
> - struct mic_bootparam *bp = sdev->dp;
> -
> - bp->c2h_scif_db = scifdev->db;
> - bp->scif_host_dma_addr = scifdev->qp_dma_addr;
> - } else {
> - struct mic_bootparam __iomem *bp = sdev->rdp;
> -
> - iowrite8(scifdev->db, &bp->h2c_scif_db);
> - writeq(scifdev->qp_dma_addr, &bp->scif_card_dma_addr);
> - }
> - schedule_delayed_work(&scifdev->qp_dwork,
> - msecs_to_jiffies(1000));
> - return rc;
> -free_qp:
> - scif_free_qp(scifdev);
> -destroy_intr:
> - scif_destroy_intr_wq(scifdev);
> -destroy_loopb:
> - if (atomic_dec_and_test(&g_loopb_cnt))
> - scif_destroy_loopback_qp(&scif_dev[sdev->snode]);
> -exit:
> - return rc;
> -}
> -
> -void scif_stop(struct scif_dev *scifdev)
> -{
> - struct scif_dev *dev;
> - int i;
> -
> - for (i = scif_info.maxid; i >= 0; i--) {
> - dev = &scif_dev[i];
> - if (scifdev_self(dev))
> - continue;
> - scif_handle_remove_node(i);
> - }
> -}
> -
> -static void scif_remove(struct scif_hw_dev *sdev)
> -{
> - struct scif_dev *scifdev = &scif_dev[sdev->dnode];
> -
> - if (scif_is_mgmt_node()) {
> - struct mic_bootparam *bp = sdev->dp;
> -
> - bp->c2h_scif_db = -1;
> - bp->scif_host_dma_addr = 0x0;
> - } else {
> - struct mic_bootparam __iomem *bp = sdev->rdp;
> -
> - iowrite8(-1, &bp->h2c_scif_db);
> - writeq(0x0, &bp->scif_card_dma_addr);
> - }
> - if (scif_is_mgmt_node()) {
> - scif_disconnect_node(scifdev->node, true);
> - } else {
> - scif_info.card_initiated_exit = true;
> - scif_stop(scifdev);
> - }
> - if (atomic_dec_and_test(&g_loopb_cnt))
> - scif_destroy_loopback_qp(&scif_dev[sdev->snode]);
> - if (scifdev->cookie) {
> - sdev->hw_ops->free_irq(sdev, scifdev->cookie, scifdev);
> - scifdev->cookie = NULL;
> - }
> - scif_destroy_intr_wq(scifdev);
> - cancel_delayed_work(&scifdev->qp_dwork);
> - scif_free_qp(scifdev);
> - scifdev->rdb = -1;
> - scifdev->sdev = NULL;
> -}
> -
> -static struct scif_hw_dev_id id_table[] = {
> - { MIC_SCIF_DEV, SCIF_DEV_ANY_ID },
> - { 0 },
> -};
> -
> -static struct scif_driver scif_driver = {
> - .driver.name = KBUILD_MODNAME,
> - .driver.owner = THIS_MODULE,
> - .id_table = id_table,
> - .probe = scif_probe,
> - .remove = scif_remove,
> -};
> -
> -static int _scif_init(void)
> -{
> - int rc;
> -
> - mutex_init(&scif_info.eplock);
> - spin_lock_init(&scif_info.rmalock);
> - spin_lock_init(&scif_info.nb_connect_lock);
> - spin_lock_init(&scif_info.port_lock);
> - mutex_init(&scif_info.conflock);
> - mutex_init(&scif_info.connlock);
> - mutex_init(&scif_info.fencelock);
> - INIT_LIST_HEAD(&scif_info.uaccept);
> - INIT_LIST_HEAD(&scif_info.listen);
> - INIT_LIST_HEAD(&scif_info.zombie);
> - INIT_LIST_HEAD(&scif_info.connected);
> - INIT_LIST_HEAD(&scif_info.disconnected);
> - INIT_LIST_HEAD(&scif_info.rma);
> - INIT_LIST_HEAD(&scif_info.rma_tc);
> - INIT_LIST_HEAD(&scif_info.mmu_notif_cleanup);
> - INIT_LIST_HEAD(&scif_info.fence);
> - INIT_LIST_HEAD(&scif_info.nb_connect_list);
> - init_waitqueue_head(&scif_info.exitwq);
> - scif_info.rma_tc_limit = SCIF_RMA_TEMP_CACHE_LIMIT;
> - scif_info.en_msg_log = 0;
> - scif_info.p2p_enable = 1;
> - rc = scif_setup_scifdev();
> - if (rc)
> - goto error;
> - unaligned_cache = kmem_cache_create("Unaligned_DMA",
> - SCIF_KMEM_UNALIGNED_BUF_SIZE,
> - 0, SLAB_HWCACHE_ALIGN, NULL);
> - if (!unaligned_cache) {
> - rc = -ENOMEM;
> - goto free_sdev;
> - }
> - INIT_WORK(&scif_info.misc_work, scif_misc_handler);
> - INIT_WORK(&scif_info.mmu_notif_work, scif_mmu_notif_handler);
> - INIT_WORK(&scif_info.conn_work, scif_conn_handler);
> - idr_init(&scif_ports);
> - return 0;
> -free_sdev:
> - scif_destroy_scifdev();
> -error:
> - return rc;
> -}
> -
> -static void _scif_exit(void)
> -{
> - idr_destroy(&scif_ports);
> - kmem_cache_destroy(unaligned_cache);
> - scif_destroy_scifdev();
> -}
> -
> -static int __init scif_init(void)
> -{
> - struct miscdevice *mdev = &scif_info.mdev;
> - int rc;
> -
> - _scif_init();
> - iova_cache_get();
> - rc = scif_peer_bus_init();
> - if (rc)
> - goto exit;
> - rc = scif_register_driver(&scif_driver);
> - if (rc)
> - goto peer_bus_exit;
> - rc = misc_register(mdev);
> - if (rc)
> - goto unreg_scif;
> - scif_init_debugfs();
> - return 0;
> -unreg_scif:
> - scif_unregister_driver(&scif_driver);
> -peer_bus_exit:
> - scif_peer_bus_exit();
> -exit:
> - _scif_exit();
> - return rc;
> -}
> -
> -static void __exit scif_exit(void)
> -{
> - scif_exit_debugfs();
> - misc_deregister(&scif_info.mdev);
> - scif_unregister_driver(&scif_driver);
> - scif_peer_bus_exit();
> - iova_cache_put();
> - _scif_exit();
> -}
> -
> -module_init(scif_init);
> -module_exit(scif_exit);
> -
> -MODULE_DEVICE_TABLE(scif, id_table);
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) SCIF driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/scif/scif_main.h
> b/drivers/misc/mic/scif/scif_main.h
> deleted file mode 100644
> index bb3ab97d5b35..000000000000
> --- a/drivers/misc/mic/scif/scif_main.h
> +++ /dev/null
> @@ -1,274 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef SCIF_MAIN_H
> -#define SCIF_MAIN_H
> -
> -#include <linux/sched/signal.h>
> -#include <linux/pci.h>
> -#include <linux/miscdevice.h>
> -#include <linux/dmaengine.h>
> -#include <linux/iova.h>
> -#include <linux/anon_inodes.h>
> -#include <linux/file.h>
> -#include <linux/vmalloc.h>
> -#include <linux/scif.h>
> -#include "../common/mic_dev.h"
> -
> -#define SCIF_MGMT_NODE 0
> -#define SCIF_DEFAULT_WATCHDOG_TO 30
> -#define SCIF_NODE_ACCEPT_TIMEOUT (3 * HZ)
> -#define SCIF_NODE_ALIVE_TIMEOUT (SCIF_DEFAULT_WATCHDOG_TO * HZ)
> -#define SCIF_RMA_TEMP_CACHE_LIMIT 0x20000
> -
> -/*
> - * Generic state used for certain node QP message exchanges
> - * like Unregister, Alloc etc.
> - */
> -enum scif_msg_state {
> - OP_IDLE = 1,
> - OP_IN_PROGRESS,
> - OP_COMPLETED,
> - OP_FAILED
> -};
> -
> -/*
> - * struct scif_info - Global SCIF information
> - *
> - * @nodeid: Node ID this node is to others
> - * @maxid: Max known node ID
> - * @total: Total number of SCIF nodes
> - * @nr_zombies: number of zombie endpoints
> - * @eplock: Lock to synchronize listening, zombie endpoint lists
> - * @connlock: Lock to synchronize connected and disconnected lists
> - * @nb_connect_lock: Synchronize non blocking connect operations
> - * @port_lock: Synchronize access to SCIF ports
> - * @uaccept: List of user acceptreq waiting for acceptreg
> - * @listen: List of listening end points
> - * @zombie: List of zombie end points with pending RMA's
> - * @connected: List of end points in connected state
> - * @disconnected: List of end points in disconnected state
> - * @nb_connect_list: List for non blocking connections
> - * @misc_work: miscellaneous SCIF tasks
> - * @conflock: Lock to synchronize SCIF node configuration changes
> - * @en_msg_log: Enable debug message logging
> - * @p2p_enable: Enable P2P SCIF network
> - * @mdev: The MISC device
> - * @conn_work: Work for workqueue handling all connections
> - * @exitwq: Wait queue for waiting for an EXIT node QP message response
> - * @loopb_dev: Dummy SCIF device used for loopback
> - * @loopb_wq: Workqueue used for handling loopback messages
> - * @loopb_wqname[16]: Name of loopback workqueue
> - * @loopb_work: Used for submitting work to loopb_wq
> - * @loopb_recv_q: List of messages received on the loopb_wq
> - * @card_initiated_exit: set when the card has initiated the exit
> - * @rmalock: Synchronize access to RMA operations
> - * @fencelock: Synchronize access to list of remote fences requested.
> - * @rma: List of temporary registered windows to be destroyed.
> - * @rma_tc: List of temporary registered & cached Windows to be destroyed
> - * @fence: List of remote fence requests
> - * @mmu_notif_work: Work for registration caching MMU notifier
> workqueue
> - * @mmu_notif_cleanup: List of temporary cached windows for reg cache
> - * @rma_tc_limit: RMA temporary cache limit
> - */
> -struct scif_info {
> - u8 nodeid;
> - u8 maxid;
> - u8 total;
> - u32 nr_zombies;
> - struct mutex eplock;
> - struct mutex connlock;
> - spinlock_t nb_connect_lock;
> - spinlock_t port_lock;
> - struct list_head uaccept;
> - struct list_head listen;
> - struct list_head zombie;
> - struct list_head connected;
> - struct list_head disconnected;
> - struct list_head nb_connect_list;
> - struct work_struct misc_work;
> - struct mutex conflock;
> - u8 en_msg_log;
> - u8 p2p_enable;
> - struct miscdevice mdev;
> - struct work_struct conn_work;
> - wait_queue_head_t exitwq;
> - struct scif_dev *loopb_dev;
> - struct workqueue_struct *loopb_wq;
> - char loopb_wqname[16];
> - struct work_struct loopb_work;
> - struct list_head loopb_recv_q;
> - bool card_initiated_exit;
> - spinlock_t rmalock;
> - struct mutex fencelock;
> - struct list_head rma;
> - struct list_head rma_tc;
> - struct list_head fence;
> - struct work_struct mmu_notif_work;
> - struct list_head mmu_notif_cleanup;
> - unsigned long rma_tc_limit;
> -};
> -
> -/*
> - * struct scif_p2p_info - SCIF mapping information used for P2P
> - *
> - * @ppi_peer_id - SCIF peer node id
> - * @ppi_sg - Scatter list for bar information (One for mmio and one for aper)
> - * @sg_nentries - Number of entries in the scatterlist
> - * @ppi_da: DMA address for MMIO and APER bars
> - * @ppi_len: Length of MMIO and APER bars
> - * @ppi_list: Link in list of mapping information
> - */
> -struct scif_p2p_info {
> - u8 ppi_peer_id;
> - struct scatterlist *ppi_sg[2];
> - u64 sg_nentries[2];
> - dma_addr_t ppi_da[2];
> - u64 ppi_len[2];
> -#define SCIF_PPI_MMIO 0
> -#define SCIF_PPI_APER 1
> - struct list_head ppi_list;
> -};
> -
> -/*
> - * struct scif_dev - SCIF remote device specific fields
> - *
> - * @node: Node id
> - * @p2p: List of P2P mapping information
> - * @qpairs: The node queue pair for exchanging control messages
> - * @intr_wq: Workqueue for handling Node QP messages
> - * @intr_wqname: Name of node QP workqueue for handling interrupts
> - * @intr_bh: Used for submitting work to intr_wq
> - * @lock: Lock used for synchronizing access to the scif device
> - * @sdev: SCIF hardware device on the SCIF hardware bus
> - * @db: doorbell the peer will trigger to generate an interrupt on self
> - * @rdb: Doorbell to trigger on the peer to generate an interrupt on the peer
> - * @cookie: Cookie received while registering the interrupt handler
> - * @peer_add_work: Work for handling device_add for peer devices
> - * @p2p_dwork: Delayed work to enable polling for P2P state
> - * @qp_dwork: Delayed work for enabling polling for remote QP
> information
> - * @p2p_retry: Number of times to retry polling of P2P state
> - * @base_addr: P2P aperture bar base address
> - * @mic_mw mmio: The peer MMIO information used for P2P
> - * @spdev: SCIF peer device on the SCIF peer bus
> - * @node_remove_ack_pending: True if a node_remove_ack is pending
> - * @exit_ack_pending: true if an exit_ack is pending
> - * @disconn_wq: Used while waiting for a node remove response
> - * @disconn_rescnt: Keeps track of number of node remove requests sent
> - * @exit: Status of exit message
> - * @qp_dma_addr: Queue pair DMA address passed to the peer
> - * @dma_ch_idx: Round robin index for DMA channels
> - * @signal_pool: DMA pool used for scheduling scif_fence_signal DMA's
> -*/
> -struct scif_dev {
> - u8 node;
> - struct list_head p2p;
> - struct scif_qp *qpairs;
> - struct workqueue_struct *intr_wq;
> - char intr_wqname[16];
> - struct work_struct intr_bh;
> - struct mutex lock;
> - struct scif_hw_dev *sdev;
> - int db;
> - int rdb;
> - struct mic_irq *cookie;
> - struct work_struct peer_add_work;
> - struct delayed_work p2p_dwork;
> - struct delayed_work qp_dwork;
> - int p2p_retry;
> - dma_addr_t base_addr;
> - struct mic_mw mmio;
> - struct scif_peer_dev __rcu *spdev;
> - bool node_remove_ack_pending;
> - bool exit_ack_pending;
> - wait_queue_head_t disconn_wq;
> - atomic_t disconn_rescnt;
> - enum scif_msg_state exit;
> - dma_addr_t qp_dma_addr;
> - int dma_ch_idx;
> - struct dma_pool *signal_pool;
> -};
> -
> -extern bool scif_reg_cache_enable;
> -extern bool scif_ulimit_check;
> -extern struct scif_info scif_info;
> -extern struct idr scif_ports;
> -extern struct bus_type scif_peer_bus;
> -extern struct scif_dev *scif_dev;
> -extern const struct file_operations scif_fops;
> -extern const struct file_operations scif_anon_fops;
> -
> -/* Size of the RB for the Node QP */
> -#define SCIF_NODE_QP_SIZE 0x10000
> -
> -#include "scif_nodeqp.h"
> -#include "scif_rma.h"
> -#include "scif_rma_list.h"
> -
> -/*
> - * scifdev_self:
> - * @dev: The remote SCIF Device
> - *
> - * Returns true if the SCIF Device passed is the self aka Loopback SCIF device.
> - */
> -static inline int scifdev_self(struct scif_dev *dev)
> -{
> - return dev->node == scif_info.nodeid;
> -}
> -
> -static inline bool scif_is_mgmt_node(void)
> -{
> - return !scif_info.nodeid;
> -}
> -
> -/*
> - * scifdev_is_p2p:
> - * @dev: The remote SCIF Device
> - *
> - * Returns true if the SCIF Device is a MIC Peer to Peer SCIF device.
> - */
> -static inline bool scifdev_is_p2p(struct scif_dev *dev)
> -{
> - if (scif_is_mgmt_node())
> - return false;
> - else
> - return dev != &scif_dev[SCIF_MGMT_NODE] &&
> - !scifdev_self(dev);
> -}
> -
> -/*
> - * scifdev_alive:
> - * @scifdev: The remote SCIF Device
> - *
> - * Returns true if the remote SCIF Device is running or sleeping for
> - * this endpoint.
> - */
> -static inline int _scifdev_alive(struct scif_dev *scifdev)
> -{
> - struct scif_peer_dev *spdev;
> -
> - rcu_read_lock();
> - spdev = rcu_dereference(scifdev->spdev);
> - rcu_read_unlock();
> - return !!spdev;
> -}
> -
> -#include "scif_epd.h"
> -
> -void __init scif_init_debugfs(void);
> -void scif_exit_debugfs(void);
> -int scif_setup_intr_wq(struct scif_dev *scifdev);
> -void scif_destroy_intr_wq(struct scif_dev *scifdev);
> -void scif_cleanup_scifdev(struct scif_dev *dev);
> -void scif_handle_remove_node(int node);
> -void scif_disconnect_node(u32 node_id, bool mgmt_initiated);
> -void scif_free_qp(struct scif_dev *dev);
> -void scif_misc_handler(struct work_struct *work);
> -void scif_stop(struct scif_dev *scifdev);
> -irqreturn_t scif_intr_handler(int irq, void *data);
> -#endif /* SCIF_MAIN_H */
> diff --git a/drivers/misc/mic/scif/scif_map.h
> b/drivers/misc/mic/scif/scif_map.h
> deleted file mode 100644
> index 96b760819bfc..000000000000
> --- a/drivers/misc/mic/scif/scif_map.h
> +++ /dev/null
> @@ -1,127 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef SCIF_MAP_H
> -#define SCIF_MAP_H
> -
> -#include "../bus/scif_bus.h"
> -
> -static __always_inline void *
> -scif_alloc_coherent(dma_addr_t *dma_handle,
> - struct scif_dev *scifdev, size_t size,
> - gfp_t gfp)
> -{
> - void *va;
> -
> - if (scifdev_self(scifdev)) {
> - va = kmalloc(size, gfp);
> - if (va)
> - *dma_handle = virt_to_phys(va);
> - } else {
> - va = dma_alloc_coherent(&scifdev->sdev->dev,
> - size, dma_handle, gfp);
> - if (va && scifdev_is_p2p(scifdev))
> - *dma_handle = *dma_handle + scifdev->base_addr;
> - }
> - return va;
> -}
> -
> -static __always_inline void
> -scif_free_coherent(void *va, dma_addr_t local,
> - struct scif_dev *scifdev, size_t size)
> -{
> - if (scifdev_self(scifdev)) {
> - kfree(va);
> - } else {
> - if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr)
> - local = local - scifdev->base_addr;
> - dma_free_coherent(&scifdev->sdev->dev,
> - size, va, local);
> - }
> -}
> -
> -static __always_inline int
> -scif_map_single(dma_addr_t *dma_handle,
> - void *local, struct scif_dev *scifdev, size_t size)
> -{
> - int err = 0;
> -
> - if (scifdev_self(scifdev)) {
> - *dma_handle = virt_to_phys((local));
> - } else {
> - *dma_handle = dma_map_single(&scifdev->sdev->dev,
> - local, size, DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(&scifdev->sdev->dev, *dma_handle))
> - err = -ENOMEM;
> - else if (scifdev_is_p2p(scifdev))
> - *dma_handle = *dma_handle + scifdev->base_addr;
> - }
> - if (err)
> - *dma_handle = 0;
> - return err;
> -}
> -
> -static __always_inline void
> -scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev,
> - size_t size)
> -{
> - if (!scifdev_self(scifdev)) {
> - if (scifdev_is_p2p(scifdev))
> - local = local - scifdev->base_addr;
> - dma_unmap_single(&scifdev->sdev->dev, local,
> - size, DMA_BIDIRECTIONAL);
> - }
> -}
> -
> -static __always_inline void *
> -scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev)
> -{
> - void *out_virt;
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - if (scifdev_self(scifdev))
> - out_virt = phys_to_virt(phys);
> - else
> - out_virt = (void __force *)
> - sdev->hw_ops->remap(sdev, phys, size);
> - return out_virt;
> -}
> -
> -static __always_inline void
> -scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
> -{
> - if (!scifdev_self(scifdev)) {
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - sdev->hw_ops->unmap(sdev, (void __force __iomem *)virt);
> - }
> -}
> -
> -static __always_inline int
> -scif_map_page(dma_addr_t *dma_handle, struct page *page,
> - struct scif_dev *scifdev)
> -{
> - int err = 0;
> -
> - if (scifdev_self(scifdev)) {
> - *dma_handle = page_to_phys(page);
> - } else {
> - struct scif_hw_dev *sdev = scifdev->sdev;
> - *dma_handle = dma_map_page(&sdev->dev,
> - page, 0x0, PAGE_SIZE,
> - DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(&sdev->dev, *dma_handle))
> - err = -ENOMEM;
> - else if (scifdev_is_p2p(scifdev))
> - *dma_handle = *dma_handle + scifdev->base_addr;
> - }
> - if (err)
> - *dma_handle = 0;
> - return err;
> -}
> -#endif /* SCIF_MAP_H */
> diff --git a/drivers/misc/mic/scif/scif_mmap.c
> b/drivers/misc/mic/scif/scif_mmap.c
> deleted file mode 100644
> index a151d416f39c..000000000000
> --- a/drivers/misc/mic/scif/scif_mmap.c
> +++ /dev/null
> @@ -1,690 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -
> -/*
> - * struct scif_vma_info - Information about a remote memory mapping
> - * created via scif_mmap(..)
> - * @vma: VM area struct
> - * @list: link to list of active vmas
> - */
> -struct scif_vma_info {
> - struct vm_area_struct *vma;
> - struct list_head list;
> -};
> -
> -void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_rma_req req;
> - struct scif_window *window = NULL;
> - struct scif_window *recv_window =
> - (struct scif_window *)msg->payload[0];
> - struct scif_endpt *ep;
> -
> - ep = (struct scif_endpt *)recv_window->ep;
> - req.out_window = &window;
> - req.offset = recv_window->offset;
> - req.prot = recv_window->prot;
> - req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
> - req.type = SCIF_WINDOW_FULL;
> - req.head = &ep->rma_info.reg_list;
> - msg->payload[0] = ep->remote_ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Does a valid window exist? */
> - if (scif_query_window(&req)) {
> - dev_err(&scifdev->sdev->dev,
> - "%s %d -ENXIO\n", __func__, __LINE__);
> - msg->uop = SCIF_UNREGISTER_ACK;
> - goto error;
> - }
> -
> - scif_put_window(window, window->nr_pages);
> -
> - if (!window->ref_count) {
> - atomic_inc(&ep->rma_info.tw_refcount);
> - ep->rma_info.async_list_del = 1;
> - list_del_init(&window->list);
> - scif_free_window_offset(ep, window, window->offset);
> - }
> -error:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (window && !window->ref_count)
> - scif_queue_for_cleanup(window, &scif_info.rma);
> -}
> -
> -/*
> - * Remove valid remote memory mappings created via scif_mmap(..) from
> the
> - * process address space since the remote node is lost
> - */
> -static void __scif_zap_mmaps(struct scif_endpt *ep)
> -{
> - struct list_head *item;
> - struct scif_vma_info *info;
> - struct vm_area_struct *vma;
> - unsigned long size;
> -
> - spin_lock(&ep->lock);
> - list_for_each(item, &ep->rma_info.vma_list) {
> - info = list_entry(item, struct scif_vma_info, list);
> - vma = info->vma;
> - size = vma->vm_end - vma->vm_start;
> - zap_vma_ptes(vma, vma->vm_start, size);
> - dev_dbg(scif_info.mdev.this_device,
> - "%s ep %p zap vma %p size 0x%lx\n",
> - __func__, ep, info->vma, size);
> - }
> - spin_unlock(&ep->lock);
> -}
> -
> -/*
> - * Traverse the list of endpoints for a particular remote node and
> - * zap valid remote memory mappings since the remote node is lost
> - */
> -static void _scif_zap_mmaps(int node, struct list_head *head)
> -{
> - struct scif_endpt *ep;
> - struct list_head *item;
> -
> - mutex_lock(&scif_info.connlock);
> - list_for_each(item, head) {
> - ep = list_entry(item, struct scif_endpt, list);
> - if (ep->remote_dev->node == node)
> - __scif_zap_mmaps(ep);
> - }
> - mutex_unlock(&scif_info.connlock);
> -}
> -
> -/*
> - * Wrapper for removing remote memory mappings for a particular node.
> This API
> - * is called by peer nodes as part of handling a lost node.
> - */
> -void scif_zap_mmaps(int node)
> -{
> - _scif_zap_mmaps(node, &scif_info.connected);
> - _scif_zap_mmaps(node, &scif_info.disconnected);
> -}
> -
> -/*
> - * This API is only called while handling a lost node:
> - * a) Remote node is dead.
> - * b) Remote memory mappings have been zapped
> - * So we can traverse the remote_reg_list without any locks. Since
> - * the window has not yet been unregistered we can drop the ref count
> - * and queue it to the cleanup thread.
> - */
> -static void __scif_cleanup_rma_for_zombies(struct scif_endpt *ep)
> -{
> - struct list_head *pos, *tmp;
> - struct scif_window *window;
> -
> - list_for_each_safe(pos, tmp, &ep->rma_info.remote_reg_list) {
> - window = list_entry(pos, struct scif_window, list);
> - if (window->ref_count)
> - scif_put_window(window, window->nr_pages);
> - else
> - dev_err(scif_info.mdev.this_device,
> - "%s %d unexpected\n",
> - __func__, __LINE__);
> - if (!window->ref_count) {
> - atomic_inc(&ep->rma_info.tw_refcount);
> - list_del_init(&window->list);
> - scif_queue_for_cleanup(window, &scif_info.rma);
> - }
> - }
> -}
> -
> -/* Cleanup remote registration lists for zombie endpoints */
> -void scif_cleanup_rma_for_zombies(int node)
> -{
> - struct scif_endpt *ep;
> - struct list_head *item;
> -
> - mutex_lock(&scif_info.eplock);
> - list_for_each(item, &scif_info.zombie) {
> - ep = list_entry(item, struct scif_endpt, list);
> - if (ep->remote_dev && ep->remote_dev->node == node)
> - __scif_cleanup_rma_for_zombies(ep);
> - }
> - mutex_unlock(&scif_info.eplock);
> - flush_work(&scif_info.misc_work);
> -}
> -
> -/* Insert the VMA into the per endpoint VMA list */
> -static int scif_insert_vma(struct scif_endpt *ep, struct vm_area_struct *vma)
> -{
> - struct scif_vma_info *info;
> - int err = 0;
> -
> - info = kzalloc(sizeof(*info), GFP_KERNEL);
> - if (!info) {
> - err = -ENOMEM;
> - goto done;
> - }
> - info->vma = vma;
> - spin_lock(&ep->lock);
> - list_add_tail(&info->list, &ep->rma_info.vma_list);
> - spin_unlock(&ep->lock);
> -done:
> - return err;
> -}
> -
> -/* Delete the VMA from the per endpoint VMA list */
> -static void scif_delete_vma(struct scif_endpt *ep, struct vm_area_struct
> *vma)
> -{
> - struct list_head *item;
> - struct scif_vma_info *info;
> -
> - spin_lock(&ep->lock);
> - list_for_each(item, &ep->rma_info.vma_list) {
> - info = list_entry(item, struct scif_vma_info, list);
> - if (info->vma == vma) {
> - list_del(&info->list);
> - kfree(info);
> - break;
> - }
> - }
> - spin_unlock(&ep->lock);
> -}
> -
> -static phys_addr_t scif_get_phys(phys_addr_t phys, struct scif_endpt *ep)
> -{
> - struct scif_dev *scifdev = (struct scif_dev *)ep->remote_dev;
> - struct scif_hw_dev *sdev = scifdev->sdev;
> - phys_addr_t out_phys, apt_base = 0;
> -
> - /*
> - * If the DMA address is card relative then we need to add the
> - * aperture base for mmap to work correctly
> - */
> - if (!scifdev_self(scifdev) && sdev->aper && sdev->card_rel_da)
> - apt_base = sdev->aper->pa;
> - out_phys = apt_base + phys;
> - return out_phys;
> -}
> -
> -int scif_get_pages(scif_epd_t epd, off_t offset, size_t len,
> - struct scif_range **pages)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scif_rma_req req;
> - struct scif_window *window = NULL;
> - int nr_pages, err, i;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI get_pinned_pages: ep %p offset 0x%lx len 0x%lx\n",
> - ep, offset, len);
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - if (!len || (offset < 0) ||
> - (offset + len < offset) ||
> - (ALIGN(offset, PAGE_SIZE) != offset) ||
> - (ALIGN(len, PAGE_SIZE) != len))
> - return -EINVAL;
> -
> - nr_pages = len >> PAGE_SHIFT;
> -
> - req.out_window = &window;
> - req.offset = offset;
> - req.prot = 0;
> - req.nr_bytes = len;
> - req.type = SCIF_WINDOW_SINGLE;
> - req.head = &ep->rma_info.remote_reg_list;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Does a valid window exist? */
> - err = scif_query_window(&req);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error;
> - }
> -
> - /* Allocate scif_range */
> - *pages = kzalloc(sizeof(**pages), GFP_KERNEL);
> - if (!*pages) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - /* Allocate phys addr array */
> - (*pages)->phys_addr = scif_zalloc(nr_pages * sizeof(dma_addr_t));
> - if (!((*pages)->phys_addr)) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev)) {
> - /* Allocate virtual address array */
> - ((*pages)->va = scif_zalloc(nr_pages * sizeof(void *)));
> - if (!(*pages)->va) {
> - err = -ENOMEM;
> - goto error;
> - }
> - }
> - /* Populate the values */
> - (*pages)->cookie = window;
> - (*pages)->nr_pages = nr_pages;
> - (*pages)->prot_flags = window->prot;
> -
> - for (i = 0; i < nr_pages; i++) {
> - (*pages)->phys_addr[i] =
> - __scif_off_to_dma_addr(window, offset +
> - (i * PAGE_SIZE));
> - (*pages)->phys_addr[i] = scif_get_phys((*pages)-
> >phys_addr[i],
> - ep);
> - if (scif_is_mgmt_node() && !scifdev_self(ep->remote_dev))
> - (*pages)->va[i] =
> - ep->remote_dev->sdev->aper->va +
> - (*pages)->phys_addr[i] -
> - ep->remote_dev->sdev->aper->pa;
> - }
> -
> - scif_get_window(window, nr_pages);
> -error:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (err) {
> - if (*pages) {
> - scif_free((*pages)->phys_addr,
> - nr_pages * sizeof(dma_addr_t));
> - scif_free((*pages)->va,
> - nr_pages * sizeof(void *));
> - kfree(*pages);
> - *pages = NULL;
> - }
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - }
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_get_pages);
> -
> -int scif_put_pages(struct scif_range *pages)
> -{
> - struct scif_endpt *ep;
> - struct scif_window *window;
> - struct scifmsg msg;
> -
> - if (!pages || !pages->cookie)
> - return -EINVAL;
> -
> - window = pages->cookie;
> -
> - if (!window || window->magic != SCIFEP_MAGIC)
> - return -EINVAL;
> -
> - ep = (struct scif_endpt *)window->ep;
> - /*
> - * If the state is SCIFEP_CONNECTED or SCIFEP_DISCONNECTED then
> the
> - * callee should be allowed to release references to the pages,
> - * else the endpoint was not connected in the first place,
> - * hence the ENOTCONN.
> - */
> - if (ep->state != SCIFEP_CONNECTED && ep->state !=
> SCIFEP_DISCONNECTED)
> - return -ENOTCONN;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> -
> - scif_put_window(window, pages->nr_pages);
> -
> - /* Initiate window destruction if ref count is zero */
> - if (!window->ref_count) {
> - list_del(&window->list);
> - mutex_unlock(&ep->rma_info.rma_lock);
> - scif_drain_dma_intr(ep->remote_dev->sdev,
> - ep->rma_info.dma_chan);
> - /* Inform the peer about this window being destroyed. */
> - msg.uop = SCIF_MUNMAP;
> - msg.src = ep->port;
> - msg.payload[0] = window->peer_window;
> - /* No error handling for notification messages */
> - scif_nodeqp_send(ep->remote_dev, &msg);
> - /* Destroy this window from the peer's registered AS */
> - scif_destroy_remote_window(window);
> - } else {
> - mutex_unlock(&ep->rma_info.rma_lock);
> - }
> -
> - scif_free(pages->phys_addr, pages->nr_pages * sizeof(dma_addr_t));
> - scif_free(pages->va, pages->nr_pages * sizeof(void *));
> - kfree(pages);
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(scif_put_pages);
> -
> -/*
> - * scif_rma_list_mmap:
> - *
> - * Traverse the remote registration list starting from start_window:
> - * 1) Create VtoP mappings via remap_pfn_range(..)
> - * 2) Once step 1) and 2) complete successfully then traverse the range of
> - * windows again and bump the reference count.
> - * RMA lock must be held.
> - */
> -static int scif_rma_list_mmap(struct scif_window *start_window, s64 offset,
> - int nr_pages, struct vm_area_struct *vma)
> -{
> - s64 end_offset, loop_offset = offset;
> - struct scif_window *window = start_window;
> - int loop_nr_pages, nr_pages_left = nr_pages;
> - struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
> - struct list_head *head = &ep->rma_info.remote_reg_list;
> - int i, err = 0;
> - dma_addr_t phys_addr;
> - struct scif_window_iter src_win_iter;
> - size_t contig_bytes = 0;
> -
> - might_sleep();
> - list_for_each_entry_from(window, head, list) {
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - loop_nr_pages = min_t(int,
> - (end_offset - loop_offset) >> PAGE_SHIFT,
> - nr_pages_left);
> - scif_init_window_iter(window, &src_win_iter);
> - for (i = 0; i < loop_nr_pages; i++) {
> - phys_addr = scif_off_to_dma_addr(window,
> loop_offset,
> - &contig_bytes,
> - &src_win_iter);
> - phys_addr = scif_get_phys(phys_addr, ep);
> - err = remap_pfn_range(vma,
> - vma->vm_start +
> - loop_offset - offset,
> - phys_addr >> PAGE_SHIFT,
> - PAGE_SIZE,
> - vma->vm_page_prot);
> - if (err)
> - goto error;
> - loop_offset += PAGE_SIZE;
> - }
> - nr_pages_left -= loop_nr_pages;
> - if (!nr_pages_left)
> - break;
> - }
> - /*
> - * No more failures expected. Bump up the ref count for all
> - * the windows. Another traversal from start_window required
> - * for handling errors encountered across windows during
> - * remap_pfn_range(..).
> - */
> - loop_offset = offset;
> - nr_pages_left = nr_pages;
> - window = start_window;
> - head = &ep->rma_info.remote_reg_list;
> - list_for_each_entry_from(window, head, list) {
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - loop_nr_pages = min_t(int,
> - (end_offset - loop_offset) >> PAGE_SHIFT,
> - nr_pages_left);
> - scif_get_window(window, loop_nr_pages);
> - nr_pages_left -= loop_nr_pages;
> - loop_offset += (loop_nr_pages << PAGE_SHIFT);
> - if (!nr_pages_left)
> - break;
> - }
> -error:
> - if (err)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - return err;
> -}
> -
> -/*
> - * scif_rma_list_munmap:
> - *
> - * Traverse the remote registration list starting from window:
> - * 1) Decrement ref count.
> - * 2) If the ref count drops to zero then send a SCIF_MUNMAP message to
> peer.
> - * RMA lock must be held.
> - */
> -static void scif_rma_list_munmap(struct scif_window *start_window,
> - s64 offset, int nr_pages)
> -{
> - struct scifmsg msg;
> - s64 loop_offset = offset, end_offset;
> - int loop_nr_pages, nr_pages_left = nr_pages;
> - struct scif_endpt *ep = (struct scif_endpt *)start_window->ep;
> - struct list_head *head = &ep->rma_info.remote_reg_list;
> - struct scif_window *window = start_window, *_window;
> -
> - msg.uop = SCIF_MUNMAP;
> - msg.src = ep->port;
> - loop_offset = offset;
> - nr_pages_left = nr_pages;
> - list_for_each_entry_safe_from(window, _window, head, list) {
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - loop_nr_pages = min_t(int,
> - (end_offset - loop_offset) >> PAGE_SHIFT,
> - nr_pages_left);
> - scif_put_window(window, loop_nr_pages);
> - if (!window->ref_count) {
> - struct scif_dev *rdev = ep->remote_dev;
> -
> - scif_drain_dma_intr(rdev->sdev,
> - ep->rma_info.dma_chan);
> - /* Inform the peer about this munmap */
> - msg.payload[0] = window->peer_window;
> - /* No error handling for Notification messages. */
> - scif_nodeqp_send(ep->remote_dev, &msg);
> - list_del(&window->list);
> - /* Destroy this window from the peer's registered AS
> */
> - scif_destroy_remote_window(window);
> - }
> - nr_pages_left -= loop_nr_pages;
> - loop_offset += (loop_nr_pages << PAGE_SHIFT);
> - if (!nr_pages_left)
> - break;
> - }
> -}
> -
> -/*
> - * The private data field of each VMA used to mmap a remote window
> - * points to an instance of struct vma_pvt
> - */
> -struct vma_pvt {
> - struct scif_endpt *ep; /* End point for remote window */
> - s64 offset; /* offset within remote window */
> - bool valid_offset; /* offset is valid only if the original
> - * mmap request was for a single page
> - * else the offset within the vma is
> - * the correct offset
> - */
> - struct kref ref;
> -};
> -
> -static void vma_pvt_release(struct kref *ref)
> -{
> - struct vma_pvt *vmapvt = container_of(ref, struct vma_pvt, ref);
> -
> - kfree(vmapvt);
> -}
> -
> -/**
> - * scif_vma_open - VMA open driver callback
> - * @vma: VMM memory area.
> - * The open method is called by the kernel to allow the subsystem
> implementing
> - * the VMA to initialize the area. This method is invoked any time a new
> - * reference to the VMA is made (when a process forks, for example).
> - * The one exception happens when the VMA is first created by mmap;
> - * in this case, the driver's mmap method is called instead.
> - * This function is also invoked when an existing VMA is split by the kernel
> - * due to a call to munmap on a subset of the VMA resulting in two VMAs.
> - * The kernel invokes this function only on one of the two VMAs.
> - */
> -static void scif_vma_open(struct vm_area_struct *vma)
> -{
> - struct vma_pvt *vmapvt = vma->vm_private_data;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI vma open: vma_start 0x%lx vma_end 0x%lx\n",
> - vma->vm_start, vma->vm_end);
> - scif_insert_vma(vmapvt->ep, vma);
> - kref_get(&vmapvt->ref);
> -}
> -
> -/**
> - * scif_munmap - VMA close driver callback.
> - * @vma: VMM memory area.
> - * When an area is destroyed, the kernel calls its close operation.
> - * Note that there's no usage count associated with VMA's; the area
> - * is opened and closed exactly once by each process that uses it.
> - */
> -static void scif_munmap(struct vm_area_struct *vma)
> -{
> - struct scif_endpt *ep;
> - struct vma_pvt *vmapvt = vma->vm_private_data;
> - int nr_pages = vma_pages(vma);
> - s64 offset;
> - struct scif_rma_req req;
> - struct scif_window *window = NULL;
> - int err;
> -
> - might_sleep();
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI munmap: vma_start 0x%lx vma_end 0x%lx\n",
> - vma->vm_start, vma->vm_end);
> - ep = vmapvt->ep;
> - offset = vmapvt->valid_offset ? vmapvt->offset :
> - (vma->vm_pgoff) << PAGE_SHIFT;
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI munmap: ep %p nr_pages 0x%x offset 0x%llx\n",
> - ep, nr_pages, offset);
> - req.out_window = &window;
> - req.offset = offset;
> - req.nr_bytes = vma->vm_end - vma->vm_start;
> - req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
> - req.type = SCIF_WINDOW_PARTIAL;
> - req.head = &ep->rma_info.remote_reg_list;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> -
> - err = scif_query_window(&req);
> - if (err)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - else
> - scif_rma_list_munmap(window, offset, nr_pages);
> -
> - mutex_unlock(&ep->rma_info.rma_lock);
> - /*
> - * The kernel probably zeroes these out but we still want
> - * to clean up our own mess just in case.
> - */
> - vma->vm_ops = NULL;
> - vma->vm_private_data = NULL;
> - kref_put(&vmapvt->ref, vma_pvt_release);
> - scif_delete_vma(ep, vma);
> -}
> -
> -static const struct vm_operations_struct scif_vm_ops = {
> - .open = scif_vma_open,
> - .close = scif_munmap,
> -};
> -
> -/**
> - * scif_mmap - Map pages in virtual address space to a remote window.
> - * @vma: VMM memory area.
> - * @epd: endpoint descriptor
> - *
> - * Return: Upon successful completion, scif_mmap() returns zero
> - * else an apt error is returned as documented in scif.h
> - */
> -int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd)
> -{
> - struct scif_rma_req req;
> - struct scif_window *window = NULL;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - s64 start_offset = vma->vm_pgoff << PAGE_SHIFT;
> - int nr_pages = vma_pages(vma);
> - int err;
> - struct vma_pvt *vmapvt;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI mmap: ep %p start_offset 0x%llx nr_pages 0x%x\n",
> - ep, start_offset, nr_pages);
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - might_sleep();
> -
> - err = scif_insert_vma(ep, vma);
> - if (err)
> - return err;
> -
> - vmapvt = kzalloc(sizeof(*vmapvt), GFP_KERNEL);
> - if (!vmapvt) {
> - scif_delete_vma(ep, vma);
> - return -ENOMEM;
> - }
> -
> - vmapvt->ep = ep;
> - kref_init(&vmapvt->ref);
> -
> - req.out_window = &window;
> - req.offset = start_offset;
> - req.nr_bytes = vma->vm_end - vma->vm_start;
> - req.prot = vma->vm_flags & (VM_READ | VM_WRITE);
> - req.type = SCIF_WINDOW_PARTIAL;
> - req.head = &ep->rma_info.remote_reg_list;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Does a valid window exist? */
> - err = scif_query_window(&req);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error_unlock;
> - }
> -
> - /* Default prot for loopback */
> - if (!scifdev_self(ep->remote_dev))
> - vma->vm_page_prot = pgprot_writecombine(vma-
> >vm_page_prot);
> -
> - /*
> - * VM_DONTCOPY - Do not copy this vma on fork
> - * VM_DONTEXPAND - Cannot expand with mremap()
> - * VM_RESERVED - Count as reserved_vm like IO
> - * VM_PFNMAP - Page-ranges managed without "struct page"
> - * VM_IO - Memory mapped I/O or similar
> - *
> - * We do not want to copy this VMA automatically on a fork(),
> - * expand this VMA due to mremap() or swap out these pages since
> - * the VMA is actually backed by physical pages in the remote
> - * node's physical memory and not via a struct page.
> - */
> - vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND |
> VM_DONTDUMP;
> -
> - if (!scifdev_self(ep->remote_dev))
> - vma->vm_flags |= VM_IO | VM_PFNMAP;
> -
> - /* Map this range of windows */
> - err = scif_rma_list_mmap(window, start_offset, nr_pages, vma);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error_unlock;
> - }
> - /* Set up the driver call back */
> - vma->vm_ops = &scif_vm_ops;
> - vma->vm_private_data = vmapvt;
> -error_unlock:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (err) {
> - kfree(vmapvt);
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - scif_delete_vma(ep, vma);
> - }
> - return err;
> -}
> diff --git a/drivers/misc/mic/scif/scif_nm.c b/drivers/misc/mic/scif/scif_nm.c
> deleted file mode 100644
> index c4d9422082b7..000000000000
> --- a/drivers/misc/mic/scif/scif_nm.c
> +++ /dev/null
> @@ -1,229 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_peer_bus.h"
> -
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -/**
> - * scif_invalidate_ep() - Set state for all connected endpoints
> - * to disconnected and wake up all send/recv waitqueues
> - *
> - * @node: Node to invalidate
> - */
> -static void scif_invalidate_ep(int node)
> -{
> - struct scif_endpt *ep;
> - struct list_head *pos, *tmpq;
> -
> - flush_work(&scif_info.conn_work);
> - mutex_lock(&scif_info.connlock);
> - list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
> - ep = list_entry(pos, struct scif_endpt, list);
> - if (ep->remote_dev->node == node) {
> - scif_unmap_all_windows(ep);
> - spin_lock(&ep->lock);
> - scif_cleanup_ep_qp(ep);
> - spin_unlock(&ep->lock);
> - }
> - }
> - list_for_each_safe(pos, tmpq, &scif_info.connected) {
> - ep = list_entry(pos, struct scif_endpt, list);
> - if (ep->remote_dev->node == node) {
> - list_del(pos);
> - spin_lock(&ep->lock);
> - ep->state = SCIFEP_DISCONNECTED;
> - list_add_tail(&ep->list, &scif_info.disconnected);
> - scif_cleanup_ep_qp(ep);
> - wake_up_interruptible(&ep->sendwq);
> - wake_up_interruptible(&ep->recvwq);
> - spin_unlock(&ep->lock);
> - scif_unmap_all_windows(ep);
> - }
> - }
> - mutex_unlock(&scif_info.connlock);
> -}
> -
> -void scif_free_qp(struct scif_dev *scifdev)
> -{
> - struct scif_qp *qp = scifdev->qpairs;
> -
> - if (!qp)
> - return;
> - scif_unmap_single(qp->local_buf, scifdev, qp->inbound_q.size);
> - kfree(qp->inbound_q.rb_base);
> - scif_unmap_single(qp->local_qp, scifdev, sizeof(struct scif_qp));
> - kfree(scifdev->qpairs);
> - scifdev->qpairs = NULL;
> -}
> -
> -static void scif_cleanup_qp(struct scif_dev *dev)
> -{
> - struct scif_qp *qp = &dev->qpairs[0];
> -
> - if (!qp)
> - return;
> - scif_iounmap((void *)qp->remote_qp, sizeof(struct scif_qp), dev);
> - scif_iounmap((void *)qp->outbound_q.rb_base,
> - sizeof(struct scif_qp), dev);
> - qp->remote_qp = NULL;
> - qp->local_write = 0;
> - qp->inbound_q.current_write_offset = 0;
> - qp->inbound_q.current_read_offset = 0;
> - if (scifdev_is_p2p(dev))
> - scif_free_qp(dev);
> -}
> -
> -void scif_send_acks(struct scif_dev *dev)
> -{
> - struct scifmsg msg;
> -
> - if (dev->node_remove_ack_pending) {
> - msg.uop = SCIF_NODE_REMOVE_ACK;
> - msg.src.node = scif_info.nodeid;
> - msg.dst.node = SCIF_MGMT_NODE;
> - msg.payload[0] = dev->node;
> - scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg);
> - dev->node_remove_ack_pending = false;
> - }
> - if (dev->exit_ack_pending) {
> - msg.uop = SCIF_EXIT_ACK;
> - msg.src.node = scif_info.nodeid;
> - msg.dst.node = dev->node;
> - scif_nodeqp_send(dev, &msg);
> - dev->exit_ack_pending = false;
> - }
> -}
> -
> -/**
> - * scif_cleanup_scifdev - Uninitialize SCIF data structures for remote
> - * SCIF device.
> - * @dev: Remote SCIF device.
> - */
> -void scif_cleanup_scifdev(struct scif_dev *dev)
> -{
> - struct scif_hw_dev *sdev = dev->sdev;
> -
> - if (!dev->sdev)
> - return;
> - if (scifdev_is_p2p(dev)) {
> - if (dev->cookie) {
> - sdev->hw_ops->free_irq(sdev, dev->cookie, dev);
> - dev->cookie = NULL;
> - }
> - scif_destroy_intr_wq(dev);
> - }
> - flush_work(&scif_info.misc_work);
> - scif_destroy_p2p(dev);
> - scif_invalidate_ep(dev->node);
> - scif_zap_mmaps(dev->node);
> - scif_cleanup_rma_for_zombies(dev->node);
> - flush_work(&scif_info.misc_work);
> - scif_send_acks(dev);
> - if (!dev->node && scif_info.card_initiated_exit) {
> - /*
> - * Send an SCIF_EXIT message which is the last message from
> MIC
> - * to the Host and wait for a SCIF_EXIT_ACK
> - */
> - scif_send_exit(dev);
> - scif_info.card_initiated_exit = false;
> - }
> - scif_cleanup_qp(dev);
> -}
> -
> -/**
> - * scif_remove_node
> - *
> - * @node: Node to remove
> - */
> -void scif_handle_remove_node(int node)
> -{
> - struct scif_dev *scifdev = &scif_dev[node];
> -
> - if (scif_peer_unregister_device(scifdev))
> - scif_send_acks(scifdev);
> -}
> -
> -static int scif_send_rmnode_msg(int node, int remove_node)
> -{
> - struct scifmsg notif_msg;
> - struct scif_dev *dev = &scif_dev[node];
> -
> - notif_msg.uop = SCIF_NODE_REMOVE;
> - notif_msg.src.node = scif_info.nodeid;
> - notif_msg.dst.node = node;
> - notif_msg.payload[0] = remove_node;
> - return scif_nodeqp_send(dev, &notif_msg);
> -}
> -
> -/**
> - * scif_node_disconnect
> - *
> - * @node_id: source node id [in]
> - * @mgmt_initiated: Disconnection initiated from the mgmt node
> - *
> - * Disconnect a node from the scif network.
> - */
> -void scif_disconnect_node(u32 node_id, bool mgmt_initiated)
> -{
> - int ret;
> - int msg_cnt = 0;
> - u32 i = 0;
> - struct scif_dev *scifdev = &scif_dev[node_id];
> -
> - if (!node_id)
> - return;
> -
> - atomic_set(&scifdev->disconn_rescnt, 0);
> -
> - /* Destroy p2p network */
> - for (i = 1; i <= scif_info.maxid; i++) {
> - if (i == node_id)
> - continue;
> - ret = scif_send_rmnode_msg(i, node_id);
> - if (!ret)
> - msg_cnt++;
> - }
> - /* Wait for the remote nodes to respond with
> SCIF_NODE_REMOVE_ACK */
> - ret = wait_event_timeout(scifdev->disconn_wq,
> - (atomic_read(&scifdev->disconn_rescnt)
> - == msg_cnt), SCIF_NODE_ALIVE_TIMEOUT);
> - /* Tell the card to clean up */
> - if (mgmt_initiated && _scifdev_alive(scifdev))
> - /*
> - * Send an SCIF_EXIT message which is the last message from
> Host
> - * to the MIC and wait for a SCIF_EXIT_ACK
> - */
> - scif_send_exit(scifdev);
> - atomic_set(&scifdev->disconn_rescnt, 0);
> - /* Tell the mgmt node to clean up */
> - ret = scif_send_rmnode_msg(SCIF_MGMT_NODE, node_id);
> - if (!ret)
> - /* Wait for mgmt node to respond with
> SCIF_NODE_REMOVE_ACK */
> - wait_event_timeout(scifdev->disconn_wq,
> - (atomic_read(&scifdev->disconn_rescnt) ==
> 1),
> - SCIF_NODE_ALIVE_TIMEOUT);
> -}
> -
> -void scif_get_node_info(void)
> -{
> - struct scifmsg msg;
> - DECLARE_COMPLETION_ONSTACK(node_info);
> -
> - msg.uop = SCIF_GET_NODE_INFO;
> - msg.src.node = scif_info.nodeid;
> - msg.dst.node = SCIF_MGMT_NODE;
> - msg.payload[3] = (u64)&node_info;
> -
> - if ((scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg)))
> - return;
> -
> - /* Wait for a response with SCIF_GET_NODE_INFO */
> - wait_for_completion(&node_info);
> -}
> diff --git a/drivers/misc/mic/scif/scif_nodeqp.c
> b/drivers/misc/mic/scif/scif_nodeqp.c
> deleted file mode 100644
> index 384ce08fa98a..000000000000
> --- a/drivers/misc/mic/scif/scif_nodeqp.c
> +++ /dev/null
> @@ -1,1349 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "../bus/scif_bus.h"
> -#include "scif_peer_bus.h"
> -#include "scif_main.h"
> -#include "scif_nodeqp.h"
> -#include "scif_map.h"
> -
> -/*
> -
> ****************************************************************
> ********
> - * SCIF node Queue Pair (QP) setup flow:
> - *
> - * 1) SCIF driver gets probed with a scif_hw_dev via the scif_hw_bus
> - * 2) scif_setup_qp(..) allocates the local qp and calls
> - * scif_setup_qp_connect(..) which allocates and maps the local
> - * buffer for the inbound QP
> - * 3) The local node updates the device page with the DMA address of the
> QP
> - * 4) A delayed work is scheduled (qp_dwork) which periodically reads if
> - * the peer node has updated its QP DMA address
> - * 5) Once a valid non zero address is found in the QP DMA address field
> - * in the device page, the local node maps the remote node's QP,
> - * updates its outbound QP and sends a SCIF_INIT message to the peer
> - * 6) The SCIF_INIT message is received by the peer node QP interrupt
> bottom
> - * half handler by calling scif_init(..)
> - * 7) scif_init(..) registers a new SCIF peer node by calling
> - * scif_peer_register_device(..) which signifies the addition of a new
> - * SCIF node
> - * 8) On the mgmt node, P2P network setup/teardown is initiated if all the
> - * remote nodes are online via scif_p2p_setup(..)
> - * 9) For P2P setup, the host maps the remote nodes' aperture and memory
> - * bars and sends a SCIF_NODE_ADD message to both nodes
> - * 10) As part of scif_nodeadd, both nodes set up their local inbound
> - * QPs and send a SCIF_NODE_ADD_ACK to the mgmt node
> - * 11) As part of scif_node_add_ack(..) the mgmt node forwards the
> - * SCIF_NODE_ADD_ACK to the remote nodes
> - * 12) As part of scif_node_add_ack(..) the remote nodes update their
> - * outbound QPs, make sure they can access memory on the remote
> node
> - * and then add a new SCIF peer node by calling
> - * scif_peer_register_device(..) which signifies the addition of a new
> - * SCIF node.
> - * 13) The SCIF network is now established across all nodes.
> - *
> -
> ****************************************************************
> ********
> - * SCIF node QP teardown flow (initiated by non mgmt node):
> - *
> - * 1) SCIF driver gets a remove callback with a scif_hw_dev via the
> scif_hw_bus
> - * 2) The device page QP DMA address field is updated with 0x0
> - * 3) A non mgmt node now cleans up all local data structures and sends a
> - * SCIF_EXIT message to the peer and waits for a SCIF_EXIT_ACK
> - * 4) As part of scif_exit(..) handling scif_disconnect_node(..) is called
> - * 5) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all
> the
> - * peers and waits for a SCIF_NODE_REMOVE_ACK
> - * 6) As part of scif_node_remove(..) a remote node unregisters the peer
> - * node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
> - * 7) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
> - * it sends itself a node remove message whose handling cleans up local
> - * data structures and unregisters the peer node from the SCIF network
> - * 8) The mgmt node sends a SCIF_EXIT_ACK
> - * 9) Upon receipt of the SCIF_EXIT_ACK the node initiating the teardown
> - * completes the SCIF remove routine
> - * 10) The SCIF network is now torn down for the node initiating the
> - * teardown sequence
> - *
> -
> ****************************************************************
> ********
> - * SCIF node QP teardown flow (initiated by mgmt node):
> - *
> - * 1) SCIF driver gets a remove callback with a scif_hw_dev via the
> scif_hw_bus
> - * 2) The device page QP DMA address field is updated with 0x0
> - * 3) The mgmt node calls scif_disconnect_node(..)
> - * 4) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all
> the peers
> - * and waits for a SCIF_NODE_REMOVE_ACK
> - * 5) As part of scif_node_remove(..) a remote node unregisters the peer
> - * node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
> - * 6) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
> - * it unregisters the peer node from the SCIF network
> - * 7) The mgmt node sends a SCIF_EXIT message and waits for a
> SCIF_EXIT_ACK.
> - * 8) A non mgmt node upon receipt of a SCIF_EXIT message calls scif_stop(..)
> - * which would clean up local data structures for all SCIF nodes and
> - * then send a SCIF_EXIT_ACK back to the mgmt node
> - * 9) Upon receipt of the SCIF_EXIT_ACK the the mgmt node sends itself a
> node
> - * remove message whose handling cleans up local data structures and
> - * destroys any P2P mappings.
> - * 10) The SCIF hardware device for which a remove callback was received is
> now
> - * disconnected from the SCIF network.
> - */
> -/*
> - * Initializes "local" data structures for the QP. Allocates the QP
> - * ring buffer (rb) and initializes the "in bound" queue.
> - */
> -int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
> - int local_size, struct scif_dev *scifdev)
> -{
> - void *local_q = qp->inbound_q.rb_base;
> - int err = 0;
> - u32 tmp_rd = 0;
> -
> - spin_lock_init(&qp->send_lock);
> - spin_lock_init(&qp->recv_lock);
> -
> - /* Allocate rb only if not already allocated */
> - if (!local_q) {
> - local_q = kzalloc(local_size, GFP_KERNEL);
> - if (!local_q) {
> - err = -ENOMEM;
> - return err;
> - }
> - }
> -
> - err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
> - if (err)
> - goto kfree;
> - /*
> - * To setup the inbound_q, the buffer lives locally, the read pointer
> - * is remote and the write pointer is local.
> - */
> - scif_rb_init(&qp->inbound_q,
> - &tmp_rd,
> - &qp->local_write,
> - local_q, get_count_order(local_size));
> - /*
> - * The read pointer is NULL initially and it is unsafe to use the ring
> - * buffer til this changes!
> - */
> - qp->inbound_q.read_ptr = NULL;
> - err = scif_map_single(qp_offset, qp,
> - scifdev, sizeof(struct scif_qp));
> - if (err)
> - goto unmap;
> - qp->local_qp = *qp_offset;
> - return err;
> -unmap:
> - scif_unmap_single(qp->local_buf, scifdev, local_size);
> - qp->local_buf = 0;
> -kfree:
> - kfree(local_q);
> - return err;
> -}
> -
> -/* When the other side has already done it's allocation, this is called */
> -int scif_setup_qp_accept(struct scif_qp *qp, dma_addr_t *qp_offset,
> - dma_addr_t phys, int local_size,
> - struct scif_dev *scifdev)
> -{
> - void *local_q;
> - void *remote_q;
> - struct scif_qp *remote_qp;
> - int remote_size;
> - int err = 0;
> -
> - spin_lock_init(&qp->send_lock);
> - spin_lock_init(&qp->recv_lock);
> - /* Start by figuring out where we need to point */
> - remote_qp = scif_ioremap(phys, sizeof(struct scif_qp), scifdev);
> - if (!remote_qp)
> - return -EIO;
> - qp->remote_qp = remote_qp;
> - if (qp->remote_qp->magic != SCIFEP_MAGIC) {
> - err = -EIO;
> - goto iounmap;
> - }
> - qp->remote_buf = remote_qp->local_buf;
> - remote_size = qp->remote_qp->inbound_q.size;
> - remote_q = scif_ioremap(qp->remote_buf, remote_size, scifdev);
> - if (!remote_q) {
> - err = -EIO;
> - goto iounmap;
> - }
> - qp->remote_qp->local_write = 0;
> - /*
> - * To setup the outbound_q, the buffer lives in remote memory,
> - * the read pointer is local, the write pointer is remote
> - */
> - scif_rb_init(&qp->outbound_q,
> - &qp->local_read,
> - &qp->remote_qp->local_write,
> - remote_q,
> - get_count_order(remote_size));
> - local_q = kzalloc(local_size, GFP_KERNEL);
> - if (!local_q) {
> - err = -ENOMEM;
> - goto iounmap_1;
> - }
> - err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
> - if (err)
> - goto kfree;
> - qp->remote_qp->local_read = 0;
> - /*
> - * To setup the inbound_q, the buffer lives locally, the read pointer
> - * is remote and the write pointer is local
> - */
> - scif_rb_init(&qp->inbound_q,
> - &qp->remote_qp->local_read,
> - &qp->local_write,
> - local_q, get_count_order(local_size));
> - err = scif_map_single(qp_offset, qp, scifdev,
> - sizeof(struct scif_qp));
> - if (err)
> - goto unmap;
> - qp->local_qp = *qp_offset;
> - return err;
> -unmap:
> - scif_unmap_single(qp->local_buf, scifdev, local_size);
> - qp->local_buf = 0;
> -kfree:
> - kfree(local_q);
> -iounmap_1:
> - scif_iounmap(remote_q, remote_size, scifdev);
> - qp->outbound_q.rb_base = NULL;
> -iounmap:
> - scif_iounmap(qp->remote_qp, sizeof(struct scif_qp), scifdev);
> - qp->remote_qp = NULL;
> - return err;
> -}
> -
> -int scif_setup_qp_connect_response(struct scif_dev *scifdev,
> - struct scif_qp *qp, u64 payload)
> -{
> - int err = 0;
> - void *r_buf;
> - int remote_size;
> - phys_addr_t tmp_phys;
> -
> - qp->remote_qp = scif_ioremap(payload, sizeof(struct scif_qp),
> scifdev);
> -
> - if (!qp->remote_qp) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - if (qp->remote_qp->magic != SCIFEP_MAGIC) {
> - dev_err(&scifdev->sdev->dev,
> - "SCIFEP_MAGIC mismatch between self %d
> remote %d\n",
> - scif_dev[scif_info.nodeid].node, scifdev->node);
> - err = -ENODEV;
> - goto error;
> - }
> -
> - tmp_phys = qp->remote_qp->local_buf;
> - remote_size = qp->remote_qp->inbound_q.size;
> - r_buf = scif_ioremap(tmp_phys, remote_size, scifdev);
> -
> - if (!r_buf)
> - return -EIO;
> -
> - qp->local_read = 0;
> - scif_rb_init(&qp->outbound_q,
> - &qp->local_read,
> - &qp->remote_qp->local_write,
> - r_buf,
> - get_count_order(remote_size));
> - /*
> - * Because the node QP may already be processing an INIT message,
> set
> - * the read pointer so the cached read offset isn't lost
> - */
> - qp->remote_qp->local_read = qp->inbound_q.current_read_offset;
> - /*
> - * resetup the inbound_q now that we know where the
> - * inbound_read really is.
> - */
> - scif_rb_init(&qp->inbound_q,
> - &qp->remote_qp->local_read,
> - &qp->local_write,
> - qp->inbound_q.rb_base,
> - get_count_order(qp->inbound_q.size));
> -error:
> - return err;
> -}
> -
> -static __always_inline void
> -scif_send_msg_intr(struct scif_dev *scifdev)
> -{
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - if (scifdev_is_p2p(scifdev))
> - sdev->hw_ops->send_p2p_intr(sdev, scifdev->rdb, &scifdev-
> >mmio);
> - else
> - sdev->hw_ops->send_intr(sdev, scifdev->rdb);
> -}
> -
> -int scif_qp_response(phys_addr_t phys, struct scif_dev *scifdev)
> -{
> - int err = 0;
> - struct scifmsg msg;
> -
> - err = scif_setup_qp_connect_response(scifdev, scifdev->qpairs, phys);
> - if (!err) {
> - /*
> - * Now that everything is setup and mapped, we're ready
> - * to tell the peer about our queue's location
> - */
> - msg.uop = SCIF_INIT;
> - msg.dst.node = scifdev->node;
> - err = scif_nodeqp_send(scifdev, &msg);
> - }
> - return err;
> -}
> -
> -void scif_send_exit(struct scif_dev *scifdev)
> -{
> - struct scifmsg msg;
> - int ret;
> -
> - scifdev->exit = OP_IN_PROGRESS;
> - msg.uop = SCIF_EXIT;
> - msg.src.node = scif_info.nodeid;
> - msg.dst.node = scifdev->node;
> - ret = scif_nodeqp_send(scifdev, &msg);
> - if (ret)
> - goto done;
> - /* Wait for a SCIF_EXIT_ACK message */
> - wait_event_timeout(scif_info.exitwq, scifdev->exit ==
> OP_COMPLETED,
> - SCIF_NODE_ALIVE_TIMEOUT);
> -done:
> - scifdev->exit = OP_IDLE;
> -}
> -
> -int scif_setup_qp(struct scif_dev *scifdev)
> -{
> - int err = 0;
> - int local_size;
> - struct scif_qp *qp;
> -
> - local_size = SCIF_NODE_QP_SIZE;
> -
> - qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> - if (!qp) {
> - err = -ENOMEM;
> - return err;
> - }
> - qp->magic = SCIFEP_MAGIC;
> - scifdev->qpairs = qp;
> - err = scif_setup_qp_connect(qp, &scifdev->qp_dma_addr,
> - local_size, scifdev);
> - if (err)
> - goto free_qp;
> - /*
> - * We're as setup as we can be. The inbound_q is setup, w/o a usable
> - * outbound q. When we get a message, the read_ptr will be
> updated,
> - * and we will pull the message.
> - */
> - return err;
> -free_qp:
> - kfree(scifdev->qpairs);
> - scifdev->qpairs = NULL;
> - return err;
> -}
> -
> -static void scif_p2p_freesg(struct scatterlist *sg)
> -{
> - kfree(sg);
> -}
> -
> -static struct scatterlist *
> -scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt)
> -{
> - struct scatterlist *sg;
> - struct page *page;
> - int i;
> -
> - sg = kmalloc_array(page_cnt, sizeof(struct scatterlist), GFP_KERNEL);
> - if (!sg)
> - return NULL;
> - sg_init_table(sg, page_cnt);
> - for (i = 0; i < page_cnt; i++) {
> - page = pfn_to_page(pa >> PAGE_SHIFT);
> - sg_set_page(&sg[i], page, page_size, 0);
> - pa += page_size;
> - }
> - return sg;
> -}
> -
> -/* Init p2p mappings required to access peerdev from scifdev */
> -static struct scif_p2p_info *
> -scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev)
> -{
> - struct scif_p2p_info *p2p;
> - int num_mmio_pages, num_aper_pages, sg_page_shift, err,
> num_aper_chunks;
> - struct scif_hw_dev *psdev = peerdev->sdev;
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - num_mmio_pages = psdev->mmio->len >> PAGE_SHIFT;
> - num_aper_pages = psdev->aper->len >> PAGE_SHIFT;
> -
> - p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
> - if (!p2p)
> - return NULL;
> - p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa,
> - PAGE_SIZE,
> num_mmio_pages);
> - if (!p2p->ppi_sg[SCIF_PPI_MMIO])
> - goto free_p2p;
> - p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
> - sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
> - num_aper_chunks = num_aper_pages >> (sg_page_shift -
> PAGE_SHIFT);
> - p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa,
> - 1 << sg_page_shift,
> - num_aper_chunks);
> - p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;
> - err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
> - num_mmio_pages, PCI_DMA_BIDIRECTIONAL);
> - if (err != num_mmio_pages)
> - goto scif_p2p_free;
> - err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
> - num_aper_chunks, PCI_DMA_BIDIRECTIONAL);
> - if (err != num_aper_chunks)
> - goto dma_unmap;
> - p2p->ppi_da[SCIF_PPI_MMIO] = sg_dma_address(p2p-
> >ppi_sg[SCIF_PPI_MMIO]);
> - p2p->ppi_da[SCIF_PPI_APER] = sg_dma_address(p2p-
> >ppi_sg[SCIF_PPI_APER]);
> - p2p->ppi_len[SCIF_PPI_MMIO] = num_mmio_pages;
> - p2p->ppi_len[SCIF_PPI_APER] = num_aper_pages;
> - p2p->ppi_peer_id = peerdev->node;
> - return p2p;
> -dma_unmap:
> - dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
> - p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
> -scif_p2p_free:
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
> -free_p2p:
> - kfree(p2p);
> - return NULL;
> -}
> -
> -/* Uninitialize and release resources from a p2p mapping */
> -static void scif_deinit_p2p_info(struct scif_dev *scifdev,
> - struct scif_p2p_info *p2p)
> -{
> - struct scif_hw_dev *sdev = scifdev->sdev;
> -
> - dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
> - p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
> - dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
> - p2p->sg_nentries[SCIF_PPI_APER], DMA_BIDIRECTIONAL);
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
> - kfree(p2p);
> -}
> -
> -/**
> - * scif_node_connect: Respond to SCIF_NODE_CONNECT interrupt message
> - * @scifdev: SCIF device
> - * @dst: Destination node
> - *
> - * Connect the src and dst node by setting up the p2p connection
> - * between them. Management node here acts like a proxy.
> - */
> -static void scif_node_connect(struct scif_dev *scifdev, int dst)
> -{
> - struct scif_dev *dev_j = scifdev;
> - struct scif_dev *dev_i = NULL;
> - struct scif_p2p_info *p2p_ij = NULL; /* bus addr for j from i */
> - struct scif_p2p_info *p2p_ji = NULL; /* bus addr for i from j */
> - struct scif_p2p_info *p2p;
> - struct list_head *pos, *tmp;
> - struct scifmsg msg;
> - int err;
> - u64 tmppayload;
> -
> - if (dst < 1 || dst > scif_info.maxid)
> - return;
> -
> - dev_i = &scif_dev[dst];
> -
> - if (!_scifdev_alive(dev_i))
> - return;
> - /*
> - * If the p2p connection is already setup or in the process of setting
> - * up then just ignore this request. The requested node will get
> - * informed by SCIF_NODE_ADD_ACK or SCIF_NODE_ADD_NACK
> - */
> - if (!list_empty(&dev_i->p2p)) {
> - list_for_each_safe(pos, tmp, &dev_i->p2p) {
> - p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
> - if (p2p->ppi_peer_id == dev_j->node)
> - return;
> - }
> - }
> - p2p_ij = scif_init_p2p_info(dev_i, dev_j);
> - if (!p2p_ij)
> - return;
> - p2p_ji = scif_init_p2p_info(dev_j, dev_i);
> - if (!p2p_ji) {
> - scif_deinit_p2p_info(dev_i, p2p_ij);
> - return;
> - }
> - list_add_tail(&p2p_ij->ppi_list, &dev_i->p2p);
> - list_add_tail(&p2p_ji->ppi_list, &dev_j->p2p);
> -
> - /*
> - * Send a SCIF_NODE_ADD to dev_i, pass it its bus address
> - * as seen from dev_j
> - */
> - msg.uop = SCIF_NODE_ADD;
> - msg.src.node = dev_j->node;
> - msg.dst.node = dev_i->node;
> -
> - msg.payload[0] = p2p_ji->ppi_da[SCIF_PPI_APER];
> - msg.payload[1] = p2p_ij->ppi_da[SCIF_PPI_MMIO];
> - msg.payload[2] = p2p_ij->ppi_da[SCIF_PPI_APER];
> - msg.payload[3] = p2p_ij->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
> -
> - err = scif_nodeqp_send(dev_i, &msg);
> - if (err) {
> - dev_err(&scifdev->sdev->dev,
> - "%s %d error %d\n", __func__, __LINE__, err);
> - return;
> - }
> -
> - /* Same as above but to dev_j */
> - msg.uop = SCIF_NODE_ADD;
> - msg.src.node = dev_i->node;
> - msg.dst.node = dev_j->node;
> -
> - tmppayload = msg.payload[0];
> - msg.payload[0] = msg.payload[2];
> - msg.payload[2] = tmppayload;
> - msg.payload[1] = p2p_ji->ppi_da[SCIF_PPI_MMIO];
> - msg.payload[3] = p2p_ji->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
> -
> - scif_nodeqp_send(dev_j, &msg);
> -}
> -
> -static void scif_p2p_setup(void)
> -{
> - int i, j;
> -
> - if (!scif_info.p2p_enable)
> - return;
> -
> - for (i = 1; i <= scif_info.maxid; i++)
> - if (!_scifdev_alive(&scif_dev[i]))
> - return;
> -
> - for (i = 1; i <= scif_info.maxid; i++) {
> - for (j = 1; j <= scif_info.maxid; j++) {
> - struct scif_dev *scifdev = &scif_dev[i];
> -
> - if (i == j)
> - continue;
> - scif_node_connect(scifdev, j);
> - }
> - }
> -}
> -
> -static char *message_types[] = {"BAD",
> - "INIT",
> - "EXIT",
> - "SCIF_EXIT_ACK",
> - "SCIF_NODE_ADD",
> - "SCIF_NODE_ADD_ACK",
> - "SCIF_NODE_ADD_NACK",
> - "REMOVE_NODE",
> - "REMOVE_NODE_ACK",
> - "CNCT_REQ",
> - "CNCT_GNT",
> - "CNCT_GNTACK",
> - "CNCT_GNTNACK",
> - "CNCT_REJ",
> - "DISCNCT",
> - "DISCNT_ACK",
> - "CLIENT_SENT",
> - "CLIENT_RCVD",
> - "SCIF_GET_NODE_INFO",
> - "REGISTER",
> - "REGISTER_ACK",
> - "REGISTER_NACK",
> - "UNREGISTER",
> - "UNREGISTER_ACK",
> - "UNREGISTER_NACK",
> - "ALLOC_REQ",
> - "ALLOC_GNT",
> - "ALLOC_REJ",
> - "FREE_PHYS",
> - "FREE_VIRT",
> - "MUNMAP",
> - "MARK",
> - "MARK_ACK",
> - "MARK_NACK",
> - "WAIT",
> - "WAIT_ACK",
> - "WAIT_NACK",
> - "SIGNAL_LOCAL",
> - "SIGNAL_REMOTE",
> - "SIG_ACK",
> - "SIG_NACK"};
> -
> -static void
> -scif_display_message(struct scif_dev *scifdev, struct scifmsg *msg,
> - const char *label)
> -{
> - if (!scif_info.en_msg_log)
> - return;
> - if (msg->uop > SCIF_MAX_MSG) {
> - dev_err(&scifdev->sdev->dev,
> - "%s: unknown msg type %d\n", label, msg->uop);
> - return;
> - }
> - dev_info(&scifdev->sdev->dev,
> - "%s: msg type %s, src %d:%d, dest %d:%d payload
> 0x%llx:0x%llx:0x%llx:0x%llx\n",
> - label, message_types[msg->uop], msg->src.node, msg-
> >src.port,
> - msg->dst.node, msg->dst.port, msg->payload[0], msg-
> >payload[1],
> - msg->payload[2], msg->payload[3]);
> -}
> -
> -int _scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_qp *qp = scifdev->qpairs;
> - int err = -ENOMEM, loop_cnt = 0;
> -
> - scif_display_message(scifdev, msg, "Sent");
> - if (!qp) {
> - err = -EINVAL;
> - goto error;
> - }
> - spin_lock(&qp->send_lock);
> -
> - while ((err = scif_rb_write(&qp->outbound_q,
> - msg, sizeof(struct scifmsg)))) {
> - mdelay(1);
> -#define SCIF_NODEQP_SEND_TO_MSEC (3 * 1000)
> - if (loop_cnt++ > (SCIF_NODEQP_SEND_TO_MSEC)) {
> - err = -ENODEV;
> - break;
> - }
> - }
> - if (!err)
> - scif_rb_commit(&qp->outbound_q);
> - spin_unlock(&qp->send_lock);
> - if (!err) {
> - if (scifdev_self(scifdev))
> - /*
> - * For loopback we need to emulate an interrupt by
> - * queuing work for the queue handling real node
> - * Qp interrupts.
> - */
> - queue_work(scifdev->intr_wq, &scifdev->intr_bh);
> - else
> - scif_send_msg_intr(scifdev);
> - }
> -error:
> - if (err)
> - dev_dbg(&scifdev->sdev->dev,
> - "%s %d error %d uop %d\n",
> - __func__, __LINE__, err, msg->uop);
> - return err;
> -}
> -
> -/**
> - * scif_nodeqp_send - Send a message on the node queue pair
> - * @scifdev: Scif Device.
> - * @msg: The message to be sent.
> - */
> -int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - int err;
> - struct device *spdev = NULL;
> -
> - if (msg->uop > SCIF_EXIT_ACK) {
> - /* Don't send messages once the exit flow has begun */
> - if (OP_IDLE != scifdev->exit)
> - return -ENODEV;
> - spdev = scif_get_peer_dev(scifdev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - return err;
> - }
> - }
> - err = _scif_nodeqp_send(scifdev, msg);
> - if (msg->uop > SCIF_EXIT_ACK)
> - scif_put_peer_dev(spdev);
> - return err;
> -}
> -
> -/*
> - * scif_misc_handler:
> - *
> - * Work queue handler for servicing miscellaneous SCIF tasks.
> - * Examples include:
> - * 1) Remote fence requests.
> - * 2) Destruction of temporary registered windows
> - * created during scif_vreadfrom()/scif_vwriteto().
> - * 3) Cleanup of zombie endpoints.
> - */
> -void scif_misc_handler(struct work_struct *work)
> -{
> - scif_rma_handle_remote_fences();
> - scif_rma_destroy_windows();
> - scif_rma_destroy_tcw_invalid();
> - scif_cleanup_zombie_epd();
> -}
> -
> -/**
> - * scif_init() - Respond to SCIF_INIT interrupt message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - */
> -static __always_inline void
> -scif_init(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - /*
> - * Allow the thread waiting for device page updates for the peer QP
> DMA
> - * address to complete initializing the inbound_q.
> - */
> - flush_delayed_work(&scifdev->qp_dwork);
> -
> - scif_peer_register_device(scifdev);
> -
> - if (scif_is_mgmt_node()) {
> - mutex_lock(&scif_info.conflock);
> - scif_p2p_setup();
> - mutex_unlock(&scif_info.conflock);
> - }
> -}
> -
> -/**
> - * scif_exit() - Respond to SCIF_EXIT interrupt message
> - * @scifdev: Remote SCIF device node
> - * @unused: Interrupt message (unused)
> - *
> - * This function stops the SCIF interface for the node which sent
> - * the SCIF_EXIT message and starts waiting for that node to
> - * resetup the queue pair again.
> - */
> -static __always_inline void
> -scif_exit(struct scif_dev *scifdev, struct scifmsg *unused)
> -{
> - scifdev->exit_ack_pending = true;
> - if (scif_is_mgmt_node())
> - scif_disconnect_node(scifdev->node, false);
> - else
> - scif_stop(scifdev);
> - schedule_delayed_work(&scifdev->qp_dwork,
> - msecs_to_jiffies(1000));
> -}
> -
> -/**
> - * scif_exitack() - Respond to SCIF_EXIT_ACK interrupt message
> - * @scifdev: Remote SCIF device node
> - * @unused: Interrupt message (unused)
> - *
> - */
> -static __always_inline void
> -scif_exit_ack(struct scif_dev *scifdev, struct scifmsg *unused)
> -{
> - scifdev->exit = OP_COMPLETED;
> - wake_up(&scif_info.exitwq);
> -}
> -
> -/**
> - * scif_node_add() - Respond to SCIF_NODE_ADD interrupt message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * When the mgmt node driver has finished initializing a MIC node queue
> pair it
> - * marks the node as online. It then looks for all currently online MIC cards
> - * and send a SCIF_NODE_ADD message to identify the ID of the new card
> for
> - * peer to peer initialization
> - *
> - * The local node allocates its incoming queue and sends its address in the
> - * SCIF_NODE_ADD_ACK message back to the mgmt node, the mgmt node
> "reflects"
> - * this message to the new node
> - */
> -static __always_inline void
> -scif_node_add(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_dev *newdev;
> - dma_addr_t qp_offset;
> - int qp_connect;
> - struct scif_hw_dev *sdev;
> -
> - dev_dbg(&scifdev->sdev->dev,
> - "Scifdev %d:%d received NODE_ADD msg for node %d\n",
> - scifdev->node, msg->dst.node, msg->src.node);
> - dev_dbg(&scifdev->sdev->dev,
> - "Remote address for this node's aperture %llx\n",
> - msg->payload[0]);
> - newdev = &scif_dev[msg->src.node];
> - newdev->node = msg->src.node;
> - newdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
> - sdev = newdev->sdev;
> -
> - if (scif_setup_intr_wq(newdev)) {
> - dev_err(&scifdev->sdev->dev,
> - "failed to setup interrupts for %d\n", msg->src.node);
> - goto interrupt_setup_error;
> - }
> - newdev->mmio.va = ioremap(msg->payload[1], sdev->mmio->len);
> - if (!newdev->mmio.va) {
> - dev_err(&scifdev->sdev->dev,
> - "failed to map mmio for %d\n", msg->src.node);
> - goto mmio_map_error;
> - }
> - newdev->qpairs = kzalloc(sizeof(*newdev->qpairs), GFP_KERNEL);
> - if (!newdev->qpairs)
> - goto qp_alloc_error;
> - /*
> - * Set the base address of the remote node's memory since it gets
> - * added to qp_offset
> - */
> - newdev->base_addr = msg->payload[0];
> -
> - qp_connect = scif_setup_qp_connect(newdev->qpairs, &qp_offset,
> - SCIF_NODE_QP_SIZE, newdev);
> - if (qp_connect) {
> - dev_err(&scifdev->sdev->dev,
> - "failed to setup qp_connect %d\n", qp_connect);
> - goto qp_connect_error;
> - }
> -
> - newdev->db = sdev->hw_ops->next_db(sdev);
> - newdev->cookie = sdev->hw_ops->request_irq(sdev,
> scif_intr_handler,
> - "SCIF_INTR", newdev,
> - newdev->db);
> - if (IS_ERR(newdev->cookie))
> - goto qp_connect_error;
> - newdev->qpairs->magic = SCIFEP_MAGIC;
> - newdev->qpairs->qp_state = SCIF_QP_OFFLINE;
> -
> - msg->uop = SCIF_NODE_ADD_ACK;
> - msg->dst.node = msg->src.node;
> - msg->src.node = scif_info.nodeid;
> - msg->payload[0] = qp_offset;
> - msg->payload[2] = newdev->db;
> - scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
> - return;
> -qp_connect_error:
> - kfree(newdev->qpairs);
> - newdev->qpairs = NULL;
> -qp_alloc_error:
> - iounmap(newdev->mmio.va);
> - newdev->mmio.va = NULL;
> -mmio_map_error:
> -interrupt_setup_error:
> - dev_err(&scifdev->sdev->dev,
> - "node add failed for node %d\n", msg->src.node);
> - msg->uop = SCIF_NODE_ADD_NACK;
> - msg->dst.node = msg->src.node;
> - msg->src.node = scif_info.nodeid;
> - scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
> -}
> -
> -void scif_poll_qp_state(struct work_struct *work)
> -{
> -#define SCIF_NODE_QP_RETRY 100
> -#define SCIF_NODE_QP_TIMEOUT 100
> - struct scif_dev *peerdev = container_of(work, struct scif_dev,
> - p2p_dwork.work);
> - struct scif_qp *qp = &peerdev->qpairs[0];
> -
> - if (qp->qp_state != SCIF_QP_ONLINE ||
> - qp->remote_qp->qp_state != SCIF_QP_ONLINE) {
> - if (peerdev->p2p_retry++ == SCIF_NODE_QP_RETRY) {
> - dev_err(&peerdev->sdev->dev,
> - "Warning: QP check timeout with state %d\n",
> - qp->qp_state);
> - goto timeout;
> - }
> - schedule_delayed_work(&peerdev->p2p_dwork,
> -
> msecs_to_jiffies(SCIF_NODE_QP_TIMEOUT));
> - return;
> - }
> - return;
> -timeout:
> - dev_err(&peerdev->sdev->dev,
> - "%s %d remote node %d offline, state = 0x%x\n",
> - __func__, __LINE__, peerdev->node, qp->qp_state);
> - qp->remote_qp->qp_state = SCIF_QP_OFFLINE;
> - scif_peer_unregister_device(peerdev);
> - scif_cleanup_scifdev(peerdev);
> -}
> -
> -/**
> - * scif_node_add_ack() - Respond to SCIF_NODE_ADD_ACK interrupt
> message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * After a MIC node receives the SCIF_NODE_ADD_ACK message it send this
> - * message to the mgmt node to confirm the sequence is finished.
> - *
> - */
> -static __always_inline void
> -scif_node_add_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_dev *peerdev;
> - struct scif_qp *qp;
> - struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
> -
> - dev_dbg(&scifdev->sdev->dev,
> - "Scifdev %d received SCIF_NODE_ADD_ACK msg src %d
> dst %d\n",
> - scifdev->node, msg->src.node, msg->dst.node);
> - dev_dbg(&scifdev->sdev->dev,
> - "payload %llx %llx %llx %llx\n", msg->payload[0],
> - msg->payload[1], msg->payload[2], msg->payload[3]);
> - if (scif_is_mgmt_node()) {
> - /*
> - * the lock serializes with scif_qp_response_ack. The mgmt
> node
> - * is forwarding the NODE_ADD_ACK message from src to dst
> we
> - * need to make sure that the dst has already received a
> - * NODE_ADD for src and setup its end of the qp to dst
> - */
> - mutex_lock(&scif_info.conflock);
> - msg->payload[1] = scif_info.maxid;
> - scif_nodeqp_send(dst_dev, msg);
> - mutex_unlock(&scif_info.conflock);
> - return;
> - }
> - peerdev = &scif_dev[msg->src.node];
> - peerdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
> - peerdev->node = msg->src.node;
> -
> - qp = &peerdev->qpairs[0];
> -
> - if ((scif_setup_qp_connect_response(peerdev, &peerdev->qpairs[0],
> - msg->payload[0])))
> - goto local_error;
> - peerdev->rdb = msg->payload[2];
> - qp->remote_qp->qp_state = SCIF_QP_ONLINE;
> -
> - scif_peer_register_device(peerdev);
> -
> - schedule_delayed_work(&peerdev->p2p_dwork, 0);
> - return;
> -local_error:
> - scif_cleanup_scifdev(peerdev);
> -}
> -
> -/**
> - * scif_node_add_nack: Respond to SCIF_NODE_ADD_NACK interrupt
> message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * SCIF_NODE_ADD failed, so inform the waiting wq.
> - */
> -static __always_inline void
> -scif_node_add_nack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - if (scif_is_mgmt_node()) {
> - struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
> -
> - dev_dbg(&scifdev->sdev->dev,
> - "SCIF_NODE_ADD_NACK received from %d\n",
> scifdev->node);
> - scif_nodeqp_send(dst_dev, msg);
> - }
> -}
> -
> -/**
> - * scif_node_remove: Handle SCIF_NODE_REMOVE message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * Handle node removal.
> - */
> -static __always_inline void
> -scif_node_remove(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - int node = msg->payload[0];
> - struct scif_dev *scdev = &scif_dev[node];
> -
> - scdev->node_remove_ack_pending = true;
> - scif_handle_remove_node(node);
> -}
> -
> -/**
> - * scif_node_remove_ack: Handle SCIF_NODE_REMOVE_ACK message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * The peer has acked a SCIF_NODE_REMOVE message.
> - */
> -static __always_inline void
> -scif_node_remove_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_dev *sdev = &scif_dev[msg->payload[0]];
> -
> - atomic_inc(&sdev->disconn_rescnt);
> - wake_up(&sdev->disconn_wq);
> -}
> -
> -/**
> - * scif_get_node_info: Respond to SCIF_GET_NODE_INFO interrupt message
> - * @scifdev: Remote SCIF device node
> - * @msg: Interrupt message
> - *
> - * Retrieve node info i.e maxid and total from the mgmt node.
> - */
> -static __always_inline void
> -scif_get_node_info_resp(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - if (scif_is_mgmt_node()) {
> - swap(msg->dst.node, msg->src.node);
> - mutex_lock(&scif_info.conflock);
> - msg->payload[1] = scif_info.maxid;
> - msg->payload[2] = scif_info.total;
> - mutex_unlock(&scif_info.conflock);
> - scif_nodeqp_send(scifdev, msg);
> - } else {
> - struct completion *node_info =
> - (struct completion *)msg->payload[3];
> -
> - mutex_lock(&scif_info.conflock);
> - scif_info.maxid = msg->payload[1];
> - scif_info.total = msg->payload[2];
> - complete_all(node_info);
> - mutex_unlock(&scif_info.conflock);
> - }
> -}
> -
> -static void
> -scif_msg_unknown(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - /* Bogus Node Qp Message? */
> - dev_err(&scifdev->sdev->dev,
> - "Unknown message 0x%xn scifdev->node 0x%x\n",
> - msg->uop, scifdev->node);
> -}
> -
> -static void (*scif_intr_func[SCIF_MAX_MSG + 1])
> - (struct scif_dev *, struct scifmsg *msg) = {
> - scif_msg_unknown, /* Error */
> - scif_init, /* SCIF_INIT */
> - scif_exit, /* SCIF_EXIT */
> - scif_exit_ack, /* SCIF_EXIT_ACK */
> - scif_node_add, /* SCIF_NODE_ADD */
> - scif_node_add_ack, /* SCIF_NODE_ADD_ACK */
> - scif_node_add_nack, /* SCIF_NODE_ADD_NACK */
> - scif_node_remove, /* SCIF_NODE_REMOVE */
> - scif_node_remove_ack, /* SCIF_NODE_REMOVE_ACK */
> - scif_cnctreq, /* SCIF_CNCT_REQ */
> - scif_cnctgnt, /* SCIF_CNCT_GNT */
> - scif_cnctgnt_ack, /* SCIF_CNCT_GNTACK */
> - scif_cnctgnt_nack, /* SCIF_CNCT_GNTNACK */
> - scif_cnctrej, /* SCIF_CNCT_REJ */
> - scif_discnct, /* SCIF_DISCNCT */
> - scif_discnt_ack, /* SCIF_DISCNT_ACK */
> - scif_clientsend, /* SCIF_CLIENT_SENT */
> - scif_clientrcvd, /* SCIF_CLIENT_RCVD */
> - scif_get_node_info_resp,/* SCIF_GET_NODE_INFO */
> - scif_recv_reg, /* SCIF_REGISTER */
> - scif_recv_reg_ack, /* SCIF_REGISTER_ACK */
> - scif_recv_reg_nack, /* SCIF_REGISTER_NACK */
> - scif_recv_unreg, /* SCIF_UNREGISTER */
> - scif_recv_unreg_ack, /* SCIF_UNREGISTER_ACK */
> - scif_recv_unreg_nack, /* SCIF_UNREGISTER_NACK */
> - scif_alloc_req, /* SCIF_ALLOC_REQ */
> - scif_alloc_gnt_rej, /* SCIF_ALLOC_GNT */
> - scif_alloc_gnt_rej, /* SCIF_ALLOC_REJ */
> - scif_free_virt, /* SCIF_FREE_VIRT */
> - scif_recv_munmap, /* SCIF_MUNMAP */
> - scif_recv_mark, /* SCIF_MARK */
> - scif_recv_mark_resp, /* SCIF_MARK_ACK */
> - scif_recv_mark_resp, /* SCIF_MARK_NACK */
> - scif_recv_wait, /* SCIF_WAIT */
> - scif_recv_wait_resp, /* SCIF_WAIT_ACK */
> - scif_recv_wait_resp, /* SCIF_WAIT_NACK */
> - scif_recv_sig_local, /* SCIF_SIG_LOCAL */
> - scif_recv_sig_remote, /* SCIF_SIG_REMOTE */
> - scif_recv_sig_resp, /* SCIF_SIG_ACK */
> - scif_recv_sig_resp, /* SCIF_SIG_NACK */
> -};
> -
> -static int scif_max_msg_id = SCIF_MAX_MSG;
> -/**
> - * scif_nodeqp_msg_handler() - Common handler for node messages
> - * @scifdev: Remote device to respond to
> - * @qp: Remote memory pointer
> - * @msg: The message to be handled.
> - *
> - * This routine calls the appropriate routine to handle a Node Qp
> - * message receipt
> - */
> -static void
> -scif_nodeqp_msg_handler(struct scif_dev *scifdev,
> - struct scif_qp *qp, struct scifmsg *msg)
> -{
> - scif_display_message(scifdev, msg, "Rcvd");
> -
> - if (msg->uop > (u32)scif_max_msg_id) {
> - /* Bogus Node Qp Message? */
> - dev_err(&scifdev->sdev->dev,
> - "Unknown message 0x%xn scifdev->node 0x%x\n",
> - msg->uop, scifdev->node);
> - return;
> - }
> -
> - scif_intr_func[msg->uop](scifdev, msg);
> -}
> -
> -/**
> - * scif_nodeqp_intrhandler() - Interrupt handler for node messages
> - * @scifdev: Remote device to respond to
> - * @qp: Remote memory pointer
> - *
> - * This routine is triggered by the interrupt mechanism. It reads
> - * messages from the node queue RB and calls the Node QP Message
> handling
> - * routine.
> - */
> -void scif_nodeqp_intrhandler(struct scif_dev *scifdev, struct scif_qp *qp)
> -{
> - struct scifmsg msg;
> - int read_size;
> -
> - do {
> - read_size = scif_rb_get_next(&qp->inbound_q, &msg,
> sizeof(msg));
> - if (!read_size)
> - break;
> - scif_nodeqp_msg_handler(scifdev, qp, &msg);
> - /*
> - * The node queue pair is unmapped so skip the read pointer
> - * update after receipt of a SCIF_EXIT_ACK
> - */
> - if (SCIF_EXIT_ACK == msg.uop)
> - break;
> - scif_rb_update_read_ptr(&qp->inbound_q);
> - } while (1);
> -}
> -
> -/**
> - * scif_loopb_wq_handler - Loopback Workqueue Handler.
> - * @unused: loop back work (unused)
> - *
> - * This work queue routine is invoked by the loopback work queue handler.
> - * It grabs the recv lock, dequeues any available messages from the head
> - * of the loopback message list, calls the node QP message handler,
> - * waits for it to return, then frees up this message and dequeues more
> - * elements of the list if available.
> - */
> -static void scif_loopb_wq_handler(struct work_struct *unused)
> -{
> - struct scif_dev *scifdev = scif_info.loopb_dev;
> - struct scif_qp *qp = scifdev->qpairs;
> - struct scif_loopb_msg *msg;
> -
> - do {
> - msg = NULL;
> - spin_lock(&qp->recv_lock);
> - if (!list_empty(&scif_info.loopb_recv_q)) {
> - msg = list_first_entry(&scif_info.loopb_recv_q,
> - struct scif_loopb_msg,
> - list);
> - list_del(&msg->list);
> - }
> - spin_unlock(&qp->recv_lock);
> -
> - if (msg) {
> - scif_nodeqp_msg_handler(scifdev, qp, &msg->msg);
> - kfree(msg);
> - }
> - } while (msg);
> -}
> -
> -/**
> - * scif_loopb_msg_handler() - Workqueue handler for loopback messages.
> - * @scifdev: SCIF device
> - * @qp: Queue pair.
> - *
> - * This work queue routine is triggered when a loopback message is received.
> - *
> - * We need special handling for receiving Node Qp messages on a loopback
> SCIF
> - * device via two workqueues for receiving messages.
> - *
> - * The reason we need the extra workqueue which is not required with
> *normal*
> - * non-loopback SCIF devices is the potential classic deadlock described
> below:
> - *
> - * Thread A tries to send a message on a loopback SCIF device and blocks
> since
> - * there is no space in the RB while it has the send_lock held or another
> - * lock called lock X for example.
> - *
> - * Thread B: The Loopback Node QP message receive workqueue receives
> the message
> - * and tries to send a message (eg an ACK) to the loopback SCIF device. It
> tries
> - * to grab the send lock again or lock X and deadlocks with Thread A. The RB
> - * cannot be drained any further due to this classic deadlock.
> - *
> - * In order to avoid deadlocks as mentioned above we have an extra level of
> - * indirection achieved by having two workqueues.
> - * 1) The first workqueue whose handler is scif_loopb_msg_handler reads
> - * messages from the Node QP RB, adds them to a list and queues work for
> the
> - * second workqueue.
> - *
> - * 2) The second workqueue whose handler is scif_loopb_wq_handler
> dequeues
> - * messages from the list, handles them, frees up the memory and
> dequeues
> - * more elements from the list if possible.
> - */
> -int
> -scif_loopb_msg_handler(struct scif_dev *scifdev, struct scif_qp *qp)
> -{
> - int read_size;
> - struct scif_loopb_msg *msg;
> -
> - do {
> - msg = kmalloc(sizeof(*msg), GFP_KERNEL);
> - if (!msg)
> - return -ENOMEM;
> - read_size = scif_rb_get_next(&qp->inbound_q, &msg->msg,
> - sizeof(struct scifmsg));
> - if (read_size != sizeof(struct scifmsg)) {
> - kfree(msg);
> - scif_rb_update_read_ptr(&qp->inbound_q);
> - break;
> - }
> - spin_lock(&qp->recv_lock);
> - list_add_tail(&msg->list, &scif_info.loopb_recv_q);
> - spin_unlock(&qp->recv_lock);
> - queue_work(scif_info.loopb_wq, &scif_info.loopb_work);
> - scif_rb_update_read_ptr(&qp->inbound_q);
> - } while (read_size == sizeof(struct scifmsg));
> - return read_size;
> -}
> -
> -/**
> - * scif_setup_loopback_qp - One time setup work for Loopback Node Qp.
> - * @scifdev: SCIF device
> - *
> - * Sets up the required loopback workqueues, queue pairs and ring buffers
> - */
> -int scif_setup_loopback_qp(struct scif_dev *scifdev)
> -{
> - int err = 0;
> - void *local_q;
> - struct scif_qp *qp;
> -
> - err = scif_setup_intr_wq(scifdev);
> - if (err)
> - goto exit;
> - INIT_LIST_HEAD(&scif_info.loopb_recv_q);
> - snprintf(scif_info.loopb_wqname, sizeof(scif_info.loopb_wqname),
> - "SCIF LOOPB %d", scifdev->node);
> - scif_info.loopb_wq =
> - alloc_ordered_workqueue(scif_info.loopb_wqname, 0);
> - if (!scif_info.loopb_wq) {
> - err = -ENOMEM;
> - goto destroy_intr;
> - }
> - INIT_WORK(&scif_info.loopb_work, scif_loopb_wq_handler);
> - /* Allocate Self Qpair */
> - scifdev->qpairs = kzalloc(sizeof(*scifdev->qpairs), GFP_KERNEL);
> - if (!scifdev->qpairs) {
> - err = -ENOMEM;
> - goto destroy_loopb_wq;
> - }
> -
> - qp = scifdev->qpairs;
> - qp->magic = SCIFEP_MAGIC;
> - spin_lock_init(&qp->send_lock);
> - spin_lock_init(&qp->recv_lock);
> -
> - local_q = kzalloc(SCIF_NODE_QP_SIZE, GFP_KERNEL);
> - if (!local_q) {
> - err = -ENOMEM;
> - goto free_qpairs;
> - }
> - /*
> - * For loopback the inbound_q and outbound_q are essentially the
> same
> - * since the Node sends a message on the loopback interface to the
> - * outbound_q which is then received on the inbound_q.
> - */
> - scif_rb_init(&qp->outbound_q,
> - &qp->local_read,
> - &qp->local_write,
> - local_q, get_count_order(SCIF_NODE_QP_SIZE));
> -
> - scif_rb_init(&qp->inbound_q,
> - &qp->local_read,
> - &qp->local_write,
> - local_q, get_count_order(SCIF_NODE_QP_SIZE));
> - scif_info.nodeid = scifdev->node;
> -
> - scif_peer_register_device(scifdev);
> -
> - scif_info.loopb_dev = scifdev;
> - return err;
> -free_qpairs:
> - kfree(scifdev->qpairs);
> -destroy_loopb_wq:
> - destroy_workqueue(scif_info.loopb_wq);
> -destroy_intr:
> - scif_destroy_intr_wq(scifdev);
> -exit:
> - return err;
> -}
> -
> -/**
> - * scif_destroy_loopback_qp - One time uninit work for Loopback Node Qp
> - * @scifdev: SCIF device
> - *
> - * Destroys the workqueues and frees up the Ring Buffer and Queue Pair
> memory.
> - */
> -int scif_destroy_loopback_qp(struct scif_dev *scifdev)
> -{
> - scif_peer_unregister_device(scifdev);
> - destroy_workqueue(scif_info.loopb_wq);
> - scif_destroy_intr_wq(scifdev);
> - kfree(scifdev->qpairs->outbound_q.rb_base);
> - kfree(scifdev->qpairs);
> - scifdev->sdev = NULL;
> - scif_info.loopb_dev = NULL;
> - return 0;
> -}
> -
> -void scif_destroy_p2p(struct scif_dev *scifdev)
> -{
> - struct scif_dev *peer_dev;
> - struct scif_p2p_info *p2p;
> - struct list_head *pos, *tmp;
> - int bd;
> -
> - mutex_lock(&scif_info.conflock);
> - /* Free P2P mappings in the given node for all its peer nodes */
> - list_for_each_safe(pos, tmp, &scifdev->p2p) {
> - p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
> - dma_unmap_sg(&scifdev->sdev->dev, p2p-
> >ppi_sg[SCIF_PPI_MMIO],
> - p2p->sg_nentries[SCIF_PPI_MMIO],
> - DMA_BIDIRECTIONAL);
> - dma_unmap_sg(&scifdev->sdev->dev, p2p-
> >ppi_sg[SCIF_PPI_APER],
> - p2p->sg_nentries[SCIF_PPI_APER],
> - DMA_BIDIRECTIONAL);
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
> - scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
> - list_del(pos);
> - kfree(p2p);
> - }
> -
> - /* Free P2P mapping created in the peer nodes for the given node */
> - for (bd = SCIF_MGMT_NODE + 1; bd <= scif_info.maxid; bd++) {
> - peer_dev = &scif_dev[bd];
> - list_for_each_safe(pos, tmp, &peer_dev->p2p) {
> - p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
> - if (p2p->ppi_peer_id == scifdev->node) {
> - dma_unmap_sg(&peer_dev->sdev->dev,
> - p2p->ppi_sg[SCIF_PPI_MMIO],
> - p2p->sg_nentries[SCIF_PPI_MMIO],
> - DMA_BIDIRECTIONAL);
> - dma_unmap_sg(&peer_dev->sdev->dev,
> - p2p->ppi_sg[SCIF_PPI_APER],
> - p2p->sg_nentries[SCIF_PPI_APER],
> - DMA_BIDIRECTIONAL);
> - scif_p2p_freesg(p2p-
> >ppi_sg[SCIF_PPI_MMIO]);
> - scif_p2p_freesg(p2p-
> >ppi_sg[SCIF_PPI_APER]);
> - list_del(pos);
> - kfree(p2p);
> - }
> - }
> - }
> - mutex_unlock(&scif_info.conflock);
> -}
> diff --git a/drivers/misc/mic/scif/scif_nodeqp.h
> b/drivers/misc/mic/scif/scif_nodeqp.h
> deleted file mode 100644
> index 95896273138e..000000000000
> --- a/drivers/misc/mic/scif/scif_nodeqp.h
> +++ /dev/null
> @@ -1,221 +0,0 @@
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * This file is provided under a dual BSD/GPLv2 license. When using or
> - * redistributing this file, you may do so under either license.
> - *
> - * GPL LICENSE SUMMARY
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * BSD LICENSE
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - * * Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in
> - * the documentation and/or other materials provided with the
> - * distribution.
> - * * Neither the name of Intel Corporation nor the names of its
> - * contributors may be used to endorse or promote products derived
> - * from this software without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> ON ANY
> - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> - *
> - * Intel SCIF driver.
> - *
> - */
> -#ifndef SCIF_NODEQP
> -#define SCIF_NODEQP
> -
> -#include "scif_rb.h"
> -#include "scif_peer_bus.h"
> -
> -#define SCIF_INIT 1 /* First message sent to the peer node for discovery */
> -#define SCIF_EXIT 2 /* Last message from the peer informing intent to exit
> */
> -#define SCIF_EXIT_ACK 3 /* Response to SCIF_EXIT message */
> -#define SCIF_NODE_ADD 4 /* Tell Online nodes a new node exits */
> -#define SCIF_NODE_ADD_ACK 5 /* Confirm to mgmt node sequence is
> finished */
> -#define SCIF_NODE_ADD_NACK 6 /* SCIF_NODE_ADD failed */
> -#define SCIF_NODE_REMOVE 7 /* Request to deactivate a SCIF node */
> -#define SCIF_NODE_REMOVE_ACK 8 /* Response to a SCIF_NODE_REMOVE
> message */
> -#define SCIF_CNCT_REQ 9 /* Phys addr of Request connection to a port */
> -#define SCIF_CNCT_GNT 10 /* Phys addr of new Grant connection request
> */
> -#define SCIF_CNCT_GNTACK 11 /* Error type Reject a connection request */
> -#define SCIF_CNCT_GNTNACK 12 /* Error type Reject a connection request
> */
> -#define SCIF_CNCT_REJ 13 /* Error type Reject a connection request */
> -#define SCIF_DISCNCT 14 /* Notify peer that connection is being terminated
> */
> -#define SCIF_DISCNT_ACK 15 /* Notify peer that connection is being
> terminated */
> -#define SCIF_CLIENT_SENT 16 /* Notify the peer that data has been written
> */
> -#define SCIF_CLIENT_RCVD 17 /* Notify the peer that data has been read */
> -#define SCIF_GET_NODE_INFO 18 /* Get current node mask from the mgmt
> node*/
> -#define SCIF_REGISTER 19 /* Tell peer about a new registered window */
> -#define SCIF_REGISTER_ACK 20 /* Notify peer about unregistration success
> */
> -#define SCIF_REGISTER_NACK 21 /* Notify peer about registration success */
> -#define SCIF_UNREGISTER 22 /* Tell peer about unregistering a window */
> -#define SCIF_UNREGISTER_ACK 23 /* Notify peer about registration failure
> */
> -#define SCIF_UNREGISTER_NACK 24 /* Notify peer about unregistration
> failure */
> -#define SCIF_ALLOC_REQ 25 /* Request a mapped buffer */
> -#define SCIF_ALLOC_GNT 26 /* Notify peer about allocation success */
> -#define SCIF_ALLOC_REJ 27 /* Notify peer about allocation failure */
> -#define SCIF_FREE_VIRT 28 /* Free previously allocated virtual memory */
> -#define SCIF_MUNMAP 29 /* Acknowledgment for a SCIF_MMAP request */
> -#define SCIF_MARK 30 /* SCIF Remote Fence Mark Request */
> -#define SCIF_MARK_ACK 31 /* SCIF Remote Fence Mark Success */
> -#define SCIF_MARK_NACK 32 /* SCIF Remote Fence Mark Failure */
> -#define SCIF_WAIT 33 /* SCIF Remote Fence Wait Request */
> -#define SCIF_WAIT_ACK 34 /* SCIF Remote Fence Wait Success */
> -#define SCIF_WAIT_NACK 35 /* SCIF Remote Fence Wait Failure */
> -#define SCIF_SIG_LOCAL 36 /* SCIF Remote Fence Local Signal Request */
> -#define SCIF_SIG_REMOTE 37 /* SCIF Remote Fence Remote Signal Request
> */
> -#define SCIF_SIG_ACK 38 /* SCIF Remote Fence Remote Signal Success */
> -#define SCIF_SIG_NACK 39 /* SCIF Remote Fence Remote Signal Failure */
> -#define SCIF_MAX_MSG SCIF_SIG_NACK
> -
> -/*
> - * struct scifmsg - Node QP message format
> - *
> - * @src: Source information
> - * @dst: Destination information
> - * @uop: The message opcode
> - * @payload: Unique payload format for each message
> - */
> -struct scifmsg {
> - struct scif_port_id src;
> - struct scif_port_id dst;
> - u32 uop;
> - u64 payload[4];
> -} __packed;
> -
> -/*
> - * struct scif_allocmsg - Used with SCIF_ALLOC_REQ to request
> - * the remote note to allocate memory
> - *
> - * phys_addr: Physical address of the buffer
> - * vaddr: Virtual address of the buffer
> - * size: Size of the buffer
> - * state: Current state
> - * allocwq: wait queue for status
> - */
> -struct scif_allocmsg {
> - dma_addr_t phys_addr;
> - unsigned long vaddr;
> - size_t size;
> - enum scif_msg_state state;
> - wait_queue_head_t allocwq;
> -};
> -
> -/*
> - * struct scif_qp - Node Queue Pair
> - *
> - * Interesting structure -- a little difficult because we can only
> - * write across the PCIe, so any r/w pointer we need to read is
> - * local. We only need to read the read pointer on the inbound_q
> - * and read the write pointer in the outbound_q
> - *
> - * @magic: Magic value to ensure the peer sees the QP correctly
> - * @outbound_q: The outbound ring buffer for sending messages
> - * @inbound_q: The inbound ring buffer for receiving messages
> - * @local_write: Local write index
> - * @local_read: Local read index
> - * @remote_qp: The remote queue pair
> - * @local_buf: DMA address of local ring buffer
> - * @local_qp: DMA address of the local queue pair data structure
> - * @remote_buf: DMA address of remote ring buffer
> - * @qp_state: QP state i.e. online or offline used for P2P
> - * @send_lock: synchronize access to outbound queue
> - * @recv_lock: Synchronize access to inbound queue
> - */
> -struct scif_qp {
> - u64 magic;
> -#define SCIFEP_MAGIC 0x5c1f000000005c1fULL
> - struct scif_rb outbound_q;
> - struct scif_rb inbound_q;
> -
> - u32 local_write __aligned(64);
> - u32 local_read __aligned(64);
> - struct scif_qp *remote_qp;
> - dma_addr_t local_buf;
> - dma_addr_t local_qp;
> - dma_addr_t remote_buf;
> - u32 qp_state;
> -#define SCIF_QP_OFFLINE 0xdead
> -#define SCIF_QP_ONLINE 0xc0de
> - spinlock_t send_lock;
> - spinlock_t recv_lock;
> -};
> -
> -/*
> - * struct scif_loopb_msg - An element in the loopback Node QP message list.
> - *
> - * @msg - The SCIF node QP message
> - * @list - link in the list of messages
> - */
> -struct scif_loopb_msg {
> - struct scifmsg msg;
> - struct list_head list;
> -};
> -
> -int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg);
> -int _scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_nodeqp_intrhandler(struct scif_dev *scifdev, struct scif_qp *qp);
> -int scif_loopb_msg_handler(struct scif_dev *scifdev, struct scif_qp *qp);
> -int scif_setup_qp(struct scif_dev *scifdev);
> -int scif_qp_response(phys_addr_t phys, struct scif_dev *dev);
> -int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
> - int local_size, struct scif_dev *scifdev);
> -int scif_setup_qp_accept(struct scif_qp *qp, dma_addr_t *qp_offset,
> - dma_addr_t phys, int local_size,
> - struct scif_dev *scifdev);
> -int scif_setup_qp_connect_response(struct scif_dev *scifdev,
> - struct scif_qp *qp, u64 payload);
> -int scif_setup_loopback_qp(struct scif_dev *scifdev);
> -int scif_destroy_loopback_qp(struct scif_dev *scifdev);
> -void scif_poll_qp_state(struct work_struct *work);
> -void scif_destroy_p2p(struct scif_dev *scifdev);
> -void scif_send_exit(struct scif_dev *scifdev);
> -static inline struct device *scif_get_peer_dev(struct scif_dev *scifdev)
> -{
> - struct scif_peer_dev *spdev;
> - struct device *spdev_ret;
> -
> - rcu_read_lock();
> - spdev = rcu_dereference(scifdev->spdev);
> - if (spdev)
> - spdev_ret = get_device(&spdev->dev);
> - else
> - spdev_ret = ERR_PTR(-ENODEV);
> - rcu_read_unlock();
> - return spdev_ret;
> -}
> -
> -static inline void scif_put_peer_dev(struct device *dev)
> -{
> - put_device(dev);
> -}
> -#endif /* SCIF_NODEQP */
> diff --git a/drivers/misc/mic/scif/scif_peer_bus.c
> b/drivers/misc/mic/scif/scif_peer_bus.c
> deleted file mode 100644
> index 6d608308bb60..000000000000
> --- a/drivers/misc/mic/scif/scif_peer_bus.c
> +++ /dev/null
> @@ -1,175 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -#include "../bus/scif_bus.h"
> -#include "scif_peer_bus.h"
> -
> -static inline struct scif_peer_dev *
> -dev_to_scif_peer(struct device *dev)
> -{
> - return container_of(dev, struct scif_peer_dev, dev);
> -}
> -
> -struct bus_type scif_peer_bus = {
> - .name = "scif_peer_bus",
> -};
> -
> -static void scif_peer_release_dev(struct device *d)
> -{
> - struct scif_peer_dev *sdev = dev_to_scif_peer(d);
> - struct scif_dev *scifdev = &scif_dev[sdev->dnode];
> -
> - scif_cleanup_scifdev(scifdev);
> - kfree(sdev);
> -}
> -
> -static int scif_peer_initialize_device(struct scif_dev *scifdev)
> -{
> - struct scif_peer_dev *spdev;
> - int ret;
> -
> - spdev = kzalloc(sizeof(*spdev), GFP_KERNEL);
> - if (!spdev) {
> - ret = -ENOMEM;
> - goto err;
> - }
> -
> - spdev->dev.parent = scifdev->sdev->dev.parent;
> - spdev->dev.release = scif_peer_release_dev;
> - spdev->dnode = scifdev->node;
> - spdev->dev.bus = &scif_peer_bus;
> - dev_set_name(&spdev->dev, "scif_peer-dev%u", spdev->dnode);
> -
> - device_initialize(&spdev->dev);
> - get_device(&spdev->dev);
> - rcu_assign_pointer(scifdev->spdev, spdev);
> -
> - mutex_lock(&scif_info.conflock);
> - scif_info.total++;
> - scif_info.maxid = max_t(u32, spdev->dnode, scif_info.maxid);
> - mutex_unlock(&scif_info.conflock);
> - return 0;
> -err:
> - dev_err(&scifdev->sdev->dev,
> - "dnode %d: initialize_device rc %d\n", scifdev->node, ret);
> - return ret;
> -}
> -
> -static int scif_peer_add_device(struct scif_dev *scifdev)
> -{
> - struct scif_peer_dev *spdev = rcu_dereference(scifdev->spdev);
> - char pool_name[16];
> - int ret;
> -
> - ret = device_add(&spdev->dev);
> - put_device(&spdev->dev);
> - if (ret) {
> - dev_err(&scifdev->sdev->dev,
> - "dnode %d: peer device_add failed\n", scifdev-
> >node);
> - goto put_spdev;
> - }
> -
> - scnprintf(pool_name, sizeof(pool_name), "scif-%d", spdev->dnode);
> - scifdev->signal_pool = dmam_pool_create(pool_name, &scifdev-
> >sdev->dev,
> - sizeof(struct scif_status), 1,
> - 0);
> - if (!scifdev->signal_pool) {
> - dev_err(&scifdev->sdev->dev,
> - "dnode %d: dmam_pool_create failed\n", scifdev-
> >node);
> - ret = -ENOMEM;
> - goto del_spdev;
> - }
> - dev_dbg(&spdev->dev, "Added peer dnode %d\n", spdev->dnode);
> - return 0;
> -del_spdev:
> - device_del(&spdev->dev);
> -put_spdev:
> - RCU_INIT_POINTER(scifdev->spdev, NULL);
> - synchronize_rcu();
> - put_device(&spdev->dev);
> -
> - mutex_lock(&scif_info.conflock);
> - scif_info.total--;
> - mutex_unlock(&scif_info.conflock);
> - return ret;
> -}
> -
> -void scif_add_peer_device(struct work_struct *work)
> -{
> - struct scif_dev *scifdev = container_of(work, struct scif_dev,
> - peer_add_work);
> -
> - scif_peer_add_device(scifdev);
> -}
> -
> -/*
> - * Peer device registration is split into a device_initialize and a device_add.
> - * The reason for doing this is as follows: First, peer device registration
> - * itself cannot be done in the message processing thread and must be
> delegated
> - * to another workqueue, otherwise if SCIF client probe, called during peer
> - * device registration, calls scif_connect(..), it will block the message
> - * processing thread causing a deadlock. Next, device_initialize is done in the
> - * "top-half" message processing thread and device_add in the "bottom-
> half"
> - * workqueue. If this is not done, SCIF_CNCT_REQ message processing
> executing
> - * concurrently with SCIF_INIT message processing is unable to get a
> reference
> - * on the peer device, thereby failing the connect request.
> - */
> -void scif_peer_register_device(struct scif_dev *scifdev)
> -{
> - int ret;
> -
> - mutex_lock(&scifdev->lock);
> - ret = scif_peer_initialize_device(scifdev);
> - if (ret)
> - goto exit;
> - schedule_work(&scifdev->peer_add_work);
> -exit:
> - mutex_unlock(&scifdev->lock);
> -}
> -
> -int scif_peer_unregister_device(struct scif_dev *scifdev)
> -{
> - struct scif_peer_dev *spdev;
> -
> - mutex_lock(&scifdev->lock);
> - /* Flush work to ensure device register is complete */
> - flush_work(&scifdev->peer_add_work);
> -
> - /*
> - * Continue holding scifdev->lock since theoretically
> unregister_device
> - * can be called simultaneously from multiple threads
> - */
> - spdev = rcu_dereference(scifdev->spdev);
> - if (!spdev) {
> - mutex_unlock(&scifdev->lock);
> - return -ENODEV;
> - }
> -
> - RCU_INIT_POINTER(scifdev->spdev, NULL);
> - synchronize_rcu();
> - mutex_unlock(&scifdev->lock);
> -
> - dev_dbg(&spdev->dev, "Removing peer dnode %d\n", spdev-
> >dnode);
> - device_unregister(&spdev->dev);
> -
> - mutex_lock(&scif_info.conflock);
> - scif_info.total--;
> - mutex_unlock(&scif_info.conflock);
> - return 0;
> -}
> -
> -int scif_peer_bus_init(void)
> -{
> - return bus_register(&scif_peer_bus);
> -}
> -
> -void scif_peer_bus_exit(void)
> -{
> - bus_unregister(&scif_peer_bus);
> -}
> diff --git a/drivers/misc/mic/scif/scif_peer_bus.h
> b/drivers/misc/mic/scif/scif_peer_bus.h
> deleted file mode 100644
> index 2ea4c51c18c1..000000000000
> --- a/drivers/misc/mic/scif/scif_peer_bus.h
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef _SCIF_PEER_BUS_H_
> -#define _SCIF_PEER_BUS_H_
> -
> -#include <linux/device.h>
> -#include <linux/mic_common.h>
> -#include <linux/scif.h>
> -
> -struct scif_dev;
> -
> -void scif_add_peer_device(struct work_struct *work);
> -void scif_peer_register_device(struct scif_dev *sdev);
> -int scif_peer_unregister_device(struct scif_dev *scifdev);
> -int scif_peer_bus_init(void);
> -void scif_peer_bus_exit(void);
> -#endif /* _SCIF_PEER_BUS_H */
> diff --git a/drivers/misc/mic/scif/scif_ports.c
> b/drivers/misc/mic/scif/scif_ports.c
> deleted file mode 100644
> index 4bdb5ef9a139..000000000000
> --- a/drivers/misc/mic/scif/scif_ports.c
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/idr.h>
> -
> -#include "scif_main.h"
> -
> -#define SCIF_PORT_COUNT 0x10000 /* Ports available */
> -
> -struct idr scif_ports;
> -
> -/**
> - * struct scif_port - SCIF port information
> - *
> - * @ref_cnt: Reference count since there can be multiple endpoints
> - * created via scif_accept(..) simultaneously using a port.
> - */
> -struct scif_port {
> - int ref_cnt;
> -};
> -
> -/**
> - * __scif_get_port - Reserve a specified port # for SCIF and add it
> - * to the global list.
> - * @start: lowest port # to be reserved (inclusive).
> - * @end: highest port # to be reserved (exclusive).
> - *
> - * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
> - * On memory allocation failure, returns -ENOMEM.
> - */
> -static int __scif_get_port(int start, int end)
> -{
> - int id;
> - struct scif_port *port = kzalloc(sizeof(*port), GFP_ATOMIC);
> -
> - if (!port)
> - return -ENOMEM;
> - spin_lock(&scif_info.port_lock);
> - id = idr_alloc(&scif_ports, port, start, end, GFP_ATOMIC);
> - if (id >= 0)
> - port->ref_cnt++;
> - spin_unlock(&scif_info.port_lock);
> - return id;
> -}
> -
> -/**
> - * scif_rsrv_port - Reserve a specified port # for SCIF.
> - * @port : port # to be reserved.
> - *
> - * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
> - * On memory allocation failure, returns -ENOMEM.
> - */
> -int scif_rsrv_port(u16 port)
> -{
> - return __scif_get_port(port, port + 1);
> -}
> -
> -/**
> - * scif_get_new_port - Get and reserve any port # for SCIF in the range
> - * SCIF_PORT_RSVD + 1 to SCIF_PORT_COUNT - 1.
> - *
> - * @return : Allocated SCIF port #, or -ENOSPC if no ports available.
> - * On memory allocation failure, returns -ENOMEM.
> - */
> -int scif_get_new_port(void)
> -{
> - return __scif_get_port(SCIF_PORT_RSVD + 1, SCIF_PORT_COUNT);
> -}
> -
> -/**
> - * scif_get_port - Increment the reference count for a SCIF port
> - * @id : SCIF port
> - *
> - * @return : None
> - */
> -void scif_get_port(u16 id)
> -{
> - struct scif_port *port;
> -
> - if (!id)
> - return;
> - spin_lock(&scif_info.port_lock);
> - port = idr_find(&scif_ports, id);
> - if (port)
> - port->ref_cnt++;
> - spin_unlock(&scif_info.port_lock);
> -}
> -
> -/**
> - * scif_put_port - Release a reserved SCIF port
> - * @id : SCIF port to be released.
> - *
> - * @return : None
> - */
> -void scif_put_port(u16 id)
> -{
> - struct scif_port *port;
> -
> - if (!id)
> - return;
> - spin_lock(&scif_info.port_lock);
> - port = idr_find(&scif_ports, id);
> - if (port) {
> - port->ref_cnt--;
> - if (!port->ref_cnt) {
> - idr_remove(&scif_ports, id);
> - kfree(port);
> - }
> - }
> - spin_unlock(&scif_info.port_lock);
> -}
> diff --git a/drivers/misc/mic/scif/scif_rb.c b/drivers/misc/mic/scif/scif_rb.c
> deleted file mode 100644
> index e425882ae06d..000000000000
> --- a/drivers/misc/mic/scif/scif_rb.c
> +++ /dev/null
> @@ -1,240 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/circ_buf.h>
> -#include <linux/types.h>
> -#include <linux/io.h>
> -#include <linux/errno.h>
> -
> -#include "scif_rb.h"
> -
> -#define scif_rb_ring_cnt(head, tail, size) CIRC_CNT(head, tail, size)
> -#define scif_rb_ring_space(head, tail, size) CIRC_SPACE(head, tail, size)
> -
> -/**
> - * scif_rb_init - Initializes the ring buffer
> - * @rb: ring buffer
> - * @read_ptr: A pointer to the read offset
> - * @write_ptr: A pointer to the write offset
> - * @rb_base: A pointer to the base of the ring buffer
> - * @size: The size of the ring buffer in powers of two
> - */
> -void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr,
> - void *rb_base, u8 size)
> -{
> - rb->rb_base = rb_base;
> - rb->size = (1 << size);
> - rb->read_ptr = read_ptr;
> - rb->write_ptr = write_ptr;
> - rb->current_read_offset = *read_ptr;
> - rb->current_write_offset = *write_ptr;
> -}
> -
> -/* Copies a message to the ring buffer -- handles the wrap around case */
> -static void memcpy_torb(struct scif_rb *rb, void *header,
> - void *msg, u32 size)
> -{
> - u32 size1, size2;
> -
> - if (header + size >= rb->rb_base + rb->size) {
> - /* Need to call two copies if it wraps around */
> - size1 = (u32)(rb->rb_base + rb->size - header);
> - size2 = size - size1;
> - memcpy_toio((void __iomem __force *)header, msg, size1);
> - memcpy_toio((void __iomem __force *)rb->rb_base,
> - msg + size1, size2);
> - } else {
> - memcpy_toio((void __iomem __force *)header, msg, size);
> - }
> -}
> -
> -/* Copies a message from the ring buffer -- handles the wrap around case */
> -static void memcpy_fromrb(struct scif_rb *rb, void *header,
> - void *msg, u32 size)
> -{
> - u32 size1, size2;
> -
> - if (header + size >= rb->rb_base + rb->size) {
> - /* Need to call two copies if it wraps around */
> - size1 = (u32)(rb->rb_base + rb->size - header);
> - size2 = size - size1;
> - memcpy_fromio(msg, (void __iomem __force *)header,
> size1);
> - memcpy_fromio(msg + size1,
> - (void __iomem __force *)rb->rb_base, size2);
> - } else {
> - memcpy_fromio(msg, (void __iomem __force *)header, size);
> - }
> -}
> -
> -/**
> - * scif_rb_space - Query space available for writing to the RB
> - * @rb: ring buffer
> - *
> - * Return: size available for writing to RB in bytes.
> - */
> -u32 scif_rb_space(struct scif_rb *rb)
> -{
> - rb->current_read_offset = *rb->read_ptr;
> - /*
> - * Update from the HW read pointer only once the peer has exposed
> the
> - * new empty slot. This barrier is paired with the memory barrier
> - * scif_rb_update_read_ptr()
> - */
> - mb();
> - return scif_rb_ring_space(rb->current_write_offset,
> - rb->current_read_offset, rb->size);
> -}
> -
> -/**
> - * scif_rb_write - Write a message to the RB
> - * @rb: ring buffer
> - * @msg: buffer to send the message. Must be at least size bytes long
> - * @size: the size (in bytes) to be copied to the RB
> - *
> - * This API does not block if there isn't enough space in the RB.
> - * Returns: 0 on success or -ENOMEM on failure
> - */
> -int scif_rb_write(struct scif_rb *rb, void *msg, u32 size)
> -{
> - void *header;
> -
> - if (scif_rb_space(rb) < size)
> - return -ENOMEM;
> - header = rb->rb_base + rb->current_write_offset;
> - memcpy_torb(rb, header, msg, size);
> - /*
> - * Wait until scif_rb_commit(). Update the local ring
> - * buffer data, not the shared data until commit.
> - */
> - rb->current_write_offset =
> - (rb->current_write_offset + size) & (rb->size - 1);
> - return 0;
> -}
> -
> -/**
> - * scif_rb_commit - To submit the message to let the peer fetch it
> - * @rb: ring buffer
> - */
> -void scif_rb_commit(struct scif_rb *rb)
> -{
> - /*
> - * We must ensure ordering between the all the data committed
> - * previously before we expose the new message to the peer by
> - * updating the write_ptr. This write barrier is paired with
> - * the read barrier in scif_rb_count(..)
> - */
> - wmb();
> - WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
> -#ifdef CONFIG_INTEL_MIC_CARD
> - /*
> - * X100 Si bug: For the case where a Core is performing an EXT_WR
> - * followed by a Doorbell Write, the Core must perform two EXT_WR
> to the
> - * same address with the same data before it does the Doorbell
> Write.
> - * This way, if ordering is violated for the Interrupt Message, it will
> - * fall just behind the first Posted associated with the first EXT_WR.
> - */
> - WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
> -#endif
> -}
> -
> -/**
> - * scif_rb_get - To get next message from the ring buffer
> - * @rb: ring buffer
> - * @size: Number of bytes to be read
> - *
> - * Return: NULL if no bytes to be read from the ring buffer, otherwise the
> - * pointer to the next byte
> - */
> -static void *scif_rb_get(struct scif_rb *rb, u32 size)
> -{
> - void *header = NULL;
> -
> - if (scif_rb_count(rb, size) >= size)
> - header = rb->rb_base + rb->current_read_offset;
> - return header;
> -}
> -
> -/*
> - * scif_rb_get_next - Read from ring buffer.
> - * @rb: ring buffer
> - * @msg: buffer to hold the message. Must be at least size bytes long
> - * @size: Number of bytes to be read
> - *
> - * Return: number of bytes read if available bytes are >= size, otherwise
> - * returns zero.
> - */
> -u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size)
> -{
> - void *header = NULL;
> - int read_size = 0;
> -
> - header = scif_rb_get(rb, size);
> - if (header) {
> - u32 next_cmd_offset =
> - (rb->current_read_offset + size) & (rb->size - 1);
> -
> - read_size = size;
> - rb->current_read_offset = next_cmd_offset;
> - memcpy_fromrb(rb, header, msg, size);
> - }
> - return read_size;
> -}
> -
> -/**
> - * scif_rb_update_read_ptr
> - * @rb: ring buffer
> - */
> -void scif_rb_update_read_ptr(struct scif_rb *rb)
> -{
> - u32 new_offset;
> -
> - new_offset = rb->current_read_offset;
> - /*
> - * We must ensure ordering between the all the data committed or
> read
> - * previously before we expose the empty slot to the peer by
> updating
> - * the read_ptr. This barrier is paired with the memory barrier in
> - * scif_rb_space(..)
> - */
> - mb();
> - WRITE_ONCE(*rb->read_ptr, new_offset);
> -#ifdef CONFIG_INTEL_MIC_CARD
> - /*
> - * X100 Si Bug: For the case where a Core is performing an EXT_WR
> - * followed by a Doorbell Write, the Core must perform two EXT_WR
> to the
> - * same address with the same data before it does the Doorbell
> Write.
> - * This way, if ordering is violated for the Interrupt Message, it will
> - * fall just behind the first Posted associated with the first EXT_WR.
> - */
> - WRITE_ONCE(*rb->read_ptr, new_offset);
> -#endif
> -}
> -
> -/**
> - * scif_rb_count
> - * @rb: ring buffer
> - * @size: Number of bytes expected to be read
> - *
> - * Return: number of bytes that can be read from the RB
> - */
> -u32 scif_rb_count(struct scif_rb *rb, u32 size)
> -{
> - if (scif_rb_ring_cnt(rb->current_write_offset,
> - rb->current_read_offset,
> - rb->size) < size) {
> - rb->current_write_offset = *rb->write_ptr;
> - /*
> - * Update from the HW write pointer if empty only once the
> peer
> - * has exposed the new message. This read barrier is paired
> - * with the write barrier in scif_rb_commit(..)
> - */
> - smp_rmb();
> - }
> - return scif_rb_ring_cnt(rb->current_write_offset,
> - rb->current_read_offset,
> - rb->size);
> -}
> diff --git a/drivers/misc/mic/scif/scif_rb.h b/drivers/misc/mic/scif/scif_rb.h
> deleted file mode 100644
> index 166dffe3093d..000000000000
> --- a/drivers/misc/mic/scif/scif_rb.h
> +++ /dev/null
> @@ -1,100 +0,0 @@
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * This file is provided under a dual BSD/GPLv2 license. When using or
> - * redistributing this file, you may do so under either license.
> - *
> - * GPL LICENSE SUMMARY
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * BSD LICENSE
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - * * Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in
> - * the documentation and/or other materials provided with the
> - * distribution.
> - * * Neither the name of Intel Corporation nor the names of its
> - * contributors may be used to endorse or promote products derived
> - * from this software without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> ON ANY
> - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef SCIF_RB_H
> -#define SCIF_RB_H
> -/*
> - * This file describes a general purpose, byte based ring buffer. Writers to
> the
> - * ring buffer need to synchronize using a lock. The same is true for readers,
> - * although in practice, the ring buffer has a single reader. It is lockless
> - * between producer and consumer so it can handle being used across the
> PCIe
> - * bus. The ring buffer ensures that there are no reads across the PCIe bus
> for
> - * performance reasons. Two of these are used to form a single bidirectional
> - * queue-pair across PCIe.
> - */
> -/*
> - * struct scif_rb - SCIF Ring Buffer
> - *
> - * @rb_base: The base of the memory used for storing RB messages
> - * @read_ptr: Pointer to the read offset
> - * @write_ptr: Pointer to the write offset
> - * @size: Size of the memory in rb_base
> - * @current_read_offset: Cached read offset for performance
> - * @current_write_offset: Cached write offset for performance
> - */
> -struct scif_rb {
> - void *rb_base;
> - u32 *read_ptr;
> - u32 *write_ptr;
> - u32 size;
> - u32 current_read_offset;
> - u32 current_write_offset;
> -};
> -
> -/* methods used by both */
> -void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr,
> - void *rb_base, u8 size);
> -/* writer only methods */
> -/* write a new command, then scif_rb_commit() */
> -int scif_rb_write(struct scif_rb *rb, void *msg, u32 size);
> -/* after write(), then scif_rb_commit() */
> -void scif_rb_commit(struct scif_rb *rb);
> -/* query space available for writing to a RB. */
> -u32 scif_rb_space(struct scif_rb *rb);
> -
> -/* reader only methods */
> -/* read a new message from the ring buffer of size bytes */
> -u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size);
> -/* update the read pointer so that the space can be reused */
> -void scif_rb_update_read_ptr(struct scif_rb *rb);
> -/* count the number of bytes that can be read */
> -u32 scif_rb_count(struct scif_rb *rb, u32 size);
> -#endif
> diff --git a/drivers/misc/mic/scif/scif_rma.c
> b/drivers/misc/mic/scif/scif_rma.c
> deleted file mode 100644
> index 18fb9d8b8a4b..000000000000
> --- a/drivers/misc/mic/scif/scif_rma.c
> +++ /dev/null
> @@ -1,1760 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include <linux/intel-iommu.h>
> -#include <linux/pagemap.h>
> -#include <linux/sched/mm.h>
> -#include <linux/sched/signal.h>
> -
> -#include "scif_main.h"
> -#include "scif_map.h"
> -
> -/* Used to skip ulimit checks for registrations with SCIF_MAP_KERNEL flag */
> -#define SCIF_MAP_ULIMIT 0x40
> -
> -bool scif_ulimit_check = 1;
> -
> -/**
> - * scif_rma_ep_init:
> - * @ep: end point
> - *
> - * Initialize RMA per EP data structures.
> - */
> -void scif_rma_ep_init(struct scif_endpt *ep)
> -{
> - struct scif_endpt_rma_info *rma = &ep->rma_info;
> -
> - mutex_init(&rma->rma_lock);
> - init_iova_domain(&rma->iovad, PAGE_SIZE, SCIF_IOVA_START_PFN);
> - spin_lock_init(&rma->tc_lock);
> - mutex_init(&rma->mmn_lock);
> - INIT_LIST_HEAD(&rma->reg_list);
> - INIT_LIST_HEAD(&rma->remote_reg_list);
> - atomic_set(&rma->tw_refcount, 0);
> - atomic_set(&rma->tcw_refcount, 0);
> - atomic_set(&rma->tcw_total_pages, 0);
> - atomic_set(&rma->fence_refcount, 0);
> -
> - rma->async_list_del = 0;
> - rma->dma_chan = NULL;
> - INIT_LIST_HEAD(&rma->mmn_list);
> - INIT_LIST_HEAD(&rma->vma_list);
> - init_waitqueue_head(&rma->markwq);
> -}
> -
> -/**
> - * scif_rma_ep_can_uninit:
> - * @ep: end point
> - *
> - * Returns 1 if an endpoint can be uninitialized and 0 otherwise.
> - */
> -int scif_rma_ep_can_uninit(struct scif_endpt *ep)
> -{
> - int ret = 0;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Destroy RMA Info only if both lists are empty */
> - if (list_empty(&ep->rma_info.reg_list) &&
> - list_empty(&ep->rma_info.remote_reg_list) &&
> - list_empty(&ep->rma_info.mmn_list) &&
> - !atomic_read(&ep->rma_info.tw_refcount) &&
> - !atomic_read(&ep->rma_info.tcw_refcount) &&
> - !atomic_read(&ep->rma_info.fence_refcount))
> - ret = 1;
> - mutex_unlock(&ep->rma_info.rma_lock);
> - return ret;
> -}
> -
> -/**
> - * scif_create_pinned_pages:
> - * @nr_pages: number of pages in window
> - * @prot: read/write protection
> - *
> - * Allocate and prepare a set of pinned pages.
> - */
> -static struct scif_pinned_pages *
> -scif_create_pinned_pages(int nr_pages, int prot)
> -{
> - struct scif_pinned_pages *pin;
> -
> - might_sleep();
> - pin = scif_zalloc(sizeof(*pin));
> - if (!pin)
> - goto error;
> -
> - pin->pages = scif_zalloc(nr_pages * sizeof(*pin->pages));
> - if (!pin->pages)
> - goto error_free_pinned_pages;
> -
> - pin->prot = prot;
> - pin->magic = SCIFEP_MAGIC;
> - return pin;
> -
> -error_free_pinned_pages:
> - scif_free(pin, sizeof(*pin));
> -error:
> - return NULL;
> -}
> -
> -/**
> - * scif_destroy_pinned_pages:
> - * @pin: A set of pinned pages.
> - *
> - * Deallocate resources for pinned pages.
> - */
> -static int scif_destroy_pinned_pages(struct scif_pinned_pages *pin)
> -{
> - int j;
> - int writeable = pin->prot & SCIF_PROT_WRITE;
> - int kernel = SCIF_MAP_KERNEL & pin->map_flags;
> -
> - if (kernel) {
> - for (j = 0; j < pin->nr_pages; j++) {
> - if (pin->pages[j] && !kernel) {
> - if (writeable)
> - set_page_dirty_lock(pin->pages[j]);
> - put_page(pin->pages[j]);
> - }
> - }
> - } else
> - unpin_user_pages_dirty_lock(pin->pages, pin->nr_pages,
> - writeable);
> - scif_free(pin->pages,
> - pin->nr_pages * sizeof(*pin->pages));
> - scif_free(pin, sizeof(*pin));
> - return 0;
> -}
> -
> -/*
> - * scif_create_window:
> - * @ep: end point
> - * @nr_pages: number of pages
> - * @offset: registration offset
> - * @temp: true if a temporary window is being created
> - *
> - * Allocate and prepare a self registration window.
> - */
> -struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
> - s64 offset, bool temp)
> -{
> - struct scif_window *window;
> -
> - might_sleep();
> - window = scif_zalloc(sizeof(*window));
> - if (!window)
> - goto error;
> -
> - window->dma_addr = scif_zalloc(nr_pages * sizeof(*window-
> >dma_addr));
> - if (!window->dma_addr)
> - goto error_free_window;
> -
> - window->num_pages = scif_zalloc(nr_pages * sizeof(*window-
> >num_pages));
> - if (!window->num_pages)
> - goto error_free_window;
> -
> - window->offset = offset;
> - window->ep = (u64)ep;
> - window->magic = SCIFEP_MAGIC;
> - window->reg_state = OP_IDLE;
> - init_waitqueue_head(&window->regwq);
> - window->unreg_state = OP_IDLE;
> - init_waitqueue_head(&window->unregwq);
> - INIT_LIST_HEAD(&window->list);
> - window->type = SCIF_WINDOW_SELF;
> - window->temp = temp;
> - return window;
> -
> -error_free_window:
> - scif_free(window->dma_addr,
> - nr_pages * sizeof(*window->dma_addr));
> - scif_free(window, sizeof(*window));
> -error:
> - return NULL;
> -}
> -
> -/**
> - * scif_destroy_incomplete_window:
> - * @ep: end point
> - * @window: registration window
> - *
> - * Deallocate resources for self window.
> - */
> -static void scif_destroy_incomplete_window(struct scif_endpt *ep,
> - struct scif_window *window)
> -{
> - int err;
> - int nr_pages = window->nr_pages;
> - struct scif_allocmsg *alloc = &window->alloc_handle;
> - struct scifmsg msg;
> -
> -retry:
> - /* Wait for a SCIF_ALLOC_GNT/REJ message */
> - err = wait_event_timeout(alloc->allocwq,
> - alloc->state != OP_IN_PROGRESS,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - if (alloc->state == OP_COMPLETED) {
> - msg.uop = SCIF_FREE_VIRT;
> - msg.src = ep->port;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = window->alloc_handle.vaddr;
> - msg.payload[2] = (u64)window;
> - msg.payload[3] = SCIF_REGISTER;
> - _scif_nodeqp_send(ep->remote_dev, &msg);
> - }
> - mutex_unlock(&ep->rma_info.rma_lock);
> -
> - scif_free_window_offset(ep, window, window->offset);
> - scif_free(window->dma_addr, nr_pages * sizeof(*window-
> >dma_addr));
> - scif_free(window->num_pages, nr_pages * sizeof(*window-
> >num_pages));
> - scif_free(window, sizeof(*window));
> -}
> -
> -/**
> - * scif_unmap_window:
> - * @remote_dev: SCIF remote device
> - * @window: registration window
> - *
> - * Delete any DMA mappings created for a registered self window
> - */
> -void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window
> *window)
> -{
> - int j;
> -
> - if (scif_is_iommu_enabled() && !scifdev_self(remote_dev)) {
> - if (window->st) {
> - dma_unmap_sg(&remote_dev->sdev->dev,
> - window->st->sgl, window->st->nents,
> - DMA_BIDIRECTIONAL);
> - sg_free_table(window->st);
> - kfree(window->st);
> - window->st = NULL;
> - }
> - } else {
> - for (j = 0; j < window->nr_contig_chunks; j++) {
> - if (window->dma_addr[j]) {
> - scif_unmap_single(window->dma_addr[j],
> - remote_dev,
> - window->num_pages[j] <<
> - PAGE_SHIFT);
> - window->dma_addr[j] = 0x0;
> - }
> - }
> - }
> -}
> -
> -static inline struct mm_struct *__scif_acquire_mm(void)
> -{
> - if (scif_ulimit_check)
> - return get_task_mm(current);
> - return NULL;
> -}
> -
> -static inline void __scif_release_mm(struct mm_struct *mm)
> -{
> - if (mm)
> - mmput(mm);
> -}
> -
> -static inline int
> -__scif_dec_pinned_vm_lock(struct mm_struct *mm,
> - int nr_pages)
> -{
> - if (!mm || !nr_pages || !scif_ulimit_check)
> - return 0;
> -
> - atomic64_sub(nr_pages, &mm->pinned_vm);
> - return 0;
> -}
> -
> -static inline int __scif_check_inc_pinned_vm(struct mm_struct *mm,
> - int nr_pages)
> -{
> - unsigned long locked, lock_limit;
> -
> - if (!mm || !nr_pages || !scif_ulimit_check)
> - return 0;
> -
> - lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
> - locked = atomic64_add_return(nr_pages, &mm->pinned_vm);
> -
> - if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
> - atomic64_sub(nr_pages, &mm->pinned_vm);
> - dev_err(scif_info.mdev.this_device,
> - "locked(%lu) > lock_limit(%lu)\n",
> - locked, lock_limit);
> - return -ENOMEM;
> - }
> - return 0;
> -}
> -
> -/**
> - * scif_destroy_window:
> - * @ep: end point
> - * @window: registration window
> - *
> - * Deallocate resources for self window.
> - */
> -int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window)
> -{
> - int j;
> - struct scif_pinned_pages *pinned_pages = window->pinned_pages;
> - int nr_pages = window->nr_pages;
> -
> - might_sleep();
> - if (!window->temp && window->mm) {
> - __scif_dec_pinned_vm_lock(window->mm, window-
> >nr_pages);
> - __scif_release_mm(window->mm);
> - window->mm = NULL;
> - }
> -
> - scif_free_window_offset(ep, window, window->offset);
> - scif_unmap_window(ep->remote_dev, window);
> - /*
> - * Decrement references for this set of pinned pages from
> - * this window.
> - */
> - j = atomic_sub_return(1, &pinned_pages->ref_count);
> - if (j < 0)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d incorrect ref count %d\n",
> - __func__, __LINE__, j);
> - /*
> - * If the ref count for pinned_pages is zero then someone
> - * has already called scif_unpin_pages() for it and we should
> - * destroy the page cache.
> - */
> - if (!j)
> - scif_destroy_pinned_pages(window->pinned_pages);
> - scif_free(window->dma_addr, nr_pages * sizeof(*window-
> >dma_addr));
> - scif_free(window->num_pages, nr_pages * sizeof(*window-
> >num_pages));
> - window->magic = 0;
> - scif_free(window, sizeof(*window));
> - return 0;
> -}
> -
> -/**
> - * scif_create_remote_lookup:
> - * @remote_dev: SCIF remote device
> - * @window: remote window
> - *
> - * Allocate and prepare lookup entries for the remote
> - * end to copy over the physical addresses.
> - * Returns 0 on success and appropriate errno on failure.
> - */
> -static int scif_create_remote_lookup(struct scif_dev *remote_dev,
> - struct scif_window *window)
> -{
> - int i, j, err = 0;
> - int nr_pages = window->nr_pages;
> - bool vmalloc_dma_phys, vmalloc_num_pages;
> -
> - might_sleep();
> - /* Map window */
> - err = scif_map_single(&window->mapped_offset,
> - window, remote_dev, sizeof(*window));
> - if (err)
> - goto error_window;
> -
> - /* Compute the number of lookup entries. 21 == 2MB Shift */
> - window->nr_lookup = ALIGN(nr_pages * PAGE_SIZE,
> - ((2) * 1024 * 1024)) >> 21;
> -
> - window->dma_addr_lookup.lookup =
> - scif_alloc_coherent(&window->dma_addr_lookup.offset,
> - remote_dev, window->nr_lookup *
> - sizeof(*window-
> >dma_addr_lookup.lookup),
> - GFP_KERNEL | __GFP_ZERO);
> - if (!window->dma_addr_lookup.lookup) {
> - err = -ENOMEM;
> - goto error_window;
> - }
> -
> - window->num_pages_lookup.lookup =
> - scif_alloc_coherent(&window->num_pages_lookup.offset,
> - remote_dev, window->nr_lookup *
> - sizeof(*window-
> >num_pages_lookup.lookup),
> - GFP_KERNEL | __GFP_ZERO);
> - if (!window->num_pages_lookup.lookup) {
> - err = -ENOMEM;
> - goto error_window;
> - }
> -
> - vmalloc_dma_phys = is_vmalloc_addr(&window->dma_addr[0]);
> - vmalloc_num_pages = is_vmalloc_addr(&window->num_pages[0]);
> -
> - /* Now map each of the pages containing physical addresses */
> - for (i = 0, j = 0; i < nr_pages; i += SCIF_NR_ADDR_IN_PAGE, j++) {
> - err = scif_map_page(&window->dma_addr_lookup.lookup[j],
> - vmalloc_dma_phys ?
> - vmalloc_to_page(&window->dma_addr[i]) :
> - virt_to_page(&window->dma_addr[i]),
> - remote_dev);
> - if (err)
> - goto error_window;
> - err = scif_map_page(&window-
> >num_pages_lookup.lookup[j],
> - vmalloc_num_pages ?
> - vmalloc_to_page(&window-
> >num_pages[i]) :
> - virt_to_page(&window->num_pages[i]),
> - remote_dev);
> - if (err)
> - goto error_window;
> - }
> - return 0;
> -error_window:
> - return err;
> -}
> -
> -/**
> - * scif_destroy_remote_lookup:
> - * @remote_dev: SCIF remote device
> - * @window: remote window
> - *
> - * Destroy lookup entries used for the remote
> - * end to copy over the physical addresses.
> - */
> -static void scif_destroy_remote_lookup(struct scif_dev *remote_dev,
> - struct scif_window *window)
> -{
> - int i, j;
> -
> - if (window->nr_lookup) {
> - struct scif_rma_lookup *lup = &window->dma_addr_lookup;
> - struct scif_rma_lookup *npup = &window-
> >num_pages_lookup;
> -
> - for (i = 0, j = 0; i < window->nr_pages;
> - i += SCIF_NR_ADDR_IN_PAGE, j++) {
> - if (lup->lookup && lup->lookup[j])
> - scif_unmap_single(lup->lookup[j],
> - remote_dev,
> - PAGE_SIZE);
> - if (npup->lookup && npup->lookup[j])
> - scif_unmap_single(npup->lookup[j],
> - remote_dev,
> - PAGE_SIZE);
> - }
> - if (lup->lookup)
> - scif_free_coherent(lup->lookup, lup->offset,
> - remote_dev, window->nr_lookup *
> - sizeof(*lup->lookup));
> - if (npup->lookup)
> - scif_free_coherent(npup->lookup, npup->offset,
> - remote_dev, window->nr_lookup *
> - sizeof(*npup->lookup));
> - if (window->mapped_offset)
> - scif_unmap_single(window->mapped_offset,
> - remote_dev, sizeof(*window));
> - window->nr_lookup = 0;
> - }
> -}
> -
> -/**
> - * scif_create_remote_window:
> - * @scifdev: SCIF device
> - * @nr_pages: number of pages in window
> - *
> - * Allocate and prepare a remote registration window.
> - */
> -static struct scif_window *
> -scif_create_remote_window(struct scif_dev *scifdev, int nr_pages)
> -{
> - struct scif_window *window;
> -
> - might_sleep();
> - window = scif_zalloc(sizeof(*window));
> - if (!window)
> - goto error_ret;
> -
> - window->magic = SCIFEP_MAGIC;
> - window->nr_pages = nr_pages;
> -
> - window->dma_addr = scif_zalloc(nr_pages * sizeof(*window-
> >dma_addr));
> - if (!window->dma_addr)
> - goto error_window;
> -
> - window->num_pages = scif_zalloc(nr_pages *
> - sizeof(*window->num_pages));
> - if (!window->num_pages)
> - goto error_window;
> -
> - if (scif_create_remote_lookup(scifdev, window))
> - goto error_window;
> -
> - window->type = SCIF_WINDOW_PEER;
> - window->unreg_state = OP_IDLE;
> - INIT_LIST_HEAD(&window->list);
> - return window;
> -error_window:
> - scif_destroy_remote_window(window);
> -error_ret:
> - return NULL;
> -}
> -
> -/**
> - * scif_destroy_remote_window:
> - * @window: remote registration window
> - *
> - * Deallocate resources for remote window.
> - */
> -void
> -scif_destroy_remote_window(struct scif_window *window)
> -{
> - scif_free(window->dma_addr, window->nr_pages *
> - sizeof(*window->dma_addr));
> - scif_free(window->num_pages, window->nr_pages *
> - sizeof(*window->num_pages));
> - window->magic = 0;
> - scif_free(window, sizeof(*window));
> -}
> -
> -/**
> - * scif_iommu_map: create DMA mappings if the IOMMU is enabled
> - * @remote_dev: SCIF remote device
> - * @window: remote registration window
> - *
> - * Map the physical pages using dma_map_sg(..) and then detect the
> number
> - * of contiguous DMA mappings allocated
> - */
> -static int scif_iommu_map(struct scif_dev *remote_dev,
> - struct scif_window *window)
> -{
> - struct scatterlist *sg;
> - int i, err;
> - scif_pinned_pages_t pin = window->pinned_pages;
> -
> - window->st = kzalloc(sizeof(*window->st), GFP_KERNEL);
> - if (!window->st)
> - return -ENOMEM;
> -
> - err = sg_alloc_table(window->st, window->nr_pages, GFP_KERNEL);
> - if (err)
> - return err;
> -
> - for_each_sg(window->st->sgl, sg, window->st->nents, i)
> - sg_set_page(sg, pin->pages[i], PAGE_SIZE, 0x0);
> -
> - err = dma_map_sg(&remote_dev->sdev->dev, window->st->sgl,
> - window->st->nents, DMA_BIDIRECTIONAL);
> - if (!err)
> - return -ENOMEM;
> - /* Detect contiguous ranges of DMA mappings */
> - sg = window->st->sgl;
> - for (i = 0; sg; i++) {
> - dma_addr_t last_da;
> -
> - window->dma_addr[i] = sg_dma_address(sg);
> - window->num_pages[i] = sg_dma_len(sg) >> PAGE_SHIFT;
> - last_da = sg_dma_address(sg) + sg_dma_len(sg);
> - while ((sg = sg_next(sg)) && sg_dma_address(sg) == last_da)
> {
> - window->num_pages[i] +=
> - (sg_dma_len(sg) >> PAGE_SHIFT);
> - last_da = window->dma_addr[i] +
> - sg_dma_len(sg);
> - }
> - window->nr_contig_chunks++;
> - }
> - return 0;
> -}
> -
> -/**
> - * scif_map_window:
> - * @remote_dev: SCIF remote device
> - * @window: self registration window
> - *
> - * Map pages of a window into the aperture/PCI.
> - * Also determine addresses required for DMA.
> - */
> -int
> -scif_map_window(struct scif_dev *remote_dev, struct scif_window
> *window)
> -{
> - int i, j, k, err = 0, nr_contig_pages;
> - scif_pinned_pages_t pin;
> - phys_addr_t phys_prev, phys_curr;
> -
> - might_sleep();
> -
> - pin = window->pinned_pages;
> -
> - if (intel_iommu_enabled && !scifdev_self(remote_dev))
> - return scif_iommu_map(remote_dev, window);
> -
> - for (i = 0, j = 0; i < window->nr_pages; i += nr_contig_pages, j++) {
> - phys_prev = page_to_phys(pin->pages[i]);
> - nr_contig_pages = 1;
> -
> - /* Detect physically contiguous chunks */
> - for (k = i + 1; k < window->nr_pages; k++) {
> - phys_curr = page_to_phys(pin->pages[k]);
> - if (phys_curr != (phys_prev + PAGE_SIZE))
> - break;
> - phys_prev = phys_curr;
> - nr_contig_pages++;
> - }
> - window->num_pages[j] = nr_contig_pages;
> - window->nr_contig_chunks++;
> - if (scif_is_mgmt_node()) {
> - /*
> - * Management node has to deal with SMPT on X100
> and
> - * hence the DMA mapping is required
> - */
> - err = scif_map_single(&window->dma_addr[j],
> - phys_to_virt(page_to_phys(
> - pin->pages[i])),
> - remote_dev,
> - nr_contig_pages << PAGE_SHIFT);
> - if (err)
> - return err;
> - } else {
> - window->dma_addr[j] = page_to_phys(pin->pages[i]);
> - }
> - }
> - return err;
> -}
> -
> -/**
> - * scif_send_scif_unregister:
> - * @ep: end point
> - * @window: self registration window
> - *
> - * Send a SCIF_UNREGISTER message.
> - */
> -static int scif_send_scif_unregister(struct scif_endpt *ep,
> - struct scif_window *window)
> -{
> - struct scifmsg msg;
> -
> - msg.uop = SCIF_UNREGISTER;
> - msg.src = ep->port;
> - msg.payload[0] = window->alloc_handle.vaddr;
> - msg.payload[1] = (u64)window;
> - return scif_nodeqp_send(ep->remote_dev, &msg);
> -}
> -
> -/**
> - * scif_unregister_window:
> - * @window: self registration window
> - *
> - * Send an unregistration request and wait for a response.
> - */
> -int scif_unregister_window(struct scif_window *window)
> -{
> - int err = 0;
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> - bool send_msg = false;
> -
> - might_sleep();
> - switch (window->unreg_state) {
> - case OP_IDLE:
> - {
> - window->unreg_state = OP_IN_PROGRESS;
> - send_msg = true;
> - }
> - fallthrough;
> - case OP_IN_PROGRESS:
> - {
> - scif_get_window(window, 1);
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (send_msg) {
> - err = scif_send_scif_unregister(ep, window);
> - if (err) {
> - window->unreg_state = OP_COMPLETED;
> - goto done;
> - }
> - } else {
> - /* Return ENXIO since unregistration is in progress */
> - mutex_lock(&ep->rma_info.rma_lock);
> - return -ENXIO;
> - }
> -retry:
> - /* Wait for a SCIF_UNREGISTER_(N)ACK message */
> - err = wait_event_timeout(window->unregwq,
> - window->unreg_state !=
> OP_IN_PROGRESS,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> - if (!err) {
> - err = -ENODEV;
> - window->unreg_state = OP_COMPLETED;
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - }
> - if (err > 0)
> - err = 0;
> -done:
> - mutex_lock(&ep->rma_info.rma_lock);
> - scif_put_window(window, 1);
> - break;
> - }
> - case OP_FAILED:
> - {
> - if (!scifdev_alive(ep)) {
> - err = -ENODEV;
> - window->unreg_state = OP_COMPLETED;
> - }
> - break;
> - }
> - case OP_COMPLETED:
> - break;
> - default:
> - err = -ENODEV;
> - }
> -
> - if (window->unreg_state == OP_COMPLETED && window->ref_count)
> - scif_put_window(window, window->nr_pages);
> -
> - if (!window->ref_count) {
> - atomic_inc(&ep->rma_info.tw_refcount);
> - list_del_init(&window->list);
> - scif_free_window_offset(ep, window, window->offset);
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if ((!!(window->pinned_pages->map_flags &
> SCIF_MAP_KERNEL)) &&
> - scifdev_alive(ep)) {
> - scif_drain_dma_intr(ep->remote_dev->sdev,
> - ep->rma_info.dma_chan);
> - } else {
> - if (!__scif_dec_pinned_vm_lock(window->mm,
> - window->nr_pages)) {
> - __scif_release_mm(window->mm);
> - window->mm = NULL;
> - }
> - }
> - scif_queue_for_cleanup(window, &scif_info.rma);
> - mutex_lock(&ep->rma_info.rma_lock);
> - }
> - return err;
> -}
> -
> -/**
> - * scif_send_alloc_request:
> - * @ep: end point
> - * @window: self registration window
> - *
> - * Send a remote window allocation request
> - */
> -static int scif_send_alloc_request(struct scif_endpt *ep,
> - struct scif_window *window)
> -{
> - struct scifmsg msg;
> - struct scif_allocmsg *alloc = &window->alloc_handle;
> -
> - /* Set up the Alloc Handle */
> - alloc->state = OP_IN_PROGRESS;
> - init_waitqueue_head(&alloc->allocwq);
> -
> - /* Send out an allocation request */
> - msg.uop = SCIF_ALLOC_REQ;
> - msg.payload[1] = window->nr_pages;
> - msg.payload[2] = (u64)&window->alloc_handle;
> - return _scif_nodeqp_send(ep->remote_dev, &msg);
> -}
> -
> -/**
> - * scif_prep_remote_window:
> - * @ep: end point
> - * @window: self registration window
> - *
> - * Send a remote window allocation request, wait for an allocation response,
> - * and prepares the remote window by copying over the page lists
> - */
> -static int scif_prep_remote_window(struct scif_endpt *ep,
> - struct scif_window *window)
> -{
> - struct scifmsg msg;
> - struct scif_window *remote_window;
> - struct scif_allocmsg *alloc = &window->alloc_handle;
> - dma_addr_t *dma_phys_lookup, *tmp, *num_pages_lookup, *tmp1;
> - int i = 0, j = 0;
> - int nr_contig_chunks, loop_nr_contig_chunks;
> - int remaining_nr_contig_chunks, nr_lookup;
> - int err, map_err;
> -
> - map_err = scif_map_window(ep->remote_dev, window);
> - if (map_err)
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d map_err %d\n", __func__, __LINE__,
> map_err);
> - remaining_nr_contig_chunks = window->nr_contig_chunks;
> - nr_contig_chunks = window->nr_contig_chunks;
> -retry:
> - /* Wait for a SCIF_ALLOC_GNT/REJ message */
> - err = wait_event_timeout(alloc->allocwq,
> - alloc->state != OP_IN_PROGRESS,
> - SCIF_NODE_ALIVE_TIMEOUT);
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Synchronize with the thread waking up allocwq */
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> -
> - if (!err)
> - err = -ENODEV;
> -
> - if (err > 0)
> - err = 0;
> - else
> - return err;
> -
> - /* Bail out. The remote end rejected this request */
> - if (alloc->state == OP_FAILED)
> - return -ENOMEM;
> -
> - if (map_err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, map_err);
> - msg.uop = SCIF_FREE_VIRT;
> - msg.src = ep->port;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = window->alloc_handle.vaddr;
> - msg.payload[2] = (u64)window;
> - msg.payload[3] = SCIF_REGISTER;
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED)
> - err = _scif_nodeqp_send(ep->remote_dev, &msg);
> - else
> - err = -ENOTCONN;
> - spin_unlock(&ep->lock);
> - return err;
> - }
> -
> - remote_window = scif_ioremap(alloc->phys_addr, sizeof(*window),
> - ep->remote_dev);
> -
> - /* Compute the number of lookup entries. 21 == 2MB Shift */
> - nr_lookup = ALIGN(nr_contig_chunks, SCIF_NR_ADDR_IN_PAGE)
> - >> ilog2(SCIF_NR_ADDR_IN_PAGE);
> -
> - dma_phys_lookup =
> - scif_ioremap(remote_window->dma_addr_lookup.offset,
> - nr_lookup *
> - sizeof(*remote_window-
> >dma_addr_lookup.lookup),
> - ep->remote_dev);
> - num_pages_lookup =
> - scif_ioremap(remote_window->num_pages_lookup.offset,
> - nr_lookup *
> - sizeof(*remote_window-
> >num_pages_lookup.lookup),
> - ep->remote_dev);
> -
> - while (remaining_nr_contig_chunks) {
> - loop_nr_contig_chunks = min_t(int,
> remaining_nr_contig_chunks,
> - (int)SCIF_NR_ADDR_IN_PAGE);
> - /* #1/2 - Copy physical addresses over to the remote side */
> -
> - /* #2/2 - Copy DMA addresses (addresses that are fed into
> the
> - * DMA engine) We transfer bus addresses which are then
> - * converted into a MIC physical address on the remote
> - * side if it is a MIC, if the remote node is a mgmt node we
> - * transfer the MIC physical address
> - */
> - tmp = scif_ioremap(dma_phys_lookup[j],
> - loop_nr_contig_chunks *
> - sizeof(*window->dma_addr),
> - ep->remote_dev);
> - tmp1 = scif_ioremap(num_pages_lookup[j],
> - loop_nr_contig_chunks *
> - sizeof(*window->num_pages),
> - ep->remote_dev);
> - if (scif_is_mgmt_node()) {
> - memcpy_toio((void __force __iomem *)tmp,
> - &window->dma_addr[i],
> loop_nr_contig_chunks
> - * sizeof(*window->dma_addr));
> - memcpy_toio((void __force __iomem *)tmp1,
> - &window->num_pages[i],
> loop_nr_contig_chunks
> - * sizeof(*window->num_pages));
> - } else {
> - if (scifdev_is_p2p(ep->remote_dev)) {
> - /*
> - * add remote node's base address for this
> node
> - * to convert it into a MIC address
> - */
> - int m;
> - dma_addr_t dma_addr;
> -
> - for (m = 0; m < loop_nr_contig_chunks; m++)
> {
> - dma_addr = window->dma_addr[i +
> m] +
> - ep->remote_dev->base_addr;
> - writeq(dma_addr,
> - (void __force __iomem
> *)&tmp[m]);
> - }
> - memcpy_toio((void __force __iomem *)tmp1,
> - &window->num_pages[i],
> - loop_nr_contig_chunks
> - * sizeof(*window->num_pages));
> - } else {
> - /* Mgmt node or loopback - transfer DMA
> - * addresses as is, this is the same as a
> - * MIC physical address (we use the
> dma_addr
> - * and not the phys_addr array since the
> - * phys_addr is only setup if there is a mmap()
> - * request from the mgmt node)
> - */
> - memcpy_toio((void __force __iomem *)tmp,
> - &window->dma_addr[i],
> - loop_nr_contig_chunks *
> - sizeof(*window->dma_addr));
> - memcpy_toio((void __force __iomem *)tmp1,
> - &window->num_pages[i],
> - loop_nr_contig_chunks *
> - sizeof(*window->num_pages));
> - }
> - }
> - remaining_nr_contig_chunks -= loop_nr_contig_chunks;
> - i += loop_nr_contig_chunks;
> - j++;
> - scif_iounmap(tmp, loop_nr_contig_chunks *
> - sizeof(*window->dma_addr), ep->remote_dev);
> - scif_iounmap(tmp1, loop_nr_contig_chunks *
> - sizeof(*window->num_pages), ep->remote_dev);
> - }
> -
> - /* Prepare the remote window for the peer */
> - remote_window->peer_window = (u64)window;
> - remote_window->offset = window->offset;
> - remote_window->prot = window->prot;
> - remote_window->nr_contig_chunks = nr_contig_chunks;
> - remote_window->ep = ep->remote_ep;
> - scif_iounmap(num_pages_lookup,
> - nr_lookup *
> - sizeof(*remote_window->num_pages_lookup.lookup),
> - ep->remote_dev);
> - scif_iounmap(dma_phys_lookup,
> - nr_lookup *
> - sizeof(*remote_window->dma_addr_lookup.lookup),
> - ep->remote_dev);
> - scif_iounmap(remote_window, sizeof(*remote_window), ep-
> >remote_dev);
> - window->peer_window = alloc->vaddr;
> - return err;
> -}
> -
> -/**
> - * scif_send_scif_register:
> - * @ep: end point
> - * @window: self registration window
> - *
> - * Send a SCIF_REGISTER message if EP is connected and wait for a
> - * SCIF_REGISTER_(N)ACK message else send a SCIF_FREE_VIRT
> - * message so that the peer can free its remote window allocated earlier.
> - */
> -static int scif_send_scif_register(struct scif_endpt *ep,
> - struct scif_window *window)
> -{
> - int err = 0;
> - struct scifmsg msg;
> -
> - msg.src = ep->port;
> - msg.payload[0] = ep->remote_ep;
> - msg.payload[1] = window->alloc_handle.vaddr;
> - msg.payload[2] = (u64)window;
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED) {
> - msg.uop = SCIF_REGISTER;
> - window->reg_state = OP_IN_PROGRESS;
> - err = _scif_nodeqp_send(ep->remote_dev, &msg);
> - spin_unlock(&ep->lock);
> - if (!err) {
> -retry:
> - /* Wait for a SCIF_REGISTER_(N)ACK message */
> - err = wait_event_timeout(window->regwq,
> - window->reg_state !=
> - OP_IN_PROGRESS,
> -
> SCIF_NODE_ALIVE_TIMEOUT);
> - if (!err && scifdev_alive(ep))
> - goto retry;
> - err = !err ? -ENODEV : 0;
> - if (window->reg_state == OP_FAILED)
> - err = -ENOTCONN;
> - }
> - } else {
> - msg.uop = SCIF_FREE_VIRT;
> - msg.payload[3] = SCIF_REGISTER;
> - err = _scif_nodeqp_send(ep->remote_dev, &msg);
> - spin_unlock(&ep->lock);
> - if (!err)
> - err = -ENOTCONN;
> - }
> - return err;
> -}
> -
> -/**
> - * scif_get_window_offset:
> - * @ep: end point descriptor
> - * @flags: flags
> - * @offset: offset hint
> - * @num_pages: number of pages
> - * @out_offset: computed offset returned by reference.
> - *
> - * Compute/Claim a new offset for this EP.
> - */
> -int scif_get_window_offset(struct scif_endpt *ep, int flags, s64 offset,
> - int num_pages, s64 *out_offset)
> -{
> - s64 page_index;
> - struct iova *iova_ptr;
> - int err = 0;
> -
> - if (flags & SCIF_MAP_FIXED) {
> - page_index = SCIF_IOVA_PFN(offset);
> - iova_ptr = reserve_iova(&ep->rma_info.iovad, page_index,
> - page_index + num_pages - 1);
> - if (!iova_ptr)
> - err = -EADDRINUSE;
> - } else {
> - iova_ptr = alloc_iova(&ep->rma_info.iovad, num_pages,
> - SCIF_DMA_63BIT_PFN - 1, 0);
> - if (!iova_ptr)
> - err = -ENOMEM;
> - }
> - if (!err)
> - *out_offset = (iova_ptr->pfn_lo) << PAGE_SHIFT;
> - return err;
> -}
> -
> -/**
> - * scif_free_window_offset:
> - * @ep: end point descriptor
> - * @window: registration window
> - * @offset: Offset to be freed
> - *
> - * Free offset for this EP. The callee is supposed to grab
> - * the RMA mutex before calling this API.
> - */
> -void scif_free_window_offset(struct scif_endpt *ep,
> - struct scif_window *window, s64 offset)
> -{
> - if ((window && !window->offset_freed) || !window) {
> - free_iova(&ep->rma_info.iovad, offset >> PAGE_SHIFT);
> - if (window)
> - window->offset_freed = true;
> - }
> -}
> -
> -/**
> - * scif_alloc_req: Respond to SCIF_ALLOC_REQ interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remote side is requesting a memory allocation.
> - */
> -void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - int err;
> - struct scif_window *window = NULL;
> - int nr_pages = msg->payload[1];
> -
> - window = scif_create_remote_window(scifdev, nr_pages);
> - if (!window) {
> - err = -ENOMEM;
> - goto error;
> - }
> -
> - /* The peer's allocation request is granted */
> - msg->uop = SCIF_ALLOC_GNT;
> - msg->payload[0] = (u64)window;
> - msg->payload[1] = window->mapped_offset;
> - err = scif_nodeqp_send(scifdev, msg);
> - if (err)
> - scif_destroy_remote_window(window);
> - return;
> -error:
> - /* The peer's allocation request is rejected */
> - dev_err(&scifdev->sdev->dev,
> - "%s %d error %d alloc_ptr %p nr_pages 0x%x\n",
> - __func__, __LINE__, err, window, nr_pages);
> - msg->uop = SCIF_ALLOC_REJ;
> - scif_nodeqp_send(scifdev, msg);
> -}
> -
> -/**
> - * scif_alloc_gnt_rej: Respond to SCIF_ALLOC_GNT/REJ interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remote side responded to a memory allocation.
> - */
> -void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_allocmsg *handle = (struct scif_allocmsg *)msg-
> >payload[2];
> - struct scif_window *window = container_of(handle, struct
> scif_window,
> - alloc_handle);
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - handle->vaddr = msg->payload[0];
> - handle->phys_addr = msg->payload[1];
> - if (msg->uop == SCIF_ALLOC_GNT)
> - handle->state = OP_COMPLETED;
> - else
> - handle->state = OP_FAILED;
> - wake_up(&handle->allocwq);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -/**
> - * scif_free_virt: Respond to SCIF_FREE_VIRT interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Free up memory kmalloc'd earlier.
> - */
> -void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_window *window = (struct scif_window *)msg-
> >payload[1];
> -
> - scif_destroy_remote_window(window);
> -}
> -
> -static void
> -scif_fixup_aper_base(struct scif_dev *dev, struct scif_window *window)
> -{
> - int j;
> - struct scif_hw_dev *sdev = dev->sdev;
> - phys_addr_t apt_base = 0;
> -
> - /*
> - * Add the aperture base if the DMA address is not card relative
> - * since the DMA addresses need to be an offset into the bar
> - */
> - if (!scifdev_self(dev) && window->type == SCIF_WINDOW_PEER &&
> - sdev->aper && !sdev->card_rel_da)
> - apt_base = sdev->aper->pa;
> - else
> - return;
> -
> - for (j = 0; j < window->nr_contig_chunks; j++) {
> - if (window->num_pages[j])
> - window->dma_addr[j] += apt_base;
> - else
> - break;
> - }
> -}
> -
> -/**
> - * scif_recv_reg: Respond to SCIF_REGISTER interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Update remote window list with a new registered window.
> - */
> -void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
> - struct scif_window *window =
> - (struct scif_window *)msg->payload[1];
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - spin_lock(&ep->lock);
> - if (ep->state == SCIFEP_CONNECTED) {
> - msg->uop = SCIF_REGISTER_ACK;
> - scif_nodeqp_send(ep->remote_dev, msg);
> - scif_fixup_aper_base(ep->remote_dev, window);
> - /* No further failures expected. Insert new window */
> - scif_insert_window(window, &ep-
> >rma_info.remote_reg_list);
> - } else {
> - msg->uop = SCIF_REGISTER_NACK;
> - scif_nodeqp_send(ep->remote_dev, msg);
> - }
> - spin_unlock(&ep->lock);
> - mutex_unlock(&ep->rma_info.rma_lock);
> - /* free up any lookup resources now that page lists are transferred
> */
> - scif_destroy_remote_lookup(ep->remote_dev, window);
> - /*
> - * We could not insert the window but we need to
> - * destroy the window.
> - */
> - if (msg->uop == SCIF_REGISTER_NACK)
> - scif_destroy_remote_window(window);
> -}
> -
> -/**
> - * scif_recv_unreg: Respond to SCIF_UNREGISTER interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Remove window from remote registration list;
> - */
> -void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_rma_req req;
> - struct scif_window *window = NULL;
> - struct scif_window *recv_window =
> - (struct scif_window *)msg->payload[0];
> - struct scif_endpt *ep;
> - int del_window = 0;
> -
> - ep = (struct scif_endpt *)recv_window->ep;
> - req.out_window = &window;
> - req.offset = recv_window->offset;
> - req.prot = 0;
> - req.nr_bytes = recv_window->nr_pages << PAGE_SHIFT;
> - req.type = SCIF_WINDOW_FULL;
> - req.head = &ep->rma_info.remote_reg_list;
> - msg->payload[0] = ep->remote_ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Does a valid window exist? */
> - if (scif_query_window(&req)) {
> - dev_err(&scifdev->sdev->dev,
> - "%s %d -ENXIO\n", __func__, __LINE__);
> - msg->uop = SCIF_UNREGISTER_ACK;
> - goto error;
> - }
> - if (window) {
> - if (window->ref_count)
> - scif_put_window(window, window->nr_pages);
> - else
> - dev_err(&scifdev->sdev->dev,
> - "%s %d ref count should be +ve\n",
> - __func__, __LINE__);
> - window->unreg_state = OP_COMPLETED;
> - if (!window->ref_count) {
> - msg->uop = SCIF_UNREGISTER_ACK;
> - atomic_inc(&ep->rma_info.tw_refcount);
> - ep->rma_info.async_list_del = 1;
> - list_del_init(&window->list);
> - del_window = 1;
> - } else {
> - /* NACK! There are valid references to this window
> */
> - msg->uop = SCIF_UNREGISTER_NACK;
> - }
> - } else {
> - /* The window did not make its way to the list at all. ACK */
> - msg->uop = SCIF_UNREGISTER_ACK;
> - scif_destroy_remote_window(recv_window);
> - }
> -error:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (del_window)
> - scif_drain_dma_intr(ep->remote_dev->sdev,
> - ep->rma_info.dma_chan);
> - scif_nodeqp_send(ep->remote_dev, msg);
> - if (del_window)
> - scif_queue_for_cleanup(window, &scif_info.rma);
> -}
> -
> -/**
> - * scif_recv_reg_ack: Respond to SCIF_REGISTER_ACK interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Wake up the window waiting to complete registration.
> - */
> -void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_window *window =
> - (struct scif_window *)msg->payload[2];
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - window->reg_state = OP_COMPLETED;
> - wake_up(&window->regwq);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -/**
> - * scif_recv_reg_nack: Respond to SCIF_REGISTER_NACK interrupt message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Wake up the window waiting to inform it that registration
> - * cannot be completed.
> - */
> -void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_window *window =
> - (struct scif_window *)msg->payload[2];
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - window->reg_state = OP_FAILED;
> - wake_up(&window->regwq);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -/**
> - * scif_recv_unreg_ack: Respond to SCIF_UNREGISTER_ACK interrupt
> message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Wake up the window waiting to complete unregistration.
> - */
> -void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_window *window =
> - (struct scif_window *)msg->payload[1];
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - window->unreg_state = OP_COMPLETED;
> - wake_up(&window->unregwq);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -/**
> - * scif_recv_unreg_nack: Respond to SCIF_UNREGISTER_NACK interrupt
> message
> - * @scifdev: SCIF device
> - * @msg: Interrupt message
> - *
> - * Wake up the window waiting to inform it that unregistration
> - * cannot be completed immediately.
> - */
> -void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg)
> -{
> - struct scif_window *window =
> - (struct scif_window *)msg->payload[1];
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - window->unreg_state = OP_FAILED;
> - wake_up(&window->unregwq);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -int __scif_pin_pages(void *addr, size_t len, int *out_prot,
> - int map_flags, scif_pinned_pages_t *pages)
> -{
> - struct scif_pinned_pages *pinned_pages;
> - int nr_pages, err = 0, i;
> - bool vmalloc_addr = false;
> - bool try_upgrade = false;
> - int prot = *out_prot;
> - int ulimit = 0;
> - struct mm_struct *mm = NULL;
> -
> - /* Unsupported flags */
> - if (map_flags & ~(SCIF_MAP_KERNEL | SCIF_MAP_ULIMIT))
> - return -EINVAL;
> - ulimit = !!(map_flags & SCIF_MAP_ULIMIT);
> -
> - /* Unsupported protection requested */
> - if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
> - return -EINVAL;
> -
> - /* addr/len must be page aligned. len should be non zero */
> - if (!len ||
> - (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
> - (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
> - return -EINVAL;
> -
> - might_sleep();
> -
> - nr_pages = len >> PAGE_SHIFT;
> -
> - /* Allocate a set of pinned pages */
> - pinned_pages = scif_create_pinned_pages(nr_pages, prot);
> - if (!pinned_pages)
> - return -ENOMEM;
> -
> - if (map_flags & SCIF_MAP_KERNEL) {
> - if (is_vmalloc_addr(addr))
> - vmalloc_addr = true;
> -
> - for (i = 0; i < nr_pages; i++) {
> - if (vmalloc_addr)
> - pinned_pages->pages[i] =
> - vmalloc_to_page(addr + (i *
> PAGE_SIZE));
> - else
> - pinned_pages->pages[i] =
> - virt_to_page(addr + (i * PAGE_SIZE));
> - }
> - pinned_pages->nr_pages = nr_pages;
> - pinned_pages->map_flags = SCIF_MAP_KERNEL;
> - } else {
> - /*
> - * SCIF supports registration caching. If a registration has
> - * been requested with read only permissions, then we try
> - * to pin the pages with RW permissions so that a subsequent
> - * transfer with RW permission can hit the cache instead of
> - * invalidating it. If the upgrade fails with RW then we
> - * revert back to R permission and retry
> - */
> - if (prot == SCIF_PROT_READ)
> - try_upgrade = true;
> - prot |= SCIF_PROT_WRITE;
> -retry:
> - mm = current->mm;
> - if (ulimit) {
> - err = __scif_check_inc_pinned_vm(mm, nr_pages);
> - if (err) {
> - pinned_pages->nr_pages = 0;
> - goto error_unmap;
> - }
> - }
> -
> - pinned_pages->nr_pages = pin_user_pages_fast(
> - (u64)addr,
> - nr_pages,
> - (prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
> - pinned_pages->pages);
> - if (nr_pages != pinned_pages->nr_pages) {
> - if (pinned_pages->nr_pages < 0)
> - pinned_pages->nr_pages = 0;
> - if (try_upgrade) {
> - if (ulimit)
> - __scif_dec_pinned_vm_lock(mm,
> nr_pages);
> - /* Roll back any pinned pages */
> - unpin_user_pages(pinned_pages->pages,
> - pinned_pages->nr_pages);
> - prot &= ~SCIF_PROT_WRITE;
> - try_upgrade = false;
> - goto retry;
> - }
> - }
> - pinned_pages->map_flags = 0;
> - }
> -
> - if (pinned_pages->nr_pages < nr_pages) {
> - err = -EFAULT;
> - goto dec_pinned;
> - }
> -
> - *out_prot = prot;
> - atomic_set(&pinned_pages->ref_count, 1);
> - *pages = pinned_pages;
> - return err;
> -dec_pinned:
> - if (ulimit)
> - __scif_dec_pinned_vm_lock(mm, nr_pages);
> - /* Something went wrong! Rollback */
> -error_unmap:
> - scif_destroy_pinned_pages(pinned_pages);
> - *pages = NULL;
> - dev_dbg(scif_info.mdev.this_device,
> - "%s %d err %d len 0x%lx\n", __func__, __LINE__, err, len);
> - return err;
> -}
> -
> -int scif_pin_pages(void *addr, size_t len, int prot,
> - int map_flags, scif_pinned_pages_t *pages)
> -{
> - return __scif_pin_pages(addr, len, &prot, map_flags, pages);
> -}
> -EXPORT_SYMBOL_GPL(scif_pin_pages);
> -
> -int scif_unpin_pages(scif_pinned_pages_t pinned_pages)
> -{
> - int err = 0, ret;
> -
> - if (!pinned_pages || SCIFEP_MAGIC != pinned_pages->magic)
> - return -EINVAL;
> -
> - ret = atomic_sub_return(1, &pinned_pages->ref_count);
> - if (ret < 0) {
> - dev_err(scif_info.mdev.this_device,
> - "%s %d scif_unpin_pages called without pinning?
> rc %d\n",
> - __func__, __LINE__, ret);
> - return -EINVAL;
> - }
> - /*
> - * Destroy the window if the ref count for this set of pinned
> - * pages has dropped to zero. If it is positive then there is
> - * a valid registered window which is backed by these pages and
> - * it will be destroyed once all such windows are unregistered.
> - */
> - if (!ret)
> - err = scif_destroy_pinned_pages(pinned_pages);
> -
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_unpin_pages);
> -
> -static inline void
> -scif_insert_local_window(struct scif_window *window, struct scif_endpt
> *ep)
> -{
> - mutex_lock(&ep->rma_info.rma_lock);
> - scif_insert_window(window, &ep->rma_info.reg_list);
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -off_t scif_register_pinned_pages(scif_epd_t epd,
> - scif_pinned_pages_t pinned_pages,
> - off_t offset, int map_flags)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - s64 computed_offset;
> - struct scif_window *window;
> - int err;
> - size_t len;
> - struct device *spdev;
> -
> - /* Unsupported flags */
> - if (map_flags & ~SCIF_MAP_FIXED)
> - return -EINVAL;
> -
> - len = pinned_pages->nr_pages << PAGE_SHIFT;
> -
> - /*
> - * Offset is not page aligned/negative or offset+len
> - * wraps around with SCIF_MAP_FIXED.
> - */
> - if ((map_flags & SCIF_MAP_FIXED) &&
> - ((ALIGN(offset, PAGE_SIZE) != offset) ||
> - (offset < 0) ||
> - (len > LONG_MAX - offset)))
> - return -EINVAL;
> -
> - might_sleep();
> -
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> - /*
> - * It is an error to pass pinned_pages to scif_register_pinned_pages()
> - * after calling scif_unpin_pages().
> - */
> - if (!atomic_add_unless(&pinned_pages->ref_count, 1, 0))
> - return -EINVAL;
> -
> - /* Compute the offset for this registration */
> - err = scif_get_window_offset(ep, map_flags, offset,
> - len, &computed_offset);
> - if (err) {
> - atomic_sub(1, &pinned_pages->ref_count);
> - return err;
> - }
> -
> - /* Allocate and prepare self registration window */
> - window = scif_create_window(ep, pinned_pages->nr_pages,
> - computed_offset, false);
> - if (!window) {
> - atomic_sub(1, &pinned_pages->ref_count);
> - scif_free_window_offset(ep, NULL, computed_offset);
> - return -ENOMEM;
> - }
> -
> - window->pinned_pages = pinned_pages;
> - window->nr_pages = pinned_pages->nr_pages;
> - window->prot = pinned_pages->prot;
> -
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - scif_destroy_window(ep, window);
> - return err;
> - }
> - err = scif_send_alloc_request(ep, window);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error_unmap;
> - }
> -
> - /* Prepare the remote registration window */
> - err = scif_prep_remote_window(ep, window);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error_unmap;
> - }
> -
> - /* Tell the peer about the new window */
> - err = scif_send_scif_register(ep, window);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error_unmap;
> - }
> -
> - scif_put_peer_dev(spdev);
> - /* No further failures expected. Insert new window */
> - scif_insert_local_window(window, ep);
> - return computed_offset;
> -error_unmap:
> - scif_destroy_window(ep, window);
> - scif_put_peer_dev(spdev);
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_register_pinned_pages);
> -
> -off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset,
> - int prot, int map_flags)
> -{
> - scif_pinned_pages_t pinned_pages;
> - off_t err;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - s64 computed_offset;
> - struct scif_window *window;
> - struct mm_struct *mm = NULL;
> - struct device *spdev;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI register: ep %p addr %p len 0x%lx offset 0x%lx prot
> 0x%x map_flags 0x%x\n",
> - epd, addr, len, offset, prot, map_flags);
> - /* Unsupported flags */
> - if (map_flags & ~(SCIF_MAP_FIXED | SCIF_MAP_KERNEL))
> - return -EINVAL;
> -
> - /*
> - * Offset is not page aligned/negative or offset+len
> - * wraps around with SCIF_MAP_FIXED.
> - */
> - if ((map_flags & SCIF_MAP_FIXED) &&
> - ((ALIGN(offset, PAGE_SIZE) != offset) ||
> - (offset < 0) ||
> - (len > LONG_MAX - offset)))
> - return -EINVAL;
> -
> - /* Unsupported protection requested */
> - if (prot & ~(SCIF_PROT_READ | SCIF_PROT_WRITE))
> - return -EINVAL;
> -
> - /* addr/len must be page aligned. len should be non zero */
> - if (!len || (ALIGN((u64)addr, PAGE_SIZE) != (u64)addr) ||
> - (ALIGN(len, PAGE_SIZE) != len))
> - return -EINVAL;
> -
> - might_sleep();
> -
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - /* Compute the offset for this registration */
> - err = scif_get_window_offset(ep, map_flags, offset,
> - len >> PAGE_SHIFT, &computed_offset);
> - if (err)
> - return err;
> -
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - scif_free_window_offset(ep, NULL, computed_offset);
> - return err;
> - }
> - /* Allocate and prepare self registration window */
> - window = scif_create_window(ep, len >> PAGE_SHIFT,
> - computed_offset, false);
> - if (!window) {
> - scif_free_window_offset(ep, NULL, computed_offset);
> - scif_put_peer_dev(spdev);
> - return -ENOMEM;
> - }
> -
> - window->nr_pages = len >> PAGE_SHIFT;
> -
> - err = scif_send_alloc_request(ep, window);
> - if (err) {
> - scif_destroy_incomplete_window(ep, window);
> - scif_put_peer_dev(spdev);
> - return err;
> - }
> -
> - if (!(map_flags & SCIF_MAP_KERNEL)) {
> - mm = __scif_acquire_mm();
> - map_flags |= SCIF_MAP_ULIMIT;
> - }
> - /* Pin down the pages */
> - err = __scif_pin_pages(addr, len, &prot,
> - map_flags & (SCIF_MAP_KERNEL |
> SCIF_MAP_ULIMIT),
> - &pinned_pages);
> - if (err) {
> - scif_destroy_incomplete_window(ep, window);
> - __scif_release_mm(mm);
> - goto error;
> - }
> -
> - window->pinned_pages = pinned_pages;
> - window->prot = pinned_pages->prot;
> - window->mm = mm;
> -
> - /* Prepare the remote registration window */
> - err = scif_prep_remote_window(ep, window);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %ld\n", __func__, __LINE__, err);
> - goto error_unmap;
> - }
> -
> - /* Tell the peer about the new window */
> - err = scif_send_scif_register(ep, window);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %ld\n", __func__, __LINE__, err);
> - goto error_unmap;
> - }
> -
> - scif_put_peer_dev(spdev);
> - /* No further failures expected. Insert new window */
> - scif_insert_local_window(window, ep);
> - dev_dbg(&ep->remote_dev->sdev->dev,
> - "SCIFAPI register: ep %p addr %p len 0x%lx computed_offset
> 0x%llx\n",
> - epd, addr, len, computed_offset);
> - return computed_offset;
> -error_unmap:
> - scif_destroy_window(ep, window);
> -error:
> - scif_put_peer_dev(spdev);
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %ld\n", __func__, __LINE__, err);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_register);
> -
> -int
> -scif_unregister(scif_epd_t epd, off_t offset, size_t len)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct scif_window *window = NULL;
> - struct scif_rma_req req;
> - int nr_pages, err;
> - struct device *spdev;
> -
> - dev_dbg(scif_info.mdev.this_device,
> - "SCIFAPI unregister: ep %p offset 0x%lx len 0x%lx\n",
> - ep, offset, len);
> - /* len must be page aligned. len should be non zero */
> - if (!len ||
> - (ALIGN((u64)len, PAGE_SIZE) != (u64)len))
> - return -EINVAL;
> -
> - /* Offset is not page aligned or offset+len wraps around */
> - if ((ALIGN(offset, PAGE_SIZE) != offset) ||
> - (offset < 0) ||
> - (len > LONG_MAX - offset))
> - return -EINVAL;
> -
> - err = scif_verify_epd(ep);
> - if (err)
> - return err;
> -
> - might_sleep();
> - nr_pages = len >> PAGE_SHIFT;
> -
> - req.out_window = &window;
> - req.offset = offset;
> - req.prot = 0;
> - req.nr_bytes = len;
> - req.type = SCIF_WINDOW_FULL;
> - req.head = &ep->rma_info.reg_list;
> -
> - spdev = scif_get_peer_dev(ep->remote_dev);
> - if (IS_ERR(spdev)) {
> - err = PTR_ERR(spdev);
> - return err;
> - }
> - mutex_lock(&ep->rma_info.rma_lock);
> - /* Does a valid window exist? */
> - err = scif_query_window(&req);
> - if (err) {
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> - goto error;
> - }
> - /* Unregister all the windows in this range */
> - err = scif_rma_list_unregister(window, offset, nr_pages);
> - if (err)
> - dev_err(&ep->remote_dev->sdev->dev,
> - "%s %d err %d\n", __func__, __LINE__, err);
> -error:
> - mutex_unlock(&ep->rma_info.rma_lock);
> - scif_put_peer_dev(spdev);
> - return err;
> -}
> -EXPORT_SYMBOL_GPL(scif_unregister);
> diff --git a/drivers/misc/mic/scif/scif_rma.h
> b/drivers/misc/mic/scif/scif_rma.h
> deleted file mode 100644
> index 964dd0fc3657..000000000000
> --- a/drivers/misc/mic/scif/scif_rma.h
> +++ /dev/null
> @@ -1,477 +0,0 @@
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * This file is provided under a dual BSD/GPLv2 license. When using or
> - * redistributing this file, you may do so under either license.
> - *
> - * GPL LICENSE SUMMARY
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * BSD LICENSE
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - * * Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in
> - * the documentation and/or other materials provided with the
> - * distribution.
> - * * Neither the name of Intel Corporation nor the names of its
> - * contributors may be used to endorse or promote products derived
> - * from this software without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> ON ANY
> - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> - *
> - * Intel SCIF driver.
> - *
> - */
> -#ifndef SCIF_RMA_H
> -#define SCIF_RMA_H
> -
> -#include <linux/intel-iommu.h>
> -#include <linux/mmu_notifier.h>
> -
> -#include "../bus/scif_bus.h"
> -
> -/* If this bit is set then the mark is a remote fence mark */
> -#define SCIF_REMOTE_FENCE_BIT 31
> -/* Magic value used to indicate a remote fence request */
> -#define SCIF_REMOTE_FENCE BIT_ULL(SCIF_REMOTE_FENCE_BIT)
> -
> -#define SCIF_MAX_UNALIGNED_BUF_SIZE (1024 * 1024ULL)
> -#define SCIF_KMEM_UNALIGNED_BUF_SIZE
> (SCIF_MAX_UNALIGNED_BUF_SIZE + \
> - (L1_CACHE_BYTES << 1))
> -
> -#define SCIF_IOVA_START_PFN (1)
> -#define SCIF_IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
> -#define SCIF_DMA_64BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(64))
> -#define SCIF_DMA_63BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(63))
> -
> -/*
> - * struct scif_endpt_rma_info - Per Endpoint Remote Memory Access
> Information
> - *
> - * @reg_list: List of registration windows for self
> - * @remote_reg_list: List of registration windows for peer
> - * @iovad: Offset generator
> - * @rma_lock: Synchronizes access to self/remote list and also protects the
> - * window from being destroyed while RMAs are in progress.
> - * @tc_lock: Synchronizes access to temporary cached windows list
> - * for SCIF Registration Caching.
> - * @mmn_lock: Synchronizes access to the list of MMU notifiers registered
> - * @tw_refcount: Keeps track of number of outstanding temporary
> registered
> - * windows created by scif_vreadfrom/scif_vwriteto which
> have
> - * not been destroyed.
> - * @tcw_refcount: Same as tw_refcount but for temporary cached windows
> - * @tcw_total_pages: Same as tcw_refcount but in terms of pages pinned
> - * @mmn_list: MMU notifier so that we can destroy the windows when
> required
> - * @fence_refcount: Keeps track of number of outstanding remote fence
> - * requests which have been received by the peer.
> - * @dma_chan: DMA channel used for all DMA transfers for this endpoint.
> - * @async_list_del: Detect asynchronous list entry deletion
> - * @vma_list: List of vmas with remote memory mappings
> - * @markwq: Wait queue used for scif_fence_mark/scif_fence_wait
> -*/
> -struct scif_endpt_rma_info {
> - struct list_head reg_list;
> - struct list_head remote_reg_list;
> - struct iova_domain iovad;
> - struct mutex rma_lock;
> - spinlock_t tc_lock;
> - struct mutex mmn_lock;
> - atomic_t tw_refcount;
> - atomic_t tcw_refcount;
> - atomic_t tcw_total_pages;
> - struct list_head mmn_list;
> - atomic_t fence_refcount;
> - struct dma_chan *dma_chan;
> - int async_list_del;
> - struct list_head vma_list;
> - wait_queue_head_t markwq;
> -};
> -
> -/*
> - * struct scif_fence_info - used for tracking fence requests
> - *
> - * @state: State of this transfer
> - * @wq: Fences wait on this queue
> - * @dma_mark: Used for storing the DMA mark
> - */
> -struct scif_fence_info {
> - enum scif_msg_state state;
> - struct completion comp;
> - int dma_mark;
> -};
> -
> -/*
> - * struct scif_remote_fence_info - used for tracking remote fence requests
> - *
> - * @msg: List of SCIF node QP fence messages
> - * @list: Link to list of remote fence requests
> - */
> -struct scif_remote_fence_info {
> - struct scifmsg msg;
> - struct list_head list;
> -};
> -
> -/*
> - * Specifies whether an RMA operation can span across partial windows, a
> single
> - * window or multiple contiguous windows. Mmaps can span across partial
> windows.
> - * Unregistration can span across complete windows. scif_get_pages() can
> span a
> - * single window. A window can also be of type self or peer.
> - */
> -enum scif_window_type {
> - SCIF_WINDOW_PARTIAL,
> - SCIF_WINDOW_SINGLE,
> - SCIF_WINDOW_FULL,
> - SCIF_WINDOW_SELF,
> - SCIF_WINDOW_PEER
> -};
> -
> -/* The number of physical addresses that can be stored in a PAGE. */
> -#define SCIF_NR_ADDR_IN_PAGE (0x1000 >> 3)
> -
> -/*
> - * struct scif_rma_lookup - RMA lookup data structure for page list transfers
> - *
> - * Store an array of lookup offsets. Each offset in this array maps
> - * one 4K page containing 512 physical addresses i.e. 2MB. 512 such
> - * offsets in a 4K page will correspond to 1GB of registered address space.
> -
> - * @lookup: Array of offsets
> - * @offset: DMA offset of lookup array
> - */
> -struct scif_rma_lookup {
> - dma_addr_t *lookup;
> - dma_addr_t offset;
> -};
> -
> -/*
> - * struct scif_pinned_pages - A set of pinned pages obtained with
> - * scif_pin_pages() which could be part of multiple registered
> - * windows across different end points.
> - *
> - * @nr_pages: Number of pages which is defined as a s64 instead of an int
> - * to avoid sign extension with buffers >= 2GB
> - * @prot: read/write protections
> - * @map_flags: Flags specified during the pin operation
> - * @ref_count: Reference count bumped in terms of number of pages
> - * @magic: A magic value
> - * @pages: Array of pointers to struct pages populated with
> get_user_pages(..)
> - */
> -struct scif_pinned_pages {
> - s64 nr_pages;
> - int prot;
> - int map_flags;
> - atomic_t ref_count;
> - u64 magic;
> - struct page **pages;
> -};
> -
> -/*
> - * struct scif_status - Stores DMA status update information
> - *
> - * @src_dma_addr: Source buffer DMA address
> - * @val: src location for value to be written to the destination
> - * @ep: SCIF endpoint
> - */
> -struct scif_status {
> - dma_addr_t src_dma_addr;
> - u64 val;
> - struct scif_endpt *ep;
> -};
> -
> -/*
> - * struct scif_cb_arg - Stores the argument of the callback func
> - *
> - * @src_dma_addr: Source buffer DMA address
> - * @status: DMA status
> - * @ep: SCIF endpoint
> - */
> -struct scif_cb_arg {
> - dma_addr_t src_dma_addr;
> - struct scif_status *status;
> - struct scif_endpt *ep;
> -};
> -
> -/*
> - * struct scif_window - Registration Window for Self and Remote
> - *
> - * @nr_pages: Number of pages which is defined as a s64 instead of an int
> - * to avoid sign extension with buffers >= 2GB
> - * @nr_contig_chunks: Number of contiguous physical chunks
> - * @prot: read/write protections
> - * @ref_count: reference count in terms of number of pages
> - * @magic: Cookie to detect corruption
> - * @offset: registered offset
> - * @va_for_temp: va address that this window represents
> - * @dma_mark: Used to determine if all DMAs against the window are done
> - * @ep: Pointer to EP. Useful for passing EP around with messages to
> - avoid expensive list traversals.
> - * @list: link to list of windows for the endpoint
> - * @type: self or peer window
> - * @peer_window: Pointer to peer window. Useful for sending messages to
> peer
> - * without requiring an extra list traversal
> - * @unreg_state: unregistration state
> - * @offset_freed: True if the offset has been freed
> - * @temp: True for temporary windows created via
> scif_vreadfrom/scif_vwriteto
> - * @mm: memory descriptor for the task_struct which initiated the RMA
> - * @st: scatter gather table for DMA mappings with IOMMU enabled
> - * @pinned_pages: The set of pinned_pages backing this window
> - * @alloc_handle: Handle for sending ALLOC_REQ
> - * @regwq: Wait Queue for an registration (N)ACK
> - * @reg_state: Registration state
> - * @unregwq: Wait Queue for an unregistration (N)ACK
> - * @dma_addr_lookup: Lookup for physical addresses used for DMA
> - * @nr_lookup: Number of entries in lookup
> - * @mapped_offset: Offset used to map the window by the peer
> - * @dma_addr: Array of physical addresses used for Mgmt node & MIC
> initiated DMA
> - * @num_pages: Array specifying number of pages for each physical address
> - */
> -struct scif_window {
> - s64 nr_pages;
> - int nr_contig_chunks;
> - int prot;
> - int ref_count;
> - u64 magic;
> - s64 offset;
> - unsigned long va_for_temp;
> - int dma_mark;
> - u64 ep;
> - struct list_head list;
> - enum scif_window_type type;
> - u64 peer_window;
> - enum scif_msg_state unreg_state;
> - bool offset_freed;
> - bool temp;
> - struct mm_struct *mm;
> - struct sg_table *st;
> - union {
> - struct {
> - struct scif_pinned_pages *pinned_pages;
> - struct scif_allocmsg alloc_handle;
> - wait_queue_head_t regwq;
> - enum scif_msg_state reg_state;
> - wait_queue_head_t unregwq;
> - };
> - struct {
> - struct scif_rma_lookup dma_addr_lookup;
> - struct scif_rma_lookup num_pages_lookup;
> - int nr_lookup;
> - dma_addr_t mapped_offset;
> - };
> - };
> - dma_addr_t *dma_addr;
> - u64 *num_pages;
> -} __packed;
> -
> -/*
> - * scif_mmu_notif - SCIF mmu notifier information
> - *
> - * @mmu_notifier ep_mmu_notifier: MMU notifier operations
> - * @tc_reg_list: List of temp registration windows for self
> - * @mm: memory descriptor for the task_struct which initiated the RMA
> - * @ep: SCIF endpoint
> - * @list: link to list of MMU notifier information
> - */
> -struct scif_mmu_notif {
> -#ifdef CONFIG_MMU_NOTIFIER
> - struct mmu_notifier ep_mmu_notifier;
> -#endif
> - struct list_head tc_reg_list;
> - struct mm_struct *mm;
> - struct scif_endpt *ep;
> - struct list_head list;
> -};
> -
> -enum scif_rma_dir {
> - SCIF_LOCAL_TO_REMOTE,
> - SCIF_REMOTE_TO_LOCAL
> -};
> -
> -extern struct kmem_cache *unaligned_cache;
> -/* Initialize RMA for this EP */
> -void scif_rma_ep_init(struct scif_endpt *ep);
> -/* Check if epd can be uninitialized */
> -int scif_rma_ep_can_uninit(struct scif_endpt *ep);
> -/* Obtain a new offset. Callee must grab RMA lock */
> -int scif_get_window_offset(struct scif_endpt *ep, int flags,
> - s64 offset, int nr_pages, s64 *out_offset);
> -/* Free offset. Callee must grab RMA lock */
> -void scif_free_window_offset(struct scif_endpt *ep,
> - struct scif_window *window, s64 offset);
> -/* Create self registration window */
> -struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
> - s64 offset, bool temp);
> -/* Destroy self registration window.*/
> -int scif_destroy_window(struct scif_endpt *ep, struct scif_window
> *window);
> -void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window
> *window);
> -/* Map pages of self window to Aperture/PCI */
> -int scif_map_window(struct scif_dev *remote_dev,
> - struct scif_window *window);
> -/* Unregister a self window */
> -int scif_unregister_window(struct scif_window *window);
> -/* Destroy remote registration window */
> -void
> -scif_destroy_remote_window(struct scif_window *window);
> -/* remove valid remote memory mappings from process address space */
> -void scif_zap_mmaps(int node);
> -/* Query if any applications have remote memory mappings */
> -bool scif_rma_do_apps_have_mmaps(int node);
> -/* Cleanup remote registration lists for zombie endpoints */
> -void scif_cleanup_rma_for_zombies(int node);
> -/* Reserve a DMA channel for a particular endpoint */
> -int scif_reserve_dma_chan(struct scif_endpt *ep);
> -/* Setup a DMA mark for an endpoint */
> -int _scif_fence_mark(scif_epd_t epd, int *mark);
> -int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
> - enum scif_window_type type);
> -void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg);
> -void scif_mmu_notif_handler(struct work_struct *work);
> -void scif_rma_handle_remote_fences(void);
> -void scif_rma_destroy_windows(void);
> -void scif_rma_destroy_tcw_invalid(void);
> -int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan);
> -
> -struct scif_window_iter {
> - s64 offset;
> - int index;
> -};
> -
> -static inline void
> -scif_init_window_iter(struct scif_window *window, struct scif_window_iter
> *iter)
> -{
> - iter->offset = window->offset;
> - iter->index = 0;
> -}
> -
> -dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
> - size_t *nr_bytes,
> - struct scif_window_iter *iter);
> -static inline
> -dma_addr_t __scif_off_to_dma_addr(struct scif_window *window, s64 off)
> -{
> - return scif_off_to_dma_addr(window, off, NULL, NULL);
> -}
> -
> -static inline bool scif_unaligned(off_t src_offset, off_t dst_offset)
> -{
> - src_offset = src_offset & (L1_CACHE_BYTES - 1);
> - dst_offset = dst_offset & (L1_CACHE_BYTES - 1);
> - return !(src_offset == dst_offset);
> -}
> -
> -/*
> - * scif_zalloc:
> - * @size: Size of the allocation request.
> - *
> - * Helper API which attempts to allocate zeroed pages via
> - * __get_free_pages(..) first and then falls back on
> - * vzalloc(..) if that fails.
> - */
> -static inline void *scif_zalloc(size_t size)
> -{
> - void *ret = NULL;
> - size_t align = ALIGN(size, PAGE_SIZE);
> -
> - if (align && get_order(align) < MAX_ORDER)
> - ret = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> - get_order(align));
> - return ret ? ret : vzalloc(align);
> -}
> -
> -/*
> - * scif_free:
> - * @addr: Address to be freed.
> - * @size: Size of the allocation.
> - * Helper API which frees memory allocated via scif_zalloc().
> - */
> -static inline void scif_free(void *addr, size_t size)
> -{
> - size_t align = ALIGN(size, PAGE_SIZE);
> -
> - if (is_vmalloc_addr(addr))
> - vfree(addr);
> - else
> - free_pages((unsigned long)addr, get_order(align));
> -}
> -
> -static inline void scif_get_window(struct scif_window *window, int nr_pages)
> -{
> - window->ref_count += nr_pages;
> -}
> -
> -static inline void scif_put_window(struct scif_window *window, int
> nr_pages)
> -{
> - window->ref_count -= nr_pages;
> -}
> -
> -static inline void scif_set_window_ref(struct scif_window *window, int
> nr_pages)
> -{
> - window->ref_count = nr_pages;
> -}
> -
> -static inline void
> -scif_queue_for_cleanup(struct scif_window *window, struct list_head *list)
> -{
> - spin_lock(&scif_info.rmalock);
> - list_add_tail(&window->list, list);
> - spin_unlock(&scif_info.rmalock);
> - schedule_work(&scif_info.misc_work);
> -}
> -
> -static inline void __scif_rma_destroy_tcw_helper(struct scif_window
> *window)
> -{
> - list_del_init(&window->list);
> - scif_queue_for_cleanup(window, &scif_info.rma_tc);
> -}
> -
> -static inline bool scif_is_iommu_enabled(void)
> -{
> -#ifdef CONFIG_INTEL_IOMMU
> - return intel_iommu_enabled;
> -#else
> - return false;
> -#endif
> -}
> -#endif /* SCIF_RMA_H */
> diff --git a/drivers/misc/mic/scif/scif_rma_list.c
> b/drivers/misc/mic/scif/scif_rma_list.c
> deleted file mode 100644
> index ef923ba134c8..000000000000
> --- a/drivers/misc/mic/scif/scif_rma_list.c
> +++ /dev/null
> @@ -1,282 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#include "scif_main.h"
> -#include <linux/mmu_notifier.h>
> -#include <linux/highmem.h>
> -
> -/*
> - * scif_insert_tcw:
> - *
> - * Insert a temp window to the temp registration list sorted by va_for_temp.
> - * RMA lock must be held.
> - */
> -void scif_insert_tcw(struct scif_window *window, struct list_head *head)
> -{
> - struct scif_window *curr = NULL;
> - struct scif_window *prev = list_entry(head, struct scif_window, list);
> - struct list_head *item;
> -
> - INIT_LIST_HEAD(&window->list);
> - /* Compare with tail and if the entry is new tail add it to the end */
> - if (!list_empty(head)) {
> - curr = list_entry(head->prev, struct scif_window, list);
> - if (curr->va_for_temp < window->va_for_temp) {
> - list_add_tail(&window->list, head);
> - return;
> - }
> - }
> - list_for_each(item, head) {
> - curr = list_entry(item, struct scif_window, list);
> - if (curr->va_for_temp > window->va_for_temp)
> - break;
> - prev = curr;
> - }
> - list_add(&window->list, &prev->list);
> -}
> -
> -/*
> - * scif_insert_window:
> - *
> - * Insert a window to the self registration list sorted by offset.
> - * RMA lock must be held.
> - */
> -void scif_insert_window(struct scif_window *window, struct list_head
> *head)
> -{
> - struct scif_window *curr = NULL, *prev = NULL;
> - struct list_head *item;
> -
> - INIT_LIST_HEAD(&window->list);
> - list_for_each(item, head) {
> - curr = list_entry(item, struct scif_window, list);
> - if (curr->offset > window->offset)
> - break;
> - prev = curr;
> - }
> - if (!prev)
> - list_add(&window->list, head);
> - else
> - list_add(&window->list, &prev->list);
> - scif_set_window_ref(window, window->nr_pages);
> -}
> -
> -/*
> - * scif_query_tcw:
> - *
> - * Query the temp cached registration list of ep for an overlapping window
> - * in case of permission mismatch, destroy the previous window. if
> permissions
> - * match and overlap is partial, destroy the window but return the new
> range
> - * RMA lock must be held.
> - */
> -int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *req)
> -{
> - struct list_head *item, *temp, *head = req->head;
> - struct scif_window *window;
> - u64 start_va_window, start_va_req = req->va_for_temp;
> - u64 end_va_window, end_va_req = start_va_req + req->nr_bytes;
> -
> - if (!req->nr_bytes)
> - return -EINVAL;
> - /*
> - * Avoid traversing the entire list to find out that there
> - * is no entry that matches
> - */
> - if (!list_empty(head)) {
> - window = list_last_entry(head, struct scif_window, list);
> - end_va_window = window->va_for_temp +
> - (window->nr_pages << PAGE_SHIFT);
> - if (start_va_req > end_va_window)
> - return -ENXIO;
> - }
> - list_for_each_safe(item, temp, head) {
> - window = list_entry(item, struct scif_window, list);
> - start_va_window = window->va_for_temp;
> - end_va_window = window->va_for_temp +
> - (window->nr_pages << PAGE_SHIFT);
> - if (start_va_req < start_va_window &&
> - end_va_req < start_va_window)
> - break;
> - if (start_va_req >= end_va_window)
> - continue;
> - if ((window->prot & req->prot) == req->prot) {
> - if (start_va_req >= start_va_window &&
> - end_va_req <= end_va_window) {
> - *req->out_window = window;
> - return 0;
> - }
> - /* expand window */
> - if (start_va_req < start_va_window) {
> - req->nr_bytes +=
> - start_va_window - start_va_req;
> - req->va_for_temp = start_va_window;
> - }
> - if (end_va_req >= end_va_window)
> - req->nr_bytes += end_va_window -
> end_va_req;
> - }
> - /* Destroy the old window to create a new one */
> - __scif_rma_destroy_tcw_helper(window);
> - break;
> - }
> - return -ENXIO;
> -}
> -
> -/*
> - * scif_query_window:
> - *
> - * Query the registration list and check if a valid contiguous
> - * range of windows exist.
> - * RMA lock must be held.
> - */
> -int scif_query_window(struct scif_rma_req *req)
> -{
> - struct list_head *item;
> - struct scif_window *window;
> - s64 end_offset, offset = req->offset;
> - u64 tmp_min, nr_bytes_left = req->nr_bytes;
> -
> - if (!req->nr_bytes)
> - return -EINVAL;
> -
> - list_for_each(item, req->head) {
> - window = list_entry(item, struct scif_window, list);
> - end_offset = window->offset +
> - (window->nr_pages << PAGE_SHIFT);
> - if (offset < window->offset)
> - /* Offset not found! */
> - return -ENXIO;
> - if (offset >= end_offset)
> - continue;
> - /* Check read/write protections. */
> - if ((window->prot & req->prot) != req->prot)
> - return -EPERM;
> - if (nr_bytes_left == req->nr_bytes)
> - /* Store the first window */
> - *req->out_window = window;
> - tmp_min = min((u64)end_offset - offset, nr_bytes_left);
> - nr_bytes_left -= tmp_min;
> - offset += tmp_min;
> - /*
> - * Range requested encompasses
> - * multiple windows contiguously.
> - */
> - if (!nr_bytes_left) {
> - /* Done for partial window */
> - if (req->type == SCIF_WINDOW_PARTIAL ||
> - req->type == SCIF_WINDOW_SINGLE)
> - return 0;
> - /* Extra logic for full windows */
> - if (offset == end_offset)
> - /* Spanning multiple whole windows */
> - return 0;
> - /* Not spanning multiple whole windows */
> - return -ENXIO;
> - }
> - if (req->type == SCIF_WINDOW_SINGLE)
> - break;
> - }
> - dev_err(scif_info.mdev.this_device,
> - "%s %d ENXIO\n", __func__, __LINE__);
> - return -ENXIO;
> -}
> -
> -/*
> - * scif_rma_list_unregister:
> - *
> - * Traverse the self registration list starting from window:
> - * 1) Call scif_unregister_window(..)
> - * RMA lock must be held.
> - */
> -int scif_rma_list_unregister(struct scif_window *window,
> - s64 offset, int nr_pages)
> -{
> - struct scif_endpt *ep = (struct scif_endpt *)window->ep;
> - struct list_head *head = &ep->rma_info.reg_list;
> - s64 end_offset;
> - int err = 0;
> - int loop_nr_pages;
> - struct scif_window *_window;
> -
> - list_for_each_entry_safe_from(window, _window, head, list) {
> - end_offset = window->offset + (window->nr_pages <<
> PAGE_SHIFT);
> - loop_nr_pages = min((int)((end_offset - offset) >>
> PAGE_SHIFT),
> - nr_pages);
> - err = scif_unregister_window(window);
> - if (err)
> - return err;
> - nr_pages -= loop_nr_pages;
> - offset += (loop_nr_pages << PAGE_SHIFT);
> - if (!nr_pages)
> - break;
> - }
> - return 0;
> -}
> -
> -/*
> - * scif_unmap_all_window:
> - *
> - * Traverse all the windows in the self registration list and:
> - * 1) Delete any DMA mappings created
> - */
> -void scif_unmap_all_windows(scif_epd_t epd)
> -{
> - struct list_head *item, *tmp;
> - struct scif_window *window;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct list_head *head = &ep->rma_info.reg_list;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> - list_for_each_safe(item, tmp, head) {
> - window = list_entry(item, struct scif_window, list);
> - scif_unmap_window(ep->remote_dev, window);
> - }
> - mutex_unlock(&ep->rma_info.rma_lock);
> -}
> -
> -/*
> - * scif_unregister_all_window:
> - *
> - * Traverse all the windows in the self registration list and:
> - * 1) Call scif_unregister_window(..)
> - * RMA lock must be held.
> - */
> -int scif_unregister_all_windows(scif_epd_t epd)
> -{
> - struct list_head *item, *tmp;
> - struct scif_window *window;
> - struct scif_endpt *ep = (struct scif_endpt *)epd;
> - struct list_head *head = &ep->rma_info.reg_list;
> - int err = 0;
> -
> - mutex_lock(&ep->rma_info.rma_lock);
> -retry:
> - item = NULL;
> - tmp = NULL;
> - list_for_each_safe(item, tmp, head) {
> - window = list_entry(item, struct scif_window, list);
> - ep->rma_info.async_list_del = 0;
> - err = scif_unregister_window(window);
> - if (err)
> - dev_err(scif_info.mdev.this_device,
> - "%s %d err %d\n",
> - __func__, __LINE__, err);
> - /*
> - * Need to restart list traversal if there has been
> - * an asynchronous list entry deletion.
> - */
> - if (READ_ONCE(ep->rma_info.async_list_del))
> - goto retry;
> - }
> - mutex_unlock(&ep->rma_info.rma_lock);
> - if (!list_empty(&ep->rma_info.mmn_list)) {
> - spin_lock(&scif_info.rmalock);
> - list_add_tail(&ep->mmu_list, &scif_info.mmu_notif_cleanup);
> - spin_unlock(&scif_info.rmalock);
> - schedule_work(&scif_info.mmu_notif_work);
> - }
> - return err;
> -}
> diff --git a/drivers/misc/mic/scif/scif_rma_list.h
> b/drivers/misc/mic/scif/scif_rma_list.h
> deleted file mode 100644
> index 0f8e0ed65614..000000000000
> --- a/drivers/misc/mic/scif/scif_rma_list.h
> +++ /dev/null
> @@ -1,48 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2015 Intel Corporation.
> - *
> - * Intel SCIF driver.
> - */
> -#ifndef SCIF_RMA_LIST_H
> -#define SCIF_RMA_LIST_H
> -
> -/*
> - * struct scif_rma_req - Self Registration list RMA Request query
> - *
> - * @out_window - Returns the window if found
> - * @offset: Starting offset
> - * @nr_bytes: number of bytes
> - * @prot: protection requested i.e. read or write or both
> - * @type: Specify single, partial or multiple windows
> - * @head: Head of list on which to search
> - * @va_for_temp: VA for searching temporary cached windows
> - */
> -struct scif_rma_req {
> - struct scif_window **out_window;
> - union {
> - s64 offset;
> - unsigned long va_for_temp;
> - };
> - size_t nr_bytes;
> - int prot;
> - enum scif_window_type type;
> - struct list_head *head;
> -};
> -
> -/* Insert */
> -void scif_insert_window(struct scif_window *window, struct list_head
> *head);
> -void scif_insert_tcw(struct scif_window *window,
> - struct list_head *head);
> -/* Query */
> -int scif_query_window(struct scif_rma_req *request);
> -int scif_query_tcw(struct scif_endpt *ep, struct scif_rma_req *request);
> -/* Called from close to unregister all self windows */
> -int scif_unregister_all_windows(scif_epd_t epd);
> -void scif_unmap_all_windows(scif_epd_t epd);
> -/* Traverse list and unregister */
> -int scif_rma_list_unregister(struct scif_window *window, s64 offset,
> - int nr_pages);
> -#endif /* SCIF_RMA_LIST_H */
> diff --git a/drivers/misc/mic/vop/Makefile b/drivers/misc/mic/vop/Makefile
> deleted file mode 100644
> index 51b9b0022786..000000000000
> --- a/drivers/misc/mic/vop/Makefile
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -# Makefile - Intel MIC Linux driver.
> -# Copyright(c) 2016, Intel Corporation.
> -#
> -obj-$(CONFIG_VOP) := vop.o
> -
> -vop-objs += vop_main.o
> -vop-objs += vop_debugfs.o
> -vop-objs += vop_vringh.o
> diff --git a/drivers/misc/mic/vop/vop_debugfs.c
> b/drivers/misc/mic/vop/vop_debugfs.c
> deleted file mode 100644
> index 9d4f175f4dd1..000000000000
> --- a/drivers/misc/mic/vop/vop_debugfs.c
> +++ /dev/null
> @@ -1,184 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Intel Virtio Over PCIe (VOP) driver.
> - */
> -#include <linux/debugfs.h>
> -#include <linux/seq_file.h>
> -
> -#include "vop_main.h"
> -
> -static int vop_dp_show(struct seq_file *s, void *pos)
> -{
> - struct mic_device_desc *d;
> - struct mic_device_ctrl *dc;
> - struct mic_vqconfig *vqconfig;
> - __u32 *features;
> - __u8 *config;
> - struct vop_info *vi = s->private;
> - struct vop_device *vpdev = vi->vpdev;
> - struct mic_bootparam *bootparam = vpdev->hw_ops-
> >get_dp(vpdev);
> - int j, k;
> -
> - seq_printf(s, "Bootparam: magic 0x%x\n",
> - bootparam->magic);
> - seq_printf(s, "Bootparam: h2c_config_db %d\n",
> - bootparam->h2c_config_db);
> - seq_printf(s, "Bootparam: node_id %d\n",
> - bootparam->node_id);
> - seq_printf(s, "Bootparam: c2h_scif_db %d\n",
> - bootparam->c2h_scif_db);
> - seq_printf(s, "Bootparam: h2c_scif_db %d\n",
> - bootparam->h2c_scif_db);
> - seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
> - bootparam->scif_host_dma_addr);
> - seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
> - bootparam->scif_card_dma_addr);
> -
> - for (j = sizeof(*bootparam);
> - j < MIC_DP_SIZE; j += mic_total_desc_size(d)) {
> - d = (void *)bootparam + j;
> - dc = (void *)d + mic_aligned_desc_size(d);
> -
> - /* end of list */
> - if (d->type == 0)
> - break;
> -
> - if (d->type == -1)
> - continue;
> -
> - seq_printf(s, "Type %d ", d->type);
> - seq_printf(s, "Num VQ %d ", d->num_vq);
> - seq_printf(s, "Feature Len %d\n", d->feature_len);
> - seq_printf(s, "Config Len %d ", d->config_len);
> - seq_printf(s, "Shutdown Status %d\n", d->status);
> -
> - for (k = 0; k < d->num_vq; k++) {
> - vqconfig = mic_vq_config(d) + k;
> - seq_printf(s, "vqconfig[%d]: ", k);
> - seq_printf(s, "address 0x%llx ",
> - vqconfig->address);
> - seq_printf(s, "num %d ", vqconfig->num);
> - seq_printf(s, "used address 0x%llx\n",
> - vqconfig->used_address);
> - }
> -
> - features = (__u32 *)mic_vq_features(d);
> - seq_printf(s, "Features: Host 0x%x ", features[0]);
> - seq_printf(s, "Guest 0x%x\n", features[1]);
> -
> - config = mic_vq_configspace(d);
> - for (k = 0; k < d->config_len; k++)
> - seq_printf(s, "config[%d]=%d\n", k, config[k]);
> -
> - seq_puts(s, "Device control:\n");
> - seq_printf(s, "Config Change %d ", dc->config_change);
> - seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
> - seq_printf(s, "Guest Ack %d ", dc->guest_ack);
> - seq_printf(s, "Host ack %d\n", dc->host_ack);
> - seq_printf(s, "Used address updated %d ",
> - dc->used_address_updated);
> - seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
> - seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
> - seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
> - }
> - schedule_work(&vi->hotplug_work);
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(vop_dp);
> -
> -static int vop_vdev_info_show(struct seq_file *s, void *unused)
> -{
> - struct vop_info *vi = s->private;
> - struct list_head *pos, *tmp;
> - struct vop_vdev *vdev;
> - int i, j;
> -
> - mutex_lock(&vi->vop_mutex);
> - list_for_each_safe(pos, tmp, &vi->vdev_list) {
> - vdev = list_entry(pos, struct vop_vdev, list);
> - seq_printf(s, "VDEV type %d state %s in %ld out %ld
> in_dma %ld out_dma %ld\n",
> - vdev->virtio_id,
> - vop_vdevup(vdev) ? "UP" : "DOWN",
> - vdev->in_bytes,
> - vdev->out_bytes,
> - vdev->in_bytes_dma,
> - vdev->out_bytes_dma);
> - for (i = 0; i < MIC_MAX_VRINGS; i++) {
> - struct vring_desc *desc;
> - struct vring_avail *avail;
> - struct vring_used *used;
> - struct vop_vringh *vvr = &vdev->vvr[i];
> - struct vringh *vrh = &vvr->vrh;
> - int num = vrh->vring.num;
> -
> - if (!num)
> - continue;
> - desc = vrh->vring.desc;
> - seq_printf(s, "vring i %d avail_idx %d",
> - i, vvr->vring.info->avail_idx & (num - 1));
> - seq_printf(s, " vring i %d avail_idx %d\n",
> - i, vvr->vring.info->avail_idx);
> - seq_printf(s, "vrh i %d weak_barriers %d",
> - i, vrh->weak_barriers);
> - seq_printf(s, " last_avail_idx %d last_used_idx %d",
> - vrh->last_avail_idx, vrh->last_used_idx);
> - seq_printf(s, " completed %d\n", vrh->completed);
> - for (j = 0; j < num; j++) {
> - seq_printf(s, "desc[%d] addr 0x%llx len %d",
> - j, desc->addr, desc->len);
> - seq_printf(s, " flags 0x%x next %d\n",
> - desc->flags, desc->next);
> - desc++;
> - }
> - avail = vrh->vring.avail;
> - seq_printf(s, "avail flags 0x%x idx %d\n",
> - vringh16_to_cpu(vrh, avail->flags),
> - vringh16_to_cpu(vrh,
> - avail->idx) & (num - 1));
> - seq_printf(s, "avail flags 0x%x idx %d\n",
> - vringh16_to_cpu(vrh, avail->flags),
> - vringh16_to_cpu(vrh, avail->idx));
> - for (j = 0; j < num; j++)
> - seq_printf(s, "avail ring[%d] %d\n",
> - j, avail->ring[j]);
> - used = vrh->vring.used;
> - seq_printf(s, "used flags 0x%x idx %d\n",
> - vringh16_to_cpu(vrh, used->flags),
> - vringh16_to_cpu(vrh, used->idx) & (num -
> 1));
> - seq_printf(s, "used flags 0x%x idx %d\n",
> - vringh16_to_cpu(vrh, used->flags),
> - vringh16_to_cpu(vrh, used->idx));
> - for (j = 0; j < num; j++)
> - seq_printf(s, "used ring[%d] id %d len %d\n",
> - j, vringh32_to_cpu(vrh,
> - used->ring[j].id),
> - vringh32_to_cpu(vrh,
> - used->ring[j].len));
> - }
> - }
> - mutex_unlock(&vi->vop_mutex);
> -
> - return 0;
> -}
> -
> -DEFINE_SHOW_ATTRIBUTE(vop_vdev_info);
> -
> -void vop_init_debugfs(struct vop_info *vi)
> -{
> - char name[16];
> -
> - snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi-
> >vpdev->dnode);
> - vi->dbg = debugfs_create_dir(name, NULL);
> - debugfs_create_file("dp", 0444, vi->dbg, vi, &vop_dp_fops);
> - debugfs_create_file("vdev_info", 0444, vi->dbg, vi,
> &vop_vdev_info_fops);
> -}
> -
> -void vop_exit_debugfs(struct vop_info *vi)
> -{
> - debugfs_remove_recursive(vi->dbg);
> -}
> diff --git a/drivers/misc/mic/vop/vop_main.c
> b/drivers/misc/mic/vop/vop_main.c
> deleted file mode 100644
> index 714b94f42d38..000000000000
> --- a/drivers/misc/mic/vop/vop_main.c
> +++ /dev/null
> @@ -1,784 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Adapted from:
> - *
> - * virtio for kvm on s390
> - *
> - * Copyright IBM Corp. 2008
> - *
> - * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
> - *
> - * Intel Virtio Over PCIe (VOP) driver.
> - */
> -#include <linux/delay.h>
> -#include <linux/module.h>
> -#include <linux/sched.h>
> -#include <linux/dma-mapping.h>
> -#include <linux/io-64-nonatomic-lo-hi.h>
> -
> -#include "vop_main.h"
> -
> -#define VOP_MAX_VRINGS 4
> -
> -/*
> - * _vop_vdev - Allocated per virtio device instance injected by the peer.
> - *
> - * @vdev: Virtio device
> - * @desc: Virtio device page descriptor
> - * @dc: Virtio device control
> - * @vpdev: VOP device which is the parent for this virtio device
> - * @vr: Buffer for accessing the VRING
> - * @used_virt: Virtual address of used ring
> - * @used: DMA address of used ring
> - * @used_size: Size of the used buffer
> - * @reset_done: Track whether VOP reset is complete
> - * @virtio_cookie: Cookie returned upon requesting a interrupt
> - * @c2h_vdev_db: The doorbell used by the guest to interrupt the host
> - * @h2c_vdev_db: The doorbell used by the host to interrupt the guest
> - * @dnode: The destination node
> - */
> -struct _vop_vdev {
> - struct virtio_device vdev;
> - struct mic_device_desc __iomem *desc;
> - struct mic_device_ctrl __iomem *dc;
> - struct vop_device *vpdev;
> - void __iomem *vr[VOP_MAX_VRINGS];
> - void *used_virt[VOP_MAX_VRINGS];
> - dma_addr_t used[VOP_MAX_VRINGS];
> - int used_size[VOP_MAX_VRINGS];
> - struct completion reset_done;
> - struct mic_irq *virtio_cookie;
> - int c2h_vdev_db;
> - int h2c_vdev_db;
> - int dnode;
> -};
> -
> -#define to_vopvdev(vd) container_of(vd, struct _vop_vdev, vdev)
> -
> -#define _vop_aligned_desc_size(d) __mic_align(_vop_desc_size(d), 8)
> -
> -/* Helper API to obtain the parent of the virtio device */
> -static inline struct device *_vop_dev(struct _vop_vdev *vdev)
> -{
> - return vdev->vdev.dev.parent;
> -}
> -
> -static inline unsigned _vop_desc_size(struct mic_device_desc __iomem
> *desc)
> -{
> - return sizeof(*desc)
> - + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig)
> - + ioread8(&desc->feature_len) * 2
> - + ioread8(&desc->config_len);
> -}
> -
> -static inline struct mic_vqconfig __iomem *
> -_vop_vq_config(struct mic_device_desc __iomem *desc)
> -{
> - return (struct mic_vqconfig __iomem *)(desc + 1);
> -}
> -
> -static inline u8 __iomem *
> -_vop_vq_features(struct mic_device_desc __iomem *desc)
> -{
> - return (u8 __iomem *)(_vop_vq_config(desc) + ioread8(&desc-
> >num_vq));
> -}
> -
> -static inline u8 __iomem *
> -_vop_vq_configspace(struct mic_device_desc __iomem *desc)
> -{
> - return _vop_vq_features(desc) + ioread8(&desc->feature_len) * 2;
> -}
> -
> -static inline unsigned
> -_vop_total_desc_size(struct mic_device_desc __iomem *desc)
> -{
> - return _vop_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
> -}
> -
> -/* This gets the device's feature bits. */
> -static u64 vop_get_features(struct virtio_device *vdev)
> -{
> - unsigned int i, bits;
> - u64 features = 0;
> - struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
> - u8 __iomem *in_features = _vop_vq_features(desc);
> - int feature_len = ioread8(&desc->feature_len);
> -
> - bits = min_t(unsigned, feature_len, sizeof(vdev->features)) * 8;
> - for (i = 0; i < bits; i++)
> - if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
> - features |= BIT_ULL(i);
> -
> - return features;
> -}
> -
> -static void vop_transport_features(struct virtio_device *vdev)
> -{
> - /*
> - * Packed ring isn't enabled on virtio_vop for now,
> - * because virtio_vop uses vring_new_virtqueue() which
> - * creates virtio rings on preallocated memory.
> - */
> - __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
> - __virtio_set_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
> -}
> -
> -static int vop_finalize_features(struct virtio_device *vdev)
> -{
> - unsigned int i, bits;
> - struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
> - u8 feature_len = ioread8(&desc->feature_len);
> - /* Second half of bitmap is features we accept. */
> - u8 __iomem *out_features =
> - _vop_vq_features(desc) + feature_len;
> -
> - /* Give virtio_ring a chance to accept features. */
> - vring_transport_features(vdev);
> -
> - /* Give virtio_vop a chance to accept features. */
> - vop_transport_features(vdev);
> -
> - memset_io(out_features, 0, feature_len);
> - bits = min_t(unsigned, feature_len,
> - sizeof(vdev->features)) * 8;
> - for (i = 0; i < bits; i++) {
> - if (__virtio_test_bit(vdev, i))
> - iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
> - &out_features[i / 8]);
> - }
> - return 0;
> -}
> -
> -/*
> - * Reading and writing elements in config space
> - */
> -static void vop_get(struct virtio_device *vdev, unsigned int offset,
> - void *buf, unsigned len)
> -{
> - struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
> -
> - if (offset + len > ioread8(&desc->config_len))
> - return;
> - memcpy_fromio(buf, _vop_vq_configspace(desc) + offset, len);
> -}
> -
> -static void vop_set(struct virtio_device *vdev, unsigned int offset,
> - const void *buf, unsigned len)
> -{
> - struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc;
> -
> - if (offset + len > ioread8(&desc->config_len))
> - return;
> - memcpy_toio(_vop_vq_configspace(desc) + offset, buf, len);
> -}
> -
> -/*
> - * The operations to get and set the status word just access the status
> - * field of the device descriptor. set_status also interrupts the host
> - * to tell about status changes.
> - */
> -static u8 vop_get_status(struct virtio_device *vdev)
> -{
> - return ioread8(&to_vopvdev(vdev)->desc->status);
> -}
> -
> -static void vop_set_status(struct virtio_device *dev, u8 status)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> - struct vop_device *vpdev = vdev->vpdev;
> -
> - if (!status)
> - return;
> - iowrite8(status, &vdev->desc->status);
> - vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
> -}
> -
> -/* Inform host on a virtio device reset and wait for ack from host */
> -static void vop_reset_inform_host(struct virtio_device *dev)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> - struct mic_device_ctrl __iomem *dc = vdev->dc;
> - struct vop_device *vpdev = vdev->vpdev;
> - int retry;
> -
> - iowrite8(0, &dc->host_ack);
> - iowrite8(1, &dc->vdev_reset);
> - vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
> -
> - /* Wait till host completes all card accesses and acks the reset */
> - for (retry = 100; retry--;) {
> - if (ioread8(&dc->host_ack))
> - break;
> - msleep(100);
> - }
> -
> - dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
> -
> - /* Reset status to 0 in case we timed out */
> - iowrite8(0, &vdev->desc->status);
> -}
> -
> -static void vop_reset(struct virtio_device *dev)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> -
> - dev_dbg(_vop_dev(vdev), "%s: virtio id %d\n",
> - __func__, dev->id.device);
> -
> - vop_reset_inform_host(dev);
> - complete_all(&vdev->reset_done);
> -}
> -
> -/*
> - * The virtio_ring code calls this API when it wants to notify the Host.
> - */
> -static bool vop_notify(struct virtqueue *vq)
> -{
> - struct _vop_vdev *vdev = vq->priv;
> - struct vop_device *vpdev = vdev->vpdev;
> -
> - vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
> - return true;
> -}
> -
> -static void vop_del_vq(struct virtqueue *vq, int n)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
> - struct vop_device *vpdev = vdev->vpdev;
> -
> - dma_unmap_single(&vpdev->dev, vdev->used[n],
> - vdev->used_size[n], DMA_BIDIRECTIONAL);
> - free_pages((unsigned long)vdev->used_virt[n],
> - get_order(vdev->used_size[n]));
> - vring_del_virtqueue(vq);
> - vpdev->hw_ops->unmap(vpdev, vdev->vr[n]);
> - vdev->vr[n] = NULL;
> -}
> -
> -static void vop_del_vqs(struct virtio_device *dev)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> - struct virtqueue *vq, *n;
> - int idx = 0;
> -
> - dev_dbg(_vop_dev(vdev), "%s\n", __func__);
> -
> - list_for_each_entry_safe(vq, n, &dev->vqs, list)
> - vop_del_vq(vq, idx++);
> -}
> -
> -static struct virtqueue *vop_new_virtqueue(unsigned int index,
> - unsigned int num,
> - struct virtio_device *vdev,
> - bool context,
> - void *pages,
> - bool (*notify)(struct virtqueue *vq),
> - void (*callback)(struct virtqueue *vq),
> - const char *name,
> - void *used)
> -{
> - bool weak_barriers = false;
> - struct vring vring;
> -
> - vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
> - vring.used = used;
> -
> - return __vring_new_virtqueue(index, vring, vdev, weak_barriers,
> context,
> - notify, callback, name);
> -}
> -
> -/*
> - * This routine will assign vring's allocated in host/io memory. Code in
> - * virtio_ring.c however continues to access this io memory as if it were local
> - * memory without io accessors.
> - */
> -static struct virtqueue *vop_find_vq(struct virtio_device *dev,
> - unsigned index,
> - void (*callback)(struct virtqueue *vq),
> - const char *name, bool ctx)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> - struct vop_device *vpdev = vdev->vpdev;
> - struct mic_vqconfig __iomem *vqconfig;
> - struct mic_vqconfig config;
> - struct virtqueue *vq;
> - void __iomem *va;
> - struct _mic_vring_info __iomem *info;
> - void *used;
> - int vr_size, _vr_size, err, magic;
> - u8 type = ioread8(&vdev->desc->type);
> -
> - if (index >= ioread8(&vdev->desc->num_vq))
> - return ERR_PTR(-ENOENT);
> -
> - if (!name)
> - return ERR_PTR(-ENOENT);
> -
> - /* First assign the vring's allocated in host memory */
> - vqconfig = _vop_vq_config(vdev->desc) + index;
> - memcpy_fromio(&config, vqconfig, sizeof(config));
> - _vr_size = round_up(vring_size(le16_to_cpu(config.num),
> MIC_VIRTIO_RING_ALIGN), 4);
> - vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
> - va = vpdev->hw_ops->remap(vpdev, le64_to_cpu(config.address),
> vr_size);
> - if (!va)
> - return ERR_PTR(-ENOMEM);
> - vdev->vr[index] = va;
> - memset_io(va, 0x0, _vr_size);
> -
> - info = va + _vr_size;
> - magic = ioread32(&info->magic);
> -
> - if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) {
> - err = -EIO;
> - goto unmap;
> - }
> -
> - vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
> - sizeof(struct vring_used_elem) *
> - le16_to_cpu(config.num));
> - used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> - get_order(vdev->used_size[index]));
> - vdev->used_virt[index] = used;
> - if (!used) {
> - err = -ENOMEM;
> - dev_err(_vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto unmap;
> - }
> -
> - vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
> - (void __force *)va, vop_notify, callback,
> - name, used);
> - if (!vq) {
> - err = -ENOMEM;
> - goto free_used;
> - }
> -
> - vdev->used[index] = dma_map_single(&vpdev->dev, used,
> - vdev->used_size[index],
> - DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(&vpdev->dev, vdev->used[index])) {
> - err = -ENOMEM;
> - dev_err(_vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto del_vq;
> - }
> - writeq(vdev->used[index], &vqconfig->used_address);
> -
> - vq->priv = vdev;
> - return vq;
> -del_vq:
> - vring_del_virtqueue(vq);
> -free_used:
> - free_pages((unsigned long)used,
> - get_order(vdev->used_size[index]));
> -unmap:
> - vpdev->hw_ops->unmap(vpdev, vdev->vr[index]);
> - return ERR_PTR(err);
> -}
> -
> -static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
> - struct virtqueue *vqs[],
> - vq_callback_t *callbacks[],
> - const char * const names[], const bool *ctx,
> - struct irq_affinity *desc)
> -{
> - struct _vop_vdev *vdev = to_vopvdev(dev);
> - struct vop_device *vpdev = vdev->vpdev;
> - struct mic_device_ctrl __iomem *dc = vdev->dc;
> - int i, err, retry, queue_idx = 0;
> -
> - /* We must have this many virtqueues. */
> - if (nvqs > ioread8(&vdev->desc->num_vq))
> - return -ENOENT;
> -
> - for (i = 0; i < nvqs; ++i) {
> - if (!names[i]) {
> - vqs[i] = NULL;
> - continue;
> - }
> -
> - dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
> - __func__, i, names[i]);
> - vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
> - ctx ? ctx[i] : false);
> - if (IS_ERR(vqs[i])) {
> - err = PTR_ERR(vqs[i]);
> - goto error;
> - }
> - }
> -
> - iowrite8(1, &dc->used_address_updated);
> - /*
> - * Send an interrupt to the host to inform it that used
> - * rings have been re-assigned.
> - */
> - vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db);
> - for (retry = 100; --retry;) {
> - if (!ioread8(&dc->used_address_updated))
> - break;
> - msleep(100);
> - }
> -
> - dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry);
> - if (!retry) {
> - err = -ENODEV;
> - goto error;
> - }
> -
> - return 0;
> -error:
> - vop_del_vqs(dev);
> - return err;
> -}
> -
> -/*
> - * The config ops structure as defined by virtio config
> - */
> -static const struct virtio_config_ops vop_vq_config_ops = {
> - .get_features = vop_get_features,
> - .finalize_features = vop_finalize_features,
> - .get = vop_get,
> - .set = vop_set,
> - .get_status = vop_get_status,
> - .set_status = vop_set_status,
> - .reset = vop_reset,
> - .find_vqs = vop_find_vqs,
> - .del_vqs = vop_del_vqs,
> -};
> -
> -static irqreturn_t vop_virtio_intr_handler(int irq, void *data)
> -{
> - struct _vop_vdev *vdev = data;
> - struct vop_device *vpdev = vdev->vpdev;
> - struct virtqueue *vq;
> -
> - vpdev->hw_ops->ack_interrupt(vpdev, vdev->h2c_vdev_db);
> - list_for_each_entry(vq, &vdev->vdev.vqs, list)
> - vring_interrupt(0, vq);
> -
> - return IRQ_HANDLED;
> -}
> -
> -static void vop_virtio_release_dev(struct device *_d)
> -{
> - struct virtio_device *vdev =
> - container_of(_d, struct virtio_device, dev);
> - struct _vop_vdev *vop_vdev =
> - container_of(vdev, struct _vop_vdev, vdev);
> -
> - kfree(vop_vdev);
> -}
> -
> -/*
> - * adds a new device and register it with virtio
> - * appropriate drivers are loaded by the device model
> - */
> -static int _vop_add_device(struct mic_device_desc __iomem *d,
> - unsigned int offset, struct vop_device *vpdev,
> - int dnode)
> -{
> - struct _vop_vdev *vdev, *reg_dev = NULL;
> - int ret;
> - u8 type = ioread8(&d->type);
> -
> - vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
> - if (!vdev)
> - return -ENOMEM;
> -
> - vdev->vpdev = vpdev;
> - vdev->vdev.dev.parent = &vpdev->dev;
> - vdev->vdev.dev.release = vop_virtio_release_dev;
> - vdev->vdev.id.device = type;
> - vdev->vdev.config = &vop_vq_config_ops;
> - vdev->desc = d;
> - vdev->dc = (void __iomem *)d + _vop_aligned_desc_size(d);
> - vdev->dnode = dnode;
> - vdev->vdev.priv = (void *)(unsigned long)dnode;
> - init_completion(&vdev->reset_done);
> -
> - vdev->h2c_vdev_db = vpdev->hw_ops->next_db(vpdev);
> - vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev,
> - vop_virtio_intr_handler, "virtio intr",
> - vdev, vdev->h2c_vdev_db);
> - if (IS_ERR(vdev->virtio_cookie)) {
> - ret = PTR_ERR(vdev->virtio_cookie);
> - goto kfree;
> - }
> - iowrite8((u8)vdev->h2c_vdev_db, &vdev->dc->h2c_vdev_db);
> - vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db);
> -
> - ret = register_virtio_device(&vdev->vdev);
> - reg_dev = vdev;
> - if (ret) {
> - dev_err(_vop_dev(vdev),
> - "Failed to register vop device %u type %u\n",
> - offset, type);
> - goto free_irq;
> - }
> - writeq((unsigned long)vdev, &vdev->dc->vdev);
> - dev_dbg(_vop_dev(vdev), "%s: registered vop device %u type %u
> vdev %p\n",
> - __func__, offset, type, vdev);
> -
> - return 0;
> -
> -free_irq:
> - vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
> -kfree:
> - if (reg_dev)
> - put_device(&vdev->vdev.dev);
> - else
> - kfree(vdev);
> - return ret;
> -}
> -
> -/*
> - * match for a vop device with a specific desc pointer
> - */
> -static int vop_match_desc(struct device *dev, void *data)
> -{
> - struct virtio_device *_dev = dev_to_virtio(dev);
> - struct _vop_vdev *vdev = to_vopvdev(_dev);
> -
> - return vdev->desc == (void __iomem *)data;
> -}
> -
> -static struct _vop_vdev *vop_dc_to_vdev(struct mic_device_ctrl __iomem
> *dc)
> -{
> - return (struct _vop_vdev *)(unsigned long)readq(&dc->vdev);
> -}
> -
> -static void _vop_handle_config_change(struct mic_device_desc __iomem *d,
> - unsigned int offset,
> - struct vop_device *vpdev)
> -{
> - struct mic_device_ctrl __iomem *dc
> - = (void __iomem *)d + _vop_aligned_desc_size(d);
> - struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
> -
> - if (ioread8(&dc->config_change) !=
> MIC_VIRTIO_PARAM_CONFIG_CHANGED)
> - return;
> -
> - dev_dbg(&vpdev->dev, "%s %d\n", __func__, __LINE__);
> - virtio_config_changed(&vdev->vdev);
> - iowrite8(1, &dc->guest_ack);
> -}
> -
> -/*
> - * removes a virtio device if a hot remove event has been
> - * requested by the host.
> - */
> -static int _vop_remove_device(struct mic_device_desc __iomem *d,
> - unsigned int offset, struct vop_device *vpdev)
> -{
> - struct mic_device_ctrl __iomem *dc
> - = (void __iomem *)d + _vop_aligned_desc_size(d);
> - struct _vop_vdev *vdev = vop_dc_to_vdev(dc);
> - u8 status;
> - int ret = -1;
> -
> - if (ioread8(&dc->config_change) ==
> MIC_VIRTIO_PARAM_DEV_REMOVE) {
> - struct device *dev = get_device(&vdev->vdev.dev);
> -
> - dev_dbg(&vpdev->dev,
> - "%s %d config_change %d type %d vdev %p\n",
> - __func__, __LINE__,
> - ioread8(&dc->config_change), ioread8(&d->type),
> vdev);
> - status = ioread8(&d->status);
> - reinit_completion(&vdev->reset_done);
> - unregister_virtio_device(&vdev->vdev);
> - vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
> - iowrite8(-1, &dc->h2c_vdev_db);
> - if (status & VIRTIO_CONFIG_S_DRIVER_OK)
> - wait_for_completion(&vdev->reset_done);
> - put_device(dev);
> - iowrite8(1, &dc->guest_ack);
> - dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
> - __func__, __LINE__, ioread8(&dc->guest_ack));
> - iowrite8(-1, &d->type);
> - ret = 0;
> - }
> - return ret;
> -}
> -
> -#define REMOVE_DEVICES true
> -
> -static void _vop_scan_devices(void __iomem *dp, struct vop_device *vpdev,
> - bool remove, int dnode)
> -{
> - s8 type;
> - unsigned int i;
> - struct mic_device_desc __iomem *d;
> - struct mic_device_ctrl __iomem *dc;
> - struct device *dev;
> -
> - for (i = sizeof(struct mic_bootparam);
> - i < MIC_DP_SIZE; i += _vop_total_desc_size(d)) {
> - d = dp + i;
> - dc = (void __iomem *)d + _vop_aligned_desc_size(d);
> - /*
> - * This read barrier is paired with the corresponding write
> - * barrier on the host which is inserted before adding or
> - * removing a virtio device descriptor, by updating the type.
> - */
> - rmb();
> - type = ioread8(&d->type);
> -
> - /* end of list */
> - if (type == 0)
> - break;
> -
> - if (type == -1)
> - continue;
> -
> - /* device already exists */
> - dev = device_find_child(&vpdev->dev, (void __force *)d,
> - vop_match_desc);
> - if (dev) {
> - if (remove)
> - iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
> - &dc->config_change);
> - put_device(dev);
> - _vop_handle_config_change(d, i, vpdev);
> - _vop_remove_device(d, i, vpdev);
> - if (remove) {
> - iowrite8(0, &dc->config_change);
> - iowrite8(0, &dc->guest_ack);
> - }
> - continue;
> - }
> -
> - /* new device */
> - dev_dbg(&vpdev->dev, "%s %d Adding new virtio
> device %p\n",
> - __func__, __LINE__, d);
> - if (!remove)
> - _vop_add_device(d, i, vpdev, dnode);
> - }
> -}
> -
> -static void vop_scan_devices(struct vop_info *vi,
> - struct vop_device *vpdev, bool remove)
> -{
> - void __iomem *dp = vpdev->hw_ops->get_remote_dp(vpdev);
> -
> - if (!dp)
> - return;
> - mutex_lock(&vi->vop_mutex);
> - _vop_scan_devices(dp, vpdev, remove, vpdev->dnode);
> - mutex_unlock(&vi->vop_mutex);
> -}
> -
> -/*
> - * vop_hotplug_device tries to find changes in the device page.
> - */
> -static void vop_hotplug_devices(struct work_struct *work)
> -{
> - struct vop_info *vi = container_of(work, struct vop_info,
> - hotplug_work);
> -
> - vop_scan_devices(vi, vi->vpdev, !REMOVE_DEVICES);
> -}
> -
> -/*
> - * Interrupt handler for hot plug/config changes etc.
> - */
> -static irqreturn_t vop_extint_handler(int irq, void *data)
> -{
> - struct vop_info *vi = data;
> - struct mic_bootparam __iomem *bp;
> - struct vop_device *vpdev = vi->vpdev;
> -
> - bp = vpdev->hw_ops->get_remote_dp(vpdev);
> - dev_dbg(&vpdev->dev, "%s %d hotplug work\n",
> - __func__, __LINE__);
> - vpdev->hw_ops->ack_interrupt(vpdev, ioread8(&bp-
> >h2c_config_db));
> - schedule_work(&vi->hotplug_work);
> - return IRQ_HANDLED;
> -}
> -
> -static int vop_driver_probe(struct vop_device *vpdev)
> -{
> - struct vop_info *vi;
> - int rc;
> -
> - vi = kzalloc(sizeof(*vi), GFP_KERNEL);
> - if (!vi) {
> - rc = -ENOMEM;
> - goto exit;
> - }
> - dev_set_drvdata(&vpdev->dev, vi);
> - vi->vpdev = vpdev;
> -
> - mutex_init(&vi->vop_mutex);
> - INIT_WORK(&vi->hotplug_work, vop_hotplug_devices);
> - if (vpdev->dnode) {
> - rc = vop_host_init(vi);
> - if (rc < 0)
> - goto free;
> - } else {
> - struct mic_bootparam __iomem *bootparam;
> -
> - vop_scan_devices(vi, vpdev, !REMOVE_DEVICES);
> -
> - vi->h2c_config_db = vpdev->hw_ops->next_db(vpdev);
> - vi->cookie = vpdev->hw_ops->request_irq(vpdev,
> - vop_extint_handler,
> - "virtio_config_intr",
> - vi, vi->h2c_config_db);
> - if (IS_ERR(vi->cookie)) {
> - rc = PTR_ERR(vi->cookie);
> - goto free;
> - }
> - bootparam = vpdev->hw_ops->get_remote_dp(vpdev);
> - iowrite8(vi->h2c_config_db, &bootparam->h2c_config_db);
> - }
> - vop_init_debugfs(vi);
> - return 0;
> -free:
> - kfree(vi);
> -exit:
> - return rc;
> -}
> -
> -static void vop_driver_remove(struct vop_device *vpdev)
> -{
> - struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
> -
> - if (vpdev->dnode) {
> - vop_host_uninit(vi);
> - } else {
> - struct mic_bootparam __iomem *bootparam =
> - vpdev->hw_ops->get_remote_dp(vpdev);
> - if (bootparam)
> - iowrite8(-1, &bootparam->h2c_config_db);
> - vpdev->hw_ops->free_irq(vpdev, vi->cookie, vi);
> - flush_work(&vi->hotplug_work);
> - vop_scan_devices(vi, vpdev, REMOVE_DEVICES);
> - }
> - vop_exit_debugfs(vi);
> - kfree(vi);
> -}
> -
> -static const struct vop_device_id id_table[] = {
> - { VOP_DEV_TRNSP, VOP_DEV_ANY_ID },
> - { 0 },
> -};
> -
> -static struct vop_driver vop_driver = {
> - .driver.name = KBUILD_MODNAME,
> - .driver.owner = THIS_MODULE,
> - .id_table = id_table,
> - .probe = vop_driver_probe,
> - .remove = vop_driver_remove,
> -};
> -
> -module_vop_driver(vop_driver);
> -
> -MODULE_DEVICE_TABLE(mbus, id_table);
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_DESCRIPTION("Intel(R) Virtio Over PCIe (VOP) driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/misc/mic/vop/vop_main.h
> b/drivers/misc/mic/vop/vop_main.h
> deleted file mode 100644
> index 2451d9218137..000000000000
> --- a/drivers/misc/mic/vop/vop_main.h
> +++ /dev/null
> @@ -1,158 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Intel Virtio Over PCIe (VOP) driver.
> - */
> -#ifndef _VOP_MAIN_H_
> -#define _VOP_MAIN_H_
> -
> -#include <linux/vringh.h>
> -#include <linux/virtio_config.h>
> -#include <linux/virtio.h>
> -#include <linux/miscdevice.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -
> -#include "../bus/vop_bus.h"
> -
> -/*
> - * Note on endianness.
> - * 1. Host can be both BE or LE
> - * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
> - * rings and ioreadXX/iowriteXX to access used ring.
> - * 3. Device page exposed by host to guest contains LE values. Guest
> - * accesses these using ioreadXX/iowriteXX etc. This way in general we
> - * obey the virtio spec according to which guest works with native
> - * endianness and host is aware of guest endianness and does all
> - * required endianness conversion.
> - * 4. Data provided from user space to guest (in ADD_DEVICE and
> - * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
> - * in guest endianness.
> - */
> -
> -/*
> - * vop_info - Allocated per invocation of VOP probe
> - *
> - * @vpdev: VOP device
> - * @hotplug_work: Handle virtio device creation, deletion and configuration
> - * @cookie: Cookie received upon requesting a virtio configuration interrupt
> - * @h2c_config_db: The doorbell used by the peer to indicate a config
> change
> - * @vdev_list: List of "active" virtio devices injected in the peer node
> - * @vop_mutex: Synchronize access to the device page as well as serialize
> - * creation/deletion of virtio devices on the peer node
> - * @dp: Peer device page information
> - * @dbg: Debugfs entry
> - * @dma_ch: The DMA channel used by this transport for data transfers.
> - * @name: Name for this transport used in misc device creation.
> - * @miscdev: The misc device registered.
> - */
> -struct vop_info {
> - struct vop_device *vpdev;
> - struct work_struct hotplug_work;
> - struct mic_irq *cookie;
> - int h2c_config_db;
> - struct list_head vdev_list;
> - struct mutex vop_mutex;
> - void __iomem *dp;
> - struct dentry *dbg;
> - struct dma_chan *dma_ch;
> - char name[16];
> - struct miscdevice miscdev;
> -};
> -
> -/**
> - * struct vop_vringh - Virtio ring host information.
> - *
> - * @vring: The VOP vring used for setting up user space mappings.
> - * @vrh: The host VRINGH used for accessing the card vrings.
> - * @riov: The VRINGH read kernel IOV.
> - * @wiov: The VRINGH write kernel IOV.
> - * @head: The VRINGH head index address passed to
> vringh_getdesc_kern(..).
> - * @vr_mutex: Mutex for synchronizing access to the VRING.
> - * @buf: Temporary kernel buffer used to copy in/out data
> - * from/to the card via DMA.
> - * @buf_da: dma address of buf.
> - * @vdev: Back pointer to VOP virtio device for vringh_notify(..).
> - */
> -struct vop_vringh {
> - struct mic_vring vring;
> - struct vringh vrh;
> - struct vringh_kiov riov;
> - struct vringh_kiov wiov;
> - u16 head;
> - struct mutex vr_mutex;
> - void *buf;
> - dma_addr_t buf_da;
> - struct vop_vdev *vdev;
> -};
> -
> -/**
> - * struct vop_vdev - Host information for a card Virtio device.
> - *
> - * @virtio_id - Virtio device id.
> - * @waitq - Waitqueue to allow ring3 apps to poll.
> - * @vpdev - pointer to VOP bus device.
> - * @poll_wake - Used for waking up threads blocked in poll.
> - * @out_bytes - Debug stats for number of bytes copied from host to card.
> - * @in_bytes - Debug stats for number of bytes copied from card to host.
> - * @out_bytes_dma - Debug stats for number of bytes copied from host to
> card
> - * using DMA.
> - * @in_bytes_dma - Debug stats for number of bytes copied from card to
> host
> - * using DMA.
> - * @tx_len_unaligned - Debug stats for number of bytes copied to the card
> where
> - * the transfer length did not have the required DMA alignment.
> - * @tx_dst_unaligned - Debug stats for number of bytes copied where the
> - * destination address on the card did not have the required DMA alignment.
> - * @vvr - Store per VRING data structures.
> - * @virtio_bh_work - Work struct used to schedule virtio bottom half
> handling.
> - * @dd - Virtio device descriptor.
> - * @dc - Virtio device control fields.
> - * @list - List of Virtio devices.
> - * @virtio_db - The doorbell used by the card to interrupt the host.
> - * @virtio_cookie - The cookie returned while requesting interrupts.
> - * @vi: Transport information.
> - * @vdev_mutex: Mutex synchronizing virtio device injection,
> - * removal and data transfers.
> - * @destroy: Track if a virtio device is being destroyed.
> - * @deleted: The virtio device has been deleted.
> - */
> -struct vop_vdev {
> - int virtio_id;
> - wait_queue_head_t waitq;
> - struct vop_device *vpdev;
> - int poll_wake;
> - unsigned long out_bytes;
> - unsigned long in_bytes;
> - unsigned long out_bytes_dma;
> - unsigned long in_bytes_dma;
> - unsigned long tx_len_unaligned;
> - unsigned long tx_dst_unaligned;
> - unsigned long rx_dst_unaligned;
> - struct vop_vringh vvr[MIC_MAX_VRINGS];
> - struct work_struct virtio_bh_work;
> - struct mic_device_desc *dd;
> - struct mic_device_ctrl *dc;
> - struct list_head list;
> - int virtio_db;
> - struct mic_irq *virtio_cookie;
> - struct vop_info *vi;
> - struct mutex vdev_mutex;
> - struct completion destroy;
> - bool deleted;
> -};
> -
> -/* Helper API to check if a virtio device is running */
> -static inline bool vop_vdevup(struct vop_vdev *vdev)
> -{
> - return !!vdev->dd->status;
> -}
> -
> -void vop_init_debugfs(struct vop_info *vi);
> -void vop_exit_debugfs(struct vop_info *vi);
> -int vop_host_init(struct vop_info *vi);
> -void vop_host_uninit(struct vop_info *vi);
> -#endif
> diff --git a/drivers/misc/mic/vop/vop_vringh.c
> b/drivers/misc/mic/vop/vop_vringh.c
> deleted file mode 100644
> index 7014ffe88632..000000000000
> --- a/drivers/misc/mic/vop/vop_vringh.c
> +++ /dev/null
> @@ -1,1166 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2016 Intel Corporation.
> - *
> - * Intel Virtio Over PCIe (VOP) driver.
> - */
> -#include <linux/sched.h>
> -#include <linux/poll.h>
> -#include <linux/dma-mapping.h>
> -
> -#include <linux/mic_common.h>
> -#include "../common/mic_dev.h"
> -
> -#include <linux/mic_ioctl.h>
> -#include "vop_main.h"
> -
> -/* Helper API to obtain the VOP PCIe device */
> -static inline struct device *vop_dev(struct vop_vdev *vdev)
> -{
> - return vdev->vpdev->dev.parent;
> -}
> -
> -/* Helper API to check if a virtio device is initialized */
> -static inline int vop_vdev_inited(struct vop_vdev *vdev)
> -{
> - if (!vdev)
> - return -EINVAL;
> - /* Device has not been created yet */
> - if (!vdev->dd || !vdev->dd->type) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, -EINVAL);
> - return -EINVAL;
> - }
> - /* Device has been removed/deleted */
> - if (vdev->dd->type == -1) {
> - dev_dbg(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, -ENODEV);
> - return -ENODEV;
> - }
> - return 0;
> -}
> -
> -static void _vop_notify(struct vringh *vrh)
> -{
> - struct vop_vringh *vvrh = container_of(vrh, struct vop_vringh, vrh);
> - struct vop_vdev *vdev = vvrh->vdev;
> - struct vop_device *vpdev = vdev->vpdev;
> - s8 db = vdev->dc->h2c_vdev_db;
> -
> - if (db != -1)
> - vpdev->hw_ops->send_intr(vpdev, db);
> -}
> -
> -static void vop_virtio_init_post(struct vop_vdev *vdev)
> -{
> - struct mic_vqconfig *vqconfig = mic_vq_config(vdev->dd);
> - struct vop_device *vpdev = vdev->vpdev;
> - int i, used_size;
> -
> - for (i = 0; i < vdev->dd->num_vq; i++) {
> - used_size = PAGE_ALIGN(sizeof(u16) * 3 +
> - sizeof(struct vring_used_elem) *
> - le16_to_cpu(vqconfig->num));
> - if (!le64_to_cpu(vqconfig[i].used_address)) {
> - dev_warn(vop_dev(vdev), "used_address zero??\n");
> - continue;
> - }
> - vdev->vvr[i].vrh.vring.used =
> - (void __force *)vpdev->hw_ops->remap(
> - vpdev,
> - le64_to_cpu(vqconfig[i].used_address),
> - used_size);
> - }
> -
> - vdev->dc->used_address_updated = 0;
> -
> - dev_info(vop_dev(vdev), "%s: device type %d LINKUP\n",
> - __func__, vdev->virtio_id);
> -}
> -
> -static inline void vop_virtio_device_reset(struct vop_vdev *vdev)
> -{
> - int i;
> -
> - dev_dbg(vop_dev(vdev), "%s: status %d device type %d RESET\n",
> - __func__, vdev->dd->status, vdev->virtio_id);
> -
> - for (i = 0; i < vdev->dd->num_vq; i++)
> - /*
> - * Avoid lockdep false positive. The + 1 is for the vop
> - * mutex which is held in the reset devices code path.
> - */
> - mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1);
> -
> - /* 0 status means "reset" */
> - vdev->dd->status = 0;
> - vdev->dc->vdev_reset = 0;
> - vdev->dc->host_ack = 1;
> -
> - for (i = 0; i < vdev->dd->num_vq; i++) {
> - struct vringh *vrh = &vdev->vvr[i].vrh;
> -
> - vdev->vvr[i].vring.info->avail_idx = 0;
> - vrh->completed = 0;
> - vrh->last_avail_idx = 0;
> - vrh->last_used_idx = 0;
> - }
> -
> - for (i = 0; i < vdev->dd->num_vq; i++)
> - mutex_unlock(&vdev->vvr[i].vr_mutex);
> -}
> -
> -static void vop_virtio_reset_devices(struct vop_info *vi)
> -{
> - struct list_head *pos, *tmp;
> - struct vop_vdev *vdev;
> -
> - list_for_each_safe(pos, tmp, &vi->vdev_list) {
> - vdev = list_entry(pos, struct vop_vdev, list);
> - vop_virtio_device_reset(vdev);
> - vdev->poll_wake = 1;
> - wake_up(&vdev->waitq);
> - }
> -}
> -
> -static void vop_bh_handler(struct work_struct *work)
> -{
> - struct vop_vdev *vdev = container_of(work, struct vop_vdev,
> - virtio_bh_work);
> -
> - if (vdev->dc->used_address_updated)
> - vop_virtio_init_post(vdev);
> -
> - if (vdev->dc->vdev_reset)
> - vop_virtio_device_reset(vdev);
> -
> - vdev->poll_wake = 1;
> - wake_up(&vdev->waitq);
> -}
> -
> -static irqreturn_t _vop_virtio_intr_handler(int irq, void *data)
> -{
> - struct vop_vdev *vdev = data;
> - struct vop_device *vpdev = vdev->vpdev;
> -
> - vpdev->hw_ops->ack_interrupt(vpdev, vdev->virtio_db);
> - schedule_work(&vdev->virtio_bh_work);
> - return IRQ_HANDLED;
> -}
> -
> -static int vop_virtio_config_change(struct vop_vdev *vdev, void *argp)
> -{
> - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
> - int ret = 0, retry, i;
> - struct vop_device *vpdev = vdev->vpdev;
> - struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
> - struct mic_bootparam *bootparam = vpdev->hw_ops-
> >get_dp(vpdev);
> - s8 db = bootparam->h2c_config_db;
> -
> - mutex_lock(&vi->vop_mutex);
> - for (i = 0; i < vdev->dd->num_vq; i++)
> - mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1);
> -
> - if (db == -1 || vdev->dd->type == -1) {
> - ret = -EIO;
> - goto exit;
> - }
> -
> - memcpy(mic_vq_configspace(vdev->dd), argp, vdev->dd-
> >config_len);
> - vdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
> - vpdev->hw_ops->send_intr(vpdev, db);
> -
> - for (retry = 100; retry--;) {
> - ret = wait_event_timeout(wake, vdev->dc->guest_ack,
> - msecs_to_jiffies(100));
> - if (ret)
> - break;
> - }
> -
> - dev_dbg(vop_dev(vdev),
> - "%s %d retry: %d\n", __func__, __LINE__, retry);
> - vdev->dc->config_change = 0;
> - vdev->dc->guest_ack = 0;
> -exit:
> - for (i = 0; i < vdev->dd->num_vq; i++)
> - mutex_unlock(&vdev->vvr[i].vr_mutex);
> - mutex_unlock(&vi->vop_mutex);
> - return ret;
> -}
> -
> -static int vop_copy_dp_entry(struct vop_vdev *vdev,
> - struct mic_device_desc *argp, __u8 *type,
> - struct mic_device_desc **devpage)
> -{
> - struct vop_device *vpdev = vdev->vpdev;
> - struct mic_device_desc *devp;
> - struct mic_vqconfig *vqconfig;
> - int ret = 0, i;
> - bool slot_found = false;
> -
> - vqconfig = mic_vq_config(argp);
> - for (i = 0; i < argp->num_vq; i++) {
> - if (le16_to_cpu(vqconfig[i].num) >
> MIC_MAX_VRING_ENTRIES) {
> - ret = -EINVAL;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - goto exit;
> - }
> - }
> -
> - /* Find the first free device page entry */
> - for (i = sizeof(struct mic_bootparam);
> - i < MIC_DP_SIZE - mic_total_desc_size(argp);
> - i += mic_total_desc_size(devp)) {
> - devp = vpdev->hw_ops->get_dp(vpdev) + i;
> - if (devp->type == 0 || devp->type == -1) {
> - slot_found = true;
> - break;
> - }
> - }
> - if (!slot_found) {
> - ret = -EINVAL;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - goto exit;
> - }
> - /*
> - * Save off the type before doing the memcpy. Type will be set in the
> - * end after completing all initialization for the new device.
> - */
> - *type = argp->type;
> - argp->type = 0;
> - memcpy(devp, argp, mic_desc_size(argp));
> -
> - *devpage = devp;
> -exit:
> - return ret;
> -}
> -
> -static void vop_init_device_ctrl(struct vop_vdev *vdev,
> - struct mic_device_desc *devpage)
> -{
> - struct mic_device_ctrl *dc;
> -
> - dc = (void *)devpage + mic_aligned_desc_size(devpage);
> -
> - dc->config_change = 0;
> - dc->guest_ack = 0;
> - dc->vdev_reset = 0;
> - dc->host_ack = 0;
> - dc->used_address_updated = 0;
> - dc->c2h_vdev_db = -1;
> - dc->h2c_vdev_db = -1;
> - vdev->dc = dc;
> -}
> -
> -static int vop_virtio_add_device(struct vop_vdev *vdev,
> - struct mic_device_desc *argp)
> -{
> - struct vop_info *vi = vdev->vi;
> - struct vop_device *vpdev = vi->vpdev;
> - struct mic_device_desc *dd = NULL;
> - struct mic_vqconfig *vqconfig;
> - int vr_size, i, j, ret;
> - u8 type = 0;
> - s8 db = -1;
> - char irqname[16];
> - struct mic_bootparam *bootparam;
> - u16 num;
> - dma_addr_t vr_addr;
> -
> - bootparam = vpdev->hw_ops->get_dp(vpdev);
> - init_waitqueue_head(&vdev->waitq);
> - INIT_LIST_HEAD(&vdev->list);
> - vdev->vpdev = vpdev;
> -
> - ret = vop_copy_dp_entry(vdev, argp, &type, &dd);
> - if (ret) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - return ret;
> - }
> -
> - vop_init_device_ctrl(vdev, dd);
> -
> - vdev->dd = dd;
> - vdev->virtio_id = type;
> - vqconfig = mic_vq_config(dd);
> - INIT_WORK(&vdev->virtio_bh_work, vop_bh_handler);
> -
> - for (i = 0; i < dd->num_vq; i++) {
> - struct vop_vringh *vvr = &vdev->vvr[i];
> - struct mic_vring *vr = &vdev->vvr[i].vring;
> -
> - num = le16_to_cpu(vqconfig[i].num);
> - mutex_init(&vvr->vr_mutex);
> - vr_size = PAGE_ALIGN(round_up(vring_size(num,
> MIC_VIRTIO_RING_ALIGN), 4) +
> - sizeof(struct _mic_vring_info));
> - vr->va = (void *)
> - __get_free_pages(GFP_KERNEL | __GFP_ZERO,
> - get_order(vr_size));
> - if (!vr->va) {
> - ret = -ENOMEM;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - goto err;
> - }
> - vr->len = vr_size;
> - vr->info = vr->va + round_up(vring_size(num,
> MIC_VIRTIO_RING_ALIGN), 4);
> - vr->info->magic = cpu_to_le32(MIC_MAGIC + vdev->virtio_id
> + i);
> - vr_addr = dma_map_single(&vpdev->dev, vr->va, vr_size,
> - DMA_BIDIRECTIONAL);
> - if (dma_mapping_error(&vpdev->dev, vr_addr)) {
> - free_pages((unsigned long)vr->va,
> get_order(vr_size));
> - ret = -ENOMEM;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - goto err;
> - }
> - vqconfig[i].address = cpu_to_le64(vr_addr);
> -
> - vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
> - ret = vringh_init_kern(&vvr->vrh,
> - *(u32 *)mic_vq_features(vdev->dd),
> - num, false, vr->vr.desc, vr->vr.avail,
> - vr->vr.used);
> - if (ret) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - goto err;
> - }
> - vringh_kiov_init(&vvr->riov, NULL, 0);
> - vringh_kiov_init(&vvr->wiov, NULL, 0);
> - vvr->head = USHRT_MAX;
> - vvr->vdev = vdev;
> - vvr->vrh.notify = _vop_notify;
> - dev_dbg(&vpdev->dev,
> - "%s %d index %d va %p info %p vr_size 0x%x\n",
> - __func__, __LINE__, i, vr->va, vr->info, vr_size);
> - vvr->buf = (void *)__get_free_pages(GFP_KERNEL,
> - get_order(VOP_INT_DMA_BUF_SIZE));
> - vvr->buf_da = dma_map_single(&vpdev->dev,
> - vvr->buf, VOP_INT_DMA_BUF_SIZE,
> - DMA_BIDIRECTIONAL);
> - }
> -
> - snprintf(irqname, sizeof(irqname), "vop%dvirtio%d", vpdev->index,
> - vdev->virtio_id);
> - vdev->virtio_db = vpdev->hw_ops->next_db(vpdev);
> - vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev,
> - _vop_virtio_intr_handler, irqname, vdev,
> - vdev->virtio_db);
> - if (IS_ERR(vdev->virtio_cookie)) {
> - ret = PTR_ERR(vdev->virtio_cookie);
> - dev_dbg(&vpdev->dev, "request irq failed\n");
> - goto err;
> - }
> -
> - vdev->dc->c2h_vdev_db = vdev->virtio_db;
> -
> - /*
> - * Order the type update with previous stores. This write barrier
> - * is paired with the corresponding read barrier before the uncached
> - * system memory read of the type, on the card while scanning the
> - * device page.
> - */
> - smp_wmb();
> - dd->type = type;
> - argp->type = type;
> -
> - if (bootparam) {
> - db = bootparam->h2c_config_db;
> - if (db != -1)
> - vpdev->hw_ops->send_intr(vpdev, db);
> - }
> - dev_dbg(&vpdev->dev, "Added virtio id %d db %d\n", dd->type, db);
> - return 0;
> -err:
> - vqconfig = mic_vq_config(dd);
> - for (j = 0; j < i; j++) {
> - struct vop_vringh *vvr = &vdev->vvr[j];
> -
> - dma_unmap_single(&vpdev->dev,
> le64_to_cpu(vqconfig[j].address),
> - vvr->vring.len, DMA_BIDIRECTIONAL);
> - free_pages((unsigned long)vvr->vring.va,
> - get_order(vvr->vring.len));
> - }
> - return ret;
> -}
> -
> -static void vop_dev_remove(struct vop_info *pvi, struct mic_device_ctrl
> *devp,
> - struct vop_device *vpdev)
> -{
> - struct mic_bootparam *bootparam = vpdev->hw_ops-
> >get_dp(vpdev);
> - s8 db;
> - int ret, retry;
> - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
> -
> - devp->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
> - db = bootparam->h2c_config_db;
> - if (db != -1)
> - vpdev->hw_ops->send_intr(vpdev, db);
> - else
> - goto done;
> - for (retry = 15; retry--;) {
> - ret = wait_event_timeout(wake, devp->guest_ack,
> - msecs_to_jiffies(1000));
> - if (ret)
> - break;
> - }
> -done:
> - devp->config_change = 0;
> - devp->guest_ack = 0;
> -}
> -
> -static void vop_virtio_del_device(struct vop_vdev *vdev)
> -{
> - struct vop_info *vi = vdev->vi;
> - struct vop_device *vpdev = vdev->vpdev;
> - int i;
> - struct mic_vqconfig *vqconfig;
> - struct mic_bootparam *bootparam = vpdev->hw_ops-
> >get_dp(vpdev);
> -
> - if (!bootparam)
> - goto skip_hot_remove;
> - vop_dev_remove(vi, vdev->dc, vpdev);
> -skip_hot_remove:
> - vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev);
> - flush_work(&vdev->virtio_bh_work);
> - vqconfig = mic_vq_config(vdev->dd);
> - for (i = 0; i < vdev->dd->num_vq; i++) {
> - struct vop_vringh *vvr = &vdev->vvr[i];
> -
> - dma_unmap_single(&vpdev->dev,
> - vvr->buf_da, VOP_INT_DMA_BUF_SIZE,
> - DMA_BIDIRECTIONAL);
> - free_pages((unsigned long)vvr->buf,
> - get_order(VOP_INT_DMA_BUF_SIZE));
> - vringh_kiov_cleanup(&vvr->riov);
> - vringh_kiov_cleanup(&vvr->wiov);
> - dma_unmap_single(&vpdev->dev,
> le64_to_cpu(vqconfig[i].address),
> - vvr->vring.len, DMA_BIDIRECTIONAL);
> - free_pages((unsigned long)vvr->vring.va,
> - get_order(vvr->vring.len));
> - }
> - /*
> - * Order the type update with previous stores. This write barrier
> - * is paired with the corresponding read barrier before the uncached
> - * system memory read of the type, on the card while scanning the
> - * device page.
> - */
> - smp_wmb();
> - vdev->dd->type = -1;
> -}
> -
> -/*
> - * vop_sync_dma - Wrapper for synchronous DMAs.
> - *
> - * @dev - The address of the pointer to the device instance used
> - * for DMA registration.
> - * @dst - destination DMA address.
> - * @src - source DMA address.
> - * @len - size of the transfer.
> - *
> - * Return DMA_SUCCESS on success
> - */
> -static int vop_sync_dma(struct vop_vdev *vdev, dma_addr_t dst,
> dma_addr_t src,
> - size_t len)
> -{
> - int err = 0;
> - struct dma_device *ddev;
> - struct dma_async_tx_descriptor *tx;
> - struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
> - struct dma_chan *vop_ch = vi->dma_ch;
> -
> - if (!vop_ch) {
> - err = -EBUSY;
> - goto error;
> - }
> - ddev = vop_ch->device;
> - tx = ddev->device_prep_dma_memcpy(vop_ch, dst, src, len,
> - DMA_PREP_FENCE);
> - if (!tx) {
> - err = -ENOMEM;
> - goto error;
> - } else {
> - dma_cookie_t cookie;
> -
> - cookie = tx->tx_submit(tx);
> - if (dma_submit_error(cookie)) {
> - err = -ENOMEM;
> - goto error;
> - }
> - dma_async_issue_pending(vop_ch);
> - err = dma_sync_wait(vop_ch, cookie);
> - }
> -error:
> - if (err)
> - dev_err(&vi->vpdev->dev, "%s %d err %d\n",
> - __func__, __LINE__, err);
> - return err;
> -}
> -
> -#define VOP_USE_DMA true
> -
> -/*
> - * Initiates the copies across the PCIe bus from card memory to a user
> - * space buffer. When transfers are done using DMA, source/destination
> - * addresses and transfer length must follow the alignment requirements of
> - * the MIC DMA engine.
> - */
> -static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
> - size_t len, u64 daddr, size_t dlen,
> - int vr_idx)
> -{
> - struct vop_device *vpdev = vdev->vpdev;
> - void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
> - struct vop_vringh *vvr = &vdev->vvr[vr_idx];
> - struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
> - size_t dma_alignment;
> - bool x200;
> - size_t dma_offset, partlen;
> - int err;
> -
> - if (!VOP_USE_DMA || !vi->dma_ch) {
> - if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
> - err = -EFAULT;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - vdev->in_bytes += len;
> - err = 0;
> - goto err;
> - }
> -
> - dma_alignment = 1 << vi->dma_ch->device->copy_align;
> - x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
> -
> - dma_offset = daddr - round_down(daddr, dma_alignment);
> - daddr -= dma_offset;
> - len += dma_offset;
> - /*
> - * X100 uses DMA addresses as seen by the card so adding
> - * the aperture base is not required for DMA. However x200
> - * requires DMA addresses to be an offset into the bar so
> - * add the aperture base for x200.
> - */
> - if (x200)
> - daddr += vpdev->aper->pa;
> - while (len) {
> - partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
> - err = vop_sync_dma(vdev, vvr->buf_da, daddr,
> - ALIGN(partlen, dma_alignment));
> - if (err) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - if (copy_to_user(ubuf, vvr->buf + dma_offset,
> - partlen - dma_offset)) {
> - err = -EFAULT;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - daddr += partlen;
> - ubuf += partlen;
> - dbuf += partlen;
> - vdev->in_bytes_dma += partlen;
> - vdev->in_bytes += partlen;
> - len -= partlen;
> - dma_offset = 0;
> - }
> - err = 0;
> -err:
> - vpdev->hw_ops->unmap(vpdev, dbuf);
> - dev_dbg(vop_dev(vdev),
> - "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
> - __func__, ubuf, dbuf, len, vr_idx);
> - return err;
> -}
> -
> -/*
> - * Initiates copies across the PCIe bus from a user space buffer to card
> - * memory. When transfers are done using DMA, source/destination
> addresses
> - * and transfer length must follow the alignment requirements of the MIC
> - * DMA engine.
> - */
> -static int vop_virtio_copy_from_user(struct vop_vdev *vdev, void __user
> *ubuf,
> - size_t len, u64 daddr, size_t dlen,
> - int vr_idx)
> -{
> - struct vop_device *vpdev = vdev->vpdev;
> - void __iomem *dbuf = vpdev->hw_ops->remap(vpdev, daddr, len);
> - struct vop_vringh *vvr = &vdev->vvr[vr_idx];
> - struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
> - size_t dma_alignment;
> - bool x200;
> - size_t partlen;
> - bool dma = VOP_USE_DMA && vi->dma_ch;
> - int err = 0;
> - size_t offset = 0;
> -
> - if (dma) {
> - dma_alignment = 1 << vi->dma_ch->device->copy_align;
> - x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
> -
> - if (daddr & (dma_alignment - 1)) {
> - vdev->tx_dst_unaligned += len;
> - dma = false;
> - } else if (ALIGN(len, dma_alignment) > dlen) {
> - vdev->tx_len_unaligned += len;
> - dma = false;
> - }
> - }
> -
> - if (!dma)
> - goto memcpy;
> -
> - /*
> - * X100 uses DMA addresses as seen by the card so adding
> - * the aperture base is not required for DMA. However x200
> - * requires DMA addresses to be an offset into the bar so
> - * add the aperture base for x200.
> - */
> - if (x200)
> - daddr += vpdev->aper->pa;
> - while (len) {
> - partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
> -
> - if (copy_from_user(vvr->buf, ubuf, partlen)) {
> - err = -EFAULT;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - err = vop_sync_dma(vdev, daddr, vvr->buf_da,
> - ALIGN(partlen, dma_alignment));
> - if (err) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - daddr += partlen;
> - ubuf += partlen;
> - dbuf += partlen;
> - vdev->out_bytes_dma += partlen;
> - vdev->out_bytes += partlen;
> - len -= partlen;
> - }
> -memcpy:
> - /*
> - * We are copying to IO below and should ideally use something
> - * like copy_from_user_toio(..) if it existed.
> - */
> - while (len) {
> - partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
> -
> - if (copy_from_user(vvr->buf, ubuf + offset, partlen)) {
> - err = -EFAULT;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - memcpy_toio(dbuf + offset, vvr->buf, partlen);
> - offset += partlen;
> - vdev->out_bytes += partlen;
> - len -= partlen;
> - }
> - err = 0;
> -err:
> - vpdev->hw_ops->unmap(vpdev, dbuf);
> - dev_dbg(vop_dev(vdev),
> - "%s: ubuf %p dbuf %p len 0x%zx vr_idx 0x%x\n",
> - __func__, ubuf, dbuf, len, vr_idx);
> - return err;
> -}
> -
> -#define MIC_VRINGH_READ true
> -
> -/* Determine the total number of bytes consumed in a VRINGH KIOV */
> -static inline u32 vop_vringh_iov_consumed(struct vringh_kiov *iov)
> -{
> - int i;
> - u32 total = iov->consumed;
> -
> - for (i = 0; i < iov->i; i++)
> - total += iov->iov[i].iov_len;
> - return total;
> -}
> -
> -/*
> - * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
> - * This API is heavily based on the vringh_iov_xfer(..) implementation
> - * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
> - * and vringh_iov_push_kern(..) directly is because there is no
> - * way to override the VRINGH xfer(..) routines as of v3.10.
> - */
> -static int vop_vringh_copy(struct vop_vdev *vdev, struct vringh_kiov *iov,
> - void __user *ubuf, size_t len, bool read, int vr_idx,
> - size_t *out_len)
> -{
> - int ret = 0;
> - size_t partlen, tot_len = 0;
> -
> - while (len && iov->i < iov->used) {
> - struct kvec *kiov = &iov->iov[iov->i];
> - unsigned long daddr = (unsigned long)kiov->iov_base;
> -
> - partlen = min(kiov->iov_len, len);
> - if (read)
> - ret = vop_virtio_copy_to_user(vdev, ubuf, partlen,
> - daddr,
> - kiov->iov_len,
> - vr_idx);
> - else
> - ret = vop_virtio_copy_from_user(vdev, ubuf, partlen,
> - daddr,
> - kiov->iov_len,
> - vr_idx);
> - if (ret) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - break;
> - }
> - len -= partlen;
> - ubuf += partlen;
> - tot_len += partlen;
> - iov->consumed += partlen;
> - kiov->iov_len -= partlen;
> - kiov->iov_base += partlen;
> - if (!kiov->iov_len) {
> - /* Fix up old iov element then increment. */
> - kiov->iov_len = iov->consumed;
> - kiov->iov_base -= iov->consumed;
> -
> - iov->consumed = 0;
> - iov->i++;
> - }
> - }
> - *out_len = tot_len;
> - return ret;
> -}
> -
> -/*
> - * Use the standard VRINGH infrastructure in the kernel to fetch new
> - * descriptors, initiate the copies and update the used ring.
> - */
> -static int _vop_virtio_copy(struct vop_vdev *vdev, struct mic_copy_desc
> *copy)
> -{
> - int ret = 0;
> - u32 iovcnt = copy->iovcnt;
> - struct iovec iov;
> - struct iovec __user *u_iov = copy->iov;
> - void __user *ubuf = NULL;
> - struct vop_vringh *vvr = &vdev->vvr[copy->vr_idx];
> - struct vringh_kiov *riov = &vvr->riov;
> - struct vringh_kiov *wiov = &vvr->wiov;
> - struct vringh *vrh = &vvr->vrh;
> - u16 *head = &vvr->head;
> - struct mic_vring *vr = &vvr->vring;
> - size_t len = 0, out_len;
> -
> - copy->out_len = 0;
> - /* Fetch a new IOVEC if all previous elements have been processed
> */
> - if (riov->i == riov->used && wiov->i == wiov->used) {
> - ret = vringh_getdesc_kern(vrh, riov, wiov,
> - head, GFP_KERNEL);
> - /* Check if there are available descriptors */
> - if (ret <= 0)
> - return ret;
> - }
> - while (iovcnt) {
> - if (!len) {
> - /* Copy over a new iovec from user space. */
> - ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
> - if (ret) {
> - ret = -EINVAL;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - break;
> - }
> - len = iov.iov_len;
> - ubuf = iov.iov_base;
> - }
> - /* Issue all the read descriptors first */
> - ret = vop_vringh_copy(vdev, riov, ubuf, len,
> - MIC_VRINGH_READ, copy->vr_idx,
> &out_len);
> - if (ret) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - break;
> - }
> - len -= out_len;
> - ubuf += out_len;
> - copy->out_len += out_len;
> - /* Issue the write descriptors next */
> - ret = vop_vringh_copy(vdev, wiov, ubuf, len,
> - !MIC_VRINGH_READ, copy->vr_idx,
> &out_len);
> - if (ret) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, ret);
> - break;
> - }
> - len -= out_len;
> - ubuf += out_len;
> - copy->out_len += out_len;
> - if (!len) {
> - /* One user space iovec is now completed */
> - iovcnt--;
> - u_iov++;
> - }
> - /* Exit loop if all elements in KIOVs have been processed. */
> - if (riov->i == riov->used && wiov->i == wiov->used)
> - break;
> - }
> - /*
> - * Update the used ring if a descriptor was available and some data
> was
> - * copied in/out and the user asked for a used ring update.
> - */
> - if (*head != USHRT_MAX && copy->out_len && copy->update_used)
> {
> - u32 total = 0;
> -
> - /* Determine the total data consumed */
> - total += vop_vringh_iov_consumed(riov);
> - total += vop_vringh_iov_consumed(wiov);
> - vringh_complete_kern(vrh, *head, total);
> - *head = USHRT_MAX;
> - if (vringh_need_notify_kern(vrh) > 0)
> - vringh_notify(vrh);
> - vringh_kiov_cleanup(riov);
> - vringh_kiov_cleanup(wiov);
> - /* Update avail idx for user space */
> - vr->info->avail_idx = vrh->last_avail_idx;
> - }
> - return ret;
> -}
> -
> -static inline int vop_verify_copy_args(struct vop_vdev *vdev,
> - struct mic_copy_desc *copy)
> -{
> - if (!vdev || copy->vr_idx >= vdev->dd->num_vq)
> - return -EINVAL;
> - return 0;
> -}
> -
> -/* Copy a specified number of virtio descriptors in a chain */
> -static int vop_virtio_copy_desc(struct vop_vdev *vdev,
> - struct mic_copy_desc *copy)
> -{
> - int err;
> - struct vop_vringh *vvr;
> -
> - err = vop_verify_copy_args(vdev, copy);
> - if (err)
> - return err;
> -
> - vvr = &vdev->vvr[copy->vr_idx];
> - mutex_lock(&vvr->vr_mutex);
> - if (!vop_vdevup(vdev)) {
> - err = -ENODEV;
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - goto err;
> - }
> - err = _vop_virtio_copy(vdev, copy);
> - if (err) {
> - dev_err(vop_dev(vdev), "%s %d err %d\n",
> - __func__, __LINE__, err);
> - }
> -err:
> - mutex_unlock(&vvr->vr_mutex);
> - return err;
> -}
> -
> -static int vop_open(struct inode *inode, struct file *f)
> -{
> - struct vop_vdev *vdev;
> - struct vop_info *vi = container_of(f->private_data,
> - struct vop_info, miscdev);
> -
> - vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
> - if (!vdev)
> - return -ENOMEM;
> - vdev->vi = vi;
> - mutex_init(&vdev->vdev_mutex);
> - f->private_data = vdev;
> - init_completion(&vdev->destroy);
> - complete(&vdev->destroy);
> - return 0;
> -}
> -
> -static int vop_release(struct inode *inode, struct file *f)
> -{
> - struct vop_vdev *vdev = f->private_data, *vdev_tmp;
> - struct vop_info *vi = vdev->vi;
> - struct list_head *pos, *tmp;
> - bool found = false;
> -
> - mutex_lock(&vdev->vdev_mutex);
> - if (vdev->deleted)
> - goto unlock;
> - mutex_lock(&vi->vop_mutex);
> - list_for_each_safe(pos, tmp, &vi->vdev_list) {
> - vdev_tmp = list_entry(pos, struct vop_vdev, list);
> - if (vdev == vdev_tmp) {
> - vop_virtio_del_device(vdev);
> - list_del(pos);
> - found = true;
> - break;
> - }
> - }
> - mutex_unlock(&vi->vop_mutex);
> -unlock:
> - mutex_unlock(&vdev->vdev_mutex);
> - if (!found)
> - wait_for_completion(&vdev->destroy);
> - f->private_data = NULL;
> - kfree(vdev);
> - return 0;
> -}
> -
> -static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
> -{
> - struct vop_vdev *vdev = f->private_data;
> - struct vop_info *vi = vdev->vi;
> - void __user *argp = (void __user *)arg;
> - int ret;
> -
> - switch (cmd) {
> - case MIC_VIRTIO_ADD_DEVICE:
> - {
> - struct mic_device_desc dd, *dd_config;
> -
> - if (copy_from_user(&dd, argp, sizeof(dd)))
> - return -EFAULT;
> -
> - if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE
> ||
> - dd.num_vq > MIC_MAX_VRINGS)
> - return -EINVAL;
> -
> - dd_config = memdup_user(argp, mic_desc_size(&dd));
> - if (IS_ERR(dd_config))
> - return PTR_ERR(dd_config);
> -
> - /* Ensure desc has not changed between the two reads */
> - if (memcmp(&dd, dd_config, sizeof(dd))) {
> - ret = -EINVAL;
> - goto free_ret;
> - }
> - mutex_lock(&vdev->vdev_mutex);
> - mutex_lock(&vi->vop_mutex);
> - ret = vop_virtio_add_device(vdev, dd_config);
> - if (ret)
> - goto unlock_ret;
> - list_add_tail(&vdev->list, &vi->vdev_list);
> -unlock_ret:
> - mutex_unlock(&vi->vop_mutex);
> - mutex_unlock(&vdev->vdev_mutex);
> -free_ret:
> - kfree(dd_config);
> - return ret;
> - }
> - case MIC_VIRTIO_COPY_DESC:
> - {
> - struct mic_copy_desc copy;
> -
> - mutex_lock(&vdev->vdev_mutex);
> - ret = vop_vdev_inited(vdev);
> - if (ret)
> - goto _unlock_ret;
> -
> - if (copy_from_user(&copy, argp, sizeof(copy))) {
> - ret = -EFAULT;
> - goto _unlock_ret;
> - }
> -
> - ret = vop_virtio_copy_desc(vdev, &copy);
> - if (ret < 0)
> - goto _unlock_ret;
> - if (copy_to_user(
> - &((struct mic_copy_desc __user *)argp)->out_len,
> - &copy.out_len, sizeof(copy.out_len)))
> - ret = -EFAULT;
> -_unlock_ret:
> - mutex_unlock(&vdev->vdev_mutex);
> - return ret;
> - }
> - case MIC_VIRTIO_CONFIG_CHANGE:
> - {
> - void *buf;
> -
> - mutex_lock(&vdev->vdev_mutex);
> - ret = vop_vdev_inited(vdev);
> - if (ret)
> - goto __unlock_ret;
> - buf = memdup_user(argp, vdev->dd->config_len);
> - if (IS_ERR(buf)) {
> - ret = PTR_ERR(buf);
> - goto __unlock_ret;
> - }
> - ret = vop_virtio_config_change(vdev, buf);
> - kfree(buf);
> -__unlock_ret:
> - mutex_unlock(&vdev->vdev_mutex);
> - return ret;
> - }
> - default:
> - return -ENOIOCTLCMD;
> - };
> - return 0;
> -}
> -
> -/*
> - * We return EPOLLIN | EPOLLOUT from poll when new buffers are
> enqueued, and
> - * not when previously enqueued buffers may be available. This means that
> - * in the card->host (TX) path, when userspace is unblocked by poll it
> - * must drain all available descriptors or it can stall.
> - */
> -static __poll_t vop_poll(struct file *f, poll_table *wait)
> -{
> - struct vop_vdev *vdev = f->private_data;
> - __poll_t mask = 0;
> -
> - mutex_lock(&vdev->vdev_mutex);
> - if (vop_vdev_inited(vdev)) {
> - mask = EPOLLERR;
> - goto done;
> - }
> - poll_wait(f, &vdev->waitq, wait);
> - if (vop_vdev_inited(vdev)) {
> - mask = EPOLLERR;
> - } else if (vdev->poll_wake) {
> - vdev->poll_wake = 0;
> - mask = EPOLLIN | EPOLLOUT;
> - }
> -done:
> - mutex_unlock(&vdev->vdev_mutex);
> - return mask;
> -}
> -
> -static inline int
> -vop_query_offset(struct vop_vdev *vdev, unsigned long offset,
> - unsigned long *size, unsigned long *pa)
> -{
> - struct vop_device *vpdev = vdev->vpdev;
> - unsigned long start = MIC_DP_SIZE;
> - int i;
> -
> - /*
> - * MMAP interface is as follows:
> - * offset region
> - * 0x0 virtio device_page
> - * 0x1000 first vring
> - * 0x1000 + size of 1st vring second vring
> - * ....
> - */
> - if (!offset) {
> - *pa = virt_to_phys(vpdev->hw_ops->get_dp(vpdev));
> - *size = MIC_DP_SIZE;
> - return 0;
> - }
> -
> - for (i = 0; i < vdev->dd->num_vq; i++) {
> - struct vop_vringh *vvr = &vdev->vvr[i];
> -
> - if (offset == start) {
> - *pa = virt_to_phys(vvr->vring.va);
> - *size = vvr->vring.len;
> - return 0;
> - }
> - start += vvr->vring.len;
> - }
> - return -1;
> -}
> -
> -/*
> - * Maps the device page and virtio rings to user space for readonly access.
> - */
> -static int vop_mmap(struct file *f, struct vm_area_struct *vma)
> -{
> - struct vop_vdev *vdev = f->private_data;
> - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
> - unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem =
> size;
> - int i, err;
> -
> - err = vop_vdev_inited(vdev);
> - if (err)
> - goto ret;
> - if (vma->vm_flags & VM_WRITE) {
> - err = -EACCES;
> - goto ret;
> - }
> - while (size_rem) {
> - i = vop_query_offset(vdev, offset, &size, &pa);
> - if (i < 0) {
> - err = -EINVAL;
> - goto ret;
> - }
> - err = remap_pfn_range(vma, vma->vm_start + offset,
> - pa >> PAGE_SHIFT, size,
> - vma->vm_page_prot);
> - if (err)
> - goto ret;
> - size_rem -= size;
> - offset += size;
> - }
> -ret:
> - return err;
> -}
> -
> -static const struct file_operations vop_fops = {
> - .open = vop_open,
> - .release = vop_release,
> - .unlocked_ioctl = vop_ioctl,
> - .poll = vop_poll,
> - .mmap = vop_mmap,
> - .owner = THIS_MODULE,
> -};
> -
> -int vop_host_init(struct vop_info *vi)
> -{
> - int rc;
> - struct miscdevice *mdev;
> - struct vop_device *vpdev = vi->vpdev;
> -
> - INIT_LIST_HEAD(&vi->vdev_list);
> - vi->dma_ch = vpdev->dma_ch;
> - mdev = &vi->miscdev;
> - mdev->minor = MISC_DYNAMIC_MINOR;
> - snprintf(vi->name, sizeof(vi->name), "vop_virtio%d", vpdev->index);
> - mdev->name = vi->name;
> - mdev->fops = &vop_fops;
> - mdev->parent = &vpdev->dev;
> -
> - rc = misc_register(mdev);
> - if (rc)
> - dev_err(&vpdev->dev, "%s failed rc %d\n", __func__, rc);
> - return rc;
> -}
> -
> -void vop_host_uninit(struct vop_info *vi)
> -{
> - struct list_head *pos, *tmp;
> - struct vop_vdev *vdev;
> -
> - mutex_lock(&vi->vop_mutex);
> - vop_virtio_reset_devices(vi);
> - list_for_each_safe(pos, tmp, &vi->vdev_list) {
> - vdev = list_entry(pos, struct vop_vdev, list);
> - list_del(pos);
> - reinit_completion(&vdev->destroy);
> - mutex_unlock(&vi->vop_mutex);
> - mutex_lock(&vdev->vdev_mutex);
> - vop_virtio_del_device(vdev);
> - vdev->deleted = true;
> - mutex_unlock(&vdev->vdev_mutex);
> - complete(&vdev->destroy);
> - mutex_lock(&vi->vop_mutex);
> - }
> - mutex_unlock(&vi->vop_mutex);
> - misc_deregister(&vi->miscdev);
> -}
> diff --git a/include/linux/mic_bus.h b/include/linux/mic_bus.h
> deleted file mode 100644
> index e99c789424e0..000000000000
> --- a/include/linux/mic_bus.h
> +++ /dev/null
> @@ -1,100 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Intel MIC Bus driver.
> - *
> - * This implementation is very similar to the virtio bus driver
> - * implementation @ include/linux/virtio.h.
> - */
> -#ifndef _MIC_BUS_H_
> -#define _MIC_BUS_H_
> -/*
> - * Everything a mbus driver needs to work with any particular mbus
> - * implementation.
> - */
> -#include <linux/interrupt.h>
> -#include <linux/dma-mapping.h>
> -
> -struct mbus_device_id {
> - __u32 device;
> - __u32 vendor;
> -};
> -
> -#define MBUS_DEV_DMA_HOST 2
> -#define MBUS_DEV_DMA_MIC 3
> -#define MBUS_DEV_ANY_ID 0xffffffff
> -
> -/**
> - * mbus_device - representation of a device using mbus
> - * @mmio_va: virtual address of mmio space
> - * @hw_ops: the hardware ops supported by this device.
> - * @id: the device type identification (used to match it with a driver).
> - * @dev: underlying device.
> - * be used to communicate with.
> - * @index: unique position on the mbus bus
> - */
> -struct mbus_device {
> - void __iomem *mmio_va;
> - struct mbus_hw_ops *hw_ops;
> - struct mbus_device_id id;
> - struct device dev;
> - int index;
> -};
> -
> -/**
> - * mbus_driver - operations for a mbus I/O driver
> - * @driver: underlying device driver (populate name and owner).
> - * @id_table: the ids serviced by this driver.
> - * @probe: the function to call when a device is found. Returns 0 or -errno.
> - * @remove: the function to call when a device is removed.
> - */
> -struct mbus_driver {
> - struct device_driver driver;
> - const struct mbus_device_id *id_table;
> - int (*probe)(struct mbus_device *dev);
> - void (*scan)(struct mbus_device *dev);
> - void (*remove)(struct mbus_device *dev);
> -};
> -
> -/**
> - * struct mic_irq - opaque pointer used as cookie
> - */
> -struct mic_irq;
> -
> -/**
> - * mbus_hw_ops - Hardware operations for accessing a MIC device on the
> MIC bus.
> - */
> -struct mbus_hw_ops {
> - struct mic_irq* (*request_threaded_irq)(struct mbus_device *mbdev,
> - irq_handler_t handler,
> - irq_handler_t thread_fn,
> - const char *name, void *data,
> - int intr_src);
> - void (*free_irq)(struct mbus_device *mbdev,
> - struct mic_irq *cookie, void *data);
> - void (*ack_interrupt)(struct mbus_device *mbdev, int num);
> -};
> -
> -struct mbus_device *
> -mbus_register_device(struct device *pdev, int id, const struct
> dma_map_ops *dma_ops,
> - struct mbus_hw_ops *hw_ops, int index,
> - void __iomem *mmio_va);
> -void mbus_unregister_device(struct mbus_device *mbdev);
> -
> -int mbus_register_driver(struct mbus_driver *drv);
> -void mbus_unregister_driver(struct mbus_driver *drv);
> -
> -static inline struct mbus_device *dev_to_mbus(struct device *_dev)
> -{
> - return container_of(_dev, struct mbus_device, dev);
> -}
> -
> -static inline struct mbus_driver *drv_to_mbus(struct device_driver *drv)
> -{
> - return container_of(drv, struct mbus_driver, driver);
> -}
> -
> -#endif /* _MIC_BUS_H */
> diff --git a/include/linux/scif.h b/include/linux/scif.h
> deleted file mode 100644
> index 329e695b8fe5..000000000000
> --- a/include/linux/scif.h
> +++ /dev/null
> @@ -1,1339 +0,0 @@
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * This file is provided under a dual BSD/GPLv2 license. When using or
> - * redistributing this file, you may do so under either license.
> - *
> - * GPL LICENSE SUMMARY
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * BSD LICENSE
> - *
> - * Copyright(c) 2014 Intel Corporation.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - * * Redistributions in binary form must reproduce the above copyright
> - * notice, this list of conditions and the following disclaimer in
> - * the documentation and/or other materials provided with the
> - * distribution.
> - * * Neither the name of Intel Corporation nor the names of its
> - * contributors may be used to endorse or promote products derived
> - * from this software without specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> ON ANY
> - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> - *
> - * Intel SCIF driver.
> - *
> - */
> -#ifndef __SCIF_H__
> -#define __SCIF_H__
> -
> -#include <linux/types.h>
> -#include <linux/poll.h>
> -#include <linux/device.h>
> -#include <linux/scif_ioctl.h>
> -
> -#define SCIF_ACCEPT_SYNC 1
> -#define SCIF_SEND_BLOCK 1
> -#define SCIF_RECV_BLOCK 1
> -
> -enum {
> - SCIF_PROT_READ = (1 << 0),
> - SCIF_PROT_WRITE = (1 << 1)
> -};
> -
> -enum {
> - SCIF_MAP_FIXED = 0x10,
> - SCIF_MAP_KERNEL = 0x20,
> -};
> -
> -enum {
> - SCIF_FENCE_INIT_SELF = (1 << 0),
> - SCIF_FENCE_INIT_PEER = (1 << 1),
> - SCIF_SIGNAL_LOCAL = (1 << 4),
> - SCIF_SIGNAL_REMOTE = (1 << 5)
> -};
> -
> -enum {
> - SCIF_RMA_USECPU = (1 << 0),
> - SCIF_RMA_USECACHE = (1 << 1),
> - SCIF_RMA_SYNC = (1 << 2),
> - SCIF_RMA_ORDERED = (1 << 3)
> -};
> -
> -/* End of SCIF Admin Reserved Ports */
> -#define SCIF_ADMIN_PORT_END 1024
> -
> -/* End of SCIF Reserved Ports */
> -#define SCIF_PORT_RSVD 1088
> -
> -typedef struct scif_endpt *scif_epd_t;
> -typedef struct scif_pinned_pages *scif_pinned_pages_t;
> -
> -/**
> - * struct scif_range - SCIF registered range used in kernel mode
> - * @cookie: cookie used internally by SCIF
> - * @nr_pages: number of pages of PAGE_SIZE
> - * @prot_flags: R/W protection
> - * @phys_addr: Array of bus addresses
> - * @va: Array of kernel virtual addresses backed by the pages in the
> phys_addr
> - * array. The va is populated only when called on the host for a remote
> - * SCIF connection on MIC. This is required to support the use case of
> DMA
> - * between MIC and another device which is not a SCIF node e.g., an IB
> or
> - * ethernet NIC.
> - */
> -struct scif_range {
> - void *cookie;
> - int nr_pages;
> - int prot_flags;
> - dma_addr_t *phys_addr;
> - void __iomem **va;
> -};
> -
> -/**
> - * struct scif_pollepd - SCIF endpoint to be monitored via scif_poll
> - * @epd: SCIF endpoint
> - * @events: requested events
> - * @revents: returned events
> - */
> -struct scif_pollepd {
> - scif_epd_t epd;
> - __poll_t events;
> - __poll_t revents;
> -};
> -
> -/**
> - * scif_peer_dev - representation of a peer SCIF device
> - *
> - * Peer devices show up as PCIe devices for the mgmt node but not the cards.
> - * The mgmt node discovers all the cards on the PCIe bus and informs the
> other
> - * cards about their peers. Upon notification of a peer a node adds a peer
> - * device to the peer bus to maintain symmetry in the way devices are
> - * discovered across all nodes in the SCIF network.
> - *
> - * @dev: underlying device
> - * @dnode - The destination node which this device will communicate with.
> - */
> -struct scif_peer_dev {
> - struct device dev;
> - u8 dnode;
> -};
> -
> -/**
> - * scif_client - representation of a SCIF client
> - * @name: client name
> - * @probe - client method called when a peer device is registered
> - * @remove - client method called when a peer device is unregistered
> - * @si - subsys_interface used internally for implementing SCIF clients
> - */
> -struct scif_client {
> - const char *name;
> - void (*probe)(struct scif_peer_dev *spdev);
> - void (*remove)(struct scif_peer_dev *spdev);
> - struct subsys_interface si;
> -};
> -
> -#define SCIF_OPEN_FAILED ((scif_epd_t)-1)
> -#define SCIF_REGISTER_FAILED ((off_t)-1)
> -#define SCIF_MMAP_FAILED ((void *)-1)
> -
> -/**
> - * scif_open() - Create an endpoint
> - *
> - * Return:
> - * Upon successful completion, scif_open() returns an endpoint descriptor
> to
> - * be used in subsequent SCIF functions calls to refer to that endpoint;
> - * otherwise in user mode SCIF_OPEN_FAILED (that is ((scif_epd_t)-1)) is
> - * returned and errno is set to indicate the error; in kernel mode a NULL
> - * scif_epd_t is returned.
> - *
> - * Errors:
> - * ENOMEM - Insufficient kernel memory was available
> - */
> -scif_epd_t scif_open(void);
> -
> -/**
> - * scif_bind() - Bind an endpoint to a port
> - * @epd: endpoint descriptor
> - * @pn: port number
> - *
> - * scif_bind() binds endpoint epd to port pn, where pn is a port number on
> the
> - * local node. If pn is zero, a port number greater than or equal to
> - * SCIF_PORT_RSVD is assigned and returned. Each endpoint may be bound
> to
> - * exactly one local port. Ports less than 1024 when requested can only be
> bound
> - * by system (or root) processes or by processes executed by privileged
> users.
> - *
> - * Return:
> - * Upon successful completion, scif_bind() returns the port number to which
> epd
> - * is bound; otherwise in user mode -1 is returned and errno is set to
> - * indicate the error; in kernel mode the negative of one of the following
> - * errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * EINVAL - the endpoint or the port is already bound
> - * EISCONN - The endpoint is already connected
> - * ENOSPC - No port number available for assignment
> - * EACCES - The port requested is protected and the user is not the
> superuser
> - */
> -int scif_bind(scif_epd_t epd, u16 pn);
> -
> -/**
> - * scif_listen() - Listen for connections on an endpoint
> - * @epd: endpoint descriptor
> - * @backlog: maximum pending connection requests
> - *
> - * scif_listen() marks the endpoint epd as a listening endpoint - that is, as
> - * an endpoint that will be used to accept incoming connection requests.
> Once
> - * so marked, the endpoint is said to be in the listening state and may not be
> - * used as the endpoint of a connection.
> - *
> - * The endpoint, epd, must have been bound to a port.
> - *
> - * The backlog argument defines the maximum length to which the queue of
> - * pending connections for epd may grow. If a connection request arrives
> when
> - * the queue is full, the client may receive an error with an indication that
> - * the connection was refused.
> - *
> - * Return:
> - * Upon successful completion, scif_listen() returns 0; otherwise in user
> mode
> - * -1 is returned and errno is set to indicate the error; in kernel mode the
> - * negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * EINVAL - the endpoint is not bound to a port
> - * EISCONN - The endpoint is already connected or listening
> - */
> -int scif_listen(scif_epd_t epd, int backlog);
> -
> -/**
> - * scif_connect() - Initiate a connection on a port
> - * @epd: endpoint descriptor
> - * @dst: global id of port to which to connect
> - *
> - * The scif_connect() function requests the connection of endpoint epd to
> remote
> - * port dst. If the connection is successful, a peer endpoint, bound to dst, is
> - * created on node dst.node. On successful return, the connection is
> complete.
> - *
> - * If the endpoint epd has not already been bound to a port, scif_connect()
> - * will bind it to an unused local port.
> - *
> - * A connection is terminated when an endpoint of the connection is closed,
> - * either explicitly by scif_close(), or when a process that owns one of the
> - * endpoints of the connection is terminated.
> - *
> - * In user space, scif_connect() supports an asynchronous connection mode
> - * if the application has set the O_NONBLOCK flag on the endpoint via the
> - * fcntl() system call. Setting this flag will result in the calling process
> - * not to wait during scif_connect().
> - *
> - * Return:
> - * Upon successful completion, scif_connect() returns the port ID to which
> the
> - * endpoint, epd, is bound; otherwise in user mode -1 is returned and errno
> is
> - * set to indicate the error; in kernel mode the negative of one of the
> - * following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNREFUSED - The destination was not listening for connections or
> refused
> - * the connection request
> - * EINVAL - dst.port is not a valid port ID
> - * EISCONN - The endpoint is already connected
> - * ENOMEM - No buffer space is available
> - * ENODEV - The destination node does not exist, or the node is lost or
> existed,
> - * but is not currently in the network since it may have crashed
> - * ENOSPC - No port number available for assignment
> - * EOPNOTSUPP - The endpoint is listening and cannot be connected
> - */
> -int scif_connect(scif_epd_t epd, struct scif_port_id *dst);
> -
> -/**
> - * scif_accept() - Accept a connection on an endpoint
> - * @epd: endpoint descriptor
> - * @peer: global id of port to which connected
> - * @newepd: new connected endpoint descriptor
> - * @flags: flags
> - *
> - * The scif_accept() call extracts the first connection request from the queue
> - * of pending connections for the port on which epd is listening. scif_accept()
> - * creates a new endpoint, bound to the same port as epd, and allocates a
> new
> - * SCIF endpoint descriptor, returned in newepd, for the endpoint. The new
> - * endpoint is connected to the endpoint through which the connection was
> - * requested. epd is unaffected by this call, and remains in the listening
> - * state.
> - *
> - * On successful return, peer holds the global port identifier (node id and
> - * local port number) of the port which requested the connection.
> - *
> - * A connection is terminated when an endpoint of the connection is closed,
> - * either explicitly by scif_close(), or when a process that owns one of the
> - * endpoints of the connection is terminated.
> - *
> - * The number of connections that can (subsequently) be accepted on epd is
> only
> - * limited by system resources (memory).
> - *
> - * The flags argument is formed by OR'ing together zero or more of the
> - * following values.
> - * SCIF_ACCEPT_SYNC - block until a connection request is presented. If
> - * SCIF_ACCEPT_SYNC is not in flags, and no pending
> - * connections are present on the queue, scif_accept()
> - * fails with an EAGAIN error
> - *
> - * In user mode, the select() and poll() functions can be used to determine
> - * when there is a connection request. In kernel mode, the scif_poll()
> - * function may be used for this purpose. A readable event will be delivered
> - * when a connection is requested.
> - *
> - * Return:
> - * Upon successful completion, scif_accept() returns 0; otherwise in user
> mode
> - * -1 is returned and errno is set to indicate the error; in kernel mode the
> - * negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EAGAIN - SCIF_ACCEPT_SYNC is not set and no connections are present to
> be
> - * accepted or SCIF_ACCEPT_SYNC is not set and remote node failed to
> complete
> - * its connection request
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * EINTR - Interrupted function
> - * EINVAL - epd is not a listening endpoint, or flags is invalid, or peer is
> - * NULL, or newepd is NULL
> - * ENODEV - The requesting node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOMEM - Not enough space
> - * ENOENT - Secondary part of epd registration failed
> - */
> -int scif_accept(scif_epd_t epd, struct scif_port_id *peer, scif_epd_t
> - *newepd, int flags);
> -
> -/**
> - * scif_close() - Close an endpoint
> - * @epd: endpoint descriptor
> - *
> - * scif_close() closes an endpoint and performs necessary teardown of
> - * facilities associated with that endpoint.
> - *
> - * If epd is a listening endpoint then it will no longer accept connection
> - * requests on the port to which it is bound. Any pending connection
> requests
> - * are rejected.
> - *
> - * If epd is a connected endpoint, then its peer endpoint is also closed.
> RMAs
> - * which are in-process through epd or its peer endpoint will complete
> before
> - * scif_close() returns. Registered windows of the local and peer endpoints
> are
> - * released as if scif_unregister() was called against each window.
> - *
> - * Closing a SCIF endpoint does not affect local registered memory mapped
> by
> - * a SCIF endpoint on a remote node. The local memory remains mapped by
> the peer
> - * SCIF endpoint explicitly removed by calling munmap(..) by the peer.
> - *
> - * If the peer endpoint's receive queue is not empty at the time that epd is
> - * closed, then the peer endpoint can be passed as the endpoint parameter
> to
> - * scif_recv() until the receive queue is empty.
> - *
> - * epd is freed and may no longer be accessed.
> - *
> - * Return:
> - * Upon successful completion, scif_close() returns 0; otherwise in user
> mode
> - * -1 is returned and errno is set to indicate the error; in kernel mode the
> - * negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - */
> -int scif_close(scif_epd_t epd);
> -
> -/**
> - * scif_send() - Send a message
> - * @epd: endpoint descriptor
> - * @msg: message buffer address
> - * @len: message length
> - * @flags: blocking mode flags
> - *
> - * scif_send() sends data to the peer of endpoint epd. Up to len bytes of
> data
> - * are copied from memory starting at address msg. On successful execution
> the
> - * return value of scif_send() is the number of bytes that were sent, and is
> - * zero if no bytes were sent because len was zero. scif_send() may be called
> - * only when the endpoint is in a connected state.
> - *
> - * If a scif_send() call is non-blocking, then it sends only those bytes which
> - * can be sent without waiting, up to a maximum of len bytes.
> - *
> - * If a scif_send() call is blocking, then it normally returns after sending
> - * all len bytes. If a blocking call is interrupted or the connection is
> - * reset, the call is considered successful if some bytes were sent or len is
> - * zero, otherwise the call is considered unsuccessful.
> - *
> - * In user mode, the select() and poll() functions can be used to determine
> - * when the send queue is not full. In kernel mode, the scif_poll() function
> - * may be used for this purpose.
> - *
> - * It is recommended that scif_send()/scif_recv() only be used for short
> - * control-type message communication between SCIF endpoints. The SCIF
> RMA
> - * APIs are expected to provide better performance for transfer sizes of
> - * 1024 bytes or longer for the current MIC hardware and software
> - * implementation.
> - *
> - * scif_send() will block until the entire message is sent if SCIF_SEND_BLOCK
> - * is passed as the flags argument.
> - *
> - * Return:
> - * Upon successful completion, scif_send() returns the number of bytes sent;
> - * otherwise in user mode -1 is returned and errno is set to indicate the
> - * error; in kernel mode the negative of one of the following errors is
> - * returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - flags is invalid, or len is negative
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOMEM - Not enough space
> - * ENOTCONN - The endpoint is not connected
> - */
> -int scif_send(scif_epd_t epd, void *msg, int len, int flags);
> -
> -/**
> - * scif_recv() - Receive a message
> - * @epd: endpoint descriptor
> - * @msg: message buffer address
> - * @len: message buffer length
> - * @flags: blocking mode flags
> - *
> - * scif_recv() receives data from the peer of endpoint epd. Up to len bytes of
> - * data are copied to memory starting at address msg. On successful
> execution
> - * the return value of scif_recv() is the number of bytes that were received,
> - * and is zero if no bytes were received because len was zero. scif_recv()
> may
> - * be called only when the endpoint is in a connected state.
> - *
> - * If a scif_recv() call is non-blocking, then it receives only those bytes
> - * which can be received without waiting, up to a maximum of len bytes.
> - *
> - * If a scif_recv() call is blocking, then it normally returns after receiving
> - * all len bytes. If the blocking call was interrupted due to a disconnection,
> - * subsequent calls to scif_recv() will copy all bytes received upto the point
> - * of disconnection.
> - *
> - * In user mode, the select() and poll() functions can be used to determine
> - * when data is available to be received. In kernel mode, the scif_poll()
> - * function may be used for this purpose.
> - *
> - * It is recommended that scif_send()/scif_recv() only be used for short
> - * control-type message communication between SCIF endpoints. The SCIF
> RMA
> - * APIs are expected to provide better performance for transfer sizes of
> - * 1024 bytes or longer for the current MIC hardware and software
> - * implementation.
> - *
> - * scif_recv() will block until the entire message is received if
> - * SCIF_RECV_BLOCK is passed as the flags argument.
> - *
> - * Return:
> - * Upon successful completion, scif_recv() returns the number of bytes
> - * received; otherwise in user mode -1 is returned and errno is set to
> - * indicate the error; in kernel mode the negative of one of the following
> - * errors is returned.
> - *
> - * Errors:
> - * EAGAIN - The destination node is returning from a low power state
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - flags is invalid, or len is negative
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOMEM - Not enough space
> - * ENOTCONN - The endpoint is not connected
> - */
> -int scif_recv(scif_epd_t epd, void *msg, int len, int flags);
> -
> -/**
> - * scif_register() - Mark a memory region for remote access.
> - * @epd: endpoint descriptor
> - * @addr: starting virtual address
> - * @len: length of range
> - * @offset: offset of window
> - * @prot_flags: read/write protection flags
> - * @map_flags: mapping flags
> - *
> - * The scif_register() function opens a window, a range of whole pages of
> the
> - * registered address space of the endpoint epd, starting at offset po and
> - * continuing for len bytes. The value of po, further described below, is a
> - * function of the parameters offset and len, and the value of map_flags.
> Each
> - * page of the window represents the physical memory page which backs
> the
> - * corresponding page of the range of virtual address pages starting at addr
> - * and continuing for len bytes. addr and len are constrained to be multiples
> - * of the page size. A successful scif_register() call returns po.
> - *
> - * When SCIF_MAP_FIXED is set in the map_flags argument, po will be offset
> - * exactly, and offset is constrained to be a multiple of the page size. The
> - * mapping established by scif_register() will not replace any existing
> - * registration; an error is returned if any page within the range [offset,
> - * offset + len - 1] intersects an existing window.
> - *
> - * When SCIF_MAP_FIXED is not set, the implementation uses offset in an
> - * implementation-defined manner to arrive at po. The po value so chosen
> will
> - * be an area of the registered address space that the implementation
> deems
> - * suitable for a mapping of len bytes. An offset value of 0 is interpreted as
> - * granting the implementation complete freedom in selecting po, subject to
> - * constraints described below. A non-zero value of offset is taken to be a
> - * suggestion of an offset near which the mapping should be placed. When
> the
> - * implementation selects a value for po, it does not replace any extant
> - * window. In all cases, po will be a multiple of the page size.
> - *
> - * The physical pages which are so represented by a window are available
> for
> - * access in calls to mmap(), scif_readfrom(), scif_writeto(),
> - * scif_vreadfrom(), and scif_vwriteto(). While a window is registered, the
> - * physical pages represented by the window will not be reused by the
> memory
> - * subsystem for any other purpose. Note that the same physical page may
> be
> - * represented by multiple windows.
> - *
> - * Subsequent operations which change the memory pages to which virtual
> - * addresses are mapped (such as mmap(), munmap()) have no effect on
> - * existing window.
> - *
> - * If the process will fork(), it is recommended that the registered
> - * virtual address range be marked with MADV_DONTFORK. Doing so will
> prevent
> - * problems due to copy-on-write semantics.
> - *
> - * The prot_flags argument is formed by OR'ing together one or more of the
> - * following values.
> - * SCIF_PROT_READ - allow read operations from the window
> - * SCIF_PROT_WRITE - allow write operations to the window
> - *
> - * Return:
> - * Upon successful completion, scif_register() returns the offset at which the
> - * mapping was placed (po); otherwise in user mode SCIF_REGISTER_FAILED
> (that
> - * is (off_t *)-1) is returned and errno is set to indicate the error; in
> - * kernel mode the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EADDRINUSE - SCIF_MAP_FIXED is set in map_flags, and pages in the
> range
> - * [offset, offset + len -1] are already registered
> - * EAGAIN - The mapping could not be performed due to lack of resources
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - map_flags is invalid, or prot_flags is invalid, or SCIF_MAP_FIXED
> is
> - * set in flags, and offset is not a multiple of the page size, or addr is not a
> - * multiple of the page size, or len is not a multiple of the page size, or is
> - * 0, or offset is negative
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOMEM - Not enough space
> - * ENOTCONN -The endpoint is not connected
> - */
> -off_t scif_register(scif_epd_t epd, void *addr, size_t len, off_t offset,
> - int prot_flags, int map_flags);
> -
> -/**
> - * scif_unregister() - Mark a memory region for remote access.
> - * @epd: endpoint descriptor
> - * @offset: start of range to unregister
> - * @len: length of range to unregister
> - *
> - * The scif_unregister() function closes those previously registered windows
> - * which are entirely within the range [offset, offset + len - 1]. It is an
> - * error to specify a range which intersects only a subrange of a window.
> - *
> - * On a successful return, pages within the window may no longer be
> specified
> - * in calls to mmap(), scif_readfrom(), scif_writeto(), scif_vreadfrom(),
> - * scif_vwriteto(), scif_get_pages, and scif_fence_signal(). The window,
> - * however, continues to exist until all previous references against it are
> - * removed. A window is referenced if there is a mapping to it created by
> - * mmap(), or if scif_get_pages() was called against the window
> - * (and the pages have not been returned via scif_put_pages()). A window is
> - * also referenced while an RMA, in which some range of the window is a
> source
> - * or destination, is in progress. Finally a window is referenced while some
> - * offset in that window was specified to scif_fence_signal(), and the RMAs
> - * marked by that call to scif_fence_signal() have not completed. While a
> - * window is in this state, its registered address space pages are not
> - * available for use in a new registered window.
> - *
> - * When all such references to the window have been removed, its
> references to
> - * all the physical pages which it represents are removed. Similarly, the
> - * registered address space pages of the window become available for
> - * registration in a new window.
> - *
> - * Return:
> - * Upon successful completion, scif_unregister() returns 0; otherwise in user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned. In the event of an
> - * error, no windows are unregistered.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - the range [offset, offset + len - 1] intersects a subrange of a
> - * window, or offset is negative
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - Offsets in the range [offset, offset + len - 1] are invalid for the
> - * registered address space of epd
> - */
> -int scif_unregister(scif_epd_t epd, off_t offset, size_t len);
> -
> -/**
> - * scif_readfrom() - Copy from a remote address space
> - * @epd: endpoint descriptor
> - * @loffset: offset in local registered address space to
> - * which to copy
> - * @len: length of range to copy
> - * @roffset: offset in remote registered address space
> - * from which to copy
> - * @rma_flags: transfer mode flags
> - *
> - * scif_readfrom() copies len bytes from the remote registered address
> space of
> - * the peer of endpoint epd, starting at the offset roffset to the local
> - * registered address space of epd, starting at the offset loffset.
> - *
> - * Each of the specified ranges [loffset, loffset + len - 1] and [roffset,
> - * roffset + len - 1] must be within some registered window or windows of
> the
> - * local and remote nodes. A range may intersect multiple registered
> windows,
> - * but only if those windows are contiguous in the registered address space.
> - *
> - * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
> - * programmed read/writes. Otherwise the data is copied using DMA. If
> rma_-
> - * flags includes SCIF_RMA_SYNC, then scif_readfrom() will return after the
> - * transfer is complete. Otherwise, the transfer may be performed
> asynchron-
> - * ously. The order in which any two asynchronous RMA operations
> complete
> - * is non-deterministic. The synchronization functions, scif_fence_mark()/
> - * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
> - * the completion of asynchronous RMA operations on the same endpoint.
> - *
> - * The DMA transfer of individual bytes is not guaranteed to complete in
> - * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
> - * cacheline or partial cacheline of the source range will become visible on
> - * the destination node after all other transferred data in the source
> - * range has become visible on the destination node.
> - *
> - * The optimal DMA performance will likely be realized if both
> - * loffset and roffset are cacheline aligned (are a multiple of 64). Lower
> - * performance will likely be realized if loffset and roffset are not
> - * cacheline aligned but are separated by some multiple of 64. The lowest
> level
> - * of performance is likely if loffset and roffset are not separated by a
> - * multiple of 64.
> - *
> - * The rma_flags argument is formed by ORing together zero or more of the
> - * following values.
> - * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use
> the DMA
> - * engine.
> - * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
> - * transfer has completed. Passing this flag results in the
> - * current implementation busy waiting and consuming CPU
> cycles
> - * while the DMA transfer is in progress for best performance
> by
> - * avoiding the interrupt latency.
> - * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline
> of
> - * the source range becomes visible on the destination node
> - * after all other transferred data in the source range has
> - * become visible on the destination
> - *
> - * Return:
> - * Upon successful completion, scif_readfrom() returns 0; otherwise in user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EACCES - Attempt to write to a read-only range
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - rma_flags is invalid
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - The range [loffset, loffset + len - 1] is invalid for the registered
> - * address space of epd, or, The range [roffset, roffset + len - 1] is invalid
> - * for the registered address space of the peer of epd, or loffset or roffset
> - * is negative
> - */
> -int scif_readfrom(scif_epd_t epd, off_t loffset, size_t len, off_t
> - roffset, int rma_flags);
> -
> -/**
> - * scif_writeto() - Copy to a remote address space
> - * @epd: endpoint descriptor
> - * @loffset: offset in local registered address space
> - * from which to copy
> - * @len: length of range to copy
> - * @roffset: offset in remote registered address space to
> - * which to copy
> - * @rma_flags: transfer mode flags
> - *
> - * scif_writeto() copies len bytes from the local registered address space of
> - * epd, starting at the offset loffset to the remote registered address space
> - * of the peer of endpoint epd, starting at the offset roffset.
> - *
> - * Each of the specified ranges [loffset, loffset + len - 1] and [roffset,
> - * roffset + len - 1] must be within some registered window or windows of
> the
> - * local and remote nodes. A range may intersect multiple registered
> windows,
> - * but only if those windows are contiguous in the registered address space.
> - *
> - * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
> - * programmed read/writes. Otherwise the data is copied using DMA. If
> rma_-
> - * flags includes SCIF_RMA_SYNC, then scif_writeto() will return after the
> - * transfer is complete. Otherwise, the transfer may be performed
> asynchron-
> - * ously. The order in which any two asynchronous RMA operations
> complete
> - * is non-deterministic. The synchronization functions, scif_fence_mark()/
> - * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
> - * the completion of asynchronous RMA operations on the same endpoint.
> - *
> - * The DMA transfer of individual bytes is not guaranteed to complete in
> - * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
> - * cacheline or partial cacheline of the source range will become visible on
> - * the destination node after all other transferred data in the source
> - * range has become visible on the destination node.
> - *
> - * The optimal DMA performance will likely be realized if both
> - * loffset and roffset are cacheline aligned (are a multiple of 64). Lower
> - * performance will likely be realized if loffset and roffset are not cacheline
> - * aligned but are separated by some multiple of 64. The lowest level of
> - * performance is likely if loffset and roffset are not separated by a multiple
> - * of 64.
> - *
> - * The rma_flags argument is formed by ORing together zero or more of the
> - * following values.
> - * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use
> the DMA
> - * engine.
> - * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
> - * transfer has completed. Passing this flag results in the
> - * current implementation busy waiting and consuming CPU
> cycles
> - * while the DMA transfer is in progress for best performance
> by
> - * avoiding the interrupt latency.
> - * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline
> of
> - * the source range becomes visible on the destination node
> - * after all other transferred data in the source range has
> - * become visible on the destination
> - *
> - * Return:
> - * Upon successful completion, scif_readfrom() returns 0; otherwise in user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EACCES - Attempt to write to a read-only range
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - rma_flags is invalid
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - The range [loffset, loffset + len - 1] is invalid for the registered
> - * address space of epd, or, The range [roffset , roffset + len -1] is invalid
> - * for the registered address space of the peer of epd, or loffset or roffset
> - * is negative
> - */
> -int scif_writeto(scif_epd_t epd, off_t loffset, size_t len, off_t
> - roffset, int rma_flags);
> -
> -/**
> - * scif_vreadfrom() - Copy from a remote address space
> - * @epd: endpoint descriptor
> - * @addr: address to which to copy
> - * @len: length of range to copy
> - * @roffset: offset in remote registered address space
> - * from which to copy
> - * @rma_flags: transfer mode flags
> - *
> - * scif_vreadfrom() copies len bytes from the remote registered address
> - * space of the peer of endpoint epd, starting at the offset roffset, to local
> - * memory, starting at addr.
> - *
> - * The specified range [roffset, roffset + len - 1] must be within some
> - * registered window or windows of the remote nodes. The range may
> - * intersect multiple registered windows, but only if those windows are
> - * contiguous in the registered address space.
> - *
> - * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
> - * programmed read/writes. Otherwise the data is copied using DMA. If
> rma_-
> - * flags includes SCIF_RMA_SYNC, then scif_vreadfrom() will return after the
> - * transfer is complete. Otherwise, the transfer may be performed
> asynchron-
> - * ously. The order in which any two asynchronous RMA operations
> complete
> - * is non-deterministic. The synchronization functions, scif_fence_mark()/
> - * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
> - * the completion of asynchronous RMA operations on the same endpoint.
> - *
> - * The DMA transfer of individual bytes is not guaranteed to complete in
> - * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
> - * cacheline or partial cacheline of the source range will become visible on
> - * the destination node after all other transferred data in the source
> - * range has become visible on the destination node.
> - *
> - * If rma_flags includes SCIF_RMA_USECACHE, then the physical pages which
> back
> - * the specified local memory range may be remain in a pinned state even
> after
> - * the specified transfer completes. This may reduce overhead if some or all
> of
> - * the same virtual address range is referenced in a subsequent call of
> - * scif_vreadfrom() or scif_vwriteto().
> - *
> - * The optimal DMA performance will likely be realized if both
> - * addr and roffset are cacheline aligned (are a multiple of 64). Lower
> - * performance will likely be realized if addr and roffset are not
> - * cacheline aligned but are separated by some multiple of 64. The lowest
> level
> - * of performance is likely if addr and roffset are not separated by a
> - * multiple of 64.
> - *
> - * The rma_flags argument is formed by ORing together zero or more of the
> - * following values.
> - * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use
> the DMA
> - * engine.
> - * SCIF_RMA_USECACHE - enable registration caching
> - * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
> - * transfer has completed. Passing this flag results in the
> - * current implementation busy waiting and consuming CPU
> cycles
> - * while the DMA transfer is in progress for best performance
> by
> - * avoiding the interrupt latency.
> - * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline
> of
> - * the source range becomes visible on the destination node
> - * after all other transferred data in the source range has
> - * become visible on the destination
> - *
> - * Return:
> - * Upon successful completion, scif_vreadfrom() returns 0; otherwise in user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EACCES - Attempt to write to a read-only range
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - rma_flags is invalid
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - Offsets in the range [roffset, roffset + len - 1] are invalid for the
> - * registered address space of epd
> - */
> -int scif_vreadfrom(scif_epd_t epd, void *addr, size_t len, off_t roffset,
> - int rma_flags);
> -
> -/**
> - * scif_vwriteto() - Copy to a remote address space
> - * @epd: endpoint descriptor
> - * @addr: address from which to copy
> - * @len: length of range to copy
> - * @roffset: offset in remote registered address space to
> - * which to copy
> - * @rma_flags: transfer mode flags
> - *
> - * scif_vwriteto() copies len bytes from the local memory, starting at addr, to
> - * the remote registered address space of the peer of endpoint epd, starting
> at
> - * the offset roffset.
> - *
> - * The specified range [roffset, roffset + len - 1] must be within some
> - * registered window or windows of the remote nodes. The range may
> intersect
> - * multiple registered windows, but only if those windows are contiguous in
> the
> - * registered address space.
> - *
> - * If rma_flags includes SCIF_RMA_USECPU, then the data is copied using
> - * programmed read/writes. Otherwise the data is copied using DMA. If
> rma_-
> - * flags includes SCIF_RMA_SYNC, then scif_vwriteto() will return after the
> - * transfer is complete. Otherwise, the transfer may be performed
> asynchron-
> - * ously. The order in which any two asynchronous RMA operations
> complete
> - * is non-deterministic. The synchronization functions, scif_fence_mark()/
> - * scif_fence_wait() and scif_fence_signal(), can be used to synchronize to
> - * the completion of asynchronous RMA operations on the same endpoint.
> - *
> - * The DMA transfer of individual bytes is not guaranteed to complete in
> - * address order. If rma_flags includes SCIF_RMA_ORDERED, then the last
> - * cacheline or partial cacheline of the source range will become visible on
> - * the destination node after all other transferred data in the source
> - * range has become visible on the destination node.
> - *
> - * If rma_flags includes SCIF_RMA_USECACHE, then the physical pages which
> back
> - * the specified local memory range may be remain in a pinned state even
> after
> - * the specified transfer completes. This may reduce overhead if some or all
> of
> - * the same virtual address range is referenced in a subsequent call of
> - * scif_vreadfrom() or scif_vwriteto().
> - *
> - * The optimal DMA performance will likely be realized if both
> - * addr and offset are cacheline aligned (are a multiple of 64). Lower
> - * performance will likely be realized if addr and offset are not cacheline
> - * aligned but are separated by some multiple of 64. The lowest level of
> - * performance is likely if addr and offset are not separated by a multiple of
> - * 64.
> - *
> - * The rma_flags argument is formed by ORing together zero or more of the
> - * following values.
> - * SCIF_RMA_USECPU - perform the transfer using the CPU, otherwise use
> the DMA
> - * engine.
> - * SCIF_RMA_USECACHE - allow registration caching
> - * SCIF_RMA_SYNC - perform the transfer synchronously, returning after the
> - * transfer has completed. Passing this flag results in the
> - * current implementation busy waiting and consuming CPU
> cycles
> - * while the DMA transfer is in progress for best performance
> by
> - * avoiding the interrupt latency.
> - * SCIF_RMA_ORDERED - ensure that the last cacheline or partial cacheline
> of
> - * the source range becomes visible on the destination node
> - * after all other transferred data in the source range has
> - * become visible on the destination
> - *
> - * Return:
> - * Upon successful completion, scif_vwriteto() returns 0; otherwise in user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EACCES - Attempt to write to a read-only range
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - rma_flags is invalid
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - Offsets in the range [roffset, roffset + len - 1] are invalid for the
> - * registered address space of epd
> - */
> -int scif_vwriteto(scif_epd_t epd, void *addr, size_t len, off_t roffset,
> - int rma_flags);
> -
> -/**
> - * scif_fence_mark() - Mark previously issued RMAs
> - * @epd: endpoint descriptor
> - * @flags: control flags
> - * @mark: marked value returned as output.
> - *
> - * scif_fence_mark() returns after marking the current set of all
> uncompleted
> - * RMAs initiated through the endpoint epd or the current set of all
> - * uncompleted RMAs initiated through the peer of endpoint epd. The RMAs
> are
> - * marked with a value returned at mark. The application may subsequently
> call
> - * scif_fence_wait(), passing the value returned at mark, to await completion
> - * of all RMAs so marked.
> - *
> - * The flags argument has exactly one of the following values.
> - * SCIF_FENCE_INIT_SELF - RMA operations initiated through endpoint
> - * epd are marked
> - * SCIF_FENCE_INIT_PEER - RMA operations initiated through the peer
> - * of endpoint epd are marked
> - *
> - * Return:
> - * Upon successful completion, scif_fence_mark() returns 0; otherwise in
> user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - flags is invalid
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENOMEM - Insufficient kernel memory was available
> - */
> -int scif_fence_mark(scif_epd_t epd, int flags, int *mark);
> -
> -/**
> - * scif_fence_wait() - Wait for completion of marked RMAs
> - * @epd: endpoint descriptor
> - * @mark: mark request
> - *
> - * scif_fence_wait() returns after all RMAs marked with mark have
> completed.
> - * The value passed in mark must have been obtained in a previous call to
> - * scif_fence_mark().
> - *
> - * Return:
> - * Upon successful completion, scif_fence_wait() returns 0; otherwise in
> user
> - * mode -1 is returned and errno is set to indicate the error; in kernel mode
> - * the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENOMEM - Insufficient kernel memory was available
> - */
> -int scif_fence_wait(scif_epd_t epd, int mark);
> -
> -/**
> - * scif_fence_signal() - Request a memory update on completion of RMAs
> - * @epd: endpoint descriptor
> - * @loff: local offset
> - * @lval: local value to write to loffset
> - * @roff: remote offset
> - * @rval: remote value to write to roffset
> - * @flags: flags
> - *
> - * scif_fence_signal() returns after marking the current set of all
> uncompleted
> - * RMAs initiated through the endpoint epd or marking the current set of all
> - * uncompleted RMAs initiated through the peer of endpoint epd.
> - *
> - * If flags includes SCIF_SIGNAL_LOCAL, then on completion of the RMAs in
> the
> - * marked set, lval is written to memory at the address corresponding to
> offset
> - * loff in the local registered address space of epd. loff must be within a
> - * registered window. If flags includes SCIF_SIGNAL_REMOTE, then on
> completion
> - * of the RMAs in the marked set, rval is written to memory at the address
> - * corresponding to offset roff in the remote registered address space of epd.
> - * roff must be within a remote registered window of the peer of epd. Note
> - * that any specified offset must be DWORD (4 byte / 32 bit) aligned.
> - *
> - * The flags argument is formed by OR'ing together the following.
> - * Exactly one of the following values.
> - * SCIF_FENCE_INIT_SELF - RMA operations initiated through endpoint
> - * epd are marked
> - * SCIF_FENCE_INIT_PEER - RMA operations initiated through the peer
> - * of endpoint epd are marked
> - * One or more of the following values.
> - * SCIF_SIGNAL_LOCAL - On completion of the marked set of RMAs, write
> lval to
> - * memory at the address corresponding to offset loff in the local
> - * registered address space of epd.
> - * SCIF_SIGNAL_REMOTE - On completion of the marked set of RMAs, write
> rval to
> - * memory at the address corresponding to offset roff in the remote
> - * registered address space of epd.
> - *
> - * Return:
> - * Upon successful completion, scif_fence_signal() returns 0; otherwise in
> - * user mode -1 is returned and errno is set to indicate the error; in kernel
> - * mode the negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EBADF, ENOTTY - epd is not a valid endpoint descriptor
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - flags is invalid, or loff or roff are not DWORD aligned
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - loff is invalid for the registered address of epd, or roff is invalid
> - * for the registered address space, of the peer of epd
> - */
> -int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval, off_t roff,
> - u64 rval, int flags);
> -
> -/**
> - * scif_get_node_ids() - Return information about online nodes
> - * @nodes: array in which to return online node IDs
> - * @len: number of entries in the nodes array
> - * @self: address to place the node ID of the local node
> - *
> - * scif_get_node_ids() fills in the nodes array with up to len node IDs of the
> - * nodes in the SCIF network. If there is not enough space in nodes, as
> - * indicated by the len parameter, only len node IDs are returned in nodes.
> The
> - * return value of scif_get_node_ids() is the total number of nodes currently
> in
> - * the SCIF network. By checking the return value against the len parameter,
> - * the user may determine if enough space for nodes was allocated.
> - *
> - * The node ID of the local node is returned at self.
> - *
> - * Return:
> - * Upon successful completion, scif_get_node_ids() returns the actual
> number of
> - * online nodes in the SCIF network including 'self'; otherwise in user mode
> - * -1 is returned and errno is set to indicate the error; in kernel mode no
> - * errors are returned.
> - */
> -int scif_get_node_ids(u16 *nodes, int len, u16 *self);
> -
> -/**
> - * scif_pin_pages() - Pin a set of pages
> - * @addr: Virtual address of range to pin
> - * @len: Length of range to pin
> - * @prot_flags: Page protection flags
> - * @map_flags: Page classification flags
> - * @pinned_pages: Handle to pinned pages
> - *
> - * scif_pin_pages() pins (locks in physical memory) the physical pages which
> - * back the range of virtual address pages starting at addr and continuing for
> - * len bytes. addr and len are constrained to be multiples of the page size. A
> - * successful scif_pin_pages() call returns a handle to pinned_pages which
> may
> - * be used in subsequent calls to scif_register_pinned_pages().
> - *
> - * The pages will remain pinned as long as there is a reference against the
> - * scif_pinned_pages_t value returned by scif_pin_pages() and until
> - * scif_unpin_pages() is called, passing the scif_pinned_pages_t value. A
> - * reference is added to a scif_pinned_pages_t value each time a window is
> - * created by calling scif_register_pinned_pages() and passing the
> - * scif_pinned_pages_t value. A reference is removed from a
> - * scif_pinned_pages_t value each time such a window is deleted.
> - *
> - * Subsequent operations which change the memory pages to which virtual
> - * addresses are mapped (such as mmap(), munmap()) have no effect on
> the
> - * scif_pinned_pages_t value or windows created against it.
> - *
> - * If the process will fork(), it is recommended that the registered
> - * virtual address range be marked with MADV_DONTFORK. Doing so will
> prevent
> - * problems due to copy-on-write semantics.
> - *
> - * The prot_flags argument is formed by OR'ing together one or more of the
> - * following values.
> - * SCIF_PROT_READ - allow read operations against the pages
> - * SCIF_PROT_WRITE - allow write operations against the pages
> - * The map_flags argument can be set as SCIF_MAP_KERNEL to interpret
> addr as a
> - * kernel space address. By default, addr is interpreted as a user space
> - * address.
> - *
> - * Return:
> - * Upon successful completion, scif_pin_pages() returns 0; otherwise the
> - * negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EINVAL - prot_flags is invalid, map_flags is invalid, or offset is negative
> - * ENOMEM - Not enough space
> - */
> -int scif_pin_pages(void *addr, size_t len, int prot_flags, int map_flags,
> - scif_pinned_pages_t *pinned_pages);
> -
> -/**
> - * scif_unpin_pages() - Unpin a set of pages
> - * @pinned_pages: Handle to pinned pages to be unpinned
> - *
> - * scif_unpin_pages() prevents scif_register_pinned_pages() from registering
> new
> - * windows against pinned_pages. The physical pages represented by
> pinned_pages
> - * will remain pinned until all windows previously registered against
> - * pinned_pages are deleted (the window is scif_unregister()'d and all
> - * references to the window are removed (see scif_unregister()).
> - *
> - * pinned_pages must have been obtain from a previous call to
> scif_pin_pages().
> - * After calling scif_unpin_pages(), it is an error to pass pinned_pages to
> - * scif_register_pinned_pages().
> - *
> - * Return:
> - * Upon successful completion, scif_unpin_pages() returns 0; otherwise the
> - * negative of one of the following errors is returned.
> - *
> - * Errors:
> - * EINVAL - pinned_pages is not valid
> - */
> -int scif_unpin_pages(scif_pinned_pages_t pinned_pages);
> -
> -/**
> - * scif_register_pinned_pages() - Mark a memory region for remote access.
> - * @epd: endpoint descriptor
> - * @pinned_pages: Handle to pinned pages
> - * @offset: Registered address space offset
> - * @map_flags: Flags which control where pages are mapped
> - *
> - * The scif_register_pinned_pages() function opens a window, a range of
> whole
> - * pages of the registered address space of the endpoint epd, starting at
> - * offset po. The value of po, further described below, is a function of the
> - * parameters offset and pinned_pages, and the value of map_flags. Each
> page of
> - * the window represents a corresponding physical memory page of the
> range
> - * represented by pinned_pages; the length of the window is the same as
> the
> - * length of range represented by pinned_pages. A successful
> - * scif_register_pinned_pages() call returns po as the return value.
> - *
> - * When SCIF_MAP_FIXED is set in the map_flags argument, po will be offset
> - * exactly, and offset is constrained to be a multiple of the page size. The
> - * mapping established by scif_register_pinned_pages() will not replace any
> - * existing registration; an error is returned if any page of the new window
> - * would intersect an existing window.
> - *
> - * When SCIF_MAP_FIXED is not set, the implementation uses offset in an
> - * implementation-defined manner to arrive at po. The po so chosen will be
> an
> - * area of the registered address space that the implementation deems
> suitable
> - * for a mapping of the required size. An offset value of 0 is interpreted as
> - * granting the implementation complete freedom in selecting po, subject to
> - * constraints described below. A non-zero value of offset is taken to be a
> - * suggestion of an offset near which the mapping should be placed. When
> the
> - * implementation selects a value for po, it does not replace any extant
> - * window. In all cases, po will be a multiple of the page size.
> - *
> - * The physical pages which are so represented by a window are available
> for
> - * access in calls to scif_get_pages(), scif_readfrom(), scif_writeto(),
> - * scif_vreadfrom(), and scif_vwriteto(). While a window is registered, the
> - * physical pages represented by the window will not be reused by the
> memory
> - * subsystem for any other purpose. Note that the same physical page may
> be
> - * represented by multiple windows.
> - *
> - * Windows created by scif_register_pinned_pages() are unregistered by
> - * scif_unregister().
> - *
> - * The map_flags argument can be set to SCIF_MAP_FIXED which interprets
> a
> - * fixed offset.
> - *
> - * Return:
> - * Upon successful completion, scif_register_pinned_pages() returns the
> offset
> - * at which the mapping was placed (po); otherwise the negative of one of
> the
> - * following errors is returned.
> - *
> - * Errors:
> - * EADDRINUSE - SCIF_MAP_FIXED is set in map_flags and pages in the new
> window
> - * would intersect an existing window
> - * EAGAIN - The mapping could not be performed due to lack of resources
> - * ECONNRESET - Connection reset by peer
> - * EINVAL - map_flags is invalid, or SCIF_MAP_FIXED is set in map_flags, and
> - * offset is not a multiple of the page size, or offset is negative
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOMEM - Not enough space
> - * ENOTCONN - The endpoint is not connected
> - */
> -off_t scif_register_pinned_pages(scif_epd_t epd,
> - scif_pinned_pages_t pinned_pages,
> - off_t offset, int map_flags);
> -
> -/**
> - * scif_get_pages() - Add references to remote registered pages
> - * @epd: endpoint descriptor
> - * @offset: remote registered offset
> - * @len: length of range of pages
> - * @pages: returned scif_range structure
> - *
> - * scif_get_pages() returns the addresses of the physical pages represented
> by
> - * those pages of the registered address space of the peer of epd, starting at
> - * offset and continuing for len bytes. offset and len are constrained to be
> - * multiples of the page size.
> - *
> - * All of the pages in the specified range [offset, offset + len - 1] must be
> - * within a single window of the registered address space of the peer of epd.
> - *
> - * The addresses are returned as a virtually contiguous array pointed to by
> the
> - * phys_addr component of the scif_range structure whose address is
> returned in
> - * pages. The nr_pages component of scif_range is the length of the array.
> The
> - * prot_flags component of scif_range holds the protection flag value passed
> - * when the pages were registered.
> - *
> - * Each physical page whose address is returned by scif_get_pages() remains
> - * available and will not be released for reuse until the scif_range structure
> - * is returned in a call to scif_put_pages(). The scif_range structure returned
> - * by scif_get_pages() must be unmodified.
> - *
> - * It is an error to call scif_close() on an endpoint on which a scif_range
> - * structure of that endpoint has not been returned to scif_put_pages().
> - *
> - * Return:
> - * Upon successful completion, scif_get_pages() returns 0; otherwise the
> - * negative of one of the following errors is returned.
> - * Errors:
> - * ECONNRESET - Connection reset by peer.
> - * EINVAL - offset is not a multiple of the page size, or offset is negative, or
> - * len is not a multiple of the page size
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - * ENXIO - Offsets in the range [offset, offset + len - 1] are invalid
> - * for the registered address space of the peer epd
> - */
> -int scif_get_pages(scif_epd_t epd, off_t offset, size_t len,
> - struct scif_range **pages);
> -
> -/**
> - * scif_put_pages() - Remove references from remote registered pages
> - * @pages: pages to be returned
> - *
> - * scif_put_pages() releases a scif_range structure previously obtained by
> - * calling scif_get_pages(). The physical pages represented by pages may
> - * be reused when the window which represented those pages is
> unregistered.
> - * Therefore, those pages must not be accessed after calling
> scif_put_pages().
> - *
> - * Return:
> - * Upon successful completion, scif_put_pages() returns 0; otherwise the
> - * negative of one of the following errors is returned.
> - * Errors:
> - * EINVAL - pages does not point to a valid scif_range structure, or
> - * the scif_range structure pointed to by pages was already returned
> - * ENODEV - The remote node is lost or existed, but is not currently in the
> - * network since it may have crashed
> - * ENOTCONN - The endpoint is not connected
> - */
> -int scif_put_pages(struct scif_range *pages);
> -
> -/**
> - * scif_poll() - Wait for some event on an endpoint
> - * @epds: Array of endpoint descriptors
> - * @nepds: Length of epds
> - * @timeout: Upper limit on time for which scif_poll() will block
> - *
> - * scif_poll() waits for one of a set of endpoints to become ready to perform
> - * an I/O operation.
> - *
> - * The epds argument specifies the endpoint descriptors to be examined and
> the
> - * events of interest for each endpoint descriptor. epds is a pointer to an
> - * array with one member for each open endpoint descriptor of interest.
> - *
> - * The number of items in the epds array is specified in nepds. The epd field
> - * of scif_pollepd is an endpoint descriptor of an open endpoint. The field
> - * events is a bitmask specifying the events which the application is
> - * interested in. The field revents is an output parameter, filled by the
> - * kernel with the events that actually occurred. The bits returned in revents
> - * can include any of those specified in events, or one of the values
> EPOLLERR,
> - * EPOLLHUP, or EPOLLNVAL. (These three bits are meaningless in the events
> - * field, and will be set in the revents field whenever the corresponding
> - * condition is true.)
> - *
> - * If none of the events requested (and no error) has occurred for any of the
> - * endpoint descriptors, then scif_poll() blocks until one of the events occurs.
> - *
> - * The timeout argument specifies an upper limit on the time for which
> - * scif_poll() will block, in milliseconds. Specifying a negative value in
> - * timeout means an infinite timeout.
> - *
> - * The following bits may be set in events and returned in revents.
> - * EPOLLIN - Data may be received without blocking. For a connected
> - * endpoint, this means that scif_recv() may be called without blocking. For a
> - * listening endpoint, this means that scif_accept() may be called without
> - * blocking.
> - * EPOLLOUT - Data may be sent without blocking. For a connected endpoint,
> this
> - * means that scif_send() may be called without blocking. EPOLLOUT may
> also be
> - * used to block waiting for a non-blocking connect to complete. This bit
> value
> - * has no meaning for a listening endpoint and is ignored if specified.
> - *
> - * The following bits are only returned in revents, and are ignored if set in
> - * events.
> - * EPOLLERR - An error occurred on the endpoint
> - * EPOLLHUP - The connection to the peer endpoint was disconnected
> - * EPOLLNVAL - The specified endpoint descriptor is invalid.
> - *
> - * Return:
> - * Upon successful completion, scif_poll() returns a non-negative value. A
> - * positive value indicates the total number of endpoint descriptors that
> have
> - * been selected (that is, endpoint descriptors for which the revents member
> is
> - * non-zero). A value of 0 indicates that the call timed out and no endpoint
> - * descriptors have been selected. Otherwise in user mode -1 is returned
> and
> - * errno is set to indicate the error; in kernel mode the negative of one of
> - * the following errors is returned.
> - *
> - * Errors:
> - * EINTR - A signal occurred before any requested event
> - * EINVAL - The nepds argument is greater than {OPEN_MAX}
> - * ENOMEM - There was no space to allocate file descriptor tables
> - */
> -int scif_poll(struct scif_pollepd *epds, unsigned int nepds, long timeout);
> -
> -/**
> - * scif_client_register() - Register a SCIF client
> - * @client: client to be registered
> - *
> - * scif_client_register() registers a SCIF client. The probe() method
> - * of the client is called when SCIF peer devices come online and the
> - * remove() method is called when the peer devices disappear.
> - *
> - * Return:
> - * Upon successful completion, scif_client_register() returns a non-negative
> - * value. Otherwise the return value is the same as
> subsys_interface_register()
> - * in the kernel.
> - */
> -int scif_client_register(struct scif_client *client);
> -
> -/**
> - * scif_client_unregister() - Unregister a SCIF client
> - * @client: client to be unregistered
> - *
> - * scif_client_unregister() unregisters a SCIF client.
> - *
> - * Return:
> - * None
> - */
> -void scif_client_unregister(struct scif_client *client);
> -
> -#endif /* __SCIF_H__ */
> diff --git a/include/uapi/linux/mic_common.h
> b/include/uapi/linux/mic_common.h
> deleted file mode 100644
> index 504e523f702c..000000000000
> --- a/include/uapi/linux/mic_common.h
> +++ /dev/null
> @@ -1,235 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License, version 2, as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * The full GNU General Public License is included in this distribution in
> - * the file called "COPYING".
> - *
> - * Intel MIC driver.
> - *
> - */
> -#ifndef __MIC_COMMON_H_
> -#define __MIC_COMMON_H_
> -
> -#include <linux/virtio_ring.h>
> -
> -#define __mic_align(a, x) (((a) + (x) - 1) & ~((x) - 1))
> -
> -/**
> - * struct mic_device_desc: Virtio device information shared between the
> - * virtio driver and userspace backend
> - *
> - * @type: Device type: console/network/disk etc. Type 0/-1 terminates.
> - * @num_vq: Number of virtqueues.
> - * @feature_len: Number of bytes of feature bits. Multiply by 2: one for
> - host features and one for guest acknowledgements.
> - * @config_len: Number of bytes of the config array after virtqueues.
> - * @status: A status byte, written by the Guest.
> - * @config: Start of the following variable length config.
> - */
> -struct mic_device_desc {
> - __s8 type;
> - __u8 num_vq;
> - __u8 feature_len;
> - __u8 config_len;
> - __u8 status;
> - __le64 config[0];
> -} __attribute__ ((aligned(8)));
> -
> -/**
> - * struct mic_device_ctrl: Per virtio device information in the device page
> - * used internally by the host and card side drivers.
> - *
> - * @vdev: Used for storing MIC vdev information by the guest.
> - * @config_change: Set to 1 by host when a config change is requested.
> - * @vdev_reset: Set to 1 by guest to indicate virtio device has been reset.
> - * @guest_ack: Set to 1 by guest to ack a command.
> - * @host_ack: Set to 1 by host to ack a command.
> - * @used_address_updated: Set to 1 by guest when the used address
> should be
> - * updated.
> - * @c2h_vdev_db: The doorbell number to be used by guest. Set by host.
> - * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
> - */
> -struct mic_device_ctrl {
> - __le64 vdev;
> - __u8 config_change;
> - __u8 vdev_reset;
> - __u8 guest_ack;
> - __u8 host_ack;
> - __u8 used_address_updated;
> - __s8 c2h_vdev_db;
> - __s8 h2c_vdev_db;
> -} __attribute__ ((aligned(8)));
> -
> -/**
> - * struct mic_bootparam: Virtio device independent information in device
> page
> - *
> - * @magic: A magic value used by the card to ensure it can see the host
> - * @h2c_config_db: Host to Card Virtio config doorbell set by card
> - * @node_id: Unique id of the node
> - * @h2c_scif_db - Host to card SCIF doorbell set by card
> - * @c2h_scif_db - Card to host SCIF doorbell set by host
> - * @scif_host_dma_addr - SCIF host queue pair DMA address
> - * @scif_card_dma_addr - SCIF card queue pair DMA address
> - */
> -struct mic_bootparam {
> - __le32 magic;
> - __s8 h2c_config_db;
> - __u8 node_id;
> - __u8 h2c_scif_db;
> - __u8 c2h_scif_db;
> - __u64 scif_host_dma_addr;
> - __u64 scif_card_dma_addr;
> -} __attribute__ ((aligned(8)));
> -
> -/**
> - * struct mic_device_page: High level representation of the device page
> - *
> - * @bootparam: The bootparam structure is used for sharing information
> and
> - * status updates between MIC host and card drivers.
> - * @desc: Array of MIC virtio device descriptors.
> - */
> -struct mic_device_page {
> - struct mic_bootparam bootparam;
> - struct mic_device_desc desc[0];
> -};
> -/**
> - * struct mic_vqconfig: This is how we expect the device configuration field
> - * for a virtqueue to be laid out in config space.
> - *
> - * @address: Guest/MIC physical address of the virtio ring
> - * (avail and desc rings)
> - * @used_address: Guest/MIC physical address of the used ring
> - * @num: The number of entries in the virtio_ring
> - */
> -struct mic_vqconfig {
> - __le64 address;
> - __le64 used_address;
> - __le16 num;
> -} __attribute__ ((aligned(8)));
> -
> -/*
> - * The alignment to use between consumer and producer parts of vring.
> - * This is pagesize for historical reasons.
> - */
> -#define MIC_VIRTIO_RING_ALIGN 4096
> -
> -#define MIC_MAX_VRINGS 4
> -#define MIC_VRING_ENTRIES 128
> -
> -/*
> - * Max vring entries (power of 2) to ensure desc and avail rings
> - * fit in a single page
> - */
> -#define MIC_MAX_VRING_ENTRIES 128
> -
> -/**
> - * Max size of the desc block in bytes: includes:
> - * - struct mic_device_desc
> - * - struct mic_vqconfig (num_vq of these)
> - * - host and guest features
> - * - virtio device config space
> - */
> -#define MIC_MAX_DESC_BLK_SIZE 256
> -
> -/**
> - * struct _mic_vring_info - Host vring info exposed to userspace backend
> - * for the avail index and magic for the card.
> - *
> - * @avail_idx: host avail idx
> - * @magic: A magic debug cookie.
> - */
> -struct _mic_vring_info {
> - __u16 avail_idx;
> - __le32 magic;
> -};
> -
> -/**
> - * struct mic_vring - Vring information.
> - *
> - * @vr: The virtio ring.
> - * @info: Host vring information exposed to the userspace backend for the
> - * avail index and magic for the card.
> - * @va: The va for the buffer allocated for vr and info.
> - * @len: The length of the buffer required for allocating vr and info.
> - */
> -struct mic_vring {
> - struct vring vr;
> - struct _mic_vring_info *info;
> - void *va;
> - int len;
> -};
> -
> -#define mic_aligned_desc_size(d) __mic_align(mic_desc_size(d), 8)
> -
> -#ifndef INTEL_MIC_CARD
> -static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
> -{
> - return sizeof(*desc) + desc->num_vq * sizeof(struct mic_vqconfig)
> - + desc->feature_len * 2 + desc->config_len;
> -}
> -
> -static inline struct mic_vqconfig *
> -mic_vq_config(const struct mic_device_desc *desc)
> -{
> - return (struct mic_vqconfig *)(desc + 1);
> -}
> -
> -static inline __u8 *mic_vq_features(const struct mic_device_desc *desc)
> -{
> - return (__u8 *)(mic_vq_config(desc) + desc->num_vq);
> -}
> -
> -static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
> -{
> - return mic_vq_features(desc) + desc->feature_len * 2;
> -}
> -static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
> -{
> - return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
> -}
> -#endif
> -
> -/* Device page size */
> -#define MIC_DP_SIZE 4096
> -
> -#define MIC_MAGIC 0xc0ffee00
> -
> -/**
> - * enum mic_states - MIC states.
> - */
> -enum mic_states {
> - MIC_READY = 0,
> - MIC_BOOTING,
> - MIC_ONLINE,
> - MIC_SHUTTING_DOWN,
> - MIC_RESETTING,
> - MIC_RESET_FAILED,
> - MIC_LAST
> -};
> -
> -/**
> - * enum mic_status - MIC status reported by card after
> - * a host or card initiated shutdown or a card crash.
> - */
> -enum mic_status {
> - MIC_NOP = 0,
> - MIC_CRASHED,
> - MIC_HALTED,
> - MIC_POWER_OFF,
> - MIC_RESTART,
> - MIC_STATUS_LAST
> -};
> -
> -#endif
> diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h
> deleted file mode 100644
> index 687b9cd9d3e2..000000000000
> --- a/include/uapi/linux/mic_ioctl.h
> +++ /dev/null
> @@ -1,77 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License, version 2, as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - *
> - * The full GNU General Public License is included in this distribution in
> - * the file called "COPYING".
> - *
> - * Intel MIC Host driver.
> - *
> - */
> -#ifndef _MIC_IOCTL_H_
> -#define _MIC_IOCTL_H_
> -
> -#include <linux/types.h>
> -
> -/*
> - * mic_copy - MIC virtio descriptor copy.
> - *
> - * @iov: An array of IOVEC structures containing user space buffers.
> - * @iovcnt: Number of IOVEC structures in iov.
> - * @vr_idx: The vring index.
> - * @update_used: A non zero value results in used index being updated.
> - * @out_len: The aggregate of the total length written to or read from
> - * the virtio device.
> - */
> -struct mic_copy_desc {
> -#ifdef __KERNEL__
> - struct iovec __user *iov;
> -#else
> - struct iovec *iov;
> -#endif
> - __u32 iovcnt;
> - __u8 vr_idx;
> - __u8 update_used;
> - __u32 out_len;
> -};
> -
> -/*
> - * Add a new virtio device
> - * The (struct mic_device_desc *) pointer points to a device page entry
> - * for the virtio device consisting of:
> - * - struct mic_device_desc
> - * - struct mic_vqconfig (num_vq of these)
> - * - host and guest features
> - * - virtio device config space
> - * The total size referenced by the pointer should equal the size returned
> - * by desc_size() in mic_common.h
> - */
> -#define MIC_VIRTIO_ADD_DEVICE _IOWR('s', 1, struct mic_device_desc *)
> -
> -/*
> - * Copy the number of entries in the iovec and update the used index
> - * if requested by the user.
> - */
> -#define MIC_VIRTIO_COPY_DESC _IOWR('s', 2, struct mic_copy_desc *)
> -
> -/*
> - * Notify virtio device of a config change
> - * The (__u8 *) pointer points to config space values for the device
> - * as they should be written into the device page. The total size
> - * referenced by the pointer should equal the config_len field of struct
> - * mic_device_desc.
> - */
> -#define MIC_VIRTIO_CONFIG_CHANGE _IOWR('s', 5, __u8 *)
> -
> -#endif
> diff --git a/samples/mic/mpssd/.gitignore b/samples/mic/mpssd/.gitignore
> deleted file mode 100644
> index aa03f1eb37a0..000000000000
> --- a/samples/mic/mpssd/.gitignore
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -mpssd
> diff --git a/samples/mic/mpssd/Makefile b/samples/mic/mpssd/Makefile
> deleted file mode 100644
> index a7a6e0c70424..000000000000
> --- a/samples/mic/mpssd/Makefile
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -ifndef CROSS_COMPILE
> -uname_M := $(shell uname -m 2>/dev/null || echo not)
> -ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
> -
> -ifeq ($(ARCH),x86)
> -
> -PROGS := mpssd
> -CC = $(CROSS_COMPILE)gcc
> -CFLAGS := -I../../../usr/include -I../../../tools/include
> -
> -ifdef DEBUG
> -CFLAGS += -DDEBUG=$(DEBUG)
> -endif
> -
> -all: $(PROGS)
> -mpssd: mpssd.c sysfs.c
> - $(CC) $(CFLAGS) mpssd.c sysfs.c -o mpssd -lpthread
> -
> -install:
> - install mpssd /usr/sbin/mpssd
> - install micctrl /usr/sbin/micctrl
> -
> -clean:
> - rm -fr $(PROGS)
> -
> -endif
> -endif
> diff --git a/samples/mic/mpssd/micctrl b/samples/mic/mpssd/micctrl
> deleted file mode 100755
> index 030a60b04046..000000000000
> --- a/samples/mic/mpssd/micctrl
> +++ /dev/null
> @@ -1,162 +0,0 @@
> -#!/bin/bash
> -# SPDX-License-Identifier: GPL-2.0-only
> -# Intel MIC Platform Software Stack (MPSS)
> -#
> -# Copyright(c) 2013 Intel Corporation.
> -#
> -# Intel MIC User Space Tools.
> -#
> -# micctrl - Controls MIC boot/start/stop.
> -#
> -# chkconfig: 2345 95 05
> -# description: start MPSS stack processing.
> -#
> -### BEGIN INIT INFO
> -# Provides: micctrl
> -### END INIT INFO
> -
> -# Source function library.
> -. /etc/init.d/functions
> -
> -sysfs="/sys/class/mic"
> -
> -_status()
> -{
> - f=$sysfs/$1
> - echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat
> $f/shutdown_status`"
> -}
> -
> -status()
> -{
> - if [ "`echo $1 | head -c3`" == "mic" ]; then
> - _status $1
> - return $?
> - fi
> - for f in $sysfs/*
> - do
> - _status `basename $f`
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && return $RETVAL
> - done
> - return 0
> -}
> -
> -_reset()
> -{
> - f=$sysfs/$1
> - echo reset > $f/state
> -}
> -
> -reset()
> -{
> - if [ "`echo $1 | head -c3`" == "mic" ]; then
> - _reset $1
> - return $?
> - fi
> - for f in $sysfs/*
> - do
> - _reset `basename $f`
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && return $RETVAL
> - done
> - return 0
> -}
> -
> -_boot()
> -{
> - f=$sysfs/$1
> - echo "linux" > $f/bootmode
> - echo "mic/uos.img" > $f/firmware
> - echo "mic/$1.image" > $f/ramdisk
> - echo "boot" > $f/state
> -}
> -
> -boot()
> -{
> - if [ "`echo $1 | head -c3`" == "mic" ]; then
> - _boot $1
> - return $?
> - fi
> - for f in $sysfs/*
> - do
> - _boot `basename $f`
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && return $RETVAL
> - done
> - return 0
> -}
> -
> -_shutdown()
> -{
> - f=$sysfs/$1
> - echo shutdown > $f/state
> -}
> -
> -shutdown()
> -{
> - if [ "`echo $1 | head -c3`" == "mic" ]; then
> - _shutdown $1
> - return $?
> - fi
> - for f in $sysfs/*
> - do
> - _shutdown `basename $f`
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && return $RETVAL
> - done
> - return 0
> -}
> -
> -_wait()
> -{
> - f=$sysfs/$1
> - while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
> - do
> - sleep 1
> - echo -e "Waiting for $1 to go offline"
> - done
> -}
> -
> -wait()
> -{
> - if [ "`echo $1 | head -c3`" == "mic" ]; then
> - _wait $1
> - return $?
> - fi
> - # Wait for the cards to go offline
> - for f in $sysfs/*
> - do
> - _wait `basename $f`
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && return $RETVAL
> - done
> - return 0
> -}
> -
> -if [ ! -d "$sysfs" ]; then
> - echo -e $"Module unloaded "
> - exit 3
> -fi
> -
> -case $1 in
> - -s)
> - status $2
> - ;;
> - -r)
> - reset $2
> - ;;
> - -b)
> - boot $2
> - ;;
> - -S)
> - shutdown $2
> - ;;
> - -w)
> - wait $2
> - ;;
> - *)
> - echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S
> (shutdown) |-w (wait)}"
> - exit 2
> -esac
> -
> -exit $?
> diff --git a/samples/mic/mpssd/mpss b/samples/mic/mpssd/mpss
> deleted file mode 100755
> index 248ac7313c71..000000000000
> --- a/samples/mic/mpssd/mpss
> +++ /dev/null
> @@ -1,189 +0,0 @@
> -#!/bin/bash
> -# SPDX-License-Identifier: GPL-2.0-only
> -# Intel MIC Platform Software Stack (MPSS)
> -#
> -# Copyright(c) 2013 Intel Corporation.
> -#
> -# Intel MIC User Space Tools.
> -#
> -# mpss Start mpssd.
> -#
> -# chkconfig: 2345 95 05
> -# description: start MPSS stack processing.
> -#
> -### BEGIN INIT INFO
> -# Provides: mpss
> -# Required-Start:
> -# Required-Stop:
> -# Short-Description: MPSS stack control
> -# Description: MPSS stack control
> -### END INIT INFO
> -
> -# Source function library.
> -. /etc/init.d/functions
> -
> -exec=/usr/sbin/mpssd
> -sysfs="/sys/class/mic"
> -mic_modules="mic_host mic_x100_dma scif vop"
> -
> -start()
> -{
> - [ -x $exec ] || exit 5
> -
> - if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ];
> then
> - echo -e $"MPSSD already running! "
> - success
> - echo
> - return 0
> - fi
> -
> - echo -e $"Starting MPSS Stack"
> - echo -e $"Loading MIC drivers:" $mic_modules
> -
> - modprobe -a $mic_modules
> - RETVAL=$?
> - if [ $RETVAL -ne 0 ]; then
> - failure
> - echo
> - return $RETVAL
> - fi
> -
> - # Start the daemon
> - echo -n $"Starting MPSSD "
> - $exec
> - RETVAL=$?
> - if [ $RETVAL -ne 0 ]; then
> - failure
> - echo
> - return $RETVAL
> - fi
> - success
> - echo
> -
> - sleep 5
> -
> - # Boot the cards
> - micctrl -b
> -
> - # Wait till ping works
> - for f in $sysfs/*
> - do
> - count=100
> - ipaddr=`cat $f/cmdline`
> - ipaddr=${ipaddr#*address,}
> - ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
> - while [ $count -ge 0 ]
> - do
> - echo -e "Pinging "`basename $f`" "
> - ping -c 1 $ipaddr &> /dev/null
> - RETVAL=$?
> - if [ $RETVAL -eq 0 ]; then
> - success
> - break
> - fi
> - sleep 1
> - count=`expr $count - 1`
> - done
> - [ $RETVAL -ne 0 ] && failure || success
> - echo
> - done
> - return $RETVAL
> -}
> -
> -stop()
> -{
> - echo -e $"Shutting down MPSS Stack: "
> -
> - # Bail out if module is unloaded
> - if [ ! -d "$sysfs" ]; then
> - echo -n $"Module unloaded "
> - success
> - echo
> - return 0
> - fi
> -
> - # Shut down the cards.
> - micctrl -S
> -
> - # Wait for the cards to go offline
> - for f in $sysfs/*
> - do
> - while [ "`cat $f/state`" != "ready" ]
> - do
> - sleep 1
> - echo -e "Waiting for "`basename $f`" to become
> ready"
> - done
> - done
> -
> - # Display the status of the cards
> - micctrl -s
> -
> - # Kill MPSSD now
> - echo -n $"Killing MPSSD"
> - killall -9 mpssd 2>/dev/null
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && failure || success
> - echo
> - return $RETVAL
> -}
> -
> -restart()
> -{
> - stop
> - sleep 5
> - start
> -}
> -
> -status()
> -{
> - micctrl -s
> - if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ];
> then
> - echo "mpssd is running"
> - else
> - echo "mpssd is stopped"
> - fi
> - return 0
> -}
> -
> -unload()
> -{
> - if [ ! -d "$sysfs" ]; then
> - echo -n $"No MIC_HOST Module: "
> - success
> - echo
> - return
> - fi
> -
> - stop
> -
> - sleep 5
> - echo -n $"Removing MIC drivers:" $mic_modules
> - modprobe -r $mic_modules
> - RETVAL=$?
> - [ $RETVAL -ne 0 ] && failure || success
> - echo
> - return $RETVAL
> -}
> -
> -case $1 in
> - start)
> - start
> - ;;
> - stop)
> - stop
> - ;;
> - restart)
> - restart
> - ;;
> - status)
> - status
> - ;;
> - unload)
> - unload
> - ;;
> - *)
> - echo $"Usage: $0 {start|stop|restart|status|unload}"
> - exit 2
> -esac
> -
> -exit $?
> diff --git a/samples/mic/mpssd/mpssd.c b/samples/mic/mpssd/mpssd.c
> deleted file mode 100644
> index c03a05d498f0..000000000000
> --- a/samples/mic/mpssd/mpssd.c
> +++ /dev/null
> @@ -1,1815 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC User Space Tools.
> - */
> -
> -#define _GNU_SOURCE
> -
> -#include <stdlib.h>
> -#include <fcntl.h>
> -#include <getopt.h>
> -#include <assert.h>
> -#include <unistd.h>
> -#include <stdbool.h>
> -#include <signal.h>
> -#include <poll.h>
> -#include <features.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/mman.h>
> -#include <sys/socket.h>
> -#include <linux/virtio_ring.h>
> -#include <linux/virtio_net.h>
> -#include <linux/virtio_console.h>
> -#include <linux/virtio_blk.h>
> -#include <linux/version.h>
> -#include "mpssd.h"
> -#include <linux/mic_ioctl.h>
> -#include <linux/mic_common.h>
> -#include <tools/endian.h>
> -
> -static void *init_mic(void *arg);
> -
> -static FILE *logfp;
> -static struct mic_info mic_list;
> -
> -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> -
> -#define min_t(type, x, y) ({ \
> - type __min1 = (x); \
> - type __min2 = (y); \
> - __min1 < __min2 ? __min1 : __min2; })
> -
> -/* align addr on a size boundary - adjust address up/down if needed */
> -#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
> -#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size)
> -
> -/* align addr on a size boundary - adjust address up if needed */
> -#define _ALIGN(addr, size) _ALIGN_UP(addr, size)
> -
> -/* to align the pointer to the (next) page boundary */
> -#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
> -
> -#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))
> -
> -#define GSO_ENABLED 1
> -#define MAX_GSO_SIZE (64 * 1024)
> -#define ETH_H_LEN 14
> -#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN,
> 64))
> -#define MIC_DEVICE_PAGE_END 0x1000
> -
> -#ifndef VIRTIO_NET_HDR_F_DATA_VALID
> -#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */
> -#endif
> -
> -static struct {
> - struct mic_device_desc dd;
> - struct mic_vqconfig vqconfig[2];
> - __u32 host_features, guest_acknowledgements;
> - struct virtio_console_config cons_config;
> -} virtcons_dev_page = {
> - .dd = {
> - .type = VIRTIO_ID_CONSOLE,
> - .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig),
> - .feature_len = sizeof(virtcons_dev_page.host_features),
> - .config_len = sizeof(virtcons_dev_page.cons_config),
> - },
> - .vqconfig[0] = {
> - .num = htole16(MIC_VRING_ENTRIES),
> - },
> - .vqconfig[1] = {
> - .num = htole16(MIC_VRING_ENTRIES),
> - },
> -};
> -
> -static struct {
> - struct mic_device_desc dd;
> - struct mic_vqconfig vqconfig[2];
> - __u32 host_features, guest_acknowledgements;
> - struct virtio_net_config net_config;
> -} virtnet_dev_page = {
> - .dd = {
> - .type = VIRTIO_ID_NET,
> - .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig),
> - .feature_len = sizeof(virtnet_dev_page.host_features),
> - .config_len = sizeof(virtnet_dev_page.net_config),
> - },
> - .vqconfig[0] = {
> - .num = htole16(MIC_VRING_ENTRIES),
> - },
> - .vqconfig[1] = {
> - .num = htole16(MIC_VRING_ENTRIES),
> - },
> -#if GSO_ENABLED
> - .host_features = htole32(
> - 1 << VIRTIO_NET_F_CSUM |
> - 1 << VIRTIO_NET_F_GSO |
> - 1 << VIRTIO_NET_F_GUEST_TSO4 |
> - 1 << VIRTIO_NET_F_GUEST_TSO6 |
> - 1 << VIRTIO_NET_F_GUEST_ECN),
> -#else
> - .host_features = 0,
> -#endif
> -};
> -
> -static const char *mic_config_dir = "/etc/mpss";
> -static const char *virtblk_backend = "VIRTBLK_BACKEND";
> -static struct {
> - struct mic_device_desc dd;
> - struct mic_vqconfig vqconfig[1];
> - __u32 host_features, guest_acknowledgements;
> - struct virtio_blk_config blk_config;
> -} virtblk_dev_page = {
> - .dd = {
> - .type = VIRTIO_ID_BLOCK,
> - .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig),
> - .feature_len = sizeof(virtblk_dev_page.host_features),
> - .config_len = sizeof(virtblk_dev_page.blk_config),
> - },
> - .vqconfig[0] = {
> - .num = htole16(MIC_VRING_ENTRIES),
> - },
> - .host_features =
> - htole32(1<<VIRTIO_BLK_F_SEG_MAX),
> - .blk_config = {
> - .seg_max = htole32(MIC_VRING_ENTRIES - 2),
> - .capacity = htole64(0),
> - }
> -};
> -
> -static char *myname;
> -
> -static int
> -tap_configure(struct mic_info *mic, char *dev)
> -{
> - pid_t pid;
> - char *ifargv[7];
> - char ipaddr[IFNAMSIZ];
> - int ret = 0;
> -
> - pid = fork();
> - if (pid == 0) {
> - ifargv[0] = "ip";
> - ifargv[1] = "link";
> - ifargv[2] = "set";
> - ifargv[3] = dev;
> - ifargv[4] = "up";
> - ifargv[5] = NULL;
> - mpsslog("Configuring %s\n", dev);
> - ret = execvp("ip", ifargv);
> - if (ret < 0) {
> - mpsslog("%s execvp failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> - }
> - if (pid < 0) {
> - mpsslog("%s fork failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> -
> - ret = waitpid(pid, NULL, 0);
> - if (ret < 0) {
> - mpsslog("%s waitpid failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> -
> - snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1);
> -
> - pid = fork();
> - if (pid == 0) {
> - ifargv[0] = "ip";
> - ifargv[1] = "addr";
> - ifargv[2] = "add";
> - ifargv[3] = ipaddr;
> - ifargv[4] = "dev";
> - ifargv[5] = dev;
> - ifargv[6] = NULL;
> - mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr);
> - ret = execvp("ip", ifargv);
> - if (ret < 0) {
> - mpsslog("%s execvp failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> - }
> - if (pid < 0) {
> - mpsslog("%s fork failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> -
> - ret = waitpid(pid, NULL, 0);
> - if (ret < 0) {
> - mpsslog("%s waitpid failed errno %s\n",
> - mic->name, strerror(errno));
> - return ret;
> - }
> - mpsslog("MIC name %s %s %d DONE!\n",
> - mic->name, __func__, __LINE__);
> - return 0;
> -}
> -
> -static int tun_alloc(struct mic_info *mic, char *dev)
> -{
> - struct ifreq ifr;
> - int fd, err;
> -#if GSO_ENABLED
> - unsigned offload;
> -#endif
> - fd = open("/dev/net/tun", O_RDWR);
> - if (fd < 0) {
> - mpsslog("Could not open /dev/net/tun %s\n",
> strerror(errno));
> - goto done;
> - }
> -
> - memset(&ifr, 0, sizeof(ifr));
> -
> - ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
> - if (*dev)
> - strncpy(ifr.ifr_name, dev, IFNAMSIZ);
> -
> - err = ioctl(fd, TUNSETIFF, (void *)&ifr);
> - if (err < 0) {
> - mpsslog("%s %s %d TUNSETIFF failed %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - close(fd);
> - return err;
> - }
> -#if GSO_ENABLED
> - offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
> TUN_F_TSO_ECN;
> -
> - err = ioctl(fd, TUNSETOFFLOAD, offload);
> - if (err < 0) {
> - mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - close(fd);
> - return err;
> - }
> -#endif
> - strcpy(dev, ifr.ifr_name);
> - mpsslog("Created TAP %s\n", dev);
> -done:
> - return fd;
> -}
> -
> -#define NET_FD_VIRTIO_NET 0
> -#define NET_FD_TUN 1
> -#define MAX_NET_FD 2
> -
> -static void set_dp(struct mic_info *mic, int type, void *dp)
> -{
> - switch (type) {
> - case VIRTIO_ID_CONSOLE:
> - mic->mic_console.console_dp = dp;
> - return;
> - case VIRTIO_ID_NET:
> - mic->mic_net.net_dp = dp;
> - return;
> - case VIRTIO_ID_BLOCK:
> - mic->mic_virtblk.block_dp = dp;
> - return;
> - }
> - mpsslog("%s %s %d not found\n", mic->name, __func__, type);
> - assert(0);
> -}
> -
> -static void *get_dp(struct mic_info *mic, int type)
> -{
> - switch (type) {
> - case VIRTIO_ID_CONSOLE:
> - return mic->mic_console.console_dp;
> - case VIRTIO_ID_NET:
> - return mic->mic_net.net_dp;
> - case VIRTIO_ID_BLOCK:
> - return mic->mic_virtblk.block_dp;
> - }
> - mpsslog("%s %s %d not found\n", mic->name, __func__, type);
> - assert(0);
> - return NULL;
> -}
> -
> -static struct mic_device_desc *get_device_desc(struct mic_info *mic, int
> type)
> -{
> - struct mic_device_desc *d;
> - int i;
> - void *dp = get_dp(mic, type);
> -
> - for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
> - i += mic_total_desc_size(d)) {
> - d = dp + i;
> -
> - /* End of list */
> - if (d->type == 0)
> - break;
> -
> - if (d->type == -1)
> - continue;
> -
> - mpsslog("%s %s d-> type %d d %p\n",
> - mic->name, __func__, d->type, d);
> -
> - if (d->type == (__u8)type)
> - return d;
> - }
> - mpsslog("%s %s %d not found\n", mic->name, __func__, type);
> - return NULL;
> -}
> -
> -/* See comments in vhost.c for explanation of next_desc() */
> -static unsigned next_desc(struct vring_desc *desc)
> -{
> - unsigned int next;
> -
> - if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT))
> - return -1U;
> - next = le16toh(desc->next);
> - return next;
> -}
> -
> -/* Sum up all the IOVEC length */
> -static ssize_t
> -sum_iovec_len(struct mic_copy_desc *copy)
> -{
> - ssize_t sum = 0;
> - unsigned int i;
> -
> - for (i = 0; i < copy->iovcnt; i++)
> - sum += copy->iov[i].iov_len;
> - return sum;
> -}
> -
> -static inline void verify_out_len(struct mic_info *mic,
> - struct mic_copy_desc *copy)
> -{
> - if (copy->out_len != sum_iovec_len(copy)) {
> - mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n",
> - mic->name, __func__, __LINE__,
> - copy->out_len, sum_iovec_len(copy));
> - assert(copy->out_len == sum_iovec_len(copy));
> - }
> -}
> -
> -/* Display an iovec */
> -static void
> -disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy,
> - const char *s, int line)
> -{
> - unsigned int i;
> -
> - for (i = 0; i < copy->iovcnt; i++)
> - mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n",
> - mic->name, s, line, i,
> - copy->iov[i].iov_base, copy->iov[i].iov_len);
> -}
> -
> -static inline __u16 read_avail_idx(struct mic_vring *vr)
> -{
> - return READ_ONCE(vr->info->avail_idx);
> -}
> -
> -static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr,
> - struct mic_copy_desc *copy, ssize_t len)
> -{
> - copy->vr_idx = tx ? 0 : 1;
> - copy->update_used = true;
> - if (type == VIRTIO_ID_NET)
> - copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr);
> - else
> - copy->iov[0].iov_len = len;
> -}
> -
> -/* Central API which triggers the copies */
> -static int
> -mic_virtio_copy(struct mic_info *mic, int fd,
> - struct mic_vring *vr, struct mic_copy_desc *copy)
> -{
> - int ret;
> -
> - ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy);
> - if (ret) {
> - mpsslog("%s %s %d errno %s ret %d\n",
> - mic->name, __func__, __LINE__,
> - strerror(errno), ret);
> - }
> - return ret;
> -}
> -
> -static inline unsigned _vring_size(unsigned int num, unsigned long align)
> -{
> - return _ALIGN_UP(((sizeof(struct vring_desc) * num + sizeof(__u16) *
> (3 + num)
> - + align - 1) & ~(align - 1))
> - + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num,
> 4);
> -}
> -
> -/*
> - * This initialization routine requires at least one
> - * vring i.e. vr0. vr1 is optional.
> - */
> -static void *
> -init_vr(struct mic_info *mic, int fd, int type,
> - struct mic_vring *vr0, struct mic_vring *vr1, int num_vq)
> -{
> - int vr_size;
> - char *va;
> -
> - vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
> - MIC_VIRTIO_RING_ALIGN) +
> - sizeof(struct _mic_vring_info));
> - va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
> - PROT_READ, MAP_SHARED, fd, 0);
> - if (MAP_FAILED == va) {
> - mpsslog("%s %s %d mmap failed errno %s\n",
> - mic->name, __func__, __LINE__,
> - strerror(errno));
> - goto done;
> - }
> - set_dp(mic, type, va);
> - vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
> - vr0->info = vr0->va +
> - _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
> - vring_init(&vr0->vr,
> - MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
> - mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
> - __func__, mic->name, vr0->va, vr0->info, vr_size,
> - _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
> - mpsslog("magic 0x%x expected 0x%x\n",
> - le32toh(vr0->info->magic), MIC_MAGIC + type);
> - assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
> - if (vr1) {
> - vr1->va = (struct mic_vring *)
> - &va[MIC_DEVICE_PAGE_END + vr_size];
> - vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES,
> - MIC_VIRTIO_RING_ALIGN);
> - vring_init(&vr1->vr,
> - MIC_VRING_ENTRIES, vr1->va,
> MIC_VIRTIO_RING_ALIGN);
> - mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x
> ",
> - __func__, mic->name, vr1->va, vr1->info, vr_size,
> - _vring_size(MIC_VRING_ENTRIES,
> MIC_VIRTIO_RING_ALIGN));
> - mpsslog("magic 0x%x expected 0x%x\n",
> - le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
> - assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
> - }
> -done:
> - return va;
> -}
> -
> -static int
> -wait_for_card_driver(struct mic_info *mic, int fd, int type)
> -{
> - struct pollfd pollfd;
> - int err;
> - struct mic_device_desc *desc = get_device_desc(mic, type);
> - __u8 prev_status;
> -
> - if (!desc)
> - return -ENODEV;
> - prev_status = desc->status;
> - pollfd.fd = fd;
> - mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
> - mic->name, __func__, type, desc->status);
> -
> - while (1) {
> - pollfd.events = POLLIN;
> - pollfd.revents = 0;
> - err = poll(&pollfd, 1, -1);
> - if (err < 0) {
> - mpsslog("%s %s poll failed %s\n",
> - mic->name, __func__, strerror(errno));
> - continue;
> - }
> -
> - if (pollfd.revents) {
> - if (desc->status != prev_status) {
> - mpsslog("%s %s Waiting... desc-> type %d "
> - "status 0x%x\n",
> - mic->name, __func__, type,
> - desc->status);
> - prev_status = desc->status;
> - }
> - if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
> - mpsslog("%s %s poll.revents %d\n",
> - mic->name, __func__, pollfd.revents);
> - mpsslog("%s %s desc-> type %d status
> 0x%x\n",
> - mic->name, __func__, type,
> - desc->status);
> - break;
> - }
> - }
> - }
> - return 0;
> -}
> -
> -/* Spin till we have some descriptors */
> -static void
> -spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr)
> -{
> - __u16 avail_idx = read_avail_idx(vr);
> -
> - while (avail_idx == le16toh(READ_ONCE(vr->vr.avail->idx))) {
> -#ifdef DEBUG
> - mpsslog("%s %s waiting for desc avail %d info_avail %d\n",
> - mic->name, __func__,
> - le16toh(vr->vr.avail->idx), vr->info->avail_idx);
> -#endif
> - sched_yield();
> - }
> -}
> -
> -static void *
> -virtio_net(void *arg)
> -{
> - static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
> - static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__
> ((aligned(64)));
> - struct iovec vnet_iov[2][2] = {
> - { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
> - { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
> - { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) },
> - { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } },
> - };
> - struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1];
> - struct mic_info *mic = (struct mic_info *)arg;
> - char if_name[IFNAMSIZ];
> - struct pollfd net_poll[MAX_NET_FD];
> - struct mic_vring tx_vr, rx_vr;
> - struct mic_copy_desc copy;
> - struct mic_device_desc *desc;
> - int err;
> -
> - snprintf(if_name, IFNAMSIZ, "mic%d", mic->id);
> - mic->mic_net.tap_fd = tun_alloc(mic, if_name);
> - if (mic->mic_net.tap_fd < 0)
> - goto done;
> -
> - if (tap_configure(mic, if_name))
> - goto done;
> - mpsslog("MIC name %s id %d\n", mic->name, mic->id);
> -
> - net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd;
> - net_poll[NET_FD_VIRTIO_NET].events = POLLIN;
> - net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd;
> - net_poll[NET_FD_TUN].events = POLLIN;
> -
> - if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd,
> - VIRTIO_ID_NET, &tx_vr, &rx_vr,
> - virtnet_dev_page.dd.num_vq)) {
> - mpsslog("%s init_vr failed %s\n",
> - mic->name, strerror(errno));
> - goto done;
> - }
> -
> - copy.iovcnt = 2;
> - desc = get_device_desc(mic, VIRTIO_ID_NET);
> -
> - while (1) {
> - ssize_t len;
> -
> - net_poll[NET_FD_VIRTIO_NET].revents = 0;
> - net_poll[NET_FD_TUN].revents = 0;
> -
> - /* Start polling for data from tap and virtio net */
> - err = poll(net_poll, 2, -1);
> - if (err < 0) {
> - mpsslog("%s poll failed %s\n",
> - __func__, strerror(errno));
> - continue;
> - }
> - if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
> - err = wait_for_card_driver(mic,
> - mic->mic_net.virtio_net_fd,
> - VIRTIO_ID_NET);
> - if (err) {
> - mpsslog("%s %s %d Exiting...\n",
> - mic->name, __func__, __LINE__);
> - break;
> - }
> - }
> - /*
> - * Check if there is data to be read from TUN and write to
> - * virtio net fd if there is.
> - */
> - if (net_poll[NET_FD_TUN].revents & POLLIN) {
> - copy.iov = iov0;
> - len = readv(net_poll[NET_FD_TUN].fd,
> - copy.iov, copy.iovcnt);
> - if (len > 0) {
> - struct virtio_net_hdr *hdr
> - = (struct virtio_net_hdr *)vnet_hdr[0];
> -
> - /* Disable checksums on the card since we
> are on
> - a reliable PCIe link */
> - hdr->flags |=
> VIRTIO_NET_HDR_F_DATA_VALID;
> -#ifdef DEBUG
> - mpsslog("%s %s %d hdr->flags 0x%x ", mic-
> >name,
> - __func__, __LINE__, hdr->flags);
> - mpsslog("copy.out_len %d hdr->gso_type
> 0x%x\n",
> - copy.out_len, hdr->gso_type);
> -#endif
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d read from tap 0x%lx\n",
> - mic->name, __func__, __LINE__,
> - len);
> -#endif
> - spin_for_descriptors(mic, &tx_vr);
> - txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr,
> &copy,
> - len);
> -
> - err = mic_virtio_copy(mic,
> - mic->mic_net.virtio_net_fd, &tx_vr,
> - &copy);
> - if (err < 0) {
> - mpsslog("%s %s %d
> mic_virtio_copy %s\n",
> - mic->name, __func__,
> __LINE__,
> - strerror(errno));
> - }
> - if (!err)
> - verify_out_len(mic, &copy);
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d wrote to net 0x%lx\n",
> - mic->name, __func__, __LINE__,
> - sum_iovec_len(&copy));
> -#endif
> - /* Reinitialize IOV for next run */
> - iov0[1].iov_len = MAX_NET_PKT_SIZE;
> - } else if (len < 0) {
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d read failed %s ", mic-
> >name,
> - __func__, __LINE__, strerror(errno));
> - mpsslog("cnt %d sum %zd\n",
> - copy.iovcnt, sum_iovec_len(&copy));
> - }
> - }
> -
> - /*
> - * Check if there is data to be read from virtio net and
> - * write to TUN if there is.
> - */
> - if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) {
> - while (rx_vr.info->avail_idx !=
> - le16toh(rx_vr.vr.avail->idx)) {
> - copy.iov = iov1;
> - txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr,
> &copy,
> - MAX_NET_PKT_SIZE
> - + sizeof(struct virtio_net_hdr));
> -
> - err = mic_virtio_copy(mic,
> - mic->mic_net.virtio_net_fd, &rx_vr,
> - &copy);
> - if (!err) {
> -#ifdef DEBUG
> - struct virtio_net_hdr *hdr
> - = (struct virtio_net_hdr *)
> - vnet_hdr[1];
> -
> - mpsslog("%s %s %d hdr->flags 0x%x,
> ",
> - mic->name, __func__,
> __LINE__,
> - hdr->flags);
> - mpsslog("out_len %d gso_type
> 0x%x\n",
> - copy.out_len,
> - hdr->gso_type);
> -#endif
> - /* Set the correct output iov_len */
> - iov1[1].iov_len = copy.out_len -
> - sizeof(struct virtio_net_hdr);
> - verify_out_len(mic, &copy);
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__,
> - __LINE__);
> - mpsslog("%s %s %d ",
> - mic->name, __func__,
> __LINE__);
> - mpsslog("read from net 0x%lx\n",
> - sum_iovec_len(&copy));
> -#endif
> - len =
> writev(net_poll[NET_FD_TUN].fd,
> - copy.iov, copy.iovcnt);
> - if (len != sum_iovec_len(&copy)) {
> - mpsslog("Tun write failed %s
> ",
> - strerror(errno));
> - mpsslog("len 0x%zx ", len);
> - mpsslog("read_len 0x%zx\n",
> -
> sum_iovec_len(&copy));
> - } else {
> -#ifdef DEBUG
> - disp_iovec(mic, &copy,
> __func__,
> - __LINE__);
> - mpsslog("%s %s %d ",
> - mic->name, __func__,
> - __LINE__);
> - mpsslog("wrote to tap
> 0x%lx\n",
> - len);
> -#endif
> - }
> - } else {
> - mpsslog("%s %s %d
> mic_virtio_copy %s\n",
> - mic->name, __func__,
> __LINE__,
> - strerror(errno));
> - break;
> - }
> - }
> - }
> - if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
> - mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
> - }
> -done:
> - pthread_exit(NULL);
> -}
> -
> -/* virtio_console */
> -#define VIRTIO_CONSOLE_FD 0
> -#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1)
> -#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1
> */
> -#define MAX_BUFFER_SIZE PAGE_SIZE
> -
> -static void *
> -virtio_console(void *arg)
> -{
> - static __u8 vcons_buf[2][PAGE_SIZE];
> - struct iovec vcons_iov[2] = {
> - { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) },
> - { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) },
> - };
> - struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1];
> - struct mic_info *mic = (struct mic_info *)arg;
> - int err;
> - struct pollfd console_poll[MAX_CONSOLE_FD];
> - int pty_fd;
> - char *pts_name;
> - ssize_t len;
> - struct mic_vring tx_vr, rx_vr;
> - struct mic_copy_desc copy;
> - struct mic_device_desc *desc;
> -
> - pty_fd = posix_openpt(O_RDWR);
> - if (pty_fd < 0) {
> - mpsslog("can't open a pseudoterminal master device: %s\n",
> - strerror(errno));
> - goto _return;
> - }
> - pts_name = ptsname(pty_fd);
> - if (pts_name == NULL) {
> - mpsslog("can't get pts name\n");
> - goto _close_pty;
> - }
> - printf("%s console message goes to %s\n", mic->name, pts_name);
> - mpsslog("%s console message goes to %s\n", mic->name, pts_name);
> - err = grantpt(pty_fd);
> - if (err < 0) {
> - mpsslog("can't grant access: %s %s\n",
> - pts_name, strerror(errno));
> - goto _close_pty;
> - }
> - err = unlockpt(pty_fd);
> - if (err < 0) {
> - mpsslog("can't unlock a pseudoterminal: %s %s\n",
> - pts_name, strerror(errno));
> - goto _close_pty;
> - }
> - console_poll[MONITOR_FD].fd = pty_fd;
> - console_poll[MONITOR_FD].events = POLLIN;
> -
> - console_poll[VIRTIO_CONSOLE_FD].fd = mic-
> >mic_console.virtio_console_fd;
> - console_poll[VIRTIO_CONSOLE_FD].events = POLLIN;
> -
> - if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd,
> - VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr,
> - virtcons_dev_page.dd.num_vq)) {
> - mpsslog("%s init_vr failed %s\n",
> - mic->name, strerror(errno));
> - goto _close_pty;
> - }
> -
> - copy.iovcnt = 1;
> - desc = get_device_desc(mic, VIRTIO_ID_CONSOLE);
> -
> - for (;;) {
> - console_poll[MONITOR_FD].revents = 0;
> - console_poll[VIRTIO_CONSOLE_FD].revents = 0;
> - err = poll(console_poll, MAX_CONSOLE_FD, -1);
> - if (err < 0) {
> - mpsslog("%s %d: poll failed: %s\n", __func__,
> __LINE__,
> - strerror(errno));
> - continue;
> - }
> - if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
> - err = wait_for_card_driver(mic,
> - mic->mic_console.virtio_console_fd,
> - VIRTIO_ID_CONSOLE);
> - if (err) {
> - mpsslog("%s %s %d Exiting...\n",
> - mic->name, __func__, __LINE__);
> - break;
> - }
> - }
> -
> - if (console_poll[MONITOR_FD].revents & POLLIN) {
> - copy.iov = iov0;
> - len = readv(pty_fd, copy.iov, copy.iovcnt);
> - if (len > 0) {
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d read from tap 0x%lx\n",
> - mic->name, __func__, __LINE__,
> - len);
> -#endif
> - spin_for_descriptors(mic, &tx_vr);
> - txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr,
> - &copy, len);
> -
> - err = mic_virtio_copy(mic,
> - mic->mic_console.virtio_console_fd,
> - &tx_vr, &copy);
> - if (err < 0) {
> - mpsslog("%s %s %d
> mic_virtio_copy %s\n",
> - mic->name, __func__,
> __LINE__,
> - strerror(errno));
> - }
> - if (!err)
> - verify_out_len(mic, &copy);
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d wrote to net 0x%lx\n",
> - mic->name, __func__, __LINE__,
> - sum_iovec_len(&copy));
> -#endif
> - /* Reinitialize IOV for next run */
> - iov0->iov_len = PAGE_SIZE;
> - } else if (len < 0) {
> - disp_iovec(mic, &copy, __func__, __LINE__);
> - mpsslog("%s %s %d read failed %s ",
> - mic->name, __func__, __LINE__,
> - strerror(errno));
> - mpsslog("cnt %d sum %zd\n",
> - copy.iovcnt, sum_iovec_len(&copy));
> - }
> - }
> -
> - if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) {
> - while (rx_vr.info->avail_idx !=
> - le16toh(rx_vr.vr.avail->idx)) {
> - copy.iov = iov1;
> - txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr,
> - &copy, PAGE_SIZE);
> -
> - err = mic_virtio_copy(mic,
> - mic->mic_console.virtio_console_fd,
> - &rx_vr, &copy);
> - if (!err) {
> - /* Set the correct output iov_len */
> - iov1->iov_len = copy.out_len;
> - verify_out_len(mic, &copy);
> -#ifdef DEBUG
> - disp_iovec(mic, &copy, __func__,
> - __LINE__);
> - mpsslog("%s %s %d ",
> - mic->name, __func__,
> __LINE__);
> - mpsslog("read from net 0x%lx\n",
> - sum_iovec_len(&copy));
> -#endif
> - len = writev(pty_fd,
> - copy.iov, copy.iovcnt);
> - if (len != sum_iovec_len(&copy)) {
> - mpsslog("Tun write failed %s
> ",
> - strerror(errno));
> - mpsslog("len 0x%zx ", len);
> - mpsslog("read_len 0x%zx\n",
> -
> sum_iovec_len(&copy));
> - } else {
> -#ifdef DEBUG
> - disp_iovec(mic, &copy,
> __func__,
> - __LINE__);
> - mpsslog("%s %s %d ",
> - mic->name, __func__,
> - __LINE__);
> - mpsslog("wrote to tap
> 0x%lx\n",
> - len);
> -#endif
> - }
> - } else {
> - mpsslog("%s %s %d
> mic_virtio_copy %s\n",
> - mic->name, __func__,
> __LINE__,
> - strerror(errno));
> - break;
> - }
> - }
> - }
> - if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
> - mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
> - }
> -_close_pty:
> - close(pty_fd);
> -_return:
> - pthread_exit(NULL);
> -}
> -
> -static void
> -add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd)
> -{
> - char path[PATH_MAX];
> - int fd, err;
> -
> - snprintf(path, PATH_MAX, "/dev/vop_virtio%d", mic->id);
> - fd = open(path, O_RDWR);
> - if (fd < 0) {
> - mpsslog("Could not open %s %s\n", path, strerror(errno));
> - return;
> - }
> -
> - err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd);
> - if (err < 0) {
> - mpsslog("Could not add %d %s\n", dd->type, strerror(errno));
> - close(fd);
> - return;
> - }
> - switch (dd->type) {
> - case VIRTIO_ID_NET:
> - mic->mic_net.virtio_net_fd = fd;
> - mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name);
> - break;
> - case VIRTIO_ID_CONSOLE:
> - mic->mic_console.virtio_console_fd = fd;
> - mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name);
> - break;
> - case VIRTIO_ID_BLOCK:
> - mic->mic_virtblk.virtio_block_fd = fd;
> - mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name);
> - break;
> - }
> -}
> -
> -static bool
> -set_backend_file(struct mic_info *mic)
> -{
> - FILE *config;
> - char buff[PATH_MAX], *line, *evv, *p;
> -
> - snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir,
> mic->id);
> - config = fopen(buff, "r");
> - if (config == NULL)
> - return false;
> - do { /* look for "virtblk_backend=XXXX" */
> - line = fgets(buff, PATH_MAX, config);
> - if (line == NULL)
> - break;
> - if (*line == '#')
> - continue;
> - p = strchr(line, '\n');
> - if (p)
> - *p = '\0';
> - } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0);
> - fclose(config);
> - if (line == NULL)
> - return false;
> - evv = strchr(line, '=');
> - if (evv == NULL)
> - return false;
> - mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1);
> - if (mic->mic_virtblk.backend_file == NULL) {
> - mpsslog("%s %d can't allocate memory\n", mic->name, mic-
> >id);
> - return false;
> - }
> - strcpy(mic->mic_virtblk.backend_file, evv + 1);
> - return true;
> -}
> -
> -#define SECTOR_SIZE 512
> -static bool
> -set_backend_size(struct mic_info *mic)
> -{
> - mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0,
> - SEEK_END);
> - if (mic->mic_virtblk.backend_size < 0) {
> - mpsslog("%s: can't seek: %s\n",
> - mic->name, mic->mic_virtblk.backend_file);
> - return false;
> - }
> - virtblk_dev_page.blk_config.capacity =
> - mic->mic_virtblk.backend_size / SECTOR_SIZE;
> - if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0)
> - virtblk_dev_page.blk_config.capacity++;
> -
> - virtblk_dev_page.blk_config.capacity =
> - htole64(virtblk_dev_page.blk_config.capacity);
> -
> - return true;
> -}
> -
> -static bool
> -open_backend(struct mic_info *mic)
> -{
> - if (!set_backend_file(mic))
> - goto _error_exit;
> - mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file,
> O_RDWR);
> - if (mic->mic_virtblk.backend < 0) {
> - mpsslog("%s: can't open: %s\n", mic->name,
> - mic->mic_virtblk.backend_file);
> - goto _error_free;
> - }
> - if (!set_backend_size(mic))
> - goto _error_close;
> - mic->mic_virtblk.backend_addr = mmap(NULL,
> - mic->mic_virtblk.backend_size,
> - PROT_READ|PROT_WRITE, MAP_SHARED,
> - mic->mic_virtblk.backend, 0L);
> - if (mic->mic_virtblk.backend_addr == MAP_FAILED) {
> - mpsslog("%s: can't map: %s %s\n",
> - mic->name, mic->mic_virtblk.backend_file,
> - strerror(errno));
> - goto _error_close;
> - }
> - return true;
> -
> - _error_close:
> - close(mic->mic_virtblk.backend);
> - _error_free:
> - free(mic->mic_virtblk.backend_file);
> - _error_exit:
> - return false;
> -}
> -
> -static void
> -close_backend(struct mic_info *mic)
> -{
> - munmap(mic->mic_virtblk.backend_addr, mic-
> >mic_virtblk.backend_size);
> - close(mic->mic_virtblk.backend);
> - free(mic->mic_virtblk.backend_file);
> -}
> -
> -static bool
> -start_virtblk(struct mic_info *mic, struct mic_vring *vring)
> -{
> - if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) {
> - mpsslog("%s: blk_config is not 8 byte aligned.\n",
> - mic->name);
> - return false;
> - }
> - add_virtio_device(mic, &virtblk_dev_page.dd);
> - if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd,
> - VIRTIO_ID_BLOCK, vring, NULL,
> - virtblk_dev_page.dd.num_vq)) {
> - mpsslog("%s init_vr failed %s\n",
> - mic->name, strerror(errno));
> - return false;
> - }
> - return true;
> -}
> -
> -static void
> -stop_virtblk(struct mic_info *mic)
> -{
> - int vr_size, ret;
> -
> - vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
> - MIC_VIRTIO_RING_ALIGN) +
> - sizeof(struct _mic_vring_info));
> - ret = munmap(mic->mic_virtblk.block_dp,
> - MIC_DEVICE_PAGE_END + vr_size *
> virtblk_dev_page.dd.num_vq);
> - if (ret < 0)
> - mpsslog("%s munmap errno %d\n", mic->name, errno);
> - close(mic->mic_virtblk.virtio_block_fd);
> -}
> -
> -static __u8
> -header_error_check(struct vring_desc *desc)
> -{
> - if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) {
> - mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n",
> - __func__, __LINE__);
> - return -EIO;
> - }
> - if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) {
> - mpsslog("%s() %d: alone\n",
> - __func__, __LINE__);
> - return -EIO;
> - }
> - if (le16toh(desc->flags) & VRING_DESC_F_WRITE) {
> - mpsslog("%s() %d: not read\n",
> - __func__, __LINE__);
> - return -EIO;
> - }
> - return 0;
> -}
> -
> -static int
> -read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx)
> -{
> - struct iovec iovec;
> - struct mic_copy_desc copy;
> -
> - iovec.iov_len = sizeof(*hdr);
> - iovec.iov_base = hdr;
> - copy.iov = &iovec;
> - copy.iovcnt = 1;
> - copy.vr_idx = 0; /* only one vring on virtio_block */
> - copy.update_used = false; /* do not update used index */
> - return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
> -}
> -
> -static int
> -transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt)
> -{
> - struct mic_copy_desc copy;
> -
> - copy.iov = iovec;
> - copy.iovcnt = iovcnt;
> - copy.vr_idx = 0; /* only one vring on virtio_block */
> - copy.update_used = false; /* do not update used index */
> - return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
> -}
> -
> -static __u8
> -status_error_check(struct vring_desc *desc)
> -{
> - if (le32toh(desc->len) != sizeof(__u8)) {
> - mpsslog("%s() %d: length is not sizeof(status)\n",
> - __func__, __LINE__);
> - return -EIO;
> - }
> - return 0;
> -}
> -
> -static int
> -write_status(int fd, __u8 *status)
> -{
> - struct iovec iovec;
> - struct mic_copy_desc copy;
> -
> - iovec.iov_base = status;
> - iovec.iov_len = sizeof(*status);
> - copy.iov = &iovec;
> - copy.iovcnt = 1;
> - copy.vr_idx = 0; /* only one vring on virtio_block */
> - copy.update_used = true; /* Update used index */
> - return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
> -}
> -
> -#ifndef VIRTIO_BLK_T_GET_ID
> -#define VIRTIO_BLK_T_GET_ID 8
> -#endif
> -
> -static void *
> -virtio_block(void *arg)
> -{
> - struct mic_info *mic = (struct mic_info *)arg;
> - int ret;
> - struct pollfd block_poll;
> - struct mic_vring vring;
> - __u16 avail_idx;
> - __u32 desc_idx;
> - struct vring_desc *desc;
> - struct iovec *iovec, *piov;
> - __u8 status;
> - __u32 buffer_desc_idx;
> - struct virtio_blk_outhdr hdr;
> - void *fos;
> -
> - for (;;) { /* forever */
> - if (!open_backend(mic)) { /* No virtblk */
> - for (mic->mic_virtblk.signaled = 0;
> - !mic->mic_virtblk.signaled;)
> - sleep(1);
> - continue;
> - }
> -
> - /* backend file is specified. */
> - if (!start_virtblk(mic, &vring))
> - goto _close_backend;
> - iovec = malloc(sizeof(*iovec) *
> - le32toh(virtblk_dev_page.blk_config.seg_max));
> - if (!iovec) {
> - mpsslog("%s: can't alloc iovec: %s\n",
> - mic->name, strerror(ENOMEM));
> - goto _stop_virtblk;
> - }
> -
> - block_poll.fd = mic->mic_virtblk.virtio_block_fd;
> - block_poll.events = POLLIN;
> - for (mic->mic_virtblk.signaled = 0;
> - !mic->mic_virtblk.signaled;) {
> - block_poll.revents = 0;
> - /* timeout in 1 sec to see signaled */
> - ret = poll(&block_poll, 1, 1000);
> - if (ret < 0) {
> - mpsslog("%s %d: poll failed: %s\n",
> - __func__, __LINE__,
> - strerror(errno));
> - continue;
> - }
> -
> - if (!(block_poll.revents & POLLIN)) {
> -#ifdef DEBUG
> - mpsslog("%s %d: block_poll.revents=0x%x\n",
> - __func__, __LINE__,
> block_poll.revents);
> -#endif
> - continue;
> - }
> -
> - /* POLLIN */
> - while (vring.info->avail_idx !=
> - le16toh(vring.vr.avail->idx)) {
> - /* read header element */
> - avail_idx =
> - vring.info->avail_idx &
> - (vring.vr.num - 1);
> - desc_idx = le16toh(
> - vring.vr.avail->ring[avail_idx]);
> - desc = &vring.vr.desc[desc_idx];
> -#ifdef DEBUG
> - mpsslog("%s() %d: avail_idx=%d ",
> - __func__, __LINE__,
> - vring.info->avail_idx);
> - mpsslog("vring.vr.num=%d desc=%p\n",
> - vring.vr.num, desc);
> -#endif
> - status = header_error_check(desc);
> - ret = read_header(
> - mic->mic_virtblk.virtio_block_fd,
> - &hdr, desc_idx);
> - if (ret < 0) {
> - mpsslog("%s() %d %s: ret=%d %s\n",
> - __func__, __LINE__,
> - mic->name, ret,
> - strerror(errno));
> - break;
> - }
> - /* buffer element */
> - piov = iovec;
> - status = 0;
> - fos = mic->mic_virtblk.backend_addr +
> - (hdr.sector * SECTOR_SIZE);
> - buffer_desc_idx = next_desc(desc);
> - desc_idx = buffer_desc_idx;
> - for (desc = &vring.vr.desc[buffer_desc_idx];
> - desc->flags & VRING_DESC_F_NEXT;
> - desc_idx = next_desc(desc),
> - desc = &vring.vr.desc[desc_idx]) {
> - piov->iov_len = desc->len;
> - piov->iov_base = fos;
> - piov++;
> - fos += desc->len;
> - }
> - /* Returning NULLs for VIRTIO_BLK_T_GET_ID.
> */
> - if (hdr.type & ~(VIRTIO_BLK_T_OUT |
> - VIRTIO_BLK_T_GET_ID)) {
> - /*
> - VIRTIO_BLK_T_IN - does not do
> - anything. Probably for documenting.
> - VIRTIO_BLK_T_SCSI_CMD - for
> - virtio_scsi.
> - VIRTIO_BLK_T_FLUSH - turned off in
> - config space.
> - VIRTIO_BLK_T_BARRIER - defined
> but not
> - used in anywhere.
> - */
> - mpsslog("%s() %d: type %x ",
> - __func__, __LINE__,
> - hdr.type);
> - mpsslog("is not supported\n");
> - status = -ENOTSUP;
> -
> - } else {
> - ret = transfer_blocks(
> - mic->mic_virtblk.virtio_block_fd,
> - iovec,
> - piov - iovec);
> - if (ret < 0 &&
> - status != 0)
> - status = ret;
> - }
> - /* write status and update used pointer */
> - if (status != 0)
> - status = status_error_check(desc);
> - ret = write_status(
> - mic->mic_virtblk.virtio_block_fd,
> - &status);
> -#ifdef DEBUG
> - mpsslog("%s() %d: write status=%d on
> desc=%p\n",
> - __func__, __LINE__,
> - status, desc);
> -#endif
> - }
> - }
> - free(iovec);
> -_stop_virtblk:
> - stop_virtblk(mic);
> -_close_backend:
> - close_backend(mic);
> - } /* forever */
> -
> - pthread_exit(NULL);
> -}
> -
> -static void
> -reset(struct mic_info *mic)
> -{
> -#define RESET_TIMEOUT 120
> - int i = RESET_TIMEOUT;
> - setsysfs(mic->name, "state", "reset");
> - while (i) {
> - char *state;
> - state = readsysfs(mic->name, "state");
> - if (!state)
> - goto retry;
> - mpsslog("%s: %s %d state %s\n",
> - mic->name, __func__, __LINE__, state);
> -
> - if (!strcmp(state, "ready")) {
> - free(state);
> - break;
> - }
> - free(state);
> -retry:
> - sleep(1);
> - i--;
> - }
> -}
> -
> -static int
> -get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
> -{
> - if (!strcmp(shutdown_status, "nop"))
> - return MIC_NOP;
> - if (!strcmp(shutdown_status, "crashed"))
> - return MIC_CRASHED;
> - if (!strcmp(shutdown_status, "halted"))
> - return MIC_HALTED;
> - if (!strcmp(shutdown_status, "poweroff"))
> - return MIC_POWER_OFF;
> - if (!strcmp(shutdown_status, "restart"))
> - return MIC_RESTART;
> - mpsslog("%s: BUG invalid status %s\n", mic->name,
> shutdown_status);
> - /* Invalid state */
> - assert(0);
> -};
> -
> -static int get_mic_state(struct mic_info *mic)
> -{
> - char *state = NULL;
> - enum mic_states mic_state;
> -
> - while (!state) {
> - state = readsysfs(mic->name, "state");
> - sleep(1);
> - }
> - mpsslog("%s: %s %d state %s\n",
> - mic->name, __func__, __LINE__, state);
> -
> - if (!strcmp(state, "ready")) {
> - mic_state = MIC_READY;
> - } else if (!strcmp(state, "booting")) {
> - mic_state = MIC_BOOTING;
> - } else if (!strcmp(state, "online")) {
> - mic_state = MIC_ONLINE;
> - } else if (!strcmp(state, "shutting_down")) {
> - mic_state = MIC_SHUTTING_DOWN;
> - } else if (!strcmp(state, "reset_failed")) {
> - mic_state = MIC_RESET_FAILED;
> - } else if (!strcmp(state, "resetting")) {
> - mic_state = MIC_RESETTING;
> - } else {
> - mpsslog("%s: BUG invalid state %s\n", mic->name, state);
> - assert(0);
> - }
> -
> - free(state);
> - return mic_state;
> -};
> -
> -static void mic_handle_shutdown(struct mic_info *mic)
> -{
> -#define SHUTDOWN_TIMEOUT 60
> - int i = SHUTDOWN_TIMEOUT;
> - char *shutdown_status;
> - while (i) {
> - shutdown_status = readsysfs(mic->name,
> "shutdown_status");
> - if (!shutdown_status) {
> - sleep(1);
> - continue;
> - }
> - mpsslog("%s: %s %d shutdown_status %s\n",
> - mic->name, __func__, __LINE__, shutdown_status);
> - switch (get_mic_shutdown_status(mic, shutdown_status)) {
> - case MIC_RESTART:
> - mic->restart = 1;
> - case MIC_HALTED:
> - case MIC_POWER_OFF:
> - case MIC_CRASHED:
> - free(shutdown_status);
> - goto reset;
> - default:
> - break;
> - }
> - free(shutdown_status);
> - sleep(1);
> - i--;
> - }
> -reset:
> - if (!i)
> - mpsslog("%s: %s %d timing out waiting for
> shutdown_status %s\n",
> - mic->name, __func__, __LINE__, shutdown_status);
> - reset(mic);
> -}
> -
> -static int open_state_fd(struct mic_info *mic)
> -{
> - char pathname[PATH_MAX];
> - int fd;
> -
> - snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
> - MICSYSFSDIR, mic->name, "state");
> -
> - fd = open(pathname, O_RDONLY);
> - if (fd < 0)
> - mpsslog("%s: opening file %s failed %s\n",
> - mic->name, pathname, strerror(errno));
> - return fd;
> -}
> -
> -static int block_till_state_change(int fd, struct mic_info *mic)
> -{
> - struct pollfd ufds[1];
> - char value[PAGE_SIZE];
> - int ret;
> -
> - ufds[0].fd = fd;
> - ufds[0].events = POLLERR | POLLPRI;
> - ret = poll(ufds, 1, -1);
> - if (ret < 0) {
> - mpsslog("%s: %s %d poll failed %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - return ret;
> - }
> -
> - ret = lseek(fd, 0, SEEK_SET);
> - if (ret < 0) {
> - mpsslog("%s: %s %d Failed to seek to 0: %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - return ret;
> - }
> -
> - ret = read(fd, value, sizeof(value));
> - if (ret < 0) {
> - mpsslog("%s: %s %d Failed to read sysfs entry: %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - return ret;
> - }
> -
> - return 0;
> -}
> -
> -static void *
> -mic_config(void *arg)
> -{
> - struct mic_info *mic = (struct mic_info *)arg;
> - int fd, ret, stat = 0;
> -
> - fd = open_state_fd(mic);
> - if (fd < 0) {
> - mpsslog("%s: %s %d open state fd failed %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - goto exit;
> - }
> -
> - do {
> - ret = block_till_state_change(fd, mic);
> - if (ret < 0) {
> - mpsslog("%s: %s %d block_till_state_change
> error %s\n",
> - mic->name, __func__, __LINE__,
> strerror(errno));
> - goto close_exit;
> - }
> -
> - switch (get_mic_state(mic)) {
> - case MIC_SHUTTING_DOWN:
> - mic_handle_shutdown(mic);
> - break;
> - case MIC_READY:
> - case MIC_RESET_FAILED:
> - ret = kill(mic->pid, SIGTERM);
> - mpsslog("%s: %s %d kill pid %d ret %d\n",
> - mic->name, __func__, __LINE__,
> - mic->pid, ret);
> - if (!ret) {
> - ret = waitpid(mic->pid, &stat,
> - WIFSIGNALED(stat));
> - mpsslog("%s: %s %d waitpid ret %d
> pid %d\n",
> - mic->name, __func__, __LINE__,
> - ret, mic->pid);
> - }
> - if (mic->boot_on_resume) {
> - setsysfs(mic->name, "state", "boot");
> - mic->boot_on_resume = 0;
> - }
> - goto close_exit;
> - default:
> - break;
> - }
> - } while (1);
> -
> -close_exit:
> - close(fd);
> -exit:
> - init_mic(mic);
> - pthread_exit(NULL);
> -}
> -
> -static void
> -set_cmdline(struct mic_info *mic)
> -{
> - char buffer[PATH_MAX];
> - int len;
> -
> - len = snprintf(buffer, PATH_MAX,
> - "clocksource=tsc highres=off nohz=off ");
> - len += snprintf(buffer + len, PATH_MAX - len,
> - "cpufreq_on;corec6_off;pc3_off;pc6_off ");
> - len += snprintf(buffer + len, PATH_MAX - len,
> - "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
> - mic->id + 1);
> -
> - setsysfs(mic->name, "cmdline", buffer);
> - mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
> - snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1);
> - mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
> -}
> -
> -static void
> -set_log_buf_info(struct mic_info *mic)
> -{
> - int fd;
> - off_t len;
> - char system_map[] = "/lib/firmware/mic/System.map";
> - char *map, *temp, log_buf[17] = {'\0'};
> -
> - fd = open(system_map, O_RDONLY);
> - if (fd < 0) {
> - mpsslog("%s: Opening System.map failed: %d\n",
> - mic->name, errno);
> - return;
> - }
> - len = lseek(fd, 0, SEEK_END);
> - if (len < 0) {
> - mpsslog("%s: Reading System.map size failed: %d\n",
> - mic->name, errno);
> - close(fd);
> - return;
> - }
> - map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
> - if (map == MAP_FAILED) {
> - mpsslog("%s: mmap of System.map failed: %d\n",
> - mic->name, errno);
> - close(fd);
> - return;
> - }
> - temp = strstr(map, "__log_buf");
> - if (!temp) {
> - mpsslog("%s: __log_buf not found: %d\n", mic->name,
> errno);
> - munmap(map, len);
> - close(fd);
> - return;
> - }
> - strncpy(log_buf, temp - 19, 16);
> - setsysfs(mic->name, "log_buf_addr", log_buf);
> - mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf);
> - temp = strstr(map, "log_buf_len");
> - if (!temp) {
> - mpsslog("%s: log_buf_len not found: %d\n", mic->name,
> errno);
> - munmap(map, len);
> - close(fd);
> - return;
> - }
> - strncpy(log_buf, temp - 19, 16);
> - setsysfs(mic->name, "log_buf_len", log_buf);
> - mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf);
> - munmap(map, len);
> - close(fd);
> -}
> -
> -static void
> -change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
> -{
> - struct mic_info *mic;
> -
> - for (mic = mic_list.next; mic != NULL; mic = mic->next)
> - mic->mic_virtblk.signaled = 1/* true */;
> -}
> -
> -static void
> -set_mic_boot_params(struct mic_info *mic)
> -{
> - set_log_buf_info(mic);
> - set_cmdline(mic);
> -}
> -
> -static void *
> -init_mic(void *arg)
> -{
> - struct mic_info *mic = (struct mic_info *)arg;
> - struct sigaction ignore = {
> - .sa_flags = 0,
> - .sa_handler = SIG_IGN
> - };
> - struct sigaction act = {
> - .sa_flags = SA_SIGINFO,
> - .sa_sigaction = change_virtblk_backend,
> - };
> - char buffer[PATH_MAX];
> - int err, fd;
> -
> - /*
> - * Currently, one virtio block device is supported for each MIC card
> - * at a time. Any user (or test) can send a SIGUSR1 to the MIC
> daemon.
> - * The signal informs the virtio block backend about a change in the
> - * configuration file which specifies the virtio backend file name on
> - * the host. Virtio block backend then re-reads the configuration file
> - * and switches to the new block device. This signalling mechanism
> may
> - * not be required once multiple virtio block devices are supported by
> - * the MIC daemon.
> - */
> - sigaction(SIGUSR1, &ignore, NULL);
> -retry:
> - fd = open_state_fd(mic);
> - if (fd < 0) {
> - mpsslog("%s: %s %d open state fd failed %s\n",
> - mic->name, __func__, __LINE__, strerror(errno));
> - sleep(2);
> - goto retry;
> - }
> -
> - if (mic->restart) {
> - snprintf(buffer, PATH_MAX, "boot");
> - setsysfs(mic->name, "state", buffer);
> - mpsslog("%s restarting mic %d\n",
> - mic->name, mic->restart);
> - mic->restart = 0;
> - }
> -
> - while (1) {
> - while (block_till_state_change(fd, mic)) {
> - mpsslog("%s: %s %d block_till_state_change
> error %s\n",
> - mic->name, __func__, __LINE__,
> strerror(errno));
> - sleep(2);
> - continue;
> - }
> -
> - if (get_mic_state(mic) == MIC_BOOTING)
> - break;
> - }
> -
> - mic->pid = fork();
> - switch (mic->pid) {
> - case 0:
> - add_virtio_device(mic, &virtcons_dev_page.dd);
> - add_virtio_device(mic, &virtnet_dev_page.dd);
> - err = pthread_create(&mic->mic_console.console_thread,
> NULL,
> - virtio_console, mic);
> - if (err)
> - mpsslog("%s virtcons pthread_create failed %s\n",
> - mic->name, strerror(err));
> - err = pthread_create(&mic->mic_net.net_thread, NULL,
> - virtio_net, mic);
> - if (err)
> - mpsslog("%s virtnet pthread_create failed %s\n",
> - mic->name, strerror(err));
> - err = pthread_create(&mic->mic_virtblk.block_thread, NULL,
> - virtio_block, mic);
> - if (err)
> - mpsslog("%s virtblk pthread_create failed %s\n",
> - mic->name, strerror(err));
> - sigemptyset(&act.sa_mask);
> - err = sigaction(SIGUSR1, &act, NULL);
> - if (err)
> - mpsslog("%s sigaction SIGUSR1 failed %s\n",
> - mic->name, strerror(errno));
> - while (1)
> - sleep(60);
> - case -1:
> - mpsslog("fork failed MIC name %s id %d errno %d\n",
> - mic->name, mic->id, errno);
> - break;
> - default:
> - err = pthread_create(&mic->config_thread, NULL,
> - mic_config, mic);
> - if (err)
> - mpsslog("%s mic_config pthread_create failed %s\n",
> - mic->name, strerror(err));
> - }
> -
> - return NULL;
> -}
> -
> -static void
> -start_daemon(void)
> -{
> - struct mic_info *mic;
> - int err;
> -
> - for (mic = mic_list.next; mic; mic = mic->next) {
> - set_mic_boot_params(mic);
> - err = pthread_create(&mic->init_thread, NULL, init_mic, mic);
> - if (err)
> - mpsslog("%s init_mic pthread_create failed %s\n",
> - mic->name, strerror(err));
> - }
> -
> - while (1)
> - sleep(60);
> -}
> -
> -static int
> -init_mic_list(void)
> -{
> - struct mic_info *mic = &mic_list;
> - struct dirent *file;
> - DIR *dp;
> - int cnt = 0;
> -
> - dp = opendir(MICSYSFSDIR);
> - if (!dp)
> - return 0;
> -
> - while ((file = readdir(dp)) != NULL) {
> - if (!strncmp(file->d_name, "mic", 3)) {
> - mic->next = calloc(1, sizeof(struct mic_info));
> - if (mic->next) {
> - mic = mic->next;
> - mic->id = atoi(&file->d_name[3]);
> - mic->name = malloc(strlen(file->d_name) +
> 16);
> - if (mic->name)
> - strcpy(mic->name, file->d_name);
> - mpsslog("MIC name %s id %d\n", mic->name,
> - mic->id);
> - cnt++;
> - }
> - }
> - }
> -
> - closedir(dp);
> - return cnt;
> -}
> -
> -void
> -mpsslog(char *format, ...)
> -{
> - va_list args;
> - char buffer[4096];
> - char ts[52], *ts1;
> - time_t t;
> -
> - if (logfp == NULL)
> - return;
> -
> - va_start(args, format);
> - vsprintf(buffer, format, args);
> - va_end(args);
> -
> - time(&t);
> - ts1 = ctime_r(&t, ts);
> - ts1[strlen(ts1) - 1] = '\0';
> - fprintf(logfp, "%s: %s", ts1, buffer);
> -
> - fflush(logfp);
> -}
> -
> -int
> -main(int argc, char *argv[])
> -{
> - int cnt;
> - pid_t pid;
> -
> - myname = argv[0];
> -
> - logfp = fopen(LOGFILE_NAME, "a+");
> - if (!logfp) {
> - fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME);
> - exit(1);
> - }
> - pid = fork();
> - switch (pid) {
> - case 0:
> - break;
> - case -1:
> - exit(2);
> - default:
> - exit(0);
> - }
> -
> - mpsslog("MIC Daemon start\n");
> -
> - cnt = init_mic_list();
> - if (cnt == 0) {
> - mpsslog("MIC module not loaded\n");
> - exit(3);
> - }
> - mpsslog("MIC found %d devices\n", cnt);
> -
> - start_daemon();
> -
> - exit(0);
> -}
> diff --git a/samples/mic/mpssd/mpssd.h b/samples/mic/mpssd/mpssd.h
> deleted file mode 100644
> index 5f98bdafe653..000000000000
> --- a/samples/mic/mpssd/mpssd.h
> +++ /dev/null
> @@ -1,89 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC User Space Tools.
> - */
> -#ifndef _MPSSD_H_
> -#define _MPSSD_H_
> -
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <fcntl.h>
> -#include <unistd.h>
> -#include <dirent.h>
> -#include <libgen.h>
> -#include <pthread.h>
> -#include <stdarg.h>
> -#include <time.h>
> -#include <errno.h>
> -#include <sys/dir.h>
> -#include <sys/ioctl.h>
> -#include <sys/poll.h>
> -#include <sys/types.h>
> -#include <sys/socket.h>
> -#include <sys/stat.h>
> -#include <sys/mman.h>
> -#include <sys/utsname.h>
> -#include <sys/wait.h>
> -#include <netinet/in.h>
> -#include <arpa/inet.h>
> -#include <netdb.h>
> -#include <signal.h>
> -#include <limits.h>
> -#include <syslog.h>
> -#include <getopt.h>
> -#include <net/if.h>
> -#include <linux/if_tun.h>
> -#include <linux/virtio_ids.h>
> -
> -#define MICSYSFSDIR "/sys/class/mic"
> -#define LOGFILE_NAME "/var/log/mpssd"
> -#define PAGE_SIZE 4096
> -
> -struct mic_console_info {
> - pthread_t console_thread;
> - int virtio_console_fd;
> - void *console_dp;
> -};
> -
> -struct mic_net_info {
> - pthread_t net_thread;
> - int virtio_net_fd;
> - int tap_fd;
> - void *net_dp;
> -};
> -
> -struct mic_virtblk_info {
> - pthread_t block_thread;
> - int virtio_block_fd;
> - void *block_dp;
> - volatile sig_atomic_t signaled;
> - char *backend_file;
> - int backend;
> - void *backend_addr;
> - long backend_size;
> -};
> -
> -struct mic_info {
> - int id;
> - char *name;
> - pthread_t config_thread;
> - pthread_t init_thread;
> - pid_t pid;
> - struct mic_console_info mic_console;
> - struct mic_net_info mic_net;
> - struct mic_virtblk_info mic_virtblk;
> - int restart;
> - int boot_on_resume;
> - struct mic_info *next;
> -};
> -
> -__attribute__((format(printf, 1, 2)))
> -void mpsslog(char *format, ...);
> -char *readsysfs(char *dir, char *entry);
> -int setsysfs(char *dir, char *entry, char *value);
> -#endif
> diff --git a/samples/mic/mpssd/sysfs.c b/samples/mic/mpssd/sysfs.c
> deleted file mode 100644
> index 3fb08eb7ed9d..000000000000
> --- a/samples/mic/mpssd/sysfs.c
> +++ /dev/null
> @@ -1,91 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Intel MIC Platform Software Stack (MPSS)
> - *
> - * Copyright(c) 2013 Intel Corporation.
> - *
> - * Intel MIC User Space Tools.
> - */
> -
> -#include "mpssd.h"
> -
> -#define PAGE_SIZE 4096
> -
> -char *
> -readsysfs(char *dir, char *entry)
> -{
> - char filename[PATH_MAX];
> - char value[PAGE_SIZE];
> - char *string = NULL;
> - int fd;
> - int len;
> -
> - if (dir == NULL)
> - snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
> - else
> - snprintf(filename, PATH_MAX,
> - "%s/%s/%s", MICSYSFSDIR, dir, entry);
> -
> - fd = open(filename, O_RDONLY);
> - if (fd < 0) {
> - mpsslog("Failed to open sysfs entry '%s': %s\n",
> - filename, strerror(errno));
> - return NULL;
> - }
> -
> - len = read(fd, value, sizeof(value));
> - if (len < 0) {
> - mpsslog("Failed to read sysfs entry '%s': %s\n",
> - filename, strerror(errno));
> - goto readsys_ret;
> - }
> - if (len == 0)
> - goto readsys_ret;
> -
> - value[len - 1] = '\0';
> -
> - string = malloc(strlen(value) + 1);
> - if (string)
> - strcpy(string, value);
> -
> -readsys_ret:
> - close(fd);
> - return string;
> -}
> -
> -int
> -setsysfs(char *dir, char *entry, char *value)
> -{
> - char filename[PATH_MAX];
> - char *oldvalue;
> - int fd, ret = 0;
> -
> - if (dir == NULL)
> - snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
> - else
> - snprintf(filename, PATH_MAX, "%s/%s/%s",
> - MICSYSFSDIR, dir, entry);
> -
> - oldvalue = readsysfs(dir, entry);
> -
> - fd = open(filename, O_RDWR);
> - if (fd < 0) {
> - ret = errno;
> - mpsslog("Failed to open sysfs entry '%s': %s\n",
> - filename, strerror(errno));
> - goto done;
> - }
> -
> - if (!oldvalue || strcmp(value, oldvalue)) {
> - if (write(fd, value, strlen(value)) < 0) {
> - ret = errno;
> - mpsslog("Failed to write new sysfs entry '%s': %s\n",
> - filename, strerror(errno));
> - }
> - }
> - close(fd);
> -done:
> - if (oldvalue)
> - free(oldvalue);
> - return ret;
> -}
> --
> 2.28.0

\
 
 \ /
  Last update: 2020-10-28 22:57    [W:0.834 / U:0.500 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site