Skip to content

Commit 1143d02

Browse files
committed
iommu: apple-dart: Use remap feature
Apple's DART have a feature to remap streams onto other streams. This should not have too much impact The USB4 NHI controller uses 21 DART streams all using remapped to the first one. Using remap improves USB4_NET iperf3 throupghput between a Apple M3 Pro system running Linux and an Apple M1 system running macOS from 1.02 (DMA) / 1.86 (DMA-FQ) Gbits/sec to 8.32 (DMA) / 10.7 (DMA-FQ) Gbits/sec. Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 01021f0 commit 1143d02

1 file changed

Lines changed: 61 additions & 9 deletions

File tree

‎drivers/iommu/apple-dart.c‎

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,16 @@
7777

7878
#define DART_T8020_STREAMS_ENABLE 0xfc
7979

80+
#define DART_T8020_REMAP 0x80
81+
82+
#define DART_REMAP_MASK(sid) GENMASK(7 + (8 * (sid % 4)), 8 * (sid % 4))
83+
#define DART_REMAP(dart, sid) ((dart)->regs + DART_T8020_REMAP + ((sid) & ~0x3))
84+
8085
#define DART_T8020_TCR 0x100
8186
#define DART_T8020_TCR_TRANSLATE_ENABLE BIT(7)
8287
#define DART_T8020_TCR_BYPASS_DART BIT(8)
8388
#define DART_T8020_TCR_BYPASS_DAPF BIT(12)
89+
#define DART_T8020_TCR_REMAP_ENABLE BIT(24)
8490

8591
#define DART_T8020_TTBR 0x200
8692
#define DART_T8020_USB4_TTBR 0x400
@@ -136,7 +142,7 @@
136142

137143
#define DART_T8110_TCR 0x1000
138144
#define DART_T8110_TCR_REMAP GENMASK(11, 8)
139-
#define DART_T8110_TCR_REMAP_EN BIT(7)
145+
#define DART_T8110_TCR_REMAP_ENABLE BIT(7)
140146
#define DART_T8110_TCR_FOUR_LEVEL BIT(3)
141147
#define DART_T8110_TCR_BYPASS_DAPF BIT(2)
142148
#define DART_T8110_TCR_BYPASS_DART BIT(1)
@@ -161,10 +167,13 @@ enum dart_type {
161167
DART_T8110,
162168
};
163169

170+
struct apple_dart;
171+
164172
struct apple_dart_hw {
165173
enum dart_type type;
166174
irqreturn_t (*irq_handler)(int irq, void *dev);
167175
int (*invalidate_tlb)(struct apple_dart_stream_map *stream_map);
176+
void (*enable_remap)(struct apple_dart *dart, int sid, int remap_to);
168177

169178
u32 oas;
170179
enum io_pgtable_fmt fmt;
@@ -332,22 +341,32 @@ apple_dart_hw_enable_translation(struct apple_dart_stream_map *stream_map, int l
332341
{
333342
struct apple_dart *dart = stream_map->dart;
334343
u32 tcr = dart->hw->tcr_enabled;
335-
int sid;
344+
int sid, remap_to;
336345

337346
if (levels == 4)
338347
tcr |= dart->hw->tcr_4level;
339348

340349
WARN_ON(levels != 3 && levels != 4);
341350
WARN_ON(levels == 4 && !dart->four_level);
342-
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
343-
writel(tcr, dart->regs + DART_TCR(dart, sid));
351+
352+
/* Search for first enabled sid and enable translation. */
353+
sid = find_first_bit(stream_map->sidmap, dart->num_streams);
354+
if (sid >= dart->num_streams)
355+
return;
356+
writel(tcr, dart->regs + DART_TCR(dart, sid));
357+
358+
/* Enable remapping for the remaining used sids. */
359+
remap_to = sid++;
360+
for_each_set_bit_from(sid, stream_map->sidmap, dart->num_streams)
361+
dart->hw->enable_remap(dart, sid, remap_to);
344362
}
345363

346364
static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream_map)
347365
{
348366
struct apple_dart *dart = stream_map->dart;
349367
int sid;
350368

369+
/* This will also disable remap enabled in apple_dart_hw_enable_translation(). */
351370
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
352371
writel(dart->hw->tcr_disabled, dart->regs + DART_TCR(dart, sid));
353372
}
@@ -371,10 +390,17 @@ static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
371390
int sid;
372391

373392
WARN_ON(paddr & ((1 << dart->hw->ttbr_shift) - 1));
374-
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams)
375-
writel(dart->hw->ttbr_valid |
376-
(paddr >> dart->hw->ttbr_shift) << dart->hw->ttbr_addr_field_shift,
377-
dart->regs + DART_TTBR(dart, sid, idx));
393+
/* Search for the first used stream and set its TTBR. All other sids
394+
* of this DART are handled via the remap feature and must not set a
395+
* valid TTBR.
396+
*/
397+
sid = find_first_bit(stream_map->sidmap, dart->num_streams);
398+
if (sid >= dart->num_streams)
399+
return;
400+
401+
writel(dart->hw->ttbr_valid |
402+
(paddr >> dart->hw->ttbr_shift) << dart->hw->ttbr_addr_field_shift,
403+
dart->regs + DART_TTBR(dart, sid, idx));
378404
}
379405

380406
static void apple_dart_hw_clear_ttbr(struct apple_dart_stream_map *stream_map,
@@ -527,7 +553,8 @@ apple_dart_t8110_hw_tlb_command(struct apple_dart_stream_map *stream_map,
527553

528554
if (ret)
529555
break;
530-
556+
/* Since remap is used only the first sid needs to be invalidated. */
557+
break;
531558
}
532559

533560
spin_unlock_irqrestore(&dart->lock, flags);
@@ -556,6 +583,27 @@ apple_dart_t8110_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
556583
stream_map, DART_T8110_TLB_CMD_OP_FLUSH_SID);
557584
}
558585

586+
static void
587+
apple_dart_t8020_hw_enable_remap(struct apple_dart *dart, int sid, int remap_to)
588+
{
589+
u32 remap = readl(DART_REMAP(dart, sid));
590+
remap = (remap & ~DART_REMAP_MASK(sid)) |
591+
field_prep(DART_REMAP_MASK(sid), remap_to);
592+
writel(remap, DART_REMAP(dart, sid));
593+
594+
u32 tcr = FIELD_PREP(DART_T8020_TCR_REMAP_ENABLE, 1) |
595+
FIELD_PREP(DART_T8020_TCR_TRANSLATE_ENABLE, 1);
596+
writel(tcr, dart->regs + DART_TCR(dart, sid));
597+
}
598+
599+
static void
600+
apple_dart_t8110_hw_enable_remap(struct apple_dart *dart, int sid, int remap_to)
601+
{
602+
u32 tcr = FIELD_PREP(DART_T8110_TCR_REMAP, remap_to) |
603+
FIELD_PREP(DART_T8110_TCR_REMAP_ENABLE, 1);
604+
writel(tcr, dart->regs + DART_TCR(dart, sid));
605+
}
606+
559607
static int apple_dart_hw_reset(struct apple_dart *dart)
560608
{
561609
struct apple_dart_stream_map stream_map;
@@ -1537,6 +1585,7 @@ static const struct apple_dart_hw apple_dart_hw_t8103 = {
15371585
.type = DART_T8020,
15381586
.irq_handler = apple_dart_t8020_irq,
15391587
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
1588+
.enable_remap = apple_dart_t8020_hw_enable_remap,
15401589
.oas = 36,
15411590
.fmt = APPLE_DART,
15421591
.max_sid_count = 16,
@@ -1563,6 +1612,7 @@ static const struct apple_dart_hw apple_dart_hw_t8103_usb4 = {
15631612
.type = DART_T8020,
15641613
.irq_handler = apple_dart_t8020_irq,
15651614
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
1615+
.enable_remap = apple_dart_t8020_hw_enable_remap,
15661616
.oas = 36,
15671617
.fmt = APPLE_DART,
15681618
.max_sid_count = 64,
@@ -1589,6 +1639,7 @@ static const struct apple_dart_hw apple_dart_hw_t6000 = {
15891639
.type = DART_T6000,
15901640
.irq_handler = apple_dart_t8020_irq,
15911641
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
1642+
.enable_remap = apple_dart_t8020_hw_enable_remap,
15921643
.oas = 42,
15931644
.fmt = APPLE_DART2,
15941645
.max_sid_count = 16,
@@ -1615,6 +1666,7 @@ static const struct apple_dart_hw apple_dart_hw_t8110 = {
16151666
.type = DART_T8110,
16161667
.irq_handler = apple_dart_t8110_irq,
16171668
.invalidate_tlb = apple_dart_t8110_hw_invalidate_tlb,
1669+
.enable_remap = apple_dart_t8110_hw_enable_remap,
16181670
.fmt = APPLE_DART2,
16191671
.max_sid_count = 256,
16201672

0 commit comments

Comments
 (0)