|
@@ -1114,11 +1114,15 @@ static int device_flush_iotlb(struct iommu_dev_data *dev_data,
|
|
|
static int device_flush_dte(struct iommu_dev_data *dev_data)
|
|
|
{
|
|
|
struct amd_iommu *iommu;
|
|
|
+ u16 alias;
|
|
|
int ret;
|
|
|
|
|
|
iommu = amd_iommu_rlookup_table[dev_data->devid];
|
|
|
+ alias = amd_iommu_alias_table[dev_data->devid];
|
|
|
|
|
|
ret = iommu_flush_dte(iommu, dev_data->devid);
|
|
|
+ if (!ret && alias != dev_data->devid)
|
|
|
+ ret = iommu_flush_dte(iommu, alias);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -1984,29 +1988,36 @@ static void do_attach(struct iommu_dev_data *dev_data,
|
|
|
struct protection_domain *domain)
|
|
|
{
|
|
|
struct amd_iommu *iommu;
|
|
|
+ u16 alias;
|
|
|
bool ats;
|
|
|
|
|
|
iommu = amd_iommu_rlookup_table[dev_data->devid];
|
|
|
+ alias = amd_iommu_alias_table[dev_data->devid];
|
|
|
ats = dev_data->ats.enabled;
|
|
|
|
|
|
/* Update data structures */
|
|
|
dev_data->domain = domain;
|
|
|
list_add(&dev_data->list, &domain->dev_list);
|
|
|
- set_dte_entry(dev_data->devid, domain, ats);
|
|
|
|
|
|
/* Do reference counting */
|
|
|
domain->dev_iommu[iommu->index] += 1;
|
|
|
domain->dev_cnt += 1;
|
|
|
|
|
|
- /* Flush the DTE entry */
|
|
|
+ /* Update device table */
|
|
|
+ set_dte_entry(dev_data->devid, domain, ats);
|
|
|
+ if (alias != dev_data->devid)
|
|
|
+ set_dte_entry(dev_data->devid, domain, ats);
|
|
|
+
|
|
|
device_flush_dte(dev_data);
|
|
|
}
|
|
|
|
|
|
static void do_detach(struct iommu_dev_data *dev_data)
|
|
|
{
|
|
|
struct amd_iommu *iommu;
|
|
|
+ u16 alias;
|
|
|
|
|
|
iommu = amd_iommu_rlookup_table[dev_data->devid];
|
|
|
+ alias = amd_iommu_alias_table[dev_data->devid];
|
|
|
|
|
|
/* decrease reference counters */
|
|
|
dev_data->domain->dev_iommu[iommu->index] -= 1;
|
|
@@ -2016,6 +2027,8 @@ static void do_detach(struct iommu_dev_data *dev_data)
|
|
|
dev_data->domain = NULL;
|
|
|
list_del(&dev_data->list);
|
|
|
clear_dte_entry(dev_data->devid);
|
|
|
+ if (alias != dev_data->devid)
|
|
|
+ clear_dte_entry(alias);
|
|
|
|
|
|
/* Flush the DTE entry */
|
|
|
device_flush_dte(dev_data);
|