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
+