Skip to content

Commit 2bf9a0a

Browse files
Wan Zongshunjoergroedel
authored andcommitted
iommu/amd: Add iommu support for ACPI HID devices
Current IOMMU driver make assumption that the downstream devices are PCI. With the newly added ACPI-HID IVHD device entry support, this is no longer true. This patch is to add dev type check and to distinguish the pci and acpihid device code path. Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com> Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 7aba6cb commit 2bf9a0a

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <linux/ratelimit.h>
2121
#include <linux/pci.h>
22+
#include <linux/acpi.h>
2223
#include <linux/pci-ats.h>
2324
#include <linux/bitmap.h>
2425
#include <linux/slab.h>
@@ -216,13 +217,60 @@ static struct iommu_dev_data *find_dev_data(u16 devid)
216217
return dev_data;
217218
}
218219

219-
static inline u16 get_device_id(struct device *dev)
220+
static inline int match_hid_uid(struct device *dev,
221+
struct acpihid_map_entry *entry)
222+
{
223+
const char *hid, *uid;
224+
225+
hid = acpi_device_hid(ACPI_COMPANION(dev));
226+
uid = acpi_device_uid(ACPI_COMPANION(dev));
227+
228+
if (!hid || !(*hid))
229+
return -ENODEV;
230+
231+
if (!uid || !(*uid))
232+
return strcmp(hid, entry->hid);
233+
234+
if (!(*entry->uid))
235+
return strcmp(hid, entry->hid);
236+
237+
return (strcmp(hid, entry->hid) || strcmp(uid, entry->uid));
238+
}
239+
240+
static inline u16 get_pci_device_id(struct device *dev)
220241
{
221242
struct pci_dev *pdev = to_pci_dev(dev);
222243

223244
return PCI_DEVID(pdev->bus->number, pdev->devfn);
224245
}
225246

247+
static inline int get_acpihid_device_id(struct device *dev,
248+
struct acpihid_map_entry **entry)
249+
{
250+
struct acpihid_map_entry *p;
251+
252+
list_for_each_entry(p, &acpihid_map, list) {
253+
if (!match_hid_uid(dev, p)) {
254+
if (entry)
255+
*entry = p;
256+
return p->devid;
257+
}
258+
}
259+
return -EINVAL;
260+
}
261+
262+
static inline int get_device_id(struct device *dev)
263+
{
264+
int devid;
265+
266+
if (dev_is_pci(dev))
267+
devid = get_pci_device_id(dev);
268+
else
269+
devid = get_acpihid_device_id(dev, NULL);
270+
271+
return devid;
272+
}
273+
226274
static struct iommu_dev_data *get_dev_data(struct device *dev)
227275
{
228276
return dev->archdata.iommu;
@@ -303,10 +351,6 @@ static bool check_device(struct device *dev)
303351
if (!dev || !dev->dma_mask)
304352
return false;
305353

306-
/* No PCI device */
307-
if (!dev_is_pci(dev))
308-
return false;
309-
310354
devid = get_device_id(dev);
311355
if (IS_ERR_VALUE(devid))
312356
return false;
@@ -344,7 +388,6 @@ static void init_iommu_group(struct device *dev)
344388

345389
static int iommu_init_device(struct device *dev)
346390
{
347-
struct pci_dev *pdev = to_pci_dev(dev);
348391
struct iommu_dev_data *dev_data;
349392
int devid;
350393

@@ -359,10 +402,10 @@ static int iommu_init_device(struct device *dev)
359402
if (!dev_data)
360403
return -ENOMEM;
361404

362-
if (pci_iommuv2_capable(pdev)) {
405+
if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
363406
struct amd_iommu *iommu;
364407

365-
iommu = amd_iommu_rlookup_table[dev_data->devid];
408+
iommu = amd_iommu_rlookup_table[dev_data->devid];
366409
dev_data->iommu_v2 = iommu->is_iommu_v2;
367410
}
368411

@@ -2239,13 +2282,17 @@ static bool pci_pri_tlp_required(struct pci_dev *pdev)
22392282
static int attach_device(struct device *dev,
22402283
struct protection_domain *domain)
22412284
{
2242-
struct pci_dev *pdev = to_pci_dev(dev);
2285+
struct pci_dev *pdev;
22432286
struct iommu_dev_data *dev_data;
22442287
unsigned long flags;
22452288
int ret;
22462289

22472290
dev_data = get_dev_data(dev);
22482291

2292+
if (!dev_is_pci(dev))
2293+
goto skip_ats_check;
2294+
2295+
pdev = to_pci_dev(dev);
22492296
if (domain->flags & PD_IOMMUV2_MASK) {
22502297
if (!dev_data->passthrough)
22512298
return -EINVAL;
@@ -2264,6 +2311,7 @@ static int attach_device(struct device *dev,
22642311
dev_data->ats.qdep = pci_ats_queue_depth(pdev);
22652312
}
22662313

2314+
skip_ats_check:
22672315
write_lock_irqsave(&amd_iommu_devtable_lock, flags);
22682316
ret = __attach_device(dev_data, domain);
22692317
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
@@ -2320,6 +2368,9 @@ static void detach_device(struct device *dev)
23202368
__detach_device(dev_data);
23212369
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
23222370

2371+
if (!dev_is_pci(dev))
2372+
return;
2373+
23232374
if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2)
23242375
pdev_iommuv2_disable(to_pci_dev(dev));
23252376
else if (dev_data->ats.enabled)

0 commit comments

Comments
 (0)