Initial commit of files contained in `mpss-modules-3.8.6.tar.bz2` for Intel Xeon...
[xeon-phi-kernel-module] / include / mic / micscif_map.h
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36#ifndef MICSCIF_MAP_H
37#define MICSCIF_MAP_H
38
39static __always_inline
40void *get_local_va(off_t off, struct reg_range_t *window, size_t len)
41{
42 struct page **pages = window->pinned_pages->pages;
43
44 uint64_t page_nr = ((off - window->offset) >> PAGE_SHIFT);
45
46 off_t page_off = off & ~PAGE_MASK;
47
48 return (void *)((uint64_t)
49 (page_address(pages[page_nr])) | page_off);
50}
51
52static __always_inline void
53scif_iounmap(void *virt, size_t len, struct micscif_dev *dev)
54{
55#ifdef _MIC_SCIF_
56 if (!is_self_scifdev(dev))
57 iounmap(virt);
58#endif
59}
60
61#ifdef _MIC_SCIF_
62/* FIXME: fix the documentation and functions names since these are also
63 * used in p2p
64 */
65/*
66 * Maps the VA passed in local to the aperture and returns the
67 * corresponding GTT index in offset by reference.
68 * In the loopback case simply return the physical address.
69 */
70static __always_inline int
71map_virt_into_aperture(phys_addr_t *out_offset,
72 void *local,
73 struct micscif_dev *dev,
74 size_t size)
75{
76 if (is_self_scifdev(dev))
77 *out_offset = virt_to_phys(local);
78 else {
79 /* Error unwinding code relies on return value being zero */
80 *out_offset = virt_to_phys(local);
81 if (dev != &scif_dev[0])
82 *out_offset = *out_offset + dev->sd_base_addr;
83 }
84
85 return 0;
86}
87
88/*
89 * Maps the struct page passed in page to the aperture and returns the
90 * corresponding GTT index in offset by reference.
91 * In the loopback case simply return the physical address.
92 */
93static __always_inline int
94map_page_into_aperture(phys_addr_t *out_offset,
95 struct page *page,
96 struct micscif_dev *dev)
97{
98 if (is_self_scifdev(dev))
99 *out_offset = page_to_phys(page);
100 else {
101 /* Error unwinding code relies on return value being zero */
102 *out_offset = page_to_phys(page);
103 if (dev != &scif_dev[0])
104 *out_offset = *out_offset + dev->sd_base_addr;
105 }
106 return 0;
107}
108
109/*
110 * Nothing to do on card side
111 */
112static __always_inline void
113unmap_from_aperture(phys_addr_t local,
114 struct micscif_dev *dev,
115 size_t size)
116{
117}
118
119/*
120 * Maps Host physical address passed in phys to MIC.
121 * In the loopback case simply return the VA from the PA.
122 */
123static __always_inline void *
124scif_ioremap(phys_addr_t phys, size_t size, struct micscif_dev *dev)
125{
126 void *out_virt;
127
128 if (is_self_scifdev(dev))
129 out_virt = phys_to_virt(phys);
130 else
131 out_virt = ioremap_nocache(phys, size);
132
133 return out_virt;
134}
135
136/*
137 * Get the system physical address from the physical address passed
138 * by the host. In the case of loopback simply return the physical
139 * address.
140 */
141static __always_inline phys_addr_t
142get_phys_addr(phys_addr_t phys, struct micscif_dev *dev)
143{
144 return phys;
145}
146
147#else /* !_MIC_SCIF_ */
148/*
149 * Maps the VA passed in local to the aperture and returns the
150 * corresponding physical address in offset.
151 * In the loopback case simply return the physical address.
152 */
153static __always_inline int
154map_virt_into_aperture(phys_addr_t *out_offset,
155 void *local,
156 struct micscif_dev *dev,
157 size_t size)
158{
159 int err = 0;
160 int bid;
161 struct pci_dev *hwdev;
162
163 if (is_self_scifdev(dev))
164 *(out_offset) = virt_to_phys((local));
165 else {
166
167 bid = dev->sd_node - 1;
168 hwdev = get_per_dev_ctx(bid)->bi_pdev;
169 *out_offset = mic_map_single(bid, hwdev, local, size);
170 if (mic_map_error(*out_offset))
171 err = -ENOMEM;
172 }
173
174 if (err)
175 *out_offset = 0;
176
177 return err;
178}
179/*
180 * Maps the struct page passed in page to the aperture and returns the
181 * corresponding physical address in offset.
182 * In the loopback case simply return the physical address.
183 */
184static __always_inline int
185map_page_into_aperture(phys_addr_t *out_offset,
186 struct page *page,
187 struct micscif_dev *dev)
188{
189 int err = 0;
190 int bid;
191 dma_addr_t mic_addr;
192 struct pci_dev *hwdev;
193
194 if (is_self_scifdev(dev))
195 *out_offset = page_to_phys(page);
196 else {
197
198 bid = dev->sd_node - 1;
199 hwdev = get_per_dev_ctx(bid)->bi_pdev;
200
201 *out_offset = pci_map_page(hwdev, page, 0x0, PAGE_SIZE,
202 PCI_DMA_BIDIRECTIONAL);
203 if (pci_dma_mapping_error(hwdev, *out_offset)) {
204 err = -EINVAL;
205 } else {
206 if (!(mic_addr = mic_map(bid, *out_offset, PAGE_SIZE))) {
207 printk(KERN_ERR "mic_map failed board id %d\
208 addr %#016llx size %#016zx\n",
209 bid, *out_offset, PAGE_SIZE);
210 pci_unmap_single(hwdev, *out_offset,
211 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
212 err = -EINVAL;
213 } else
214 *out_offset = mic_addr;
215 }
216 }
217
218 if (err)
219 *out_offset = 0;
220
221 return err;
222}
223
224/*
225 * Unmaps the physical address passed in lo/al from the PCIe aperture.
226 * Nothing to do in the loopback case.
227 */
228static __always_inline void
229unmap_from_aperture(phys_addr_t local,
230 struct micscif_dev *dev,
231 size_t size)
232{
233
234 if (!is_self_scifdev(dev))
235 mic_ctx_unmap_single(get_per_dev_ctx(dev->sd_node - 1),
236 local, size);
237}
238
239/*
240 * TODO: I'm thinking maybe we should take the apt_phys offset off of this macro
241 * and have it be outside ...
242 * Maps the page corresponding to the GTT offset passed in phys.
243 * In the loopback case simply return the VA from the PA.
244 */
245static __always_inline void *
246scif_ioremap(phys_addr_t phys, size_t size, struct micscif_dev *dev)
247{
248 void *out_virt;
249
250 if (is_self_scifdev(dev))
251 out_virt = phys_to_virt(phys);
252 else {
253 out_virt = get_per_dev_ctx(dev->sd_node - 1)->aper.va + phys;
254 }
255 return out_virt;
256}
257
258static __always_inline phys_addr_t
259get_phys_addr(phys_addr_t phys, struct micscif_dev *dev)
260{
261 phys_addr_t out_phys;
262
263 if (is_self_scifdev(dev))
264 out_phys = phys;
265 else {
266 phys_addr_t __apt_base =
267 (phys_addr_t)get_per_dev_ctx(dev->sd_node - 1)->aper.pa;
268 out_phys = phys + __apt_base;
269 }
270
271 return out_phys;
272}
273
274#endif /* !_MIC_SCIF_ */
275
276#endif /* MICSCIF_MAP_H */