^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Intel(R) Trace Hub Memory Storage Unit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014-2015 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/set_memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/intel_th.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "intel_th.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "msu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define msc_dev(x) (&(x)->thdev->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * Lockout state transitions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * READY -> INUSE -+-> LOCKED -+-> READY -> etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * \-----------/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * WIN_READY: window can be used by HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * WIN_INUSE: window is in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * WIN_LOCKED: window is filled up and is being processed by the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * handling code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * All state transitions happen automatically, except for the LOCKED->READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * which needs to be signalled by the buffer code by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * intel_th_msc_window_unlock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * When the interrupt handler has to switch to the next window, it checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * whether it's READY, and if it is, it performs the switch and tracing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * continues. If it's LOCKED, it stops the trace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum lockout_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) WIN_READY = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) WIN_INUSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) WIN_LOCKED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * struct msc_window - multiblock mode window descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * @entry: window list linkage (msc::win_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @pgoff: page offset into the buffer that this window starts at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @lockout: lockout state, see comment below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @lo_lock: lockout state serialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @nr_blocks: number of blocks (pages) in this window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @nr_segs: number of segments in this window (<= @nr_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @_sgt: array of block descriptors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * @sgt: array of block descriptors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct msc_window {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct list_head entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned long pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) enum lockout_state lockout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) spinlock_t lo_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int nr_segs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct msc *msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct sg_table _sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct sg_table *sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * struct msc_iter - iterator for msc buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * @entry: msc::iter_list linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * @msc: pointer to the MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @start_win: oldest window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @win: current window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @offset: current logical offset into the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @start_block: oldest block in the window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @block: block number in the window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @block_off: offset into current block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @wrap_count: block wrapping handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @eof: end of buffer reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct msc_iter {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct list_head entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct msc *msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct msc_window *start_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct scatterlist *start_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct scatterlist *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned int block_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int wrap_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int eof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * struct msc - MSC device representation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @reg_base: register window base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @thdev: intel_th_device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @mbuf: MSU buffer, if assigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @mbuf_priv MSU buffer's private data, if @mbuf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @win_list: list of windows in multiblock mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @single_sgt: single mode buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @cur_win: current window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @nr_pages: total number of pages allocated for this buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @single_sz: amount of data in single mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @single_wrap: single mode wrap occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @base: buffer's base pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @base_addr: buffer's base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @user_count: number of users of the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @mmap_count: number of mappings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * @buf_mutex: mutex to serialize access to buffer-related bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @enabled: MSC is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @wrap: wrapping is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @mode: MSC operating mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @burst_len: write burst length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @index: number of this MSC in the MSU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct msc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) void __iomem *reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) void __iomem *msu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct intel_th_device *thdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const struct msu_buffer *mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) void *mbuf_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct list_head win_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct sg_table single_sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct msc_window *cur_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct msc_window *switch_on_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned long nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned long single_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int single_wrap : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) void *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dma_addr_t base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 orig_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 orig_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* <0: no buffer, 0: no users, >0: active users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) atomic_t user_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) atomic_t mmap_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct mutex buf_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct list_head iter_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bool stop_on_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned int enabled : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) wrap : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) do_irq : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) multi_is_broken : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int burst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static LIST_HEAD(msu_buffer_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static DEFINE_MUTEX(msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * struct msu_buffer_entry - internal MSU buffer bookkeeping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * @entry: link to msu_buffer_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @mbuf: MSU buffer object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @owner: module that provides this MSU buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct msu_buffer_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct list_head entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) const struct msu_buffer *mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct module *owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static struct msu_buffer_entry *__msu_buffer_entry_find(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct msu_buffer_entry *mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) lockdep_assert_held(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) list_for_each_entry(mbe, &msu_buffer_list, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!strcmp(mbe->mbuf->name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static const struct msu_buffer *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) msu_buffer_get(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct msu_buffer_entry *mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mutex_lock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) mbe = __msu_buffer_entry_find(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (mbe && !try_module_get(mbe->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mbe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mutex_unlock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return mbe ? mbe->mbuf : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void msu_buffer_put(const struct msu_buffer *mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct msu_buffer_entry *mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) mutex_lock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) mbe = __msu_buffer_entry_find(mbuf->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (mbe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) module_put(mbe->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) mutex_unlock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int intel_th_msu_buffer_register(const struct msu_buffer *mbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct module *owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct msu_buffer_entry *mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mbe = kzalloc(sizeof(*mbe), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!mbe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mutex_lock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (__msu_buffer_entry_find(mbuf->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) kfree(mbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mbe->mbuf = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mbe->owner = owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) list_add_tail(&mbe->entry, &msu_buffer_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) mutex_unlock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) EXPORT_SYMBOL_GPL(intel_th_msu_buffer_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) void intel_th_msu_buffer_unregister(const struct msu_buffer *mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct msu_buffer_entry *mbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) mutex_lock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mbe = __msu_buffer_entry_find(mbuf->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (mbe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) list_del(&mbe->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) kfree(mbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mutex_unlock(&msu_buffer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) EXPORT_SYMBOL_GPL(intel_th_msu_buffer_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static inline bool msc_block_is_empty(struct msc_block_desc *bdesc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* header hasn't been written */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (!bdesc->valid_dw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* valid_dw includes the header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!msc_data_sz(bdesc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static inline struct scatterlist *msc_win_base_sg(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return win->sgt->sgl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static inline struct msc_block_desc *msc_win_base(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return sg_virt(msc_win_base_sg(win));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static inline dma_addr_t msc_win_base_dma(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return sg_dma_address(msc_win_base_sg(win));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) msc_win_base_pfn(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return PFN_DOWN(msc_win_base_dma(win));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * msc_is_last_win() - check if a window is the last one for a given MSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @win: window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Return: true if @win is the last window in MSC's multiblock buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static inline bool msc_is_last_win(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return win->entry.next == &win->msc->win_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * msc_next_window() - return next window in the multiblock buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @win: current window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Return: window following the current one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static struct msc_window *msc_next_window(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (msc_is_last_win(win))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return list_first_entry(&win->msc->win_list, struct msc_window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return list_next_entry(win, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static size_t msc_win_total_sz(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) unsigned int blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) size_t size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct msc_block_desc *bdesc = sg_virt(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (msc_block_wrapped(bdesc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return (size_t)win->nr_blocks << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) size += msc_total_sz(bdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (msc_block_last_written(bdesc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * msc_find_window() - find a window matching a given sg_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * @sgt: SG table of the window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * @nonempty: skip over empty windows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * Return: MSC window structure pointer or NULL if the window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * could not be found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static struct msc_window *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) msc_find_window(struct msc *msc, struct sg_table *sgt, bool nonempty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) unsigned int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (list_empty(&msc->win_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * we might need a radix tree for this, depending on how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * many windows a typical user would allocate; ideally it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * something like 2, in which case we're good
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) list_for_each_entry(win, &msc->win_list, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (win->sgt == sgt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* skip the empty ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (nonempty && msc_block_is_empty(msc_win_base(win)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * msc_oldest_window() - locate the window with oldest data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * This should only be used in multiblock mode. Caller should hold the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * msc::user_count reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Return: the oldest window with valid data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static struct msc_window *msc_oldest_window(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (list_empty(&msc->win_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) win = msc_find_window(msc, msc_next_window(msc->cur_win)->sgt, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return list_first_entry(&msc->win_list, struct msc_window, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * msc_win_oldest_sg() - locate the oldest block in a given window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * @win: window to look at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * Return: index of the block with the oldest data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static struct scatterlist *msc_win_oldest_sg(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) unsigned int blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct msc_block_desc *bdesc = msc_win_base(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* without wrapping, first block is the oldest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!msc_block_wrapped(bdesc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return msc_win_base_sg(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * with wrapping, last written block contains both the newest and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * oldest data for this window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct msc_block_desc *bdesc = sg_virt(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (msc_block_last_written(bdesc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return msc_win_base_sg(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static struct msc_block_desc *msc_iter_bdesc(struct msc_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return sg_virt(iter->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static struct msc_iter *msc_iter_install(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct msc_iter *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) iter = kzalloc(sizeof(*iter), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * Reading and tracing are mutually exclusive; if msc is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * enabled, open() will fail; otherwise existing readers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * will prevent enabling the msc and the rest of fops don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * need to worry about it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (msc->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) kfree(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) iter = ERR_PTR(-EBUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) iter->msc = msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) list_add_tail(&iter->entry, &msc->iter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) list_del(&iter->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) kfree(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static void msc_iter_block_start(struct msc_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (iter->start_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) iter->start_block = msc_win_oldest_sg(iter->win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) iter->block = iter->start_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) iter->wrap_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * start with the block with oldest data; if data has wrapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * in this window, it should be in this block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (msc_block_wrapped(msc_iter_bdesc(iter)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) iter->wrap_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int msc_iter_win_start(struct msc_iter *iter, struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* already started, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (iter->start_win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) iter->start_win = msc_oldest_window(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!iter->start_win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) iter->win = iter->start_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) iter->start_block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) msc_iter_block_start(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int msc_iter_win_advance(struct msc_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) iter->win = msc_next_window(iter->win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) iter->start_block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (iter->win == iter->start_win) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) iter->eof++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) msc_iter_block_start(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int msc_iter_block_advance(struct msc_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) iter->block_off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* wrapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (iter->wrap_count && iter->block == iter->start_block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) iter->wrap_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!iter->wrap_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* copied newest data from the wrapped block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return msc_iter_win_advance(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* no wrapping, check for last written block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!iter->wrap_count && msc_block_last_written(msc_iter_bdesc(iter)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* copied newest data for the window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return msc_iter_win_advance(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* block advance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (sg_is_last(iter->block))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) iter->block = msc_win_base_sg(iter->win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) iter->block = sg_next(iter->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* no wrapping, sanity check in case there is no last written block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!iter->wrap_count && iter->block == iter->start_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return msc_iter_win_advance(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * msc_buffer_iterate() - go through multiblock buffer's data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * @iter: iterator structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * @size: amount of data to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * @data: callback's private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * @fn: iterator callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * This will start at the window which will be written to next (containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * the oldest data) and work its way to the current window, calling @fn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * for each chunk of data as it goes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * Caller should have msc::user_count reference to make sure the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * doesn't disappear from under us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * Return: amount of data actually scanned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) msc_buffer_iterate(struct msc_iter *iter, size_t size, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) unsigned long (*fn)(void *, void *, size_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) size_t len = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) unsigned int advance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (iter->eof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* start with the oldest window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (msc_iter_win_start(iter, msc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned long data_bytes = msc_data_sz(msc_iter_bdesc(iter));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) void *src = (void *)msc_iter_bdesc(iter) + MSC_BDESC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) size_t tocopy = data_bytes, copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) size_t remaining = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) advance = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * If block wrapping happened, we need to visit the last block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * twice, because it contains both the oldest and the newest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * data in this window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * First time (wrap_count==2), in the very beginning, to collect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * the oldest data, which is in the range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * (data_bytes..DATA_IN_PAGE).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * Second time (wrap_count==1), it's just like any other block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * containing data in the range of [MSC_BDESC..data_bytes].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (iter->block == iter->start_block && iter->wrap_count == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) tocopy = DATA_IN_PAGE - data_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) src += data_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!tocopy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) goto next_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) tocopy -= iter->block_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) src += iter->block_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (len < tocopy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) tocopy = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) advance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) remaining = fn(data, src, tocopy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) advance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) copied = tocopy - remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) len -= copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) iter->block_off += copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) iter->offset += copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!advance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) next_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (msc_iter_block_advance(iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) } while (len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return size - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * msc_buffer_clear_hw_header() - clear hw header for multiblock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static void msc_buffer_clear_hw_header(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) list_for_each_entry(win, &msc->win_list, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) unsigned int blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) size_t hw_sz = sizeof(struct msc_block_desc) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) offsetof(struct msc_block_desc, hw_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct msc_block_desc *bdesc = sg_virt(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) memset(&bdesc->hw_tag, 0, hw_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int intel_th_msu_init(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) u32 mintctl, msusts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!msc->do_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (!msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mintctl = ioread32(msc->msu_base + REG_MSU_MINTCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mintctl |= msc->index ? M1BLIE : M0BLIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) iowrite32(mintctl, msc->msu_base + REG_MSU_MINTCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (mintctl != ioread32(msc->msu_base + REG_MSU_MINTCTL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) dev_info(msc_dev(msc), "MINTCTL ignores writes: no usable interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) msc->do_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) msusts = ioread32(msc->msu_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) iowrite32(msusts, msc->msu_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static void intel_th_msu_deinit(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) u32 mintctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (!msc->do_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) mintctl = ioread32(msc->msu_base + REG_MSU_MINTCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mintctl &= msc->index ? ~M1BLIE : ~M0BLIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) iowrite32(mintctl, msc->msu_base + REG_MSU_MINTCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int msc_win_set_lockout(struct msc_window *win,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) enum lockout_state expect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) enum lockout_state new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) enum lockout_state old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!win->msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_lock_irqsave(&win->lo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) old = win->lockout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (old != expect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) win->lockout = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (old == expect && new == WIN_LOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) atomic_inc(&win->msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) else if (old == expect && old == WIN_LOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) atomic_dec(&win->msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) spin_unlock_irqrestore(&win->lo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (expect == WIN_READY && old == WIN_LOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* from intel_th_msc_window_unlock(), don't warn if not locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (expect == WIN_LOCKED && old == new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dev_warn_ratelimited(msc_dev(win->msc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) "expected lockout state %d, got %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) expect, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * msc_configure() - set up MSC hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * @msc: the MSC device to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * Program storage mode, wrapping, burst length and trace buffer address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * into a given MSC. Then, enable tracing and set msc::enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * The latter is serialized on msc::buf_mutex, so make sure to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static int msc_configure(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) lockdep_assert_held(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (msc->mode > MSC_MODE_MULTI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (msc->mode == MSC_MODE_MULTI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (msc_win_set_lockout(msc->cur_win, WIN_READY, WIN_INUSE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) msc_buffer_clear_hw_header(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) msc->orig_addr = ioread32(msc->reg_base + REG_MSU_MSC0BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) msc->orig_sz = ioread32(msc->reg_base + REG_MSU_MSC0SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) reg = msc->base_addr >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) iowrite32(reg, msc->reg_base + REG_MSU_MSC0BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (msc->mode == MSC_MODE_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) reg = msc->nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) iowrite32(reg, msc->reg_base + REG_MSU_MSC0SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) reg |= MSC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) reg |= msc->mode << __ffs(MSC_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) reg |= msc->burst_len << __ffs(MSC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (msc->wrap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) reg |= MSC_WRAPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) intel_th_msu_init(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) intel_th_trace_enable(msc->thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) msc->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (msc->mbuf && msc->mbuf->activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) msc->mbuf->activate(msc->mbuf_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * msc_disable() - disable MSC hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * @msc: MSC device to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * If @msc is enabled, disable tracing on the switch and then disable MSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * storage. Caller must hold msc::buf_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static void msc_disable(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct msc_window *win = msc->cur_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) lockdep_assert_held(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (msc->mode == MSC_MODE_MULTI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) msc_win_set_lockout(win, WIN_INUSE, WIN_LOCKED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (msc->mbuf && msc->mbuf->deactivate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) msc->mbuf->deactivate(msc->mbuf_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) intel_th_msu_deinit(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) intel_th_trace_disable(msc->thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (msc->mode == MSC_MODE_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) reg = ioread32(msc->reg_base + REG_MSU_MSC0STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) msc->single_wrap = !!(reg & MSCSTS_WRAPSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) reg = ioread32(msc->reg_base + REG_MSU_MSC0MWP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) msc->single_sz = reg & ((msc->nr_pages << PAGE_SHIFT) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) dev_dbg(msc_dev(msc), "MSCnMWP: %08x/%08lx, wrap: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) reg, msc->single_sz, msc->single_wrap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) reg &= ~MSC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (msc->mbuf && msc->mbuf->ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) msc->mbuf->ready(msc->mbuf_priv, win->sgt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) msc_win_total_sz(win));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) msc->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) iowrite32(msc->orig_addr, msc->reg_base + REG_MSU_MSC0BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) iowrite32(msc->orig_sz, msc->reg_base + REG_MSU_MSC0SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) dev_dbg(msc_dev(msc), "MSCnNWSA: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ioread32(msc->reg_base + REG_MSU_MSC0NWSA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) reg = ioread32(msc->reg_base + REG_MSU_MSC0STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dev_dbg(msc_dev(msc), "MSCnSTS: %08x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) reg = ioread32(msc->reg_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) reg &= msc->index ? MSUSTS_MSC1BLAST : MSUSTS_MSC0BLAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) iowrite32(reg, msc->reg_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static int intel_th_msc_activate(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (!atomic_inc_unless_negative(&msc->user_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /* if there are readers, refuse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (list_empty(&msc->iter_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ret = msc_configure(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) atomic_dec(&msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static void intel_th_msc_deactivate(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (msc->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) msc_disable(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) atomic_dec(&msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * msc_buffer_contig_alloc() - allocate a contiguous buffer for SINGLE mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * @size: allocation size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) * This modifies msc::base, which requires msc::buf_mutex to serialize, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * Return: 0 on success, -errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static int msc_buffer_contig_alloc(struct msc *msc, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) unsigned long nr_pages = size >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) unsigned int order = get_order(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ret = sg_alloc_table(&msc->single_sgt, 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) page = alloc_pages(GFP_KERNEL | __GFP_ZERO | GFP_DMA32, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) goto err_free_sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) split_page(page, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) sg_set_buf(msc->single_sgt.sgl, page_address(page), size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ret = dma_map_sg(msc_dev(msc)->parent->parent, msc->single_sgt.sgl, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) goto err_free_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) msc->nr_pages = nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) msc->base = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) msc->base_addr = sg_dma_address(msc->single_sgt.sgl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) err_free_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) __free_pages(page, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) err_free_sgt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) sg_free_table(&msc->single_sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * msc_buffer_contig_free() - free a contiguous buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * @msc: MSC configured in SINGLE mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static void msc_buffer_contig_free(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unsigned long off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) dma_unmap_sg(msc_dev(msc)->parent->parent, msc->single_sgt.sgl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) 1, DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) sg_free_table(&msc->single_sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct page *page = virt_to_page(msc->base + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) page->mapping = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) __free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) msc->nr_pages = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * msc_buffer_contig_get_page() - find a page at a given offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * @msc: MSC configured in SINGLE mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * @pgoff: page offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * Return: page, if @pgoff is within the range, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static struct page *msc_buffer_contig_get_page(struct msc *msc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) unsigned long pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (pgoff >= msc->nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return virt_to_page(msc->base + (pgoff << PAGE_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static int __msc_buffer_win_alloc(struct msc_window *win,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) unsigned int nr_segs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct scatterlist *sg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) void *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ret = sg_alloc_table(win->sgt, nr_segs, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) for_each_sg(win->sgt->sgl, sg_ptr, nr_segs, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) block = dma_alloc_coherent(msc_dev(win->msc)->parent->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) PAGE_SIZE, &sg_dma_address(sg_ptr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (!block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) goto err_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) sg_set_buf(sg_ptr, block, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return nr_segs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) err_nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) for_each_sg(win->sgt->sgl, sg_ptr, i, ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) sg_virt(sg_ptr), sg_dma_address(sg_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) sg_free_table(win->sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static void msc_buffer_set_uc(struct msc_window *win, unsigned int nr_segs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct scatterlist *sg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) for_each_sg(win->sgt->sgl, sg_ptr, nr_segs, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* Set the page as uncached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) set_memory_uc((unsigned long)sg_virt(sg_ptr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) PFN_DOWN(sg_ptr->length));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void msc_buffer_set_wb(struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct scatterlist *sg_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for_each_sg(win->sgt->sgl, sg_ptr, win->nr_segs, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /* Reset the page to write-back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) set_memory_wb((unsigned long)sg_virt(sg_ptr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) PFN_DOWN(sg_ptr->length));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) #else /* !X86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) msc_buffer_set_uc(struct msc_window *win, unsigned int nr_segs) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) static inline void msc_buffer_set_wb(struct msc_window *win) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) #endif /* CONFIG_X86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * msc_buffer_win_alloc() - alloc a window for a multiblock mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * @nr_blocks: number of pages in this window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * to serialize, so the caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * Return: 0 on success, -errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (!nr_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) win = kzalloc(sizeof(*win), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (!win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) win->msc = msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) win->sgt = &win->_sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) win->lockout = WIN_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) spin_lock_init(&win->lo_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (!list_empty(&msc->win_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct msc_window *prev = list_last_entry(&msc->win_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct msc_window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) win->pgoff = prev->pgoff + prev->nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (msc->mbuf && msc->mbuf->alloc_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) ret = msc->mbuf->alloc_window(msc->mbuf_priv, &win->sgt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) nr_blocks << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) ret = __msc_buffer_win_alloc(win, nr_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) goto err_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) msc_buffer_set_uc(win, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) win->nr_segs = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) win->nr_blocks = nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (list_empty(&msc->win_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) msc->base = msc_win_base(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) msc->base_addr = msc_win_base_dma(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) msc->cur_win = win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) list_add_tail(&win->entry, &msc->win_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) msc->nr_pages += nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) err_nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) kfree(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct page *page = sg_page(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) page->mapping = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sg_virt(sg), sg_dma_address(sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) sg_free_table(win->sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) * msc_buffer_win_free() - free a window from MSC's window list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * @win: window to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * to serialize, so the caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static void msc_buffer_win_free(struct msc *msc, struct msc_window *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) msc->nr_pages -= win->nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) list_del(&win->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (list_empty(&msc->win_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) msc->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) msc->base_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) msc_buffer_set_wb(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (msc->mbuf && msc->mbuf->free_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) msc->mbuf->free_window(msc->mbuf_priv, win->sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) __msc_buffer_win_free(msc, win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) kfree(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * msc_buffer_relink() - set up block descriptors for multiblock mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * This traverses msc::win_list, which requires msc::buf_mutex to serialize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * so the caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) static void msc_buffer_relink(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct msc_window *win, *next_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) /* call with msc::mutex locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) list_for_each_entry(win, &msc->win_list, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) unsigned int blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) u32 sw_tag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * Last window's next_win should point to the first window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) * and MSC_SW_TAG_LASTWIN should be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (msc_is_last_win(win)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) sw_tag |= MSC_SW_TAG_LASTWIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) next_win = list_first_entry(&msc->win_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) struct msc_window, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) next_win = list_next_entry(win, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct msc_block_desc *bdesc = sg_virt(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) memset(bdesc, 0, sizeof(*bdesc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) bdesc->next_win = msc_win_base_pfn(next_win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * Similarly to last window, last block should point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * to the first one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (blk == win->nr_segs - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) sw_tag |= MSC_SW_TAG_LASTBLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) bdesc->next_blk = msc_win_base_pfn(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) dma_addr_t addr = sg_dma_address(sg_next(sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) bdesc->next_blk = PFN_DOWN(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) bdesc->sw_tag = sw_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) bdesc->block_sz = sg->length / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * Make the above writes globally visible before tracing is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * enabled to make sure hardware sees them coherently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) static void msc_buffer_multi_free(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct msc_window *win, *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) list_for_each_entry_safe(win, iter, &msc->win_list, entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) msc_buffer_win_free(msc, win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static int msc_buffer_multi_alloc(struct msc *msc, unsigned long *nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) unsigned int nr_wins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) for (i = 0; i < nr_wins; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) ret = msc_buffer_win_alloc(msc, nr_pages[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) msc_buffer_multi_free(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) msc_buffer_relink(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * msc_buffer_free() - free buffers for MSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * Free MSC's storage buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * This modifies msc::win_list and msc::base, which requires msc::buf_mutex to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * serialize, so the caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static void msc_buffer_free(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (msc->mode == MSC_MODE_SINGLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) msc_buffer_contig_free(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) else if (msc->mode == MSC_MODE_MULTI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) msc_buffer_multi_free(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * msc_buffer_alloc() - allocate a buffer for MSC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * @size: allocation size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * Allocate a storage buffer for MSC, depending on the msc::mode, it will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * either done via msc_buffer_contig_alloc() for SINGLE operation mode or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * msc_buffer_win_alloc() for multiblock operation. The latter allocates one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * window per invocation, so in multiblock mode this can be called multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * times for the same MSC to allocate multiple windows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * This modifies msc::win_list and msc::base, which requires msc::buf_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * to serialize, so the caller is expected to hold it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * Return: 0 on success, -errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) static int msc_buffer_alloc(struct msc *msc, unsigned long *nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) unsigned int nr_wins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* -1: buffer not allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (atomic_read(&msc->user_count) != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (msc->mode == MSC_MODE_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (nr_wins != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ret = msc_buffer_contig_alloc(msc, nr_pages[0] << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) } else if (msc->mode == MSC_MODE_MULTI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) /* allocation should be visible before the counter goes to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) smp_mb__before_atomic();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (WARN_ON_ONCE(atomic_cmpxchg(&msc->user_count, -1, 0) != -1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * msc_buffer_unlocked_free_unless_used() - free a buffer unless it's in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * This will free MSC buffer unless it is in use or there is no allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) * Caller needs to hold msc::buf_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * Return: 0 on successful deallocation or if there was no buffer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * deallocate, -EBUSY if there are active users.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) static int msc_buffer_unlocked_free_unless_used(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) int count, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) count = atomic_cmpxchg(&msc->user_count, 0, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /* > 0: buffer is allocated and has users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (count > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) /* 0: buffer is allocated, no users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) else if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) msc_buffer_free(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) /* < 0: no buffer, nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * msc_buffer_free_unless_used() - free a buffer unless it's in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) * This is a locked version of msc_buffer_unlocked_free_unless_used().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) static int msc_buffer_free_unless_used(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ret = msc_buffer_unlocked_free_unless_used(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * msc_buffer_get_page() - get MSC buffer page at a given offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * @msc: MSC device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * @pgoff: page offset into the storage buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) * This traverses msc::win_list, so holding msc::buf_mutex is expected from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * Return: page if @pgoff corresponds to a valid buffer page or NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) static struct page *msc_buffer_get_page(struct msc *msc, unsigned long pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) unsigned int blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (msc->mode == MSC_MODE_SINGLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return msc_buffer_contig_get_page(msc, pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) list_for_each_entry(win, &msc->win_list, entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (pgoff >= win->pgoff && pgoff < win->pgoff + win->nr_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) pgoff -= win->pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct page *page = sg_page(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) size_t pgsz = PFN_DOWN(sg->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (pgoff < pgsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return page + pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) pgoff -= pgsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) * struct msc_win_to_user_struct - data for copy_to_user() callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) * @buf: userspace buffer to copy data to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * @offset: running offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) struct msc_win_to_user_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) char __user *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * msc_win_to_user() - iterator for msc_buffer_iterate() to copy data to user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * @data: callback's private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * @src: source buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * @len: amount of data to copy from the source buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) static unsigned long msc_win_to_user(void *data, void *src, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) struct msc_win_to_user_struct *u = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) unsigned long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) ret = copy_to_user(u->buf + u->offset, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) u->offset += len - ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * file operations' callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) static int intel_th_msc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) struct intel_th_device *thdev = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct msc_iter *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) iter = msc_iter_install(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (IS_ERR(iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return PTR_ERR(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) file->private_data = iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) return nonseekable_open(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) static int intel_th_msc_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) struct msc_iter *iter = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) msc_iter_remove(iter, msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) msc_single_to_user(struct msc *msc, char __user *buf, loff_t off, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) unsigned long size = msc->nr_pages << PAGE_SHIFT, rem = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) unsigned long start = off, tocopy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (msc->single_wrap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) start += msc->single_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (start < size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) tocopy = min(rem, size - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (copy_to_user(buf, msc->base + start, tocopy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) buf += tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) rem -= tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) start += tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) start &= size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) tocopy = min(rem, msc->single_sz - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (copy_to_user(buf, msc->base + start, tocopy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) rem -= tocopy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return len - rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (copy_to_user(buf, msc->base + start, rem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) size_t len, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) struct msc_iter *iter = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) loff_t off = *ppos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (!atomic_inc_unless_negative(&msc->user_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) size = msc->single_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) size = msc->nr_pages << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) goto put_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (off >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) goto put_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) if (off + len >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) len = size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (msc->mode == MSC_MODE_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) ret = msc_single_to_user(msc, buf, off, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) *ppos += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) } else if (msc->mode == MSC_MODE_MULTI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct msc_win_to_user_struct u = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) ret = msc_buffer_iterate(iter, len, &u, msc_win_to_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) *ppos = iter->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) put_count:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) atomic_dec(&msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * vm operations callbacks (vm_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) static void msc_mmap_open(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct msc_iter *iter = vma->vm_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) atomic_inc(&msc->mmap_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) static void msc_mmap_close(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) struct msc_iter *iter = vma->vm_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) unsigned long pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) /* drop page _refcounts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) for (pg = 0; pg < msc->nr_pages; pg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) struct page *page = msc_buffer_get_page(msc, pg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (WARN_ON_ONCE(!page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) if (page->mapping)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) page->mapping = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* last mapping -- drop user_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) atomic_dec(&msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) static vm_fault_t msc_mmap_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) struct msc_iter *iter = vmf->vma->vm_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) vmf->page = msc_buffer_get_page(msc, vmf->pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) if (!vmf->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) get_page(vmf->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) vmf->page->mapping = vmf->vma->vm_file->f_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) vmf->page->index = vmf->pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) static const struct vm_operations_struct msc_mmap_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .open = msc_mmap_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) .close = msc_mmap_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) .fault = msc_mmap_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) static int intel_th_msc_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) unsigned long size = vma->vm_end - vma->vm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) struct msc_iter *iter = vma->vm_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) struct msc *msc = iter->msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (!size || offset_in_page(size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) if (vma->vm_pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /* grab user_count once per mmap; drop in msc_mmap_close() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (!atomic_inc_unless_negative(&msc->user_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (msc->mode != MSC_MODE_SINGLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) msc->mode != MSC_MODE_MULTI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) if (size >> PAGE_SHIFT != msc->nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) atomic_set(&msc->mmap_count, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) atomic_dec(&msc->user_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) vma->vm_flags |= VM_DONTEXPAND | VM_DONTCOPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) vma->vm_ops = &msc_mmap_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) static const struct file_operations intel_th_msc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) .open = intel_th_msc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) .release = intel_th_msc_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) .read = intel_th_msc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) .mmap = intel_th_msc_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) static void intel_th_msc_wait_empty(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) unsigned long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) for (reg = 0, count = MSC_PLE_WAITLOOP_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) count && !(reg & MSCSTS_PLE); count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) reg = __raw_readl(msc->reg_base + REG_MSU_MSC0STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) dev_dbg(msc_dev(msc), "timeout waiting for MSC0 PLE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) static int intel_th_msc_init(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) atomic_set(&msc->user_count, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) msc->mode = msc->multi_is_broken ? MSC_MODE_SINGLE : MSC_MODE_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) mutex_init(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) INIT_LIST_HEAD(&msc->win_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) INIT_LIST_HEAD(&msc->iter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) msc->burst_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) (ioread32(msc->reg_base + REG_MSU_MSC0CTL) & MSC_LEN) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) __ffs(MSC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) static int msc_win_switch(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct msc_window *first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (list_empty(&msc->win_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) first = list_first_entry(&msc->win_list, struct msc_window, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (msc_is_last_win(msc->cur_win))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) msc->cur_win = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) msc->cur_win = list_next_entry(msc->cur_win, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) msc->base = msc_win_base(msc->cur_win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) msc->base_addr = msc_win_base_dma(msc->cur_win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) intel_th_trace_switch(msc->thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * intel_th_msc_window_unlock - put the window back in rotation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * @dev: MSC device to which this relates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * @sgt: buffer's sg_table for the window, does nothing if NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (!sgt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) win = msc_find_window(msc, sgt, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (!win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) msc_win_set_lockout(win, WIN_LOCKED, WIN_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (msc->switch_on_unlock == win) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) msc->switch_on_unlock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) msc_win_switch(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) EXPORT_SYMBOL_GPL(intel_th_msc_window_unlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) static void msc_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) struct msc *msc = container_of(work, struct msc, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) intel_th_msc_deactivate(msc->thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) static irqreturn_t intel_th_msc_interrupt(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) u32 msusts = ioread32(msc->msu_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) u32 mask = msc->index ? MSUSTS_MSC1BLAST : MSUSTS_MSC0BLAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) struct msc_window *win, *next_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (!msc->do_irq || !msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) msusts &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!msusts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) return msc->enabled ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) iowrite32(msusts, msc->msu_base + REG_MSU_MSUSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) if (!msc->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) /* grab the window before we do the switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) win = msc->cur_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if (!win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) next_win = msc_next_window(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (!next_win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) /* next window: if READY, proceed, if LOCKED, stop the trace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (msc_win_set_lockout(next_win, WIN_READY, WIN_INUSE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (msc->stop_on_full)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) schedule_work(&msc->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) msc->switch_on_unlock = next_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) /* current window: INUSE -> LOCKED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) msc_win_set_lockout(win, WIN_INUSE, WIN_LOCKED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) msc_win_switch(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (msc->mbuf && msc->mbuf->ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) msc->mbuf->ready(msc->mbuf_priv, win->sgt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) msc_win_total_sz(win));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) static const char * const msc_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) [MSC_MODE_SINGLE] = "single",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) [MSC_MODE_MULTI] = "multi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) [MSC_MODE_EXI] = "ExI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) [MSC_MODE_DEBUG] = "debug",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) wrap_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) return scnprintf(buf, PAGE_SIZE, "%d\n", msc->wrap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) wrap_store(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) ret = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) msc->wrap = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) static DEVICE_ATTR_RW(wrap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) static void msc_buffer_unassign(struct msc *msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) lockdep_assert_held(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) if (!msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) msc->mbuf->unassign(msc->mbuf_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) msu_buffer_put(msc->mbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) msc->mbuf_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) msc->mbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) mode_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) const char *mode = msc_mode[msc->mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) mode = msc->mbuf->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) ret = scnprintf(buf, PAGE_SIZE, "%s\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) mode_store(struct device *dev, struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) const struct msu_buffer *mbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) size_t len = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) char *cp, *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) cp = memchr(buf, '\n', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) len = cp - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) mode = kstrndup(buf, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) i = match_string(msc_mode, ARRAY_SIZE(msc_mode), mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) kfree(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) /* Buffer sinks only work with a usable IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) if (!msc->do_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) kfree(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) mbuf = msu_buffer_get(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) kfree(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) if (mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) if (i == MSC_MODE_MULTI && msc->multi_is_broken)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /* Same buffer: do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) if (mbuf && mbuf == msc->mbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) /* put the extra reference we just got */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) msu_buffer_put(mbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) ret = msc_buffer_unlocked_free_unless_used(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (mbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) void *mbuf_priv = mbuf->assign(dev, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (!mbuf_priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) msc_buffer_unassign(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) msc->mbuf_priv = mbuf_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) msc->mbuf = mbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) msc_buffer_unassign(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) msc->mode = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) if (ret && mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) msu_buffer_put(mbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) return ret ? ret : size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) static DEVICE_ATTR_RW(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) nr_pages_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) struct msc_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) size_t count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) if (msc->mode == MSC_MODE_SINGLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) count = scnprintf(buf, PAGE_SIZE, "%ld\n", msc->nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) else if (msc->mode == MSC_MODE_MULTI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) list_for_each_entry(win, &msc->win_list, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) count += scnprintf(buf + count, PAGE_SIZE - count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) "%d%c", win->nr_blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) msc_is_last_win(win) ? '\n' : ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) count = scnprintf(buf, PAGE_SIZE, "unsupported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) nr_pages_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) unsigned long val, *win = NULL, *rewin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) size_t len = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) const char *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) char *end, *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) int ret, nr_wins = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) ret = msc_buffer_free_unless_used(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) /* scan the comma-separated list of allocation sizes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) end = memchr(buf, '\n', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) len = end - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) end = memchr(p, ',', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) s = kstrndup(p, end ? end - p : len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) if (!s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) goto free_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) ret = kstrtoul(s, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) kfree(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) if (ret || !val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) goto free_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (nr_wins && msc->mode == MSC_MODE_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) goto free_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) nr_wins++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) rewin = krealloc(win, sizeof(*win) * nr_wins, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) if (!rewin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) kfree(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) win = rewin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) win[nr_wins - 1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) if (!end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) /* consume the number and the following comma, hence +1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) len -= end - p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) p = end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) } while (len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) ret = msc_buffer_alloc(msc, win, nr_wins);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) free_win:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) kfree(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) return ret ? ret : size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) static DEVICE_ATTR_RW(nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) win_switch_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) ret = kstrtoul(buf, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) if (val != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) mutex_lock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) * Window switch can only happen in the "multi" mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) * If a external buffer is engaged, they have the full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) * control over window switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) if (msc->mode == MSC_MODE_MULTI && !msc->mbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) ret = msc_win_switch(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) mutex_unlock(&msc->buf_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) return ret ? ret : size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) static DEVICE_ATTR_WO(win_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) static ssize_t stop_on_full_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) return sprintf(buf, "%d\n", msc->stop_on_full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) static ssize_t stop_on_full_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) struct msc *msc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) ret = kstrtobool(buf, &msc->stop_on_full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) static DEVICE_ATTR_RW(stop_on_full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) static struct attribute *msc_output_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) &dev_attr_wrap.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) &dev_attr_mode.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) &dev_attr_nr_pages.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) &dev_attr_win_switch.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) &dev_attr_stop_on_full.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) static struct attribute_group msc_output_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) .attrs = msc_output_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) static int intel_th_msc_probe(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) struct device *dev = &thdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) struct msc *msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) base = devm_ioremap(dev, res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) msc = devm_kzalloc(dev, sizeof(*msc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) if (!msc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) res = intel_th_device_get_resource(thdev, IORESOURCE_IRQ, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) msc->do_irq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) if (INTEL_TH_CAP(to_intel_th(thdev), multi_is_broken))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) msc->multi_is_broken = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) msc->index = thdev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) msc->thdev = thdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) msc->reg_base = base + msc->index * 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) msc->msu_base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) INIT_WORK(&msc->work, msc_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) err = intel_th_msc_init(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) dev_set_drvdata(dev, msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) static void intel_th_msc_remove(struct intel_th_device *thdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) struct msc *msc = dev_get_drvdata(&thdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) intel_th_msc_deactivate(thdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) * Buffers should not be used at this point except if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) * output character device is still open and the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) * device gets detached from its bus, which is a FIXME.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) ret = msc_buffer_free_unless_used(msc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) WARN_ON_ONCE(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) static struct intel_th_driver intel_th_msc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) .probe = intel_th_msc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) .remove = intel_th_msc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) .irq = intel_th_msc_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) .wait_empty = intel_th_msc_wait_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) .activate = intel_th_msc_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) .deactivate = intel_th_msc_deactivate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) .fops = &intel_th_msc_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) .attr_group = &msc_output_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) .name = "msc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) module_driver(intel_th_msc_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) intel_th_driver_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) intel_th_driver_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) MODULE_DESCRIPTION("Intel(R) Trace Hub Memory Storage Unit driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");