@@ -79,6 +79,8 @@ static void set_dte_entry(struct amd_iommu *iommu,
7979
8080static void iommu_flush_dte_sync (struct amd_iommu * iommu , u16 devid );
8181
82+ static struct iommu_dev_data * find_dev_data (struct amd_iommu * iommu , u16 devid );
83+
8284/****************************************************************************
8385 *
8486 * Helper functions
@@ -196,6 +198,21 @@ static void update_dte256(struct amd_iommu *iommu, struct iommu_dev_data *dev_da
196198 spin_unlock_irqrestore (& dev_data -> dte_lock , flags );
197199}
198200
201+ static void get_dte256 (struct amd_iommu * iommu , struct iommu_dev_data * dev_data ,
202+ struct dev_table_entry * dte )
203+ {
204+ unsigned long flags ;
205+ struct dev_table_entry * ptr ;
206+ struct dev_table_entry * dev_table = get_dev_table (iommu );
207+
208+ ptr = & dev_table [dev_data -> devid ];
209+
210+ spin_lock_irqsave (& dev_data -> dte_lock , flags );
211+ dte -> data128 [0 ] = ptr -> data128 [0 ];
212+ dte -> data128 [1 ] = ptr -> data128 [1 ];
213+ spin_unlock_irqrestore (& dev_data -> dte_lock , flags );
214+ }
215+
199216static inline bool pdom_is_v2_pgtbl_mode (struct protection_domain * pdom )
200217{
201218 return (pdom && (pdom -> pd_mode == PD_MODE_V2 ));
@@ -367,9 +384,11 @@ static struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid
367384
368385static int clone_alias (struct pci_dev * pdev , u16 alias , void * data )
369386{
387+ struct dev_table_entry new ;
370388 struct amd_iommu * iommu ;
371- struct dev_table_entry * dev_table ;
389+ struct iommu_dev_data * dev_data , * alias_data ;
372390 u16 devid = pci_dev_id (pdev );
391+ int ret = 0 ;
373392
374393 if (devid == alias )
375394 return 0 ;
@@ -378,13 +397,27 @@ static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
378397 if (!iommu )
379398 return 0 ;
380399
381- amd_iommu_set_rlookup_table (iommu , alias );
382- dev_table = get_dev_table (iommu );
383- memcpy (dev_table [alias ].data ,
384- dev_table [devid ].data ,
385- sizeof (dev_table [alias ].data ));
400+ /* Copy the data from pdev */
401+ dev_data = dev_iommu_priv_get (& pdev -> dev );
402+ if (!dev_data ) {
403+ pr_err ("%s : Failed to get dev_data for 0x%x\n" , __func__ , devid );
404+ ret = - EINVAL ;
405+ goto out ;
406+ }
407+ get_dte256 (iommu , dev_data , & new );
386408
387- return 0 ;
409+ /* Setup alias */
410+ alias_data = find_dev_data (iommu , alias );
411+ if (!alias_data ) {
412+ pr_err ("%s : Failed to get alias dev_data for 0x%x\n" , __func__ , alias );
413+ ret = - EINVAL ;
414+ goto out ;
415+ }
416+ update_dte256 (iommu , alias_data , & new );
417+
418+ amd_iommu_set_rlookup_table (iommu , alias );
419+ out :
420+ return ret ;
388421}
389422
390423static void clone_aliases (struct amd_iommu * iommu , struct device * dev )
@@ -657,6 +690,12 @@ static int iommu_init_device(struct amd_iommu *iommu, struct device *dev)
657690 return - ENOMEM ;
658691
659692 dev_data -> dev = dev ;
693+
694+ /*
695+ * The dev_iommu_priv_set() needes to be called before setup_aliases.
696+ * Otherwise, subsequent call to dev_iommu_priv_get() will fail.
697+ */
698+ dev_iommu_priv_set (dev , dev_data );
660699 setup_aliases (iommu , dev );
661700
662701 /*
@@ -670,8 +709,6 @@ static int iommu_init_device(struct amd_iommu *iommu, struct device *dev)
670709 dev_data -> flags = pdev_get_caps (to_pci_dev (dev ));
671710 }
672711
673- dev_iommu_priv_set (dev , dev_data );
674-
675712 return 0 ;
676713}
677714
@@ -718,10 +755,13 @@ static void amd_iommu_uninit_device(struct device *dev)
718755static void dump_dte_entry (struct amd_iommu * iommu , u16 devid )
719756{
720757 int i ;
721- struct dev_table_entry * dev_table = get_dev_table (iommu );
758+ struct dev_table_entry dte ;
759+ struct iommu_dev_data * dev_data = find_dev_data (iommu , devid );
760+
761+ get_dte256 (iommu , dev_data , & dte );
722762
723763 for (i = 0 ; i < 4 ; ++ i )
724- pr_err ("DTE[%d]: %016llx\n" , i , dev_table [ devid ] .data [i ]);
764+ pr_err ("DTE[%d]: %016llx\n" , i , dte .data [i ]);
725765}
726766
727767static void dump_command (unsigned long phys_addr )
0 commit comments