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/intel-iommu.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_cb_arg - Stores the argument of the callback func
 210 *
 211 * @src_dma_addr: Source buffer DMA address
 212 * @status: DMA status
 213 * @ep: SCIF endpoint
 214 */
 215struct scif_cb_arg {
 216        dma_addr_t src_dma_addr;
 217        struct scif_status *status;
 218        struct scif_endpt *ep;
 219};
 220
 221/*
 222 * struct scif_window - Registration Window for Self and Remote
 223 *
 224 * @nr_pages: Number of pages which is defined as a s64 instead of an int
 225 * to avoid sign extension with buffers >= 2GB
 226 * @nr_contig_chunks: Number of contiguous physical chunks
 227 * @prot: read/write protections
 228 * @ref_count: reference count in terms of number of pages
 229 * @magic: Cookie to detect corruption
 230 * @offset: registered offset
 231 * @va_for_temp: va address that this window represents
 232 * @dma_mark: Used to determine if all DMAs against the window are done
 233 * @ep: Pointer to EP. Useful for passing EP around with messages to
 234        avoid expensive list traversals.
 235 * @list: link to list of windows for the endpoint
 236 * @type: self or peer window
 237 * @peer_window: Pointer to peer window. Useful for sending messages to peer
 238 *               without requiring an extra list traversal
 239 * @unreg_state: unregistration state
 240 * @offset_freed: True if the offset has been freed
 241 * @temp: True for temporary windows created via scif_vreadfrom/scif_vwriteto
 242 * @mm: memory descriptor for the task_struct which initiated the RMA
 243 * @st: scatter gather table for DMA mappings with IOMMU enabled
 244 * @pinned_pages: The set of pinned_pages backing this window
 245 * @alloc_handle: Handle for sending ALLOC_REQ
 246 * @regwq: Wait Queue for an registration (N)ACK
 247 * @reg_state: Registration state
 248 * @unregwq: Wait Queue for an unregistration (N)ACK
 249 * @dma_addr_lookup: Lookup for physical addresses used for DMA
 250 * @nr_lookup: Number of entries in lookup
 251 * @mapped_offset: Offset used to map the window by the peer
 252 * @dma_addr: Array of physical addresses used for Mgmt node & MIC initiated DMA
 253 * @num_pages: Array specifying number of pages for each physical address
 254 */
 255struct scif_window {
 256        s64 nr_pages;
 257        int nr_contig_chunks;
 258        int prot;
 259        int ref_count;
 260        u64 magic;
 261        s64 offset;
 262        unsigned long va_for_temp;
 263        int dma_mark;
 264        u64 ep;
 265        struct list_head list;
 266        enum scif_window_type type;
 267        u64 peer_window;
 268        enum scif_msg_state unreg_state;
 269        bool offset_freed;
 270        bool temp;
 271        struct mm_struct *mm;
 272        struct sg_table *st;
 273        union {
 274                struct {
 275                        struct scif_pinned_pages *pinned_pages;
 276                        struct scif_allocmsg alloc_handle;
 277                        wait_queue_head_t regwq;
 278                        enum scif_msg_state reg_state;
 279                        wait_queue_head_t unregwq;
 280                };
 281                struct {
 282                        struct scif_rma_lookup dma_addr_lookup;
 283                        struct scif_rma_lookup num_pages_lookup;
 284                        int nr_lookup;
 285                        dma_addr_t mapped_offset;
 286                };
 287        };
 288        dma_addr_t *dma_addr;
 289        u64 *num_pages;
 290} __packed;
 291
 292/*
 293 * scif_mmu_notif - SCIF mmu notifier information
 294 *
 295 * @mmu_notifier ep_mmu_notifier: MMU notifier operations
 296 * @tc_reg_list: List of temp registration windows for self
 297 * @mm: memory descriptor for the task_struct which initiated the RMA
 298 * @ep: SCIF endpoint
 299 * @list: link to list of MMU notifier information
 300 */
 301struct scif_mmu_notif {
 302#ifdef CONFIG_MMU_NOTIFIER
 303        struct mmu_notifier ep_mmu_notifier;
 304#endif
 305        struct list_head tc_reg_list;
 306        struct mm_struct *mm;
 307        struct scif_endpt *ep;
 308        struct list_head list;
 309};
 310
 311enum scif_rma_dir {
 312        SCIF_LOCAL_TO_REMOTE,
 313        SCIF_REMOTE_TO_LOCAL
 314};
 315
 316extern struct kmem_cache *unaligned_cache;
 317/* Initialize RMA for this EP */
 318void scif_rma_ep_init(struct scif_endpt *ep);
 319/* Check if epd can be uninitialized */
 320int scif_rma_ep_can_uninit(struct scif_endpt *ep);
 321/* Obtain a new offset. Callee must grab RMA lock */
 322int scif_get_window_offset(struct scif_endpt *ep, int flags,
 323                           s64 offset, int nr_pages, s64 *out_offset);
 324/* Free offset. Callee must grab RMA lock */
 325void scif_free_window_offset(struct scif_endpt *ep,
 326                             struct scif_window *window, s64 offset);
 327/* Create self registration window */
 328struct scif_window *scif_create_window(struct scif_endpt *ep, int nr_pages,
 329                                       s64 offset, bool temp);
 330/* Destroy self registration window.*/
 331int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window);
 332void scif_unmap_window(struct scif_dev *remote_dev, struct scif_window *window);
 333/* Map pages of self window to Aperture/PCI */
 334int scif_map_window(struct scif_dev *remote_dev,
 335                    struct scif_window *window);
 336/* Unregister a self window */
 337int scif_unregister_window(struct scif_window *window);
 338/* Destroy remote registration window */
 339void
 340scif_destroy_remote_window(struct scif_window *window);
 341/* remove valid remote memory mappings from process address space */
 342void scif_zap_mmaps(int node);
 343/* Query if any applications have remote memory mappings */
 344bool scif_rma_do_apps_have_mmaps(int node);
 345/* Cleanup remote registration lists for zombie endpoints */
 346void scif_cleanup_rma_for_zombies(int node);
 347/* Reserve a DMA channel for a particular endpoint */
 348int scif_reserve_dma_chan(struct scif_endpt *ep);
 349/* Setup a DMA mark for an endpoint */
 350int _scif_fence_mark(scif_epd_t epd, int *mark);
 351int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
 352                     enum scif_window_type type);
 353void scif_alloc_req(struct scif_dev *scifdev, struct scifmsg *msg);
 354void scif_alloc_gnt_rej(struct scif_dev *scifdev, struct scifmsg *msg);
 355void scif_free_virt(struct scif_dev *scifdev, struct scifmsg *msg);
 356void scif_recv_reg(struct scif_dev *scifdev, struct scifmsg *msg);
 357void scif_recv_unreg(struct scif_dev *scifdev, struct scifmsg *msg);
 358void scif_recv_reg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
 359void scif_recv_reg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
 360void scif_recv_unreg_ack(struct scif_dev *scifdev, struct scifmsg *msg);
 361void scif_recv_unreg_nack(struct scif_dev *scifdev, struct scifmsg *msg);
 362void scif_recv_munmap(struct scif_dev *scifdev, struct scifmsg *msg);
 363void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg);
 364void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 365void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg);
 366void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 367void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg);
 368void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg);
 369void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg);
 370void scif_mmu_notif_handler(struct work_struct *work);
 371void scif_rma_handle_remote_fences(void);
 372void scif_rma_destroy_windows(void);
 373void scif_rma_destroy_tcw_invalid(void);
 374int scif_drain_dma_intr(struct scif_hw_dev *sdev, struct dma_chan *chan);
 375
 376struct scif_window_iter {
 377        s64 offset;
 378        int index;
 379};
 380
 381static inline void
 382scif_init_window_iter(struct scif_window *window, struct scif_window_iter *iter)
 383{
 384        iter->offset = window->offset;
 385        iter->index = 0;
 386}
 387
 388dma_addr_t scif_off_to_dma_addr(struct scif_window *window, s64 off,
 389                                size_t *nr_bytes,
 390                                struct scif_window_iter *iter);
 391static inline
 392dma_addr_t __scif_off_to_dma_addr(struct scif_window *window, s64 off)
 393{
 394        return scif_off_to_dma_addr(window, off, NULL, NULL);
 395}
 396
 397static inline bool scif_unaligned(off_t src_offset, off_t dst_offset)
 398{
 399        src_offset = src_offset & (L1_CACHE_BYTES - 1);
 400        dst_offset = dst_offset & (L1_CACHE_BYTES - 1);
 401        return !(src_offset == dst_offset);
 402}
 403
 404/*
 405 * scif_zalloc:
 406 * @size: Size of the allocation request.
 407 *
 408 * Helper API which attempts to allocate zeroed pages via
 409 * __get_free_pages(..) first and then falls back on
 410 * vzalloc(..) if that fails.
 411 */
 412static inline void *scif_zalloc(size_t size)
 413{
 414        void *ret = NULL;
 415        size_t align = ALIGN(size, PAGE_SIZE);
 416
 417        if (align && get_order(align) < MAX_ORDER)
 418                ret = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 419                                               get_order(align));
 420        return ret ? ret : vzalloc(align);
 421}
 422
 423/*
 424 * scif_free:
 425 * @addr: Address to be freed.
 426 * @size: Size of the allocation.
 427 * Helper API which frees memory allocated via scif_zalloc().
 428 */
 429static inline void scif_free(void *addr, size_t size)
 430{
 431        size_t align = ALIGN(size, PAGE_SIZE);
 432
 433        if (is_vmalloc_addr(addr))
 434                vfree(addr);
 435        else
 436                free_pages((unsigned long)addr, get_order(align));
 437}
 438
 439static inline void scif_get_window(struct scif_window *window, int nr_pages)
 440{
 441        window->ref_count += nr_pages;
 442}
 443
 444static inline void scif_put_window(struct scif_window *window, int nr_pages)
 445{
 446        window->ref_count -= nr_pages;
 447}
 448
 449static inline void scif_set_window_ref(struct scif_window *window, int nr_pages)
 450{
 451        window->ref_count = nr_pages;
 452}
 453
 454static inline void
 455scif_queue_for_cleanup(struct scif_window *window, struct list_head *list)
 456{
 457        spin_lock(&scif_info.rmalock);
 458        list_add_tail(&window->list, list);
 459        spin_unlock(&scif_info.rmalock);
 460        schedule_work(&scif_info.misc_work);
 461}
 462
 463static inline void __scif_rma_destroy_tcw_helper(struct scif_window *window)
 464{
 465        list_del_init(&window->list);
 466        scif_queue_for_cleanup(window, &scif_info.rma_tc);
 467}
 468
 469static inline bool scif_is_iommu_enabled(void)
 470{
 471#ifdef CONFIG_INTEL_IOMMU
 472        return intel_iommu_enabled;
 473#else
 474        return false;
 475#endif
 476}
 477#endif /* SCIF_RMA_H */
 478