if (ret) {
dev_err(stream_map->dart->dev,
"busy bit did not clear after command %x for streams %lx\n",
- ------ command, stream_map->sidmap);
+ ++++++ command, stream_map->sidmap[0]);
+ +++++ return ret;
+ +++++ }
+ +++++
+ +++++ return 0;
+ +++++ }
+ +++++
+ +++++ static int
-apple_dart_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+ ++++++apple_dart_t8110_hw_tlb_command(struct apple_dart_stream_map *stream_map,
+ ++++++ u32 command)
+ +++++ {
- return apple_dart_hw_stream_command(stream_map,
- DART_STREAM_COMMAND_INVALIDATE);
+ ++++++ struct apple_dart *dart = stream_map->dart;
+ ++++++ unsigned long flags;
+ ++++++ int ret = 0;
+ ++++++ int sid;
+ ++++++
+ ++++++ spin_lock_irqsave(&dart->lock, flags);
+ ++++++
+ ++++++ for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) {
+ ++++++ u32 val = FIELD_PREP(DART_T8110_TLB_CMD_OP, command) |
+ ++++++ FIELD_PREP(DART_T8110_TLB_CMD_STREAM, sid);
+ ++++++ writel(val, dart->regs + DART_T8110_TLB_CMD);
+ ++++++
+ ++++++ ret = readl_poll_timeout_atomic(
+ ++++++ dart->regs + DART_T8110_TLB_CMD, val,
+ ++++++ !(val & DART_T8110_TLB_CMD_BUSY), 1,
+ ++++++ DART_STREAM_COMMAND_BUSY_TIMEOUT);
+ ++++++
+ ++++++ if (ret)
+ ++++++ break;
+ ++++++
+ ++++++ }
+ ++++++
+ ++++++ spin_unlock_irqrestore(&dart->lock, flags);
+ ++++++
+ ++++++ if (ret) {
+ ++++++ dev_err(stream_map->dart->dev,
+ ++++++ "busy bit did not clear after command %x for stream %d\n",
+ ++++++ command, sid);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
- ----- apple_dart_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+ ++++++apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+ ++++++{
+ ++++++ return apple_dart_t8020_hw_stream_command(
+ ++++++ stream_map, DART_T8020_STREAM_COMMAND_INVALIDATE);
+ ++++++}
+ ++++++
+ ++++++static int
+ ++++++apple_dart_t8110_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+{
- ----- return apple_dart_hw_stream_command(stream_map,
- ----- DART_STREAM_COMMAND_INVALIDATE);
+ ++++++ return apple_dart_t8110_hw_tlb_command(
+ ++++++ stream_map, DART_T8110_TLB_CMD_OP_FLUSH_SID);
}
static int apple_dart_hw_reset(struct apple_dart *dart)
apple_dart_hw_clear_all_ttbrs(&stream_map);
/* enable all streams globally since TCR is used to control isolation */
- ------ writel(DART_STREAM_ALL, dart->regs + DART_STREAMS_ENABLE);
+ ++++++ for (i = 0; i < BITS_TO_U32(dart->num_streams); i++)
+ ++++++ writel(U32_MAX, dart->regs + dart->hw->enable_streams + 4 * i);
/* clear any pending errors before the interrupt is unmasked */
- ------ writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR);
+ ++++++ writel(readl(dart->regs + dart->hw->error), dart->regs + dart->hw->error);
+ +++++
- return apple_dart_hw_invalidate_tlb(&stream_map);
+ ++++++ if (dart->hw->type == DART_T8110)
+ ++++++ writel(0, dart->regs + DART_T8110_ERROR_MASK);
+
- ----- return apple_dart_hw_invalidate_tlb(&stream_map);
+ ++++++ return dart->hw->invalidate_tlb(&stream_map);
}
static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
if (!group)
goto out;
- ------ group_master_cfg = kmemdup(cfg, sizeof(*group_master_cfg), GFP_KERNEL);
- ------ if (!group_master_cfg) {
- ------ iommu_group_put(group);
- ------ goto out;
- ------ }
+ ++++++ group_master_cfg = iommu_group_get_iommudata(group);
+ ++++++ if (group_master_cfg) {
+ ++++++ int ret;
+ +++++
- iommu_group_set_iommudata(group, group_master_cfg,
- apple_dart_release_group);
+ ++++++ ret = apple_dart_merge_master_cfg(group_master_cfg, cfg);
+ ++++++ if (ret) {
+ ++++++ dev_err(dev, "Failed to merge DART IOMMU grups.\n");
+ ++++++ iommu_group_put(group);
+ ++++++ res = ERR_PTR(ret);
+ ++++++ goto out;
+ ++++++ }
+ ++++++ } else {
+ ++++++ group_master_cfg = kmemdup(cfg, sizeof(*group_master_cfg),
+ ++++++ GFP_KERNEL);
+ ++++++ if (!group_master_cfg) {
+ ++++++ iommu_group_put(group);
+ ++++++ goto out;
+ ++++++ }
+
- ----- iommu_group_set_iommudata(group, group_master_cfg,
- ----- apple_dart_release_group);
+ ++++++ iommu_group_set_iommudata(group, group_master_cfg,
+ ++++++ apple_dart_release_group);
+ ++++++ }
for_each_stream_map(i, cfg, stream_map)
- ------ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ ++++++ for_each_set_bit(sid, stream_map->sidmap, stream_map->dart->num_streams)
stream_map->dart->sid2group[sid] = group;
res = group;
.flush_end = 0x24,
.int_status = 0x60,
.int_clear = 0x64,
-- ---- /* SysMMU v7: VM capable register set */
++ +++++
++ +++++ .get_fault_info = exynos_sysmmu_v5_get_fault_info,
+};
+
-/* SysMMU v7: VM capable register set */
++ +++++/* SysMMU v7: non-VM capable register layout */
++ +++++static const struct sysmmu_variant sysmmu_v7_variant = {
++ +++++ .pt_base = 0x0c,
++ +++++ .flush_all = 0x10,
++ +++++ .flush_entry = 0x14,
++ +++++ .flush_range = 0x18,
++ +++++ .flush_start = 0x20,
++ +++++ .flush_end = 0x24,
++ +++++ .int_status = 0x60,
++ +++++ .int_clear = 0x64,
++ +++++ .fault_va = 0x70,
++ +++++ .fault_info = 0x78,
++ +++++
++ +++++ .get_fault_info = exynos_sysmmu_v7_get_fault_info,
++ ++++ };
++ ++++
++ +++++/* SysMMU v7: VM capable register layout */
static const struct sysmmu_variant sysmmu_v7_vm_variant = {
.pt_base = 0x800c,
.flush_all = 0x8010,
if (!pages)
return;
------- ret = iommu_map(domain->domain, 0, page_to_phys(pages), PAGE_SIZE * 2,
------ IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE);
- IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE, GFP_KERNEL);
------- if (!ret) {
------- size_t unmapped = iommu_unmap(domain->domain, 0, PAGE_SIZE);
+++++++ list_for_each_entry(region, regions, list) {
+++++++ start = ALIGN(region->start, PAGE_SIZE * 2);
+++++++ if (start >= region->end || (region->end - start < PAGE_SIZE * 2))
+++++++ continue;
------- if (unmapped == PAGE_SIZE)
------- iommu_unmap(domain->domain, PAGE_SIZE, PAGE_SIZE);
------- else
------- domain->fgsp = true;
+++++++ ret = iommu_map(domain->domain, start, page_to_phys(pages), PAGE_SIZE * 2,
- IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE);
++++++++ IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE, GFP_KERNEL);
+++++++ if (!ret) {
+++++++ size_t unmapped = iommu_unmap(domain->domain, start, PAGE_SIZE);
+++++++
+++++++ if (unmapped == PAGE_SIZE)
+++++++ iommu_unmap(domain->domain, start + PAGE_SIZE, PAGE_SIZE);
+++++++ else
+++++++ domain->fgsp = true;
+++++++ }
+++++++ break;
}
__free_pages(pages, order);