linux/drivers/misc/mic/scif/scif_rma.h
<<
>>
Prefs
   1/*
   2 * Intel MIC Platform Software Stack (MPSS)
   3 *
   4 * This file is provided under a dual BSD/GPLv2 license.  When using or
   5 * redistributing this file, you may do so under either license.
   6 *
   7 * GPL LICENSE SUMMARY
   8 *
   9 * Copyright(c) 2015 Intel Corporation.
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of version 2 of the GNU General Public License as
  13 * published by the Free Software Foundation.
  14 *
  15 * This program is distributed in the hope that it will be useful, but
  16 * WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * General Public License for more details.
  19 *
  20 * BSD LICENSE
  21 *
  22 * Copyright(c) 2015 Intel Corporation.
  23 *
  24 * Redistribution and use in source and binary forms, with or without
  25 * modification, are permitted provided that the following conditions
  26 * are met:
  27 *
  28 * * Redistributions of source code must retain the above copyright
  29 *   notice, this list of conditions and the following disclaimer.
  30 * * Redistributions in binary form must reproduce the above copyright
  31 *   notice, this list of conditions and the following disclaimer in
  32 *   the documentation and/or other materials provided with the
  33 *   distribution.
  34 * * Neither the name of Intel Corporation nor the names of its
  35 *   contributors may be used to endorse or promote products derived
  36 *   from this software without specific prior written permission.
  37 *
  38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  39 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  40 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  41 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  42 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  48 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  49 *
  50 * Intel SCIF driver.
  51 *
  52 */
  53#ifndef SCIF_RMA_H
  54#define SCIF_RMA_H
  55
  56#include <linux/dma_remapping.h>
  57#include <linux/mmu_notifier.h>
  58
  59#include "../bus/scif_bus.h"
  60
  61/* If this bit is set then the mark is a remote fence mark */
  62#define SCIF_REMOTE_FENCE_BIT          31
  63/* Magic value used to indicate a remote fence request */
  64#define SCIF_REMOTE_FENCE BIT_ULL(SCIF_REMOTE_FENCE_BIT)
  65
  66#define SCIF_MAX_UNALIGNED_BUF_SIZE (1024 * 1024ULL)
  67#define SCIF_KMEM_UNALIGNED_BUF_SIZE (SCIF_MAX_UNALIGNED_BUF_SIZE + \
  68                                      (L1_CACHE_BYTES << 1))
  69
  70#define SCIF_IOVA_START_PFN             (1)
  71#define SCIF_IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
  72#define SCIF_DMA_64BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(64))
  73#define SCIF_DMA_63BIT_PFN SCIF_IOVA_PFN(DMA_BIT_MASK(63))
  74
  75/*
  76 * struct scif_endpt_rma_info - Per Endpoint Remote Memory Access Information
  77 *
  78 * @reg_list: List of registration windows for self
  79 * @remote_reg_list: List of registration windows for peer
  80 * @iovad: Offset generator
  81 * @rma_lock: Synchronizes access to self/remote list and also protects the
  82 *            window from being destroyed while RMAs are in progress.
  83 * @tc_lock: Synchronizes access to temporary cached windows list
  84 *           for SCIF Registration Caching.
  85 * @mmn_lock: Synchronizes access to the list of MMU notifiers registered
  86 * @tw_refcount: Keeps track of number of outstanding temporary registered
  87 *               windows created by scif_vreadfrom/scif_vwriteto which have
  88 *               not been destroyed.
  89 * @tcw_refcount: Same as tw_refcount but for temporary cached windows
  90 * @tcw_total_pages: Same as tcw_refcount but in terms of pages pinned
  91 * @mmn_list: MMU notifier so that we can destroy the windows when required
  92 * @fence_refcount: Keeps track of number of outstanding remote fence
  93 *                  requests which have been received by the peer.
  94 * @dma_chan: DMA channel used for all DMA transfers for this endpoint.
  95 * @async_list_del: Detect asynchronous list entry deletion
  96 * @vma_list: List of vmas with remote memory mappings
  97 * @markwq: Wait queue used for scif_fence_mark/scif_fence_wait
  98*/
  99struct scif_endpt_rma_info {
 100        struct list_head reg_list;
 101        struct list_head remote_reg_list;
 102        struct iova_domain iovad;
 103        struct mutex rma_lock;
 104        spinlock_t tc_lock;
 105        struct mutex mmn_lock;
 106        atomic_t tw_refcount;
 107        atomic_t tcw_refcount;
 108        atomic_t tcw_total_pages;
 109        struct list_head mmn_list;
 110        atomic_t fence_refcount;
 111        struct dma_chan *dma_chan;
 112        int async_list_del;
 113        struct list_head vma_list;
 114        wait_queue_head_t markwq;
 115};
 116
 117/*
 118 * struct scif_fence_info - used for tracking fence requests
 119 *
 120 * @state: State of this transfer
 121 * @wq: Fences wait on this queue
 122 * @dma_mark: Used for storing the DMA mark
 123 */
 124struct scif_fence_info {
 125        enum scif_msg_state state;
 126        struct completion comp;
 127        int dma_mark;
 128};
 129
 130/*
 131 * struct scif_remote_fence_info - used for tracking remote fence requests
 132 *
 133 * @msg: List of SCIF node QP fence messages
 134 * @list: Link to list of remote fence requests
 135 */
 136struct scif_remote_fence_info {
 137        struct scifmsg msg;
 138        struct list_head list;
 139};
 140
 141/*
 142 * Specifies whether an RMA operation can span across partial windows, a single
 143 * window or multiple contiguous windows. Mmaps can span across partial windows.
 144 * Unregistration can span across complete windows. scif_get_pages() can span a
 145 * single window. A window can also be of type self or peer.
 146 */
 147enum scif_window_type {
 148        SCIF_WINDOW_PARTIAL,
 149        SCIF_WINDOW_SINGLE,
 150        SCIF_WINDOW_FULL,
 151        SCIF_WINDOW_SELF,
 152        SCIF_WINDOW_PEER
 153};
 154
 155/* The number of physical addresses that can be stored in a PAGE. */
 156#define SCIF_NR_ADDR_IN_PAGE   (0x1000 >> 3)
 157
 158/*
 159 * struct scif_rma_lookup - RMA lookup data structure for page list transfers
 160 *
 161 * Store an array of lookup offsets. Each offset in this array maps
 162 * one 4K page containing 512 physical addresses i.e. 2MB. 512 such
 163 * offsets in a 4K page will correspond to 1GB of registered address space.
 164
 165 * @lookup: Array of offsets
 166 * @offset: DMA offset of lookup array
 167 */
 168struct scif_rma_lookup {
 169        dma_addr_t *lookup;
 170        dma_addr_t offset;
 171};
 172
 173/*
 174 * struct scif_pinned_pages - A set of pinned pages obtained with
 175 * scif_pin_pages() which could be part of multiple registered
 176 * windows across different end points.
 177 *
 178 * @nr_pages: Number of pages which is defined as a s64 instead of an int
 179 * to avoid sign extension with buffers >= 2GB
 180 * @prot: read/write protections
 181 * @map_flags: Flags specified during the pin operation
 182 * @ref_count: Reference count bumped in terms of number of pages
 183 * @magic: A magic value
 184 * @pages: Array of pointers to struct pages populated with get_user_pages(..)
 185 */
 186struct scif_pinned_pages {
 187        s64 nr_pages;
 188        int prot;
 189        int map_flags;
 190        atomic_t ref_count;
 191        u64 magic;
 192        struct page **pages;
 193};
 194
 195/*
 196 * struct scif_status - Stores DMA status update information
 197 *
 198 * @src_dma_addr: Source buffer DMA address
 199 * @val: src location for value to be written to the destination
 200 * @ep: SCIF endpoint
 201 */
 202struct scif_status {
 203        dma_addr_t src_dma_addr;
 204        u64 val;
 205        struct scif_endpt *ep;
 206};
 207
 208/*
 209 * struct scif_window - Registration Window for Self and Remote
 210 *
 211 * @nr_pages: Number of pages which is defined as a s64 instead of an int
 212 * to avoid sign extension with buffers >= 2GB
 213 * @nr_contig_chunks: Number of contiguous physical chunks
 214 * @prot: read/write protections
 215 * @ref_count: reference count in terms of number of pages
 216 * @magic: Cookie to detect corruption
 217 * @offset: registered offset
 218 * @va_for_temp: va address that this window represents
 219 * @dma_mark: Used to determine if all DMAs against the window are done
 220 * @ep: Pointer to EP. Useful for passing EP around with messages to
 221        avoid expensive list traversals.
 222 * @list: link to list of windows for the endpoint
 223 * @type: self or peer window
 224 * @peer_window: Pointer to peer window. Useful for sending messages to peer
 225 *               without requiring an extra list traversal
 226 * @unreg_state: unregistration state
 227 * @offset_freed: True if the offset has been freed
 228 * @temp: True for temporary windows created via scif_vreadfrom/scif_vwriteto
 229 * @mm: memory descriptor for the task_struct which initiated the RMA
 230 * @st: scatter gather table for DMA mappings with IOMMU enabled
 231 * @pinned_pages: The set of pinned_pages backing this window
 232 * @alloc_handle: Handle for sending ALLOC_REQ
 233 * @regwq: Wait Queue for an registration (N)ACK
 234 * @reg_state: Registration state
 235 * @unregwq: Wait Queue for an unregistration (N)ACK
 236 * @dma_addr_lookup: Lookup for physical addresses used for DMA
 237 * @nr_lookup: Number of entries in lookup
 238 * @mapped_offset: Offset used to map the window by the peer
 239 * @dma_addr: Array of physical addresses used for Mgmt node & MIC initiated DMA
 240 * @num_pages: Array specifying number of pages for each physical address
 241 */
 242struct scif_window {
 243        s64 nr_pages;
 244        int nr_contig_chunks;
 245        int prot;
 246        int ref_count;
 247        u64 magic;
 248        s64 offset;
 249        unsigned long va_for_temp;
 250        int dma_mark;
 251        u64 ep;
 252        struct list_head list;
 253        enum scif_window_type type;
 254        u64 peer_window;
 255        enum scif_msg_state unreg_state;
 256        bool offset_freed;
 257        bool temp;
 258        struct mm_struct *mm;
 259        struct sg_table *st;
 260        union {
 261                struct {
 262                        struct scif_pinned_pages *pinned_pages;
 263                        struct scif_allocmsg alloc_handle;
 264                        wait_queue_head_t regwq;
 265                        enum scif_msg_state reg_state;
 266                        wait_queue_head_t unregwq;
 267                };
 268                struct {
 269                        struct scif_rma_lookup dma_addr_lookup;
 270                        struct scif_rma_lookup num_pages_lookup;
 271                        int nr_lookup;
 272                        dma_addr_t mapped_offset;
 273                };
 274        };
 275        dma_addr_t *dma_addr;
 276        u64 *num_pages;
 277} __packed;
 278
 279/*
 280 * scif_mmu_notif - SCIF mmu notifier information
 281 *
 282 * @mmu_notifier ep_mmu_notifier: MMU notifier operations
 283 * @tc_reg_list: List of temp registration windows for self
 284 * @mm: memory descriptor for the task_struct which initiated the RMA
 285 * @ep: SCIF endpoint
 286 * @list: link to list of MMU notifier information
 287 */
 288struct scif_mmu_notif {
 289#ifdef CONFIG_MMU_NOTIFIER
 290        struct mmu_notifier ep_mmu_notifier;
 291#endif
 292        struct list_head tc_reg_list;
 293        struct mm_struct *mm;
 294        struct scif_endpt *ep;
 295        struct list_head list;
 296};
 297
 298enum scif_rma_dir {
 299        SCIF_LOCAL_TO_REMOTE,
 300        SCIF_REMOTE_TO_LOCAL
 301};
 302
 303extern struct kmem_cache *unaligned_cache;
 304/* Initialize RMA for this EP */
 305void scif_rma_ep_init(struct scif_endpt *ep);
 306/* Check if epd can be uninitialized */
 307int scif_rma_ep_can_uninit(struct scif_endpt *ep);
 308/* Obtain a new offset. Callee must grab RMA lock */
 309int scif_get_window_offset(struct scif_endpt *ep, int flags,
 310                           s64 offset, int nr_pages, s64 *out_offset);
 311/* Free offset. Callee must grab RMA lock */
 312void scif_free_window_offset(struct scif_endpt *ep,
 313                             struct scif_window *window, s64 offset);
 314/* Create self registration window */
 315struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
 316                                       s64 offset, bool temp);
 317/* Destroy self registration window.*/
 318int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window);
 319void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window);
 320/* Map pages of self window to Aperture/PCI */
 321int scif_map_window(struct scif_dev *remote_dev,
 322                    struct scif_window *window);
 323/* Unregister a self window */
 324int scif_unregister_window(struct scif_window *window);
 325/* Destroy remote registration window */
 326void
 327scif_destroy_remote_window(struct scif_window *window);
 328/* remove valid remote memory mappings from process address space */
 329void scif_zap_mmaps(int node);
 330/* Query if any applications have remote memory mappings */
 331bool scif_rma_do_apps_have_mmaps(int node);
 332/* Cleanup remote registration lists for zombie endpoints */
 333void scif_cleanup_rma_for_zombies(int node);
 334/* Reserve a DMA channel for a particular endpoint */
 335int scif_reserve_dma_chan(struct scif_endpt *ep);
 336/* Setup a DMA mark for an endpoint */
 337int _scif_fence_mark(scif_epd_t epd, int *mark);
 338int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
 339                     enum scif_window_type type);
 340void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg);
 341void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg);
 342void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg);
 343void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg);
 344void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg);
 345void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
 346void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
 347void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
 348void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
 349void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg);
 350void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg);
 351void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 352void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg);
 353void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 354void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg);
 355void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg);
 356void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 357void scif_mmu_notif_handler(struct work_struct *work);
 358void scif_rma_handle_remote_fences(void);
 359void scif_rma_destroy_windows(void);
 360void scif_rma_destroy_tcw_invalid(void);
 361int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan);
 362
 363struct scif_window_iter {
 364        s64 offset;
 365        int index;
 366};
 367
 368static inline void
 369scif_init_window_iter(struct scif_window *window, struct scif_window_iter *iter)
 370{
 371        iter->offset = window->offset;
 372        iter->index = 0;
 373}
 374
 375dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
 376                                size_t *nr_bytes,
 377                                struct scif_window_iter *iter);
 378static inline
 379dma_addr_t __scif_off_to_dma_addr(struct scif_window *window, s64 off)
 380{
 381        return scif_off_to_dma_addr(window, off, NULL, NULL);
 382}
 383
 384static inline bool scif_unaligned(off_t src_offset, off_t dst_offset)
 385{
 386        src_offset = src_offset & (L1_CACHE_BYTES - 1);
 387        dst_offset = dst_offset & (L1_CACHE_BYTES - 1);
 388        return !(src_offset == dst_offset);
 389}
 390
 391/*
 392 * scif_zalloc:
 393 * @size: Size of the allocation request.
 394 *
 395 * Helper API which attempts to allocate zeroed pages via
 396 * __get_free_pages(..) first and then falls back on
 397 * vzalloc(..) if that fails.
 398 */
 399static inline void *scif_zalloc(size_t size)
 400{
 401        void *ret = NULL;
 402        size_t align = ALIGN(size, PAGE_SIZE);
 403
 404        if (align && get_order(align) < MAX_ORDER)
 405                ret = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 406                                               get_order(align));
 407        return ret ? ret : vzalloc(align);
 408}
 409
 410/*
 411 * scif_free:
 412 * @addr: Address to be freed.
 413 * @size: Size of the allocation.
 414 * Helper API which frees memory allocated via scif_zalloc().
 415 */
 416static inline void scif_free(void *addr, size_t size)
 417{
 418        size_t align = ALIGN(size, PAGE_SIZE);
 419
 420        if (is_vmalloc_addr(addr))
 421                vfree(addr);
 422        else
 423                free_pages((unsigned long)addr, get_order(align));
 424}
 425
 426static inline void scif_get_window(struct scif_window *window, int nr_pages)
 427{
 428        window->ref_count += nr_pages;
 429}
 430
 431static inline void scif_put_window(struct scif_window *window, int nr_pages)
 432{
 433        window->ref_count -= nr_pages;
 434}
 435
 436static inline void scif_set_window_ref(struct scif_window *window, int nr_pages)
 437{
 438        window->ref_count = nr_pages;
 439}
 440
 441static inline void
 442scif_queue_for_cleanup(struct scif_window *window, struct list_head *list)
 443{
 444        spin_lock(&scif_info.rmalock);
 445        list_add_tail(&window->list, list);
 446        spin_unlock(&scif_info.rmalock);
 447        schedule_work(&scif_info.misc_work);
 448}
 449
 450static inline void __scif_rma_destroy_tcw_helper(struct scif_window *window)
 451{
 452        list_del_init(&window->list);
 453        scif_queue_for_cleanup(window, &scif_info.rma_tc);
 454}
 455
 456static inline bool scif_is_iommu_enabled(void)
 457{
 458#ifdef CONFIG_INTEL_IOMMU
 459        return intel_iommu_enabled;
 460#else
 461        return false;
 462#endif
 463}
 464#endif /* SCIF_RMA_H */
 465