]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommu/amd: Introduce helper function get_dte256()
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Mon, 18 Nov 2024 05:49:34 +0000 (05:49 +0000)
committerJoerg Roedel <jroedel@suse.de>
Wed, 18 Dec 2024 08:37:41 +0000 (09:37 +0100)
And use it in clone_alias() along with update_dte256().
Also use get_dte256() in dump_dte_entry().

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Link: https://lore.kernel.org/r/20241118054937.5203-7-suravee.suthikulpanit@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/amd/iommu.c

index 0f4b5f4acd307c660326bf1435f496ae6bd45214..b7b5dce10813c8fede720ad1b457f4440edd3ee8 100644 (file)
@@ -85,6 +85,8 @@ static void set_dte_entry(struct amd_iommu *iommu,
 
 static void iommu_flush_dte_sync(struct amd_iommu *iommu, u16 devid);
 
+static struct iommu_dev_data *find_dev_data(struct amd_iommu *iommu, u16 devid);
+
 /****************************************************************************
  *
  * Helper functions
@@ -202,6 +204,21 @@ static void update_dte256(struct amd_iommu *iommu, struct iommu_dev_data *dev_da
        spin_unlock_irqrestore(&dev_data->dte_lock, flags);
 }
 
+static void get_dte256(struct amd_iommu *iommu, struct iommu_dev_data *dev_data,
+                     struct dev_table_entry *dte)
+{
+       unsigned long flags;
+       struct dev_table_entry *ptr;
+       struct dev_table_entry *dev_table = get_dev_table(iommu);
+
+       ptr = &dev_table[dev_data->devid];
+
+       spin_lock_irqsave(&dev_data->dte_lock, flags);
+       dte->data128[0] = ptr->data128[0];
+       dte->data128[1] = ptr->data128[1];
+       spin_unlock_irqrestore(&dev_data->dte_lock, flags);
+}
+
 static inline bool pdom_is_v2_pgtbl_mode(struct protection_domain *pdom)
 {
        return (pdom && (pdom->pd_mode == PD_MODE_V2));
@@ -350,9 +367,11 @@ static struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid
 
 static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
+       struct dev_table_entry new;
        struct amd_iommu *iommu;
-       struct dev_table_entry *dev_table;
+       struct iommu_dev_data *dev_data, *alias_data;
        u16 devid = pci_dev_id(pdev);
+       int ret = 0;
 
        if (devid == alias)
                return 0;
@@ -361,13 +380,27 @@ static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
        if (!iommu)
                return 0;
 
-       amd_iommu_set_rlookup_table(iommu, alias);
-       dev_table = get_dev_table(iommu);
-       memcpy(dev_table[alias].data,
-              dev_table[devid].data,
-              sizeof(dev_table[alias].data));
+       /* Copy the data from pdev */
+       dev_data = dev_iommu_priv_get(&pdev->dev);
+       if (!dev_data) {
+               pr_err("%s : Failed to get dev_data for 0x%x\n", __func__, devid);
+               ret = -EINVAL;
+               goto out;
+       }
+       get_dte256(iommu, dev_data, &new);
 
-       return 0;
+       /* Setup alias */
+       alias_data = find_dev_data(iommu, alias);
+       if (!alias_data) {
+               pr_err("%s : Failed to get alias dev_data for 0x%x\n", __func__, alias);
+               ret = -EINVAL;
+               goto out;
+       }
+       update_dte256(iommu, alias_data, &new);
+
+       amd_iommu_set_rlookup_table(iommu, alias);
+out:
+       return ret;
 }
 
 static void clone_aliases(struct amd_iommu *iommu, struct device *dev)
@@ -640,6 +673,12 @@ static int iommu_init_device(struct amd_iommu *iommu, struct device *dev)
                return -ENOMEM;
 
        dev_data->dev = dev;
+
+       /*
+        * The dev_iommu_priv_set() needes to be called before setup_aliases.
+        * Otherwise, subsequent call to dev_iommu_priv_get() will fail.
+        */
+       dev_iommu_priv_set(dev, dev_data);
        setup_aliases(iommu, dev);
 
        /*
@@ -653,8 +692,6 @@ static int iommu_init_device(struct amd_iommu *iommu, struct device *dev)
                dev_data->flags = pdev_get_caps(to_pci_dev(dev));
        }
 
-       dev_iommu_priv_set(dev, dev_data);
-
        return 0;
 }
 
@@ -685,10 +722,13 @@ static void iommu_ignore_device(struct amd_iommu *iommu, struct device *dev)
 static void dump_dte_entry(struct amd_iommu *iommu, u16 devid)
 {
        int i;
-       struct dev_table_entry *dev_table = get_dev_table(iommu);
+       struct dev_table_entry dte;
+       struct iommu_dev_data *dev_data = find_dev_data(iommu, devid);
+
+       get_dte256(iommu, dev_data, &dte);
 
        for (i = 0; i < 4; ++i)
-               pr_err("DTE[%d]: %016llx\n", i, dev_table[devid].data[i]);
+               pr_err("DTE[%d]: %016llx\n", i, dte.data[i]);
 }
 
 static void dump_command(unsigned long phys_addr)