@@ -85,6 +85,8 @@ static void set_dte_entry(struct amd_iommu *iommu,
8585
8686static void iommu_flush_dte_sync (struct amd_iommu * iommu , u16 devid );
8787
88+ static struct iommu_dev_data * find_dev_data (struct amd_iommu * iommu , u16 devid );
89+
8890/****************************************************************************
8991 *
9092 * Helper functions
@@ -202,6 +204,21 @@ static void update_dte256(struct amd_iommu *iommu, struct iommu_dev_data *dev_da
202204 spin_unlock_irqrestore (& dev_data -> dte_lock , flags );
203205}
204206
207+ static void get_dte256 (struct amd_iommu * iommu , struct iommu_dev_data * dev_data ,
208+ struct dev_table_entry * dte )
209+ {
210+ unsigned long flags ;
211+ struct dev_table_entry * ptr ;
212+ struct dev_table_entry * dev_table = get_dev_table (iommu );
213+
214+ ptr = & dev_table [dev_data -> devid ];
215+
216+ spin_lock_irqsave (& dev_data -> dte_lock , flags );
217+ dte -> data128 [0 ] = ptr -> data128 [0 ];
218+ dte -> data128 [1 ] = ptr -> data128 [1 ];
219+ spin_unlock_irqrestore (& dev_data -> dte_lock , flags );
220+ }
221+
205222static inline bool pdom_is_v2_pgtbl_mode (struct protection_domain * pdom )
206223{
207224 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
350367
351368static int clone_alias (struct pci_dev * pdev , u16 alias , void * data )
352369{
370+ struct dev_table_entry new ;
353371 struct amd_iommu * iommu ;
354- struct dev_table_entry * dev_table ;
372+ struct iommu_dev_data * dev_data , * alias_data ;
355373 u16 devid = pci_dev_id (pdev );
374+ int ret = 0 ;
356375
357376 if (devid == alias )
358377 return 0 ;
@@ -361,13 +380,27 @@ static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
361380 if (!iommu )
362381 return 0 ;
363382
364- amd_iommu_set_rlookup_table (iommu , alias );
365- dev_table = get_dev_table (iommu );
366- memcpy (dev_table [alias ].data ,
367- dev_table [devid ].data ,
368- sizeof (dev_table [alias ].data ));
383+ /* Copy the data from pdev */
384+ dev_data = dev_iommu_priv_get (& pdev -> dev );
385+ if (!dev_data ) {
386+ pr_err ("%s : Failed to get dev_data for 0x%x\n" , __func__ , devid );
387+ ret = - EINVAL ;
388+ goto out ;
389+ }
390+ get_dte256 (iommu , dev_data , & new );
369391
370- return 0 ;
392+ /* Setup alias */
393+ alias_data = find_dev_data (iommu , alias );
394+ if (!alias_data ) {
395+ pr_err ("%s : Failed to get alias dev_data for 0x%x\n" , __func__ , alias );
396+ ret = - EINVAL ;
397+ goto out ;
398+ }
399+ update_dte256 (iommu , alias_data , & new );
400+
401+ amd_iommu_set_rlookup_table (iommu , alias );
402+ out :
403+ return ret ;
371404}
372405
373406static 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)
640673 return - ENOMEM ;
641674
642675 dev_data -> dev = dev ;
676+
677+ /*
678+ * The dev_iommu_priv_set() needes to be called before setup_aliases.
679+ * Otherwise, subsequent call to dev_iommu_priv_get() will fail.
680+ */
681+ dev_iommu_priv_set (dev , dev_data );
643682 setup_aliases (iommu , dev );
644683
645684 /*
@@ -653,8 +692,6 @@ static int iommu_init_device(struct amd_iommu *iommu, struct device *dev)
653692 dev_data -> flags = pdev_get_caps (to_pci_dev (dev ));
654693 }
655694
656- dev_iommu_priv_set (dev , dev_data );
657-
658695 return 0 ;
659696}
660697
@@ -685,10 +722,13 @@ static void iommu_ignore_device(struct amd_iommu *iommu, struct device *dev)
685722static void dump_dte_entry (struct amd_iommu * iommu , u16 devid )
686723{
687724 int i ;
688- struct dev_table_entry * dev_table = get_dev_table (iommu );
725+ struct dev_table_entry dte ;
726+ struct iommu_dev_data * dev_data = find_dev_data (iommu , devid );
727+
728+ get_dte256 (iommu , dev_data , & dte );
689729
690730 for (i = 0 ; i < 4 ; ++ i )
691- pr_err ("DTE[%d]: %016llx\n" , i , dev_table [ devid ] .data [i ]);
731+ pr_err ("DTE[%d]: %016llx\n" , i , dte .data [i ]);
692732}
693733
694734static void dump_command (unsigned long phys_addr )
0 commit comments