hc
2023-08-30 862c27fc9920c83318c784bfdadf43a65df1ec8f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
 *
 * author:
 *    Alpha Lin, alpha.lin@rock-chips.com
 *    Randy Li, randy.li@rock-chips.com
 *    Ding Wei, leo.ding@rock-chips.com
 *
 */
#ifndef __ROCKCHIP_MPP_IOMMU_H__
#define __ROCKCHIP_MPP_IOMMU_H__
 
#include <linux/iommu.h>
#include <linux/dma-mapping.h>
 
struct mpp_dma_buffer {
   /* link to dma session buffer list */
   struct list_head link;
 
   /* dma session belong */
   struct mpp_dma_session *dma;
   /* DMABUF information */
   struct dma_buf *dmabuf;
   struct dma_buf_attachment *attach;
   struct sg_table *sgt;
   struct sg_table *copy_sgt;
   enum dma_data_direction dir;
 
   dma_addr_t iova;
   unsigned long size;
   void *vaddr;
 
   struct kref ref;
   ktime_t last_used;
   /* alloc by device */
   struct device *dev;
};
 
#define MPP_SESSION_MAX_BUFFERS        60
 
struct mpp_dma_session {
   /* the buffer used in session */
   struct list_head unused_list;
   struct list_head used_list;
   struct mpp_dma_buffer dma_bufs[MPP_SESSION_MAX_BUFFERS];
   /* the mutex for the above buffer list */
   struct mutex list_mutex;
   /* the max buffer num for the buffer list */
   u32 max_buffers;
   /* the count for the buffer list */
   int buffer_count;
 
   struct device *dev;
};
 
struct mpp_rk_iommu {
   struct list_head link;
   u32 grf_val;
   int mmu_num;
   u32 base_addr[2];
   void __iomem *bases[2];
   u32 dte_addr;
   u32 is_paged;
};
 
struct mpp_iommu_info {
   struct rw_semaphore rw_sem;
 
   struct device *dev;
   struct platform_device *pdev;
   struct iommu_domain *domain;
   struct iommu_group *group;
   struct mpp_rk_iommu *iommu;
   iommu_fault_handler_t hdl;
};
 
struct mpp_dma_session *
mpp_dma_session_create(struct device *dev, u32 max_buffers);
int mpp_dma_session_destroy(struct mpp_dma_session *dma);
 
struct mpp_dma_buffer *
mpp_dma_alloc(struct device *dev, size_t size);
int mpp_dma_free(struct mpp_dma_buffer *buffer);
 
struct mpp_dma_buffer *
mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
         struct mpp_dma_session *dma, int fd);
int mpp_dma_release(struct mpp_dma_session *dma,
           struct mpp_dma_buffer *buffer);
int mpp_dma_release_fd(struct mpp_dma_session *dma, int fd);
 
int mpp_dma_unmap_kernel(struct mpp_dma_session *dma,
            struct mpp_dma_buffer *buffer);
int mpp_dma_map_kernel(struct mpp_dma_session *dma,
              struct mpp_dma_buffer *buffer);
 
struct mpp_iommu_info *
mpp_iommu_probe(struct device *dev);
int mpp_iommu_remove(struct mpp_iommu_info *info);
 
int mpp_iommu_attach(struct mpp_iommu_info *info);
int mpp_iommu_detach(struct mpp_iommu_info *info);
 
int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev);
int mpp_iommu_flush_tlb(struct mpp_iommu_info *info);
 
static inline int mpp_iommu_down_read(struct mpp_iommu_info *info)
{
   if (info)
       down_read(&info->rw_sem);
 
   return 0;
}
 
static inline int mpp_iommu_up_read(struct mpp_iommu_info *info)
{
   if (info)
       up_read(&info->rw_sem);
 
   return 0;
}
 
static inline int mpp_iommu_down_write(struct mpp_iommu_info *info)
{
   if (info)
       down_write(&info->rw_sem);
 
   return 0;
}
 
static inline int mpp_iommu_up_write(struct mpp_iommu_info *info)
{
   if (info)
       up_write(&info->rw_sem);
 
   return 0;
}
 
#endif