--- v1
+++ v4
@@ -17,21 +17,35 @@
Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
---
- include/linux/swiotlb.h | 6 ++++
- kernel/dma/swiotlb.c | 75 ++++++++++++++++++++++++++++++++++++-----
- 2 files changed, 73 insertions(+), 8 deletions(-)
+Change since v3:
+ * Fix boot up failure on the host with mem_encrypt=on.
+ Move calloing of set_memory_decrypted() back from
+ swiotlb_init_io_tlb_mem to swiotlb_late_init_with_tbl()
+ and rmem_swiotlb_device_init().
+
+Change since v2:
+ * Leave mem->vaddr with phys_to_virt(mem->start) when fail
+ to remap swiotlb memory.
+
+Change since v1:
+ * Rework comment in the swiotlb_init_io_tlb_mem()
+ * Make swiotlb_init_io_tlb_mem() back to return void.
+---
+ include/linux/swiotlb.h | 6 ++++++
+ kernel/dma/swiotlb.c | 43 +++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
-index 569272871375..09a140d617fa 100644
+index 569272871375..f6c3638255d5 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -73,6 +73,9 @@ extern enum swiotlb_force swiotlb_force;
* @end: The end address of the swiotlb memory pool. Used to do a quick
* range check to see if the memory was in fact allocated by this
* API.
-+ * @vaddr: The vaddr of the swiotlb memory pool. The swiotlb
-+ * memory pool may be remapped in the memory encrypted case and store
-+ * virtual address for bounce buffer operation.
++ * @vaddr: The vaddr of the swiotlb memory pool. The swiotlb memory pool
++ * may be remapped in the memory encrypted case and store virtual
++ * address for bounce buffer operation.
* @nslabs: The number of IO TLB blocks (in groups of 64) between @start and
* @end. For default swiotlb, this is command line adjustable via
* setup_io_tlb_npages.
@@ -51,7 +65,7 @@
+
#endif /* __LINUX_SWIOTLB_H */
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
-index 8e840fbbed7c..4735c5e0f44d 100644
+index 8e840fbbed7c..34e6ade4f73c 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -50,6 +50,7 @@
@@ -71,7 +85,7 @@
/*
* Max segment that we can provide which (if pages are contingous) will
* not be bounced (unless SWIOTLB_FORCE is set).
-@@ -155,6 +158,31 @@ static inline unsigned long nr_slots(u64 val)
+@@ -155,6 +158,27 @@ static inline unsigned long nr_slots(u64 val)
return DIV_ROUND_UP(val, IO_TLB_SIZE);
}
@@ -82,120 +96,56 @@
+ */
+void *swiotlb_mem_remap(struct io_tlb_mem *mem, unsigned long bytes)
+{
-+ void *vaddr;
++ void *vaddr = NULL;
+
+ if (swiotlb_unencrypted_base) {
+ phys_addr_t paddr = mem->start + swiotlb_unencrypted_base;
+
+ vaddr = memremap(paddr, bytes, MEMREMAP_WB);
-+ if (!vaddr) {
++ if (!vaddr)
+ pr_err("Failed to map the unencrypted memory %llx size %lx.\n",
+ paddr, bytes);
-+ return NULL;
-+ }
-+
-+ return vaddr;
+ }
+
-+ return phys_to_virt(mem->start);
++ return vaddr;
+}
+
/*
* Early SWIOTLB allocation may be too early to allow an architecture to
* perform the desired operations. This function allows the architecture to
-@@ -172,10 +200,17 @@ void __init swiotlb_update_mem_attributes(void)
+@@ -172,7 +196,12 @@ void __init swiotlb_update_mem_attributes(void)
vaddr = phys_to_virt(mem->start);
bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT);
set_memory_decrypted((unsigned long)vaddr, bytes >> PAGE_SHIFT);
- memset(vaddr, 0, bytes);
+
+ mem->vaddr = swiotlb_mem_remap(mem, bytes);
-+ if (!mem->vaddr) {
-+ pr_err("Fail to remap swiotlb mem.\n");
-+ return;
-+ }
++ if (!mem->vaddr)
++ mem->vaddr = vaddr;
+
+ memset(mem->vaddr, 0, bytes);
}
--static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
-+static int swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
- unsigned long nslabs, bool late_alloc)
- {
- void *vaddr = phys_to_virt(start);
-@@ -196,13 +231,28 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
+ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
+@@ -196,7 +225,17 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
mem->slots[i].orig_addr = INVALID_PHYS_ADDR;
mem->slots[i].alloc_size = 0;
}
+
+ /*
-+ * With swiotlb_unencrypted_base setting, swiotlb bounce buffer will
-+ * be remapped in the swiotlb_update_mem_attributes() and return here
-+ * directly.
++ * If swiotlb_unencrypted_base is set, the bounce buffer memory will
++ * be remapped and cleared in swiotlb_update_mem_attributes.
+ */
+ if (swiotlb_unencrypted_base)
-+ return 0;
-+
-+ if (set_memory_decrypted((unsigned long)vaddr, bytes >> PAGE_SHIFT))
-+ return -EFAULT;
++ return;
+
memset(vaddr, 0, bytes);
+ mem->vaddr = vaddr;
-+ return 0;
++ return;
}
int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
- {
- struct io_tlb_mem *mem = &io_tlb_default_mem;
- size_t alloc_size;
-+ int ret;
-
- if (swiotlb_force == SWIOTLB_NO_FORCE)
- return 0;
-@@ -217,7 +267,11 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
- panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
- __func__, alloc_size, PAGE_SIZE);
-
-- swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, false);
-+ ret = swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, false);
-+ if (ret) {
-+ memblock_free(mem->slots, alloc_size);
-+ return ret;
-+ }
-
- if (verbose)
- swiotlb_print_info();
-@@ -304,7 +358,9 @@ int
- swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
- {
- struct io_tlb_mem *mem = &io_tlb_default_mem;
-- unsigned long bytes = nslabs << IO_TLB_SHIFT;
-+ unsigned long order
-+ = get_order(array_size(sizeof(*mem->slots), nslabs));
-+ int ret;
-
- if (swiotlb_force == SWIOTLB_NO_FORCE)
- return 0;
-@@ -314,12 +370,15 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
- return -ENOMEM;
-
- mem->slots = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-- get_order(array_size(sizeof(*mem->slots), nslabs)));
-+ order);
- if (!mem->slots)
- return -ENOMEM;
-
-- set_memory_decrypted((unsigned long)tlb, bytes >> PAGE_SHIFT);
-- swiotlb_init_io_tlb_mem(mem, virt_to_phys(tlb), nslabs, true);
-+ ret = swiotlb_init_io_tlb_mem(mem, virt_to_phys(tlb), nslabs, true);
-+ if (ret) {
-+ free_pages((unsigned long)mem->slots, order);
-+ return ret;
-+ }
-
- swiotlb_print_info();
- swiotlb_set_max_segment(mem->nslabs << IO_TLB_SHIFT);
-@@ -371,7 +430,7 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
+@@ -371,7 +410,7 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
phys_addr_t orig_addr = mem->slots[index].orig_addr;
size_t alloc_size = mem->slots[index].alloc_size;
unsigned long pfn = PFN_DOWN(orig_addr);