diff --git a/acs-drv/files/bsa_acs_drv.c b/acs-drv/files/bsa_acs_drv.c index 82356177da2b8a8127e32583615cbf13759944b8..efb842a6fcd95c04e2f0a89f5cde11a3a0d1c696 100755 --- a/acs-drv/files/bsa_acs_drv.c +++ b/acs-drv/files/bsa_acs_drv.c @@ -67,6 +67,8 @@ char *g_msg_buf; int tail_msg; extern int num_msg; +int val_glue_execute_command(void); + int val_glue_execute_command(void) { diff --git a/acs-drv/files/bsa_acs_drv.h b/acs-drv/files/bsa_acs_drv.h index b19126b2ef1874e56df0c5302174ac26f2d1ab73..59c312366223f1e6af924e0ddf8f7e1f5e3a4327 100644 --- a/acs-drv/files/bsa_acs_drv.h +++ b/acs-drv/files/bsa_acs_drv.h @@ -43,7 +43,7 @@ #define PE_INFO_TBL_SZ 16384 /* Supports maximum 400 PEs [40 B each + 4 B header] */ #define IOVIRT_INFO_TBL_SZ 1048576 /* Supports maximum 2400 iort nodes [268+32*5 B each + 24 B header] */ #define PERIPHERAL_INFO_TBL_SZ 8192 /* Supports maximum 145 PCIe peripheral device (anykind) [56 B each + 16 B header] */ -#define PCIE_INFO_TBL_SZ 512 /* Supports maximum 20 PCIe ECAM block [24 B each + 4 B header] */ +#define PCIE_INFO_TBL_SZ 1024 /* Supports maximum 40 PCIe ECAM block [24 B each + 4 B header] */ #define DMA_INFO_TBL_SZ 1024 /* Supports maximum 30 DMA ctrl [32 B each + 4 B header] */ #define ACS_PCIE_RCiEP_DISABLE 0 diff --git a/acs-drv/files/platform/pal_linux/files/MakefileSBSA b/acs-drv/files/platform/pal_linux/files/MakefileSBSA index c686f5ec8d576d270d23ba77c62b71a8ac26ab7a..95500ba79f86c39496b69a6d57afa7cde742b65a 100644 --- a/acs-drv/files/platform/pal_linux/files/MakefileSBSA +++ b/acs-drv/files/platform/pal_linux/files/MakefileSBSA @@ -30,7 +30,7 @@ sbsa_acs_pal-objs += $(COMMON_PAL_SRC)/pal_misc.o \ $(COMMON_PAL_SRC)/pal_pe.o $(COMMON_PAL_SRC)/pal_pcie.o $(COMMON_PAL_SRC)/pal_pcie_enumeration.o \ $(COMMON_PAL_SRC)/pal_smmu.o $(COMMON_PAL_SRC)/pal_iovirt.o $(COMMON_PAL_SRC)/pal_peripherals.o \ $(COMMON_PAL_SRC)/pal_dma.o $(COMMON_PAL_SRC)/pal_acpi.o $(COMMON_PAL_SRC)/pal_gic.o \ - $(SBSA_PAL_SRC)/sbsa_pal_iovirt.o $(COMMON_PAL_SRC)/pal_exerciser.o + $(SBSA_PAL_SRC)/sbsa_pal_iovirt.o $(COMMON_PAL_SRC)/pal_exerciser.o $(SBSA_PAL_SRC)/sbsa_pal_pcie.o ccflags-y=-I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD) -I$(PWD)/../../ -I$(PWD)/../../../ -DTARGET_LINUX -DBUILD_SBSA -Wall -Werror diff --git a/acs-drv/files/platform/pal_linux/files/common/include/pal_exerciser.h b/acs-drv/files/platform/pal_linux/files/common/include/pal_exerciser.h index b342aed24bb0c5cea4270afd04b607d11d4ffdc4..942994ea2b71a744e0487e2f6d5a9267160be56f 100644 --- a/acs-drv/files/platform/pal_linux/files/common/include/pal_exerciser.h +++ b/acs-drv/files/platform/pal_linux/files/common/include/pal_exerciser.h @@ -134,5 +134,6 @@ uint32_t pal_exerciser_set_state(EXERCISER_STATE state, uint64_t *value, uint32_ uint32_t pal_exerciser_get_state(EXERCISER_STATE *state, uint32_t bdf); uint32_t pal_exerciser_ops(EXERCISER_OPS ops, uint64_t param, uint32_t instance); uint32_t pal_exerciser_get_data(EXERCISER_DATA_TYPE type, exerciser_data_t *data, uint32_t instance); +uint32_t pal_is_bdf_exerciser(uint32_t bdf); #endif diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_acpi.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_acpi.c index 0101cf8a1380fefeff1c6fab48f5d66012eb52fc..95e8bca5426f12ca3b8fcfbf4b250d9bfa76201f 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_acpi.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_acpi.c @@ -71,3 +71,5 @@ pal_target_is_dt() { return 0; } + +MODULE_LICENSE("GPL"); diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_dma.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_dma.c index dca91790cd7dd4dbfdf73ffeb0508d2a453cf370..c40b7ebd603a8adb67b9d889e9b11ccc3747bae3 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_dma.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_dma.c @@ -94,15 +94,6 @@ pal_dma_mem_free(void *buffer, addr_t mem_dma, unsigned int length, void *port, } -void -pal_dma_poll_for_completion(unsigned int timeout) -{ - - /* scsi execute takes care of this. */ - return; - -} - void pal_dma_create_info_table(DMA_INFO_TABLE *dma_info_table) { @@ -189,30 +180,6 @@ pal_dma_start_from_device(void *dma_target_buf, unsigned int length, return result; } -unsigned int -pal_dma_start_to_device(void *dma_source_buf, unsigned int length, - void *host, void *target, unsigned int timeout) -{ - - unsigned char cmd[10]; - int ret; - struct scsi_device *sdev = (struct scsi_device *)target; - - memset(cmd, 0, 10); - - cmd[0] = WRITE_10; - cmd[8] = 1; //one block only for now -#if LINUX_VERSION_CODE > KERNEL_VERSION(6,2,0) - ret = scsi_execute_cmd(sdev, cmd, DMA_TO_DEVICE, dma_source_buf, length, - timeout, 1, NULL); -#else - ret = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, dma_source_buf, length, - NULL, timeout, 1, NULL); -#endif - - return 0; -} - static int is_pte(uint64_t val) diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_gic.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_gic.c index 3ba5b3050a075b973ba583bbf3b33058c6786b12..1a02d4d3a2a277cc5d380e9b17d2dc1100ad8515 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_gic.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_gic.c @@ -95,30 +95,3 @@ void pal_gic_free_irq(unsigned int irq_num, unsigned int mapped_irq_num) { free_irq(mapped_irq_num, NULL); } - -/* Placeholder for MSI related implementation*/ -uint32_t pal_gic_request_msi(unsigned int its_id, unsigned int device_id, - unsigned int int_id, unsigned int msi_index, - unsigned int *msi_addr, unsigned int *msi_data) -{ - return 0; -} - -/* Placeholder for MSI related implementation*/ -void pal_gic_free_msi(unsigned int its_id, unsigned int device_id, - unsigned int int_id, unsigned int msi_index) -{ - return; -} - -/* Placeholder for ITS Configuration */ -uint32_t pal_gic_its_configure(void) -{ - return 0; -} - -/* Placeholder for returning max LPI supported */ -uint32_t pal_gic_get_max_lpi_id(void) -{ - return 0; -} diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_pcie.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_pcie.c index 5f26ac95336b905eb2178414f61c3f2ce48e73f0..5f4ce7bec7a638d9734657c92d73e6891a450a32 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_pcie.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_pcie.c @@ -572,26 +572,6 @@ pal_pcie_dev_p2p_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn) return 1; } -/** - @brief This API checks the PCIe device multifunction support - 1. Caller - Test Suite - @param bdf - PCIe BUS/Device/Function - @return 1 - Multifunction feature not supported 0 - Multifunction feature supported -**/ -uint32_t -pal_pcie_multifunction_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn) -{ - struct pci_dev *pdev; - - pdev = pci_get_domain_bus_and_slot(seg, bus, PCI_DEVFN(dev, fn)); - if(pdev == NULL) - return 1; - - if (!pdev->multifunction) - return 1; - - return 0; -} uint32_t pal_pcie_io_read_cfg(uint32_t bdf, uint32_t offset, uint32_t *data) { @@ -635,22 +615,6 @@ pal_pcie_is_cache_present(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn) return 1; /* SBSA has it return 0 TODO */ } -/** - @brief Gets RP support of transaction forwarding. - - @param bus PCI bus address - @param dev PCI device address - @param fn PCI function number - @param seg PCI segment number - - @return 0 if rp not involved in transaction forwarding - 1 if rp is involved in transaction forwarding -**/ -uint32_t -pal_pcie_get_rp_transaction_frwd_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn) -{ - return 1; -} /** @brief Returns whether a PCIe Function is an on-chip peripheral or not diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_pe.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_pe.c index c47aa3f05bc20124348d1a3f49f854fcd0b7b41f..14d17d69dd7ec7b67a7d0d8431090521b42aaf92 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_pe.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_pe.c @@ -95,10 +95,6 @@ pal_pe_install_esr(unsigned int ExceptionType, void (*esr)(unsigned long long, return 0; /* IN SBSA it is 1 TODO */ } -void -pal_pe_increment_elr(unsigned long long offset) -{ -} void pal_pe_data_cache_ops_by_va(unsigned long long addr, unsigned type) diff --git a/acs-drv/files/platform/pal_linux/files/common/src/pal_smmu.c b/acs-drv/files/platform/pal_linux/files/common/src/pal_smmu.c index a7cedd35df8d97c3b3f44538611fa961a3a908fd..ec441944f2f3d22869f98a0437c8751922f5376f 100644 --- a/acs-drv/files/platform/pal_linux/files/common/src/pal_smmu.c +++ b/acs-drv/files/platform/pal_linux/files/common/src/pal_smmu.c @@ -111,15 +111,6 @@ pal_smmu_check_device_iova(void *port, unsigned long long dma_addr) return PAL_LINUX_ERR; } -uint32_t -pal_smmu_max_pasids(uint64_t smmu_base) -{ - uint32_t reg = pal_mmio_read(smmu_base + SMMU_V3_IDR1); - uint32_t pasid_bits = reg >> SMMU_V3_IDR1_PASID_SHIFT & SMMU_V3_IDR1_PASID_MASK; - if(pasid_bits == 0) - return 0; - return (1 << pasid_bits); -} uint32_t pal_smmu_create_pasid_entry(uint64_t smmu_base, uint32_t pasid) { diff --git a/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_iovirt.c b/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_iovirt.c index e1c6df5a7dad139c94ac417d26959e5f56ad2bb7..aa53c04a9b0c15bfda2ef724ed98a8df9db11e0c 100644 --- a/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_iovirt.c +++ b/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_iovirt.c @@ -26,9 +26,11 @@ #include "common/include/pal_linux.h" #include "sbsa/include/sbsa_pal_linux.h" +#include "val/sbsa/include/sbsa_pal_interface.h" #define NOT_IMPLEMENTED 0x4B1D +acpi_status user_function(acpi_handle handle, uint32_t level, void *context, void **return_value); /** @brief This function is called by the val function pal_get_device_path when the hid type is found diff --git a/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_pcie.c b/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_pcie.c new file mode 100644 index 0000000000000000000000000000000000000000..df9cd7af21faada4865dcf93b609b24abf01244e --- /dev/null +++ b/acs-drv/files/platform/pal_linux/files/sbsa/src/sbsa_pal_pcie.c @@ -0,0 +1,44 @@ +/* + * BSA SBSA ACS Platform module. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Copyright (C) 2016-2019, 2021, 2023, 2024, Arm Limited + * + * Author: Sakar Arora + * + */ + +#include +#include +#include +#include + +#include "val/sbsa/include/sbsa_pal_interface.h" + +/** + @brief Gets RP support of transaction forwarding. + + @param bus PCI bus address + @param dev PCI device address + @param fn PCI function number + @param seg PCI segment number + + @return 0 if rp not involved in transaction forwarding + 1 if rp is involved in transaction forwarding +**/ +uint32_t +pal_pcie_get_rp_transaction_frwd_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn) +{ + return 1; +} diff --git a/acs-drv/files/sbsa_acs_drv.c b/acs-drv/files/sbsa_acs_drv.c index df0a82dabe64b4b1aca53949ee7f48167b1ed3ef..ccf86310c40f25d915c04f99cfdf2f03b8a1845b 100755 --- a/acs-drv/files/sbsa_acs_drv.c +++ b/acs-drv/files/sbsa_acs_drv.c @@ -65,6 +65,7 @@ uint64_t *g_iovirt_info_ptr; char *g_msg_buf; int tail_msg; extern int num_msg; +int val_glue_execute_command(void); int val_glue_execute_command(void) diff --git a/acs-drv/files/sbsa_acs_drv.h b/acs-drv/files/sbsa_acs_drv.h index 83cd26d6aaaff34fc3ba1bd7110b6548e4d050f2..68efdb3e12ad5137a810923316871dc402d2e5de 100644 --- a/acs-drv/files/sbsa_acs_drv.h +++ b/acs-drv/files/sbsa_acs_drv.h @@ -40,7 +40,7 @@ #define PE_INFO_TBL_SZ 16384 /* Supports maximum 400 PEs [40 B each + 4 B header] */ #define IOVIRT_INFO_TBL_SZ 1048576 /* Supports maximum 2400 iort nodes [268+32*5 B each + 24 B header] */ #define PERIPHERAL_INFO_TBL_SZ 8192 /* Supports maximum 145 PCIe peripheral device (anykind) [56 B each + 16 B header] */ -#define PCIE_INFO_TBL_SZ 512 /* Supports maximum 20 PCIe ECAM block [24 B each + 4 B header] */ +#define PCIE_INFO_TBL_SZ 1024 /* Supports maximum 40 PCIe ECAM block [24 B each + 4 B header] */ #define DMA_INFO_TBL_SZ 1024 /* Supports maximum 30 DMA ctrl [32 B each + 4 B header] */ typedef diff --git a/kernel/src/0001-BSA-ACS-Linux-6.8.patch b/kernel/src/0001-BSA-ACS-Linux-6.8.patch new file mode 100644 index 0000000000000000000000000000000000000000..82ae1d5f7b12791d0c26b182639c28ba157cfe0d --- /dev/null +++ b/kernel/src/0001-BSA-ACS-Linux-6.8.patch @@ -0,0 +1,505 @@ +From e6785c2b94353028081f65a0e4157ee350221d94 Mon Sep 17 00:00:00 2001 +From: Guru9902 +Date: Wed, 24 Apr 2024 11:55:29 +0000 +Subject: [PATCH] BSA ACS Linux 6.8 + +Signed-off-by: Guru9902 +--- + drivers/ata/libahci.c | 3 + + drivers/ata/sata_sil24.c | 3 + + drivers/iommu/Makefile | 1 + + drivers/iommu/bsa-dma-iommu.c | 238 ++++++++++++++++++++++++++++++++++ + drivers/iommu/dma-iommu.c | 7 + + drivers/iommu/iommu.c | 3 + + drivers/irqchip/irq-gic-v3.c | 15 +++ + include/linux/bsa-iommu.h | 50 +++++++ + include/linux/irqdomain.h | 2 + + kernel/irq/irqdomain.c | 2 +- + mm/init-mm.c | 2 + + 11 files changed, 325 insertions(+), 1 deletion(-) + create mode 100644 drivers/iommu/bsa-dma-iommu.c + create mode 100644 include/linux/bsa-iommu.h + +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 1a63200ea..384b03d53 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1654,6 +1654,8 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class) + } + } + ++void bsa_scsi_sata_fill_dma_addr(struct scatterlist *sg); ++ + static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) + { + struct scatterlist *sg; +@@ -1663,6 +1665,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) + /* + * Next, the S/G list. + */ ++ bsa_scsi_sata_fill_dma_addr(qc->sg); + for_each_sg(qc->sg, sg, qc->n_elem, si) { + dma_addr_t addr = sg_dma_address(sg); + u32 sg_len = sg_dma_len(sg); +diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c +index 142e70bfc..e7cf8b1f1 100644 +--- a/drivers/ata/sata_sil24.c ++++ b/drivers/ata/sata_sil24.c +@@ -687,6 +687,8 @@ static int sil24_softreset(struct ata_link *link, unsigned int *class, + return -EIO; + } + ++void bsa_scsi_sata_fill_dma_addr(struct scatterlist *sg); ++ + static int sil24_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) + { +@@ -773,6 +775,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, + struct sil24_sge *last_sge = NULL; + unsigned int si; + ++ bsa_scsi_sata_fill_dma_addr(qc->sg); + for_each_sg(qc->sg, sg, qc->n_elem, si) { + sge->addr = cpu_to_le64(sg_dma_address(sg)); + sge->cnt = cpu_to_le32(sg_dma_len(sg)); +diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile +index 95ad9dbfb..ebeb74e2c 100644 +--- a/drivers/iommu/Makefile ++++ b/drivers/iommu/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_IOMMU_API) += iommu-traces.o + obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o + obj-$(CONFIG_IOMMU_DEBUGFS) += iommu-debugfs.o + obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o ++obj-$(CONFIG_IOMMU_DMA) += bsa-dma-iommu.o + obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o + obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o + obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o +diff --git a/drivers/iommu/bsa-dma-iommu.c b/drivers/iommu/bsa-dma-iommu.c +new file mode 100644 +index 000000000..c5ee940fb +--- /dev/null ++++ b/drivers/iommu/bsa-dma-iommu.c +@@ -0,0 +1,238 @@ ++/* ++ * The IOMMU-API to BSA Architecture Compliance Suite glue layer. ++ * ++ * Copyright (C) 2021 ARM Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++#include "dma-iommu.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++bsa_iova_array g_bsa_iova_array[BSA_IOVA_DMA_ARRAY_LEN]; ++ ++struct iommu_domain *g_bsa_iommu_domain = NULL; ++ ++struct iova_domain *cookie_iovad_bsa(struct iommu_domain *domain); ++ ++/** ++ @brief This API returns the DMA address for a given index from the active IOVA table. ++ 1. Caller - Platform Abstraction Layer. ++ 2. Prerequisite - None ++ @param dev - device whose domain IOVA table is checked ++ @param base - return DMA address base ++ @param in_node - return first entry if NULL, else continue from in_node ++ @return length of the DMA range ++**/ ++void * ++bsa_iommu_dma_get_iova(struct device *dev, unsigned long long *base, unsigned long int *size, ++ phys_addr_t *phy_addr, void *in_node) ++{ ++ struct iova_domain *iovad = cookie_iovad_bsa(iommu_get_domain_for_dev(dev)); ++ unsigned long shift; ++ struct rb_node *node; ++ ++ if(!iovad) ++ return NULL; ++ ++ shift = iova_shift(iovad); ++ ++ if (in_node == NULL) ++ node = rb_last(&iovad->rbroot); ++ else ++ node = rb_prev((struct rb_node *)in_node); ++ ++ while (node) ++ { ++ struct iova *iova = container_of(node, struct iova, node); ++ unsigned long pfn_lo = iova->pfn_lo; ++ unsigned long pfn_hi = iova->pfn_hi + 1; ++ phys_addr_t phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), ++ pfn_lo << shift); ++ ++ if (phys) { ++ *base = pfn_lo << shift; ++ *size = (pfn_hi - pfn_lo) << shift; ++ *phy_addr = phys; ++ break; ++ } ++ node = rb_prev(node); ++ } ++ return (void *)node; ++} ++EXPORT_SYMBOL(bsa_iommu_dma_get_iova); ++ ++static int bsa_get_sata_dev(void) ++{ ++ int ret = -1; ++ struct Scsi_Host *shost; ++ struct ata_port *ap; ++ struct scsi_device *sdev = NULL; ++ unsigned int i = 0; ++ ++ do { ++ shost = scsi_host_lookup(i++); ++ if (shost) { ++ sdev = NULL; ++ ap = ata_shost_to_port(shost); ++ if ((ap == NULL) || (ap->dev == NULL)) ++ continue; //Not a ATA port ++ if ((ap->scsi_host == NULL) || (ap->scsi_host != shost)) ++ continue; //Not a valid ATA Port ++ do { ++ /* get the device connected to this host */ ++ sdev = __scsi_iterate_devices(shost, sdev); ++ if (sdev) { ++ g_bsa_iommu_domain = iommu_get_domain_for_dev(ap->dev); ++ ret = 0; ++ } ++ } while(sdev); ++ scsi_host_put(shost); ++ } ++ } while(shost); ++ ++ return ret; ++} ++ ++/** ++ @brief This API is used to indicate which device IOMMU transactions are to be monitored. ++ 1. Caller - Platform Abstraction Layer. ++ 2. Prerequisite - None ++ @param dev - device whose domain IOVA table is checked ++ @return None ++**/ ++void ++bsa_iommu_dev_start_monitor(struct device *dev) ++{ ++ /* We only monitor 1 domain for now */ ++ ++ g_bsa_iommu_domain = iommu_get_domain_for_dev(dev); ++} ++EXPORT_SYMBOL(bsa_iommu_dev_start_monitor); ++ ++void ++bsa_iommu_dev_stop_monitor(struct device *dev) ++{ ++ g_bsa_iommu_domain = NULL; ++} ++EXPORT_SYMBOL(bsa_iommu_dev_stop_monitor); ++ ++int ++bsa_is_domain_monitored(struct iommu_domain *dom) ++{ ++ int ret = 0; ++ ++ if (g_bsa_iommu_domain == NULL ) ++ ret = bsa_get_sata_dev(); ++ ++ if (g_bsa_iommu_domain == dom) ++ return 1; ++ ++ return 0; ++} ++ ++void ++bsa_iommu_iova_save_addr(dma_addr_t addr, unsigned int length) ++{ ++ ++ static unsigned int index = 0; ++ ++ g_bsa_iova_array[index].dma_addr = addr; ++ g_bsa_iova_array[index].dma_len = length; ++ ++ index++; ++ ++ if (index >= BSA_IOVA_DMA_ARRAY_LEN) ++ index = 0; ++} ++ ++/** ++ @brief This API returns the DMA address for a given index from the saved IOVA addresses. ++ 1. Caller - Platform Abstraction Layer. ++ 2. Prerequisite - bsa_iommu_iova_save_addr. ++ @param index - index of the entry ++ @param addr - dma address returned ++ @return length of the DMA range ++**/ ++unsigned int ++bsa_iommu_iova_get_addr(unsigned int index, dma_addr_t *addr) ++{ ++ ++ if (index >= BSA_IOVA_DMA_ARRAY_LEN) ++ return 0; ++ ++ *addr = g_bsa_iova_array[index].dma_addr; ++ ++ return g_bsa_iova_array[index].dma_len; ++ ++} ++EXPORT_SYMBOL(bsa_iommu_iova_get_addr); ++ ++/** ++ @brief This API gets the DMA attributes of a device. ++ 1. Caller - Platform Abstraction Layer. ++ 2. Prerequisite - None. ++ @param dev - device structure. ++ @return Coherent or Not. ++**/ ++enum ++dev_dma_attr bsa_dev_get_dma_attr(struct device *dev) ++{ ++ ++ return device_get_dma_attr(dev); ++} ++EXPORT_SYMBOL(bsa_dev_get_dma_attr); ++ ++/* BSA ACS Hook functions to export the DMA address used by the controller */ ++dma_addr_t bsa_dma_addr; ++unsigned int bsa_dma_len; ++ ++int ++bsa_scsi_sata_get_dma_addr(struct ata_port *ap, dma_addr_t *dma_addr, unsigned int *dma_len) ++{ ++ //Not used struct sil24_port_priv *pp = ap->private_data; ++ ++ *dma_addr = bsa_dma_addr; ++ *dma_len = bsa_dma_len; ++ ++ return 0; ++} ++EXPORT_SYMBOL(bsa_scsi_sata_get_dma_addr); ++ ++void ++bsa_scsi_sata_fill_dma_addr(struct scatterlist *sg) ++{ ++ ++ bsa_dma_addr = cpu_to_le64(sg_dma_address(sg)); ++ bsa_dma_len = cpu_to_le32(sg_dma_len(sg)); ++} ++EXPORT_SYMBOL(bsa_scsi_sata_fill_dma_addr); +\ No newline at end of file +diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c +index 50ccc4f1e..42130e538 100644 +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -87,6 +87,13 @@ struct iommu_dma_cookie { + struct mutex mutex; + }; + ++struct iova_domain *cookie_iovad_bsa(struct iommu_domain *domain) ++{ ++ if (domain) ++ return &((struct iommu_dma_cookie *)domain->iova_cookie)->iovad; ++ return NULL; ++} ++ + static DEFINE_STATIC_KEY_FALSE(iommu_deferred_attach_enabled); + bool iommu_dma_forcedac __read_mostly; + +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index d14413916..f8386b8d8 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -37,6 +37,7 @@ + #include "iommu-priv.h" + + #include "iommu-sva.h" ++#include + + static struct kset *iommu_group_kset; + static DEFINE_IDA(iommu_group_ida); +@@ -2635,6 +2636,8 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, + } + + pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size); ++ if (bsa_is_domain_monitored(domain)) ++ bsa_iommu_iova_save_addr((dma_addr_t)iova, (unsigned int)size); + + while (size) { + size_t pgsize, count, mapped = 0; +diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c +index 98b0329b7..7163829b8 100644 +--- a/drivers/irqchip/irq-gic-v3.c ++++ b/drivers/irqchip/irq-gic-v3.c +@@ -64,6 +64,9 @@ struct gic_chip_data { + struct partition_desc **ppi_descs; + }; + ++/* ACS GIC Patch */ ++struct irq_domain *acs_irq_domain = NULL; ++ + #define T241_CHIPS_MAX 4 + static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly; + static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum); +@@ -180,6 +183,14 @@ static enum gic_intid_range get_intid_range(struct irq_data *d) + return __get_intid_range(d->hwirq); + } + ++struct irq_domain* acs_get_irq_domain(void) ++{ ++ if (acs_irq_domain) ++ return acs_irq_domain; ++ return 0; ++} ++EXPORT_SYMBOL(acs_get_irq_domain); ++ + static inline unsigned int gic_irq(struct irq_data *d) + { + return d->hwirq; +@@ -1657,6 +1668,10 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, + if (ret) + return ret; + } ++ /* ACS GIC Patch */ ++ if (domain) { ++ acs_irq_domain = domain; ++ } + + return 0; + } +diff --git a/include/linux/bsa-iommu.h b/include/linux/bsa-iommu.h +new file mode 100644 +index 000000000..81a516e5b +--- /dev/null ++++ b/include/linux/bsa-iommu.h +@@ -0,0 +1,50 @@ ++/* ++ * The IOMMU-API to BSA Architecture Compliance Suite glue layer. ++ * ++ * Copyright (C) 2021 ARM Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef __BSA_IOMMU_H ++#define __BSA_IOMMU_H ++ ++#ifdef CONFIG_IOMMU_DMA ++#include ++ ++#include ++ ++ ++#define BSA_IOVA_DMA_ARRAY_LEN 4 ++ ++typedef struct _bsa_iova_array_ { ++ dma_addr_t dma_addr; ++ unsigned int dma_len; ++}bsa_iova_array; ++ ++void *bsa_iommu_dma_get_iova(struct device *dev, unsigned long long *base, unsigned long int *size, ++ phys_addr_t *phy_addr, void *in_node); ++ ++void bsa_iommu_dev_start_monitor(struct device *dev); ++ ++void bsa_iommu_dev_stop_monitor(struct device *dev); ++int bsa_is_domain_monitored(struct iommu_domain *dom); ++ ++void bsa_iommu_iova_save_addr(dma_addr_t addr, unsigned int length); ++ ++unsigned int bsa_iommu_iova_get_addr(unsigned int index, dma_addr_t *addr); ++ ++enum dev_dma_attr bsa_dev_get_dma_attr(struct device *dev); ++ ++#endif ++#endif +\ No newline at end of file +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index ee0a82c60..4bf73cb17 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -627,5 +627,7 @@ static inline struct irq_domain *irq_find_matching_fwnode( + return NULL; + } + #endif /* !CONFIG_IRQ_DOMAIN */ ++/* ACS GIC Patch */ ++struct irq_domain* acs_get_irq_domain(void); + + #endif /* _LINUX_IRQDOMAIN_H */ +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 0bdef4fe9..7d1591f76 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -1552,7 +1552,7 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, + + return ret; + } +-EXPORT_SYMBOL_GPL(__irq_domain_alloc_irqs); ++EXPORT_SYMBOL(__irq_domain_alloc_irqs); + + /* The irq_data was moved, fix the revmap to refer to the new location */ + static void irq_domain_fix_revmap(struct irq_data *d) +diff --git a/mm/init-mm.c b/mm/init-mm.c +index 24c809379..6ab2e9e1e 100644 +--- a/mm/init-mm.c ++++ b/mm/init-mm.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -46,6 +47,7 @@ struct mm_struct init_mm = { + .cpu_bitmap = CPU_BITS_NONE, + INIT_MM_CONTEXT(init_mm) + }; ++EXPORT_SYMBOL(init_mm); + + void setup_initial_init_mm(void *start_code, void *end_code, + void *end_data, void *brk) +-- +2.34.1 +