• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Intel MIC Platform Software Stack (MPSS)
4  *
5  * Copyright(c) 2013 Intel Corporation.
6  *
7  * Intel MIC Host driver.
8  */
9 #include <linux/pci.h>
10 
11 #include "../common/mic_dev.h"
12 #include "mic_device.h"
13 #include "mic_smpt.h"
14 
mic_system_page_mask(struct mic_device * mdev)15 static inline u64 mic_system_page_mask(struct mic_device *mdev)
16 {
17 	return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
18 }
19 
mic_sys_addr_to_smpt(struct mic_device * mdev,dma_addr_t pa)20 static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
21 {
22 	return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
23 }
24 
mic_smpt_to_pa(struct mic_device * mdev,u8 index)25 static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
26 {
27 	return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
28 }
29 
mic_smpt_offset(struct mic_device * mdev,dma_addr_t pa)30 static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
31 {
32 	return pa & mic_system_page_mask(mdev);
33 }
34 
mic_smpt_align_low(struct mic_device * mdev,dma_addr_t pa)35 static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
36 {
37 	return ALIGN(pa - mic_system_page_mask(mdev),
38 		mdev->smpt->info.page_size);
39 }
40 
mic_smpt_align_high(struct mic_device * mdev,dma_addr_t pa)41 static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
42 {
43 	return ALIGN(pa, mdev->smpt->info.page_size);
44 }
45 
46 /* Total Cumulative system memory accessible by MIC across all SMPT entries */
mic_max_system_memory(struct mic_device * mdev)47 static inline u64 mic_max_system_memory(struct mic_device *mdev)
48 {
49 	return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
50 }
51 
52 /* Maximum system memory address accessible by MIC */
mic_max_system_addr(struct mic_device * mdev)53 static inline u64 mic_max_system_addr(struct mic_device *mdev)
54 {
55 	return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
56 }
57 
58 /* Check if the DMA address is a MIC system memory address */
59 static inline bool
mic_is_system_addr(struct mic_device * mdev,dma_addr_t pa)60 mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
61 {
62 	return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
63 }
64 
65 /* Populate an SMPT entry and update the reference counts. */
mic_add_smpt_entry(int spt,s64 * ref,u64 addr,int entries,struct mic_device * mdev)66 static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
67 			       int entries, struct mic_device *mdev)
68 {
69 	struct mic_smpt_info *smpt_info = mdev->smpt;
70 	int i;
71 
72 	for (i = spt; i < spt + entries; i++,
73 		addr += smpt_info->info.page_size) {
74 		if (!smpt_info->entry[i].ref_count &&
75 		    (smpt_info->entry[i].dma_addr != addr)) {
76 			mdev->smpt_ops->set(mdev, addr, i);
77 			smpt_info->entry[i].dma_addr = addr;
78 		}
79 		smpt_info->entry[i].ref_count += ref[i - spt];
80 	}
81 }
82 
83 /*
84  * Find an available MIC address in MIC SMPT address space
85  * for a given DMA address and size.
86  */
mic_smpt_op(struct mic_device * mdev,u64 dma_addr,int entries,s64 * ref,size_t size)87 static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
88 			      int entries, s64 *ref, size_t size)
89 {
90 	int spt;
91 	int ae = 0;
92 	int i;
93 	unsigned long flags;
94 	dma_addr_t mic_addr = 0;
95 	dma_addr_t addr = dma_addr;
96 	struct mic_smpt_info *smpt_info = mdev->smpt;
97 
98 	spin_lock_irqsave(&smpt_info->smpt_lock, flags);
99 
100 	/* find existing entries */
101 	for (i = 0; i < smpt_info->info.num_reg; i++) {
102 		if (smpt_info->entry[i].dma_addr == addr) {
103 			ae++;
104 			addr += smpt_info->info.page_size;
105 		} else if (ae) /* cannot find contiguous entries */
106 			goto not_found;
107 
108 		if (ae == entries)
109 			goto found;
110 	}
111 
112 	/* find free entry */
113 	for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
114 		ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
115 		if (ae == entries)
116 			goto found;
117 	}
118 
119 not_found:
120 	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
121 	return mic_addr;
122 
123 found:
124 	spt = i - entries + 1;
125 	mic_addr = mic_smpt_to_pa(mdev, spt);
126 	mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
127 	smpt_info->map_count++;
128 	smpt_info->ref_count += (s64)size;
129 	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
130 	return mic_addr;
131 }
132 
133 /*
134  * Returns number of smpt entries needed for dma_addr to dma_addr + size
135  * also returns the reference count array for each of those entries
136  * and the starting smpt address
137  */
mic_get_smpt_ref_count(struct mic_device * mdev,dma_addr_t dma_addr,size_t size,s64 * ref,u64 * smpt_start)138 static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
139 				  size_t size, s64 *ref,  u64 *smpt_start)
140 {
141 	u64 start =  dma_addr;
142 	u64 end = dma_addr + size;
143 	int i = 0;
144 
145 	while (start < end) {
146 		ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
147 			end) - start;
148 		start = mic_smpt_align_high(mdev, start + 1);
149 	}
150 
151 	if (smpt_start)
152 		*smpt_start = mic_smpt_align_low(mdev, dma_addr);
153 
154 	return i;
155 }
156 
157 /*
158  * mic_to_dma_addr - Converts a MIC address to a DMA address.
159  *
160  * @mdev: pointer to mic_device instance.
161  * @mic_addr: MIC address.
162  *
163  * returns a DMA address.
164  */
mic_to_dma_addr(struct mic_device * mdev,dma_addr_t mic_addr)165 dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
166 {
167 	struct mic_smpt_info *smpt_info = mdev->smpt;
168 	int spt;
169 	dma_addr_t dma_addr;
170 
171 	if (!mic_is_system_addr(mdev, mic_addr)) {
172 		dev_err(&mdev->pdev->dev,
173 			"mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
174 		return -EINVAL;
175 	}
176 	spt = mic_sys_addr_to_smpt(mdev, mic_addr);
177 	dma_addr = smpt_info->entry[spt].dma_addr +
178 		mic_smpt_offset(mdev, mic_addr);
179 	return dma_addr;
180 }
181 
182 /**
183  * mic_map - Maps a DMA address to a MIC physical address.
184  *
185  * @mdev: pointer to mic_device instance.
186  * @dma_addr: DMA address.
187  * @size: Size of the region to be mapped.
188  *
189  * This API converts the DMA address provided to a DMA address understood
190  * by MIC. Caller should check for errors by calling mic_map_error(..).
191  *
192  * returns DMA address as required by MIC.
193  */
mic_map(struct mic_device * mdev,dma_addr_t dma_addr,size_t size)194 dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
195 {
196 	dma_addr_t mic_addr = 0;
197 	int num_entries;
198 	s64 *ref;
199 	u64 smpt_start;
200 
201 	if (!size || size > mic_max_system_memory(mdev))
202 		return mic_addr;
203 
204 	ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
205 	if (!ref)
206 		return mic_addr;
207 
208 	num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
209 					     ref, &smpt_start);
210 
211 	/* Set the smpt table appropriately and get 16G aligned mic address */
212 	mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
213 
214 	kfree(ref);
215 
216 	/*
217 	 * If mic_addr is zero then its an error case
218 	 * since mic_addr can never be zero.
219 	 * else generate mic_addr by adding the 16G offset in dma_addr
220 	 */
221 	if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
222 		dev_err(&mdev->pdev->dev,
223 			"mic_map failed dma_addr 0x%llx size 0x%lx\n",
224 			dma_addr, size);
225 		return mic_addr;
226 	} else {
227 		return mic_addr + mic_smpt_offset(mdev, dma_addr);
228 	}
229 }
230 
231 /**
232  * mic_unmap - Unmaps a MIC physical address.
233  *
234  * @mdev: pointer to mic_device instance.
235  * @mic_addr: MIC physical address.
236  * @size: Size of the region to be unmapped.
237  *
238  * This API unmaps the mappings created by mic_map(..).
239  *
240  * returns None.
241  */
mic_unmap(struct mic_device * mdev,dma_addr_t mic_addr,size_t size)242 void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
243 {
244 	struct mic_smpt_info *smpt_info = mdev->smpt;
245 	s64 *ref;
246 	int num_smpt;
247 	int spt;
248 	int i;
249 	unsigned long flags;
250 
251 	if (!size)
252 		return;
253 
254 	if (!mic_is_system_addr(mdev, mic_addr)) {
255 		dev_err(&mdev->pdev->dev,
256 			"invalid address: 0x%llx\n", mic_addr);
257 		return;
258 	}
259 
260 	spt = mic_sys_addr_to_smpt(mdev, mic_addr);
261 	ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
262 	if (!ref)
263 		return;
264 
265 	/* Get number of smpt entries to be mapped, ref count array */
266 	num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
267 
268 	spin_lock_irqsave(&smpt_info->smpt_lock, flags);
269 	smpt_info->unmap_count++;
270 	smpt_info->ref_count -= (s64)size;
271 
272 	for (i = spt; i < spt + num_smpt; i++) {
273 		smpt_info->entry[i].ref_count -= ref[i - spt];
274 		if (smpt_info->entry[i].ref_count < 0)
275 			dev_warn(&mdev->pdev->dev,
276 				 "ref count for entry %d is negative\n", i);
277 	}
278 	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
279 	kfree(ref);
280 }
281 
282 /**
283  * mic_map_single - Maps a virtual address to a MIC physical address.
284  *
285  * @mdev: pointer to mic_device instance.
286  * @va: Kernel direct mapped virtual address.
287  * @size: Size of the region to be mapped.
288  *
289  * This API calls pci_map_single(..) for the direct mapped virtual address
290  * and then converts the DMA address provided to a DMA address understood
291  * by MIC. Caller should check for errors by calling mic_map_error(..).
292  *
293  * returns DMA address as required by MIC.
294  */
mic_map_single(struct mic_device * mdev,void * va,size_t size)295 dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
296 {
297 	dma_addr_t mic_addr = 0;
298 	struct pci_dev *pdev = mdev->pdev;
299 	dma_addr_t dma_addr =
300 		pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
301 
302 	if (!pci_dma_mapping_error(pdev, dma_addr)) {
303 		mic_addr = mic_map(mdev, dma_addr, size);
304 		if (!mic_addr) {
305 			dev_err(&mdev->pdev->dev,
306 				"mic_map failed dma_addr 0x%llx size 0x%lx\n",
307 				dma_addr, size);
308 			pci_unmap_single(pdev, dma_addr,
309 					 size, PCI_DMA_BIDIRECTIONAL);
310 		}
311 	}
312 	return mic_addr;
313 }
314 
315 /**
316  * mic_unmap_single - Unmaps a MIC physical address.
317  *
318  * @mdev: pointer to mic_device instance.
319  * @mic_addr: MIC physical address.
320  * @size: Size of the region to be unmapped.
321  *
322  * This API unmaps the mappings created by mic_map_single(..).
323  *
324  * returns None.
325  */
326 void
mic_unmap_single(struct mic_device * mdev,dma_addr_t mic_addr,size_t size)327 mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
328 {
329 	struct pci_dev *pdev = mdev->pdev;
330 	dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
331 	mic_unmap(mdev, mic_addr, size);
332 	pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
333 }
334 
335 /**
336  * mic_smpt_init - Initialize MIC System Memory Page Tables.
337  *
338  * @mdev: pointer to mic_device instance.
339  *
340  * returns 0 for success and -errno for error.
341  */
mic_smpt_init(struct mic_device * mdev)342 int mic_smpt_init(struct mic_device *mdev)
343 {
344 	int i, err = 0;
345 	dma_addr_t dma_addr;
346 	struct mic_smpt_info *smpt_info;
347 
348 	mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
349 	if (!mdev->smpt)
350 		return -ENOMEM;
351 
352 	smpt_info = mdev->smpt;
353 	mdev->smpt_ops->init(mdev);
354 	smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
355 					 sizeof(*smpt_info->entry), GFP_KERNEL);
356 	if (!smpt_info->entry) {
357 		err = -ENOMEM;
358 		goto free_smpt;
359 	}
360 	spin_lock_init(&smpt_info->smpt_lock);
361 	for (i = 0; i < smpt_info->info.num_reg; i++) {
362 		dma_addr = i * smpt_info->info.page_size;
363 		smpt_info->entry[i].dma_addr = dma_addr;
364 		smpt_info->entry[i].ref_count = 0;
365 		mdev->smpt_ops->set(mdev, dma_addr, i);
366 	}
367 	smpt_info->ref_count = 0;
368 	smpt_info->map_count = 0;
369 	smpt_info->unmap_count = 0;
370 	return 0;
371 free_smpt:
372 	kfree(smpt_info);
373 	return err;
374 }
375 
376 /**
377  * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
378  *
379  * @mdev: pointer to mic_device instance.
380  *
381  * returns None.
382  */
mic_smpt_uninit(struct mic_device * mdev)383 void mic_smpt_uninit(struct mic_device *mdev)
384 {
385 	struct mic_smpt_info *smpt_info = mdev->smpt;
386 	int i;
387 
388 	dev_dbg(&mdev->pdev->dev,
389 		"nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
390 		mdev->id, smpt_info->ref_count,
391 		smpt_info->map_count, smpt_info->unmap_count);
392 
393 	for (i = 0; i < smpt_info->info.num_reg; i++) {
394 		dev_dbg(&mdev->pdev->dev,
395 			"SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
396 			i, smpt_info->entry[i].dma_addr,
397 			smpt_info->entry[i].ref_count);
398 		if (smpt_info->entry[i].ref_count)
399 			dev_warn(&mdev->pdev->dev,
400 				 "ref count for entry %d is not zero\n", i);
401 	}
402 	kfree(smpt_info->entry);
403 	kfree(smpt_info);
404 }
405 
406 /**
407  * mic_smpt_restore - Restore MIC System Memory Page Tables.
408  *
409  * @mdev: pointer to mic_device instance.
410  *
411  * Restore the SMPT registers to values previously stored in the
412  * SW data structures. Some MIC steppings lose register state
413  * across resets and this API should be called for performing
414  * a restore operation if required.
415  *
416  * returns None.
417  */
mic_smpt_restore(struct mic_device * mdev)418 void mic_smpt_restore(struct mic_device *mdev)
419 {
420 	int i;
421 	dma_addr_t dma_addr;
422 
423 	for (i = 0; i < mdev->smpt->info.num_reg; i++) {
424 		dma_addr = mdev->smpt->entry[i].dma_addr;
425 		mdev->smpt_ops->set(mdev, dma_addr, i);
426 	}
427 }
428