Skip to content

Commit

Permalink
loongarch: fix DMA address offset
Browse files Browse the repository at this point in the history
Loongarch CPUs are using HT bus interface, which is only 40-bit wide,
to communicate with the bridge chipset. However, the actual memory
bus of the CPUs is 48-bit wide, and the available address space of DMA
requests of PCI devices is also larger than the 40-bit address space.
The address space of loongarch systems is not continuous, the bits
[47:44] of which are used to denote the belonging node id, which is
far beyond the space provided by the 40-bit wide HT bus. As a result,
a translation on the both LS7A and CPU sides is needed.

The translation happens on the LS7A side is controlled by the higher
half of the register, HT_ROUTE. Bits [12:8] denotes dma_node_id_offset
and bits[15:13] denotes dma_node_id_offset_mapped. The behavior of the
translation is that the chip extracts the node id from bit
dma_node_id_offset + 36 of a DMA address, places it at bit
dma_node_id_offset_mapped + 32, and generates the address on the HT bus.
On the CPU side, an alike translation happens, to convert the address on
the HT bus back to a proper memory address.

On machines with legacy firmware with BPI01000 version,
dma_node_id_offset is configured with 0, resulting the address which
should be used by the DMA engine of a PCI device differs from the
actural physical memeory address, which requires a pair of arch-specific
phys_to_dma and dma_to_phys functions or setting up the whole mapping
in the _DMA method of the PCI root device in the DSDT table.

The former method requires we add back the prevoiusly removed functions,
and the latter method degrades the performance since when the
translation happens, the mapping table is scanned linearly.

This patch addresses this issue by directly setting dma_node_id_offset
to 8, like what is done by modern firmwares, making the address used by
the DMA engine just the same as the actual physical memory address, and
eliminating the need of DMA address translation on the kernel side.
  • Loading branch information
shankerwangmiao authored and MingcongBai committed Aug 14, 2024
1 parent f3b9321 commit f6db7f6
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions arch/loongarch/kernel/legacy_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ enum bpi_mem_type {
#define MSI_MSG_ADDRESS 0x2FF00000
#define MSI_MSG_DEFAULT_COUNT 0xC0

/*
``This should be configured by firmware"
-- Section 4, Page 25 of Loongson-7A1000 User Manual v2.0
but unable to figure out the exact value.
The manual gives a typical value in Table 3.2, Page 23.
*/
#define LS7A_CHIPCFG_REG_OFF 0x00010000

/* Section 4.1, Page 26 of Loongson-7A1000 User Manual v2.0 */
#define LS7A_DMA_CFG_OFF 0x041c
#define LS7A_DMA_NODE_ID_OFFSET_SHF 8
#define LS7A_DMA_NODE_ID_OFFSET_MASK GENMASK(12, 8)

struct loongarch_bpi_mem_map {
struct loongarch_bpi_ext_hdr header; /*{"M", "E", "M"}*/
u8 map_count;
Expand Down Expand Up @@ -588,6 +601,20 @@ static void __init init_acpi_arch_os_table_override (struct acpi_table_header *e
new_madt->header.checksum = 0 - ext_listhdr_checksum((u8 *)new_madt, new_madt_size);
new_mcfg->header.checksum = 0 - ext_listhdr_checksum((u8 *)new_mcfg, new_mcfg_size);
*new_table = (struct acpi_table_header *)new_madt;

// Override LS7A dma_node_id_offset
for(int i = 0; i < io_apic_count; i++){
u64 ls7a_base_addr = bio_pics[i].address;
void __iomem *dma_node_id_addr = (void __iomem *) TO_UNCACHE(ls7a_base_addr + LS7A_CHIPCFG_REG_OFF + LS7A_DMA_CFG_OFF);
u32 dma_cfg = readl(dma_node_id_addr);
u32 dma_node_id_offset = (dma_cfg & LS7A_DMA_NODE_ID_OFFSET_MASK) >> LS7A_DMA_NODE_ID_OFFSET_SHF;
if(dma_node_id_offset != 8){
pr_info("BPI: LS7A %d DMA node id offset is %d, will set to 8\n", i, dma_node_id_offset);
dma_cfg &= ~LS7A_DMA_NODE_ID_OFFSET_MASK;
dma_cfg |= 8 << LS7A_DMA_NODE_ID_OFFSET_SHF;
writel(dma_cfg, dma_node_id_addr);
}
}
}

void acpi_arch_os_table_override (struct acpi_table_header *existing_table, struct acpi_table_header **new_table){
Expand Down

0 comments on commit f6db7f6

Please sign in to comment.