Commit | Line | Data |
---|---|---|
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 | ||
39 | static __always_inline | |
40 | void *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 | ||
52 | static __always_inline void | |
53 | scif_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 | */ | |
70 | static __always_inline int | |
71 | map_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 | */ | |
93 | static __always_inline int | |
94 | map_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 | */ | |
112 | static __always_inline void | |
113 | unmap_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 | */ | |
123 | static __always_inline void * | |
124 | scif_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 | */ | |
141 | static __always_inline phys_addr_t | |
142 | get_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 | */ | |
153 | static __always_inline int | |
154 | map_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 | */ | |
184 | static __always_inline int | |
185 | map_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 | */ | |
228 | static __always_inline void | |
229 | unmap_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 | */ | |
245 | static __always_inline void * | |
246 | scif_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 | ||
258 | static __always_inline phys_addr_t | |
259 | get_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 */ |