]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.46/intel_th-msu-fix-single-mode-with-iommu.patch
Linux 4.19.46
[thirdparty/kernel/stable-queue.git] / releases / 4.19.46 / intel_th-msu-fix-single-mode-with-iommu.patch
1 From 4e0eaf239fb33ebc671303e2b736fa043462e2f4 Mon Sep 17 00:00:00 2001
2 From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
3 Date: Fri, 3 May 2019 11:44:34 +0300
4 Subject: intel_th: msu: Fix single mode with IOMMU
5
6 From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
7
8 commit 4e0eaf239fb33ebc671303e2b736fa043462e2f4 upstream.
9
10 Currently, the pages that are allocated for the single mode of MSC are not
11 mapped into the device's dma space and the code is incorrectly using
12 *_to_phys() in place of a dma address. This fails with IOMMU enabled and
13 is otherwise bad practice.
14
15 Fix the single mode buffer allocation to map the pages into the device's
16 DMA space.
17
18 Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
19 Fixes: ba82664c134e ("intel_th: Add Memory Storage Unit driver")
20 Cc: stable@vger.kernel.org # v4.4+
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23 ---
24 drivers/hwtracing/intel_th/msu.c | 35 ++++++++++++++++++++++++++++++++---
25 1 file changed, 32 insertions(+), 3 deletions(-)
26
27 --- a/drivers/hwtracing/intel_th/msu.c
28 +++ b/drivers/hwtracing/intel_th/msu.c
29 @@ -84,6 +84,7 @@ struct msc_iter {
30 * @reg_base: register window base address
31 * @thdev: intel_th_device pointer
32 * @win_list: list of windows in multiblock mode
33 + * @single_sgt: single mode buffer
34 * @nr_pages: total number of pages allocated for this buffer
35 * @single_sz: amount of data in single mode
36 * @single_wrap: single mode wrap occurred
37 @@ -104,6 +105,7 @@ struct msc {
38 struct intel_th_device *thdev;
39
40 struct list_head win_list;
41 + struct sg_table single_sgt;
42 unsigned long nr_pages;
43 unsigned long single_sz;
44 unsigned int single_wrap : 1;
45 @@ -617,22 +619,45 @@ static void intel_th_msc_deactivate(stru
46 */
47 static int msc_buffer_contig_alloc(struct msc *msc, unsigned long size)
48 {
49 + unsigned long nr_pages = size >> PAGE_SHIFT;
50 unsigned int order = get_order(size);
51 struct page *page;
52 + int ret;
53
54 if (!size)
55 return 0;
56
57 + ret = sg_alloc_table(&msc->single_sgt, 1, GFP_KERNEL);
58 + if (ret)
59 + goto err_out;
60 +
61 + ret = -ENOMEM;
62 page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
63 if (!page)
64 - return -ENOMEM;
65 + goto err_free_sgt;
66
67 split_page(page, order);
68 - msc->nr_pages = size >> PAGE_SHIFT;
69 + sg_set_buf(msc->single_sgt.sgl, page_address(page), size);
70 +
71 + ret = dma_map_sg(msc_dev(msc)->parent->parent, msc->single_sgt.sgl, 1,
72 + DMA_FROM_DEVICE);
73 + if (ret < 0)
74 + goto err_free_pages;
75 +
76 + msc->nr_pages = nr_pages;
77 msc->base = page_address(page);
78 - msc->base_addr = page_to_phys(page);
79 + msc->base_addr = sg_dma_address(msc->single_sgt.sgl);
80
81 return 0;
82 +
83 +err_free_pages:
84 + __free_pages(page, order);
85 +
86 +err_free_sgt:
87 + sg_free_table(&msc->single_sgt);
88 +
89 +err_out:
90 + return ret;
91 }
92
93 /**
94 @@ -643,6 +668,10 @@ static void msc_buffer_contig_free(struc
95 {
96 unsigned long off;
97
98 + dma_unmap_sg(msc_dev(msc)->parent->parent, msc->single_sgt.sgl,
99 + 1, DMA_FROM_DEVICE);
100 + sg_free_table(&msc->single_sgt);
101 +
102 for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) {
103 struct page *page = virt_to_page(msc->base + off);
104