Re: [PATCH] pci, dmar: Update dmar units devices list during hotplug

From: Yinghai Lu
Date: Wed May 25 2011 - 01:45:57 EST


On 05/24/2011 04:02 PM, Yinghai Lu wrote:
> On 05/24/2011 03:38 PM, Alex Williamson wrote:
>> On Tue, 2011-05-24 at 14:45 -0700, Yinghai Lu wrote:
>>> No, it does not work.
>>
>> I didn't say this wasn't without some effort, just thought it might give
>> you a jump start.
>
> ok, let me debug it tonight.
>
> looks like that pdev is not freed, but already get removed from the device tree.
>
> may need to pass pci_dev pointer directly.
>

keep getting:

[ 784.364244] BUG: sleeping function called from invalid context at kernel/rwsem.c:21
[ 784.364253] in_atomic(): 0, irqs_disabled(): 1, pid: 29398, name: work_for_cpu
[ 784.364259] INFO: lockdep is turned off.
[ 784.364265] irq event stamp: 0
[ 784.364271] hardirqs last enabled at (0): [< (null)>] (null)
[ 784.364282] hardirqs last disabled at (0): [<ffffffff8107ba5e>] copy_process+0x43b/0xd95
[ 784.364305] softirqs last enabled at (0): [<ffffffff8107ba5e>] copy_process+0x43b/0xd95
[ 784.364318] softirqs last disabled at (0): [< (null)>] (null)
[ 784.364332] Pid: 29398, comm: work_for_cpu Not tainted 2.6.39-tip-yh-06791-gb282579-dirty #1047
[ 784.364339] Call Trace:
[ 784.364375] [<ffffffff810ad12a>] ? print_irqtrace_events+0xd0/0xd4
[ 784.364392] [<ffffffff81071572>] __might_sleep+0xf2/0xf6
[ 784.364410] [<ffffffff81c20fc0>] down_read+0x26/0x91
[ 784.364429] [<ffffffff8134c089>] pci_find_next_bus+0x45/0x75
[ 784.364442] [<ffffffff8134c0fa>] pci_find_bus+0x41/0x54
[ 784.364457] [<ffffffff8136263f>] dmar_get_scope_dev+0x2f/0xe3
[ 784.364474] [<ffffffff813353ad>] ? random32+0x19/0x1b
[ 784.364488] [<ffffffff8136273d>] dmar_match_scope+0x4a/0xb6
[ 784.364502] [<ffffffff813628d4>] dmar_find_matched_drhd_unit+0x55/0x6f
[ 784.364519] [<ffffffff81367018>] get_domain_for_dev.clone.2+0x103/0x392
[ 784.364533] [<ffffffff81367459>] __get_valid_domain_for_dev+0x14/0x88
[ 784.364546] [<ffffffff813676c5>] __intel_map_single+0x58/0x174
[ 784.364559] [<ffffffff813678eb>] intel_alloc_coherent+0xc7/0xee
[ 784.364575] [<ffffffff811281dc>] pool_alloc_page.clone.0+0xc9/0x140
[ 784.364588] [<ffffffff811282d8>] dma_pool_alloc+0x85/0x131
[ 784.364603] [<ffffffff81134b8c>] ? should_failslab+0x44/0x48
[ 784.364618] [<ffffffff81132d62>] ? kmem_cache_alloc_trace+0x5e/0x123
[ 784.364635] [<ffffffff818429aa>] ehci_qh_alloc+0x59/0xd2
[ 784.364649] [<ffffffff81844451>] ehci_mem_init.clone.1+0x84/0x25c
[ 784.364660] [<ffffffff8184471b>] ehci_init+0xf2/0x245
[ 784.364671] [<ffffffff81844999>] ehci_pci_setup+0x12b/0x564
[ 784.364687] [<ffffffff818323d5>] usb_add_hcd+0x10f/0x318
[ 784.364703] [<ffffffff8183e31e>] usb_hcd_pci_probe+0x1e4/0x312
[ 784.364722] [<ffffffff8134ae25>] local_pci_probe+0x4d/0x96
[ 784.364739] [<ffffffff81093c4b>] ? cwq_dec_nr_in_flight+0x81/0x81
[ 784.364754] [<ffffffff81093c63>] do_work_for_cpu+0x18/0x2b
[ 784.364770] [<ffffffff81093c4b>] ? cwq_dec_nr_in_flight+0x81/0x81
[ 784.364787] [<ffffffff81099ea5>] kthread+0xa0/0xa8
[ 784.364801] [<ffffffff810adbcc>] ? trace_hardirqs_on_caller+0x1f/0x178
[ 784.364818] [<ffffffff81c2a214>] kernel_thread_helper+0x4/0x10
[ 784.364832] [<ffffffff81c224cc>] ? _raw_spin_unlock_irq+0x30/0x36
[ 784.364846] [<ffffffff810add32>] ? trace_hardirqs_on+0xd/0xf
[ 784.364861] [<ffffffff81c227c0>] ? retint_restore_args+0xe/0xe
[ 784.364880] [<ffffffff81099e05>] ? __init_kthread_worker+0x5b/0x5b
[ 784.364893] [<ffffffff81c2a210>] ? gs_change+0xb/0xb
[ 784.364902] DMAR: Device scope device [0000:40:00.00] not found
[ 784.364910] DMAR: Device scope device [0000:40:01.00] not found
[ 784.364931] DMAR: Device scope device [0000:40:03.00] not found
[ 784.364948] DMAR: Device scope device [0000:40:05.00] not found
[ 784.364961] DMAR: Device scope device [0000:40:07.00] not found
[ 784.364978] DMAR: Device scope device [0000:40:09.00] not found
[ 784.365019] DMAR: Device scope device [0000:80:00.00] not found
[ 784.365034] DMAR: Device scope device [0000:80:01.00] not found
[ 784.365053] DMAR: Device scope device [0000:80:03.00] not found
[ 784.365075] DMAR: Device scope device [0000:80:05.00] not found
[ 784.365094] DMAR: Device scope device [0000:80:07.00] not found
[ 784.365116] DMAR: Device scope device [0000:80:09.00] not found
[ 784.365166] DMAR: Device scope device [0000:c0:00.00] not found
[ 784.365193] DMAR: Device scope device [0000:c0:01.00] not found
[ 784.365216] DMAR: Device scope device [0000:c0:03.00] not found
[ 784.365243] DMAR: Device scope device [0000:c0:05.00] not found
[ 784.365266] DMAR: Device scope device [0000:c0:07.00] not found
[ 784.365284] DMAR: Device scope device [0000:c0:09.00] not found


updated patch:

---

drivers/pci/dmar.c | 164 ++++++++++++++++++++++++----------------------
drivers/pci/intel-iommu.c | 161 +++++++++++++++++++++++++--------------------
include/linux/dmar.h | 29 ++++++--
3 files changed, 202 insertions(+), 152 deletions(-)


Index: linux-2.6/drivers/pci/dmar.c
===================================================================
--- linux-2.6.orig/drivers/pci/dmar.c
+++ linux-2.6/drivers/pci/dmar.c
@@ -61,8 +61,8 @@ static void __init dmar_register_drhd_un
list_add(&drhd->list, &dmar_drhd_units);
}

-static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
- struct pci_dev **dev, u16 segment)
+struct pci_dev *dmar_get_scope_dev(struct acpi_dmar_device_scope *scope,
+ u16 segment)
{
struct pci_bus *bus;
struct pci_dev *pdev = NULL;
@@ -74,7 +74,7 @@ static int __init dmar_parse_one_dev_sco
count = (scope->length - sizeof(struct acpi_dmar_device_scope))
/ sizeof(struct acpi_dmar_pci_path);

- while (count) {
+ for (; count; path++, count--, bus = pdev->subordinate) {
if (pdev)
pci_dev_put(pdev);
/*
@@ -82,53 +82,77 @@ static int __init dmar_parse_one_dev_sco
* ignore it
*/
if (!bus) {
- printk(KERN_WARNING
- PREFIX "Device scope bus [%d] not found\n",
- scope->bus);
- break;
+ printk(KERN_WARNING PREFIX
+ "Device scope bus [%d] not found\n", scope->bus);
+ return NULL;
}
pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
if (!pdev) {
printk(KERN_WARNING PREFIX
- "Device scope device [%04x:%02x:%02x.%02x] not found\n",
- segment, bus->number, path->dev, path->fn);
- break;
+ "Device scope device [%04x:%02x:%02x.%02x] not found\n",
+ segment, bus->number, path->dev, path->fn);
+ return NULL;
}
- path ++;
- count --;
- bus = pdev->subordinate;
- }
- if (!pdev) {
- printk(KERN_WARNING PREFIX
- "Device scope device [%04x:%02x:%02x.%02x] not found\n",
- segment, scope->bus, path->dev, path->fn);
- *dev = NULL;
+ }
+
+ return pdev;
+}
+
+static int dmar_match_scope_one(struct acpi_dmar_device_scope *scope,
+ struct pci_dev *dev, u16 segment)
+{
+ struct pci_dev *pdev;
+ int ret = 0;
+
+ if (segment != pci_domain_nr(dev->bus))
+ return 0;
+
+ pdev = dmar_get_scope_dev(scope, segment);
+ if (!pdev)
return 0;
+
+ if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT) {
+ if (dev == pdev)
+ ret = 1;
+ } else {
+ while (dev) {
+ if (dev == pdev) {
+ ret = 1;
+ break;
+ }
+ dev = dev->bus->self;
+ }
}
- if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
- pdev->subordinate) || (scope->entry_type == \
- ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
- pci_dev_put(pdev);
- printk(KERN_WARNING PREFIX
- "Device scope type does not match for %s\n",
- pci_name(pdev));
- return -EINVAL;
+
+ pci_dev_put(pdev);
+
+ return ret;
+}
+
+int dmar_match_scope(struct acpi_dmar_device_scope **scopes, int cnt,
+ struct pci_dev *dev, u16 segment)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++) {
+ if (dmar_match_scope_one(scopes[i], dev, segment))
+ return 1;
}
- *dev = pdev;
return 0;
}

static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
- struct pci_dev ***devices, u16 segment)
+ struct acpi_dmar_device_scope ***scopes)
{
struct acpi_dmar_device_scope *scope;
- void * tmp = start;
- int index;
- int ret;
+ void *tmp = start;
+ int index = 0;

*cnt = 0;
+
while (start < end) {
scope = start;
+
if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
(*cnt)++;
@@ -138,27 +162,23 @@ static int __init dmar_parse_dev_scope(v
}
start += scope->length;
}
+
if (*cnt == 0)
return 0;

- *devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
- if (!*devices)
+ *scopes = kcalloc(*cnt, sizeof(struct acpi_dmar_device_scope *),
+ GFP_KERNEL);
+ if (!*scopes)
return -ENOMEM;

start = tmp;
- index = 0;
while (start < end) {
scope = start;
+
if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
- scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) {
- ret = dmar_parse_one_dev_scope(scope,
- &(*devices)[index], segment);
- if (ret) {
- kfree(*devices);
- return ret;
- }
- index ++;
- }
+ scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
+ (*scopes)[index++] = scope;
+
start += scope->length;
}

@@ -207,9 +227,8 @@ static int __init dmar_parse_dev(struct
return 0;

ret = dmar_parse_dev_scope((void *)(drhd + 1),
- ((void *)drhd) + drhd->header.length,
- &dmaru->devices_cnt, &dmaru->devices,
- drhd->segment);
+ ((void *)drhd) + drhd->header.length,
+ &dmaru->scopes_cnt, &dmaru->scopes);
if (ret) {
list_del(&dmaru->list);
kfree(dmaru);
@@ -253,10 +272,10 @@ rmrr_parse_dev(struct dmar_rmrr_unit *rm

rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
ret = dmar_parse_dev_scope((void *)(rmrr + 1),
- ((void *)rmrr) + rmrr->header.length,
- &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+ ((void *)rmrr) + rmrr->header.length,
+ &rmrru->scopes_cnt, &rmrru->scopes);

- if (ret || (rmrru->devices_cnt == 0)) {
+ if (ret || (rmrru->scopes_cnt == 0)) {
list_del(&rmrru->list);
kfree(rmrru);
}
@@ -293,10 +312,9 @@ static int __init atsr_parse_dev(struct

atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
rc = dmar_parse_dev_scope((void *)(atsr + 1),
- (void *)atsr + atsr->header.length,
- &atsru->devices_cnt, &atsru->devices,
- atsr->segment);
- if (rc || !atsru->devices_cnt) {
+ (void *)atsr + atsr->header.length,
+ &atsru->scopes_cnt, &atsru->scopes);
+ if (rc || !atsru->scopes_cnt) {
list_del(&atsru->list);
kfree(atsru);
}
@@ -310,6 +328,7 @@ int dmar_find_matched_atsr_unit(struct p
struct pci_bus *bus;
struct acpi_dmar_atsr *atsr;
struct dmar_atsr_unit *atsru;
+ struct pci_dev *pdev;

dev = pci_physfn(dev);

@@ -330,10 +349,18 @@ found:
return 0;

if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
- for (i = 0; i < atsru->devices_cnt; i++)
- if (atsru->devices[i] == bridge)
+ for (i = 0; i < atsru->scopes_cnt; i++) {
+ pdev = dmar_get_scope_dev(atsru->scopes[i],
+ atsr->segment);
+ if (!pdev)
+ continue;
+
+ if (pdev == bridge) {
+ pci_dev_put(pdev);
return 1;
- break;
+ }
+ pci_dev_put(pdev);
+ }
}
}

@@ -513,23 +540,6 @@ parse_dmar_table(void)
return ret;
}

-static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
- struct pci_dev *dev)
-{
- int index;
-
- while (dev) {
- for (index = 0; index < cnt; index++)
- if (dev == devices[index])
- return 1;
-
- /* Check our parent */
- dev = dev->bus->self;
- }
-
- return 0;
-}
-
struct dmar_drhd_unit *
dmar_find_matched_drhd_unit(struct pci_dev *dev)
{
@@ -544,11 +554,11 @@ dmar_find_matched_drhd_unit(struct pci_d
header);

if (dmaru->include_all &&
- drhd->segment == pci_domain_nr(dev->bus))
+ dmaru->segment == pci_domain_nr(dev->bus))
return dmaru;

- if (dmar_pci_device_match(dmaru->devices,
- dmaru->devices_cnt, dev))
+ if (dmar_match_scope(dmaru->scopes, dmaru->scopes_cnt,
+ dev, dmaru->segment))
return dmaru;
}

Index: linux-2.6/drivers/pci/intel-iommu.c
===================================================================
--- linux-2.6.orig/drivers/pci/intel-iommu.c
+++ linux-2.6/drivers/pci/intel-iommu.c
@@ -562,34 +562,49 @@ static void domain_update_iommu_cap(stru
domain_update_iommu_snooping(domain);
}

-static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
+static struct intel_iommu *__device_to_iommu(struct pci_dev *pdev)
{
- struct dmar_drhd_unit *drhd = NULL;
- int i;
+ struct dmar_drhd_unit *dmaru = NULL;
+ struct intel_iommu *found = NULL;
+ int segment = pci_domain_nr(pdev->bus);

- for_each_drhd_unit(drhd) {
- if (drhd->ignored)
+ for_each_drhd_unit(dmaru) {
+ if (dmaru->ignored)
continue;
- if (segment != drhd->segment)
+ if (segment != dmaru->segment)
continue;

- for (i = 0; i < drhd->devices_cnt; i++) {
- if (drhd->devices[i] &&
- drhd->devices[i]->bus->number == bus &&
- drhd->devices[i]->devfn == devfn)
- return drhd->iommu;
- if (drhd->devices[i] &&
- drhd->devices[i]->subordinate &&
- drhd->devices[i]->subordinate->number <= bus &&
- drhd->devices[i]->subordinate->subordinate >= bus)
- return drhd->iommu;
+ if (dmaru->include_all) {
+ found = dmaru->iommu;
+ break;
+ }
+
+ if (dmar_match_scope(dmaru->scopes, dmaru->scopes_cnt,
+ pdev, dmaru->segment)) {
+ found = dmaru->iommu;
+ break;
}

- if (drhd->include_all)
- return drhd->iommu;
}

- return NULL;
+ return found;
+}
+
+static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
+{
+ struct pci_dev *pdev;
+ struct intel_iommu *found = NULL;
+
+ pdev = pci_get_domain_bus_and_slot(segment, bus, devfn);
+
+ if (!pdev)
+ return NULL;
+
+ found = __device_to_iommu(pdev);
+
+ pci_dev_put(pdev);
+
+ return found;
}

static void domain_flush_cache(struct dmar_domain *domain,
@@ -990,12 +1005,12 @@ static void __iommu_flush_iotlb(struct i
}

static struct device_domain_info *iommu_support_dev_iotlb(
- struct dmar_domain *domain, int segment, u8 bus, u8 devfn)
+ struct dmar_domain *domain, struct intel_iommu *iommu,
+ int segment, u8 bus, u8 devfn)
{
int found = 0;
unsigned long flags;
struct device_domain_info *info;
- struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);

if (!ecap_dev_iotlb_support(iommu->ecap))
return NULL;
@@ -1441,8 +1456,8 @@ static void domain_exit(struct dmar_doma
free_domain_mem(domain);
}

-static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
- u8 bus, u8 devfn, int translation)
+static int domain_context_mapping_one(struct dmar_domain *domain,
+ struct pci_dev *pdev, int translation)
{
struct context_entry *context;
unsigned long flags;
@@ -1461,11 +1476,12 @@ static int domain_context_mapping_one(st
BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
translation != CONTEXT_TT_MULTI_LEVEL);

- iommu = device_to_iommu(segment, bus, devfn);
+ iommu = __device_to_iommu(pdev);
if (!iommu)
return -ENODEV;

- context = device_to_context_entry(iommu, bus, devfn);
+ context = device_to_context_entry(iommu, pdev->bus->number,
+ pdev->devfn);
if (!context)
return -ENOMEM;
spin_lock_irqsave(&iommu->lock, flags);
@@ -1522,7 +1538,7 @@ static int domain_context_mapping_one(st
context_set_domain_id(context, id);

if (translation != CONTEXT_TT_PASS_THROUGH) {
- info = iommu_support_dev_iotlb(domain, segment, bus, devfn);
+ info = iommu_support_dev_iotlb(domain, iommu, pdev);
translation = info ? CONTEXT_TT_DEV_IOTLB :
CONTEXT_TT_MULTI_LEVEL;
}
@@ -1578,9 +1594,7 @@ domain_context_mapping(struct dmar_domai
int ret;
struct pci_dev *tmp, *parent;

- ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
- pdev->bus->number, pdev->devfn,
- translation);
+ ret = domain_context_mapping_one(domain, pdev, translation);
if (ret)
return ret;

@@ -1591,25 +1605,19 @@ domain_context_mapping(struct dmar_domai
/* Secondary interface's bus number and devfn 0 */
parent = pdev->bus->self;
while (parent != tmp) {
- ret = domain_context_mapping_one(domain,
- pci_domain_nr(parent->bus),
- parent->bus->number,
- parent->devfn, translation);
+ ret = domain_context_mapping_one(domain, parent, translation);
if (ret)
return ret;
parent = parent->bus->self;
}
- if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
- return domain_context_mapping_one(domain,
- pci_domain_nr(tmp->subordinate),
- tmp->subordinate->number, 0,
- translation);
- else /* this is a legacy PCI bridge */
- return domain_context_mapping_one(domain,
- pci_domain_nr(tmp->bus),
- tmp->bus->number,
- tmp->devfn,
- translation);
+ if (pci_is_pcie(tmp)) {
+ /* this is a PCIe-to-PCI bridge */
+ struct pci_dev *child = pci_get_slot(tmp->subordinate, 0);
+ ret = domain_context_mapping_one(domain, child, translation);
+ pci_dev_put(child);
+ return ret;
+ } else /* this is a legacy PCI bridge */
+ return domain_context_mapping_one(domain, tmp, translation);
}

static int domain_context_mapped(struct pci_dev *pdev)
@@ -1618,8 +1626,7 @@ static int domain_context_mapped(struct
struct pci_dev *tmp, *parent;
struct intel_iommu *iommu;

- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
+ iommu = __device_to_iommu(pdev);
if (!iommu)
return -ENODEV;

@@ -2233,7 +2240,7 @@ static int __init init_dmars(int force_o
struct dmar_rmrr_unit *rmrr;
struct pci_dev *pdev;
struct intel_iommu *iommu;
- int i, ret;
+ int ret;

/*
* for each drhd
@@ -2382,18 +2389,22 @@ static int __init init_dmars(int force_o
*/
printk(KERN_INFO "IOMMU: Setting RMRR:\n");
for_each_rmrr_units(rmrr) {
- for (i = 0; i < rmrr->devices_cnt; i++) {
- pdev = rmrr->devices[i];
- /*
- * some BIOS lists non-exist devices in DMAR
- * table.
- */
+ struct acpi_dmar_reserved_memory *rmrrh;
+ int i;
+
+ rmrrh = container_of(rmrr->hdr,
+ struct acpi_dmar_reserved_memory, header);
+
+ for (i = 0; i < rmrr->scopes_cnt; i++) {
+ pdev = dmar_get_scope_dev(rmrr->scopes[i],
+ rmrrh->segment);
if (!pdev)
continue;
- ret = iommu_prepare_rmrr_dev(rmrr, pdev);
- if (ret)
+
+ if (iommu_prepare_rmrr_dev(rmrr, pdev))
printk(KERN_ERR
"IOMMU: mapping reserved region failed\n");
+ pci_dev_put(pdev);
}
}

@@ -3075,15 +3086,21 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_I
static void __init init_no_remapping_devices(void)
{
struct dmar_drhd_unit *drhd;
+ struct pci_dev *pdev;

for_each_drhd_unit(drhd) {
if (!drhd->include_all) {
int i;
- for (i = 0; i < drhd->devices_cnt; i++)
- if (drhd->devices[i] != NULL)
+ for (i = 0; i < drhd->scopes_cnt; i++) {
+ pdev = dmar_get_scope_dev(drhd->scopes[i],
+ drhd->segment);
+ if (pdev) {
+ pci_dev_put(pdev);
break;
+ }
+ }
/* ignore DMAR unit if no pci devices exist */
- if (i == drhd->devices_cnt)
+ if (i == drhd->scopes_cnt)
drhd->ignored = 1;
}
}
@@ -3096,20 +3113,28 @@ static void __init init_no_remapping_dev
if (drhd->ignored || drhd->include_all)
continue;

- for (i = 0; i < drhd->devices_cnt; i++)
- if (drhd->devices[i] &&
- !IS_GFX_DEVICE(drhd->devices[i]))
+ for (i = 0; i < drhd->scopes_cnt; i++) {
+ pdev = dmar_get_scope_dev(drhd->scopes[i],
+ drhd->segment);
+ if (pdev && !IS_GFX_DEVICE(pdev)) {
+ pci_dev_put(pdev);
break;
+ }
+ pci_dev_put(pdev);
+ }

- if (i < drhd->devices_cnt)
+ if (i < drhd->scopes_cnt)
continue;

/* bypass IOMMU if it is just for gfx devices */
drhd->ignored = 1;
- for (i = 0; i < drhd->devices_cnt; i++) {
- if (!drhd->devices[i])
+ for (i = 0; i < drhd->scopes_cnt; i++) {
+ pdev = dmar_get_scope_dev(drhd->scopes[i],
+ drhd->segment);
+ if (!pdev)
continue;
- drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+ pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+ pci_dev_put(pdev);
}
}
}
@@ -3378,8 +3403,7 @@ static void domain_remove_one_dev_info(s
int found = 0;
struct list_head *entry, *tmp;

- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
+ iommu = __device_to_iommu(pdev);
if (!iommu)
return;

@@ -3622,8 +3646,7 @@ static int intel_iommu_attach_device(str
}
}

- iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
- pdev->devfn);
+ iommu = __device_to_iommu(pdev);
if (!iommu)
return -ENODEV;

Index: linux-2.6/include/linux/dmar.h
===================================================================
--- linux-2.6.orig/include/linux/dmar.h
+++ linux-2.6/include/linux/dmar.h
@@ -32,8 +32,8 @@ struct dmar_drhd_unit {
struct list_head list; /* list of drhd units */
struct acpi_dmar_header *hdr; /* ACPI header */
u64 reg_base_addr; /* register base address*/
- struct pci_dev **devices; /* target device array */
- int devices_cnt; /* target device count */
+ struct acpi_dmar_device_scope **scopes; /* target scope array */
+ int scopes_cnt; /* target scope count */
u16 segment; /* PCI domain */
u8 ignored:1; /* ignore drhd */
u8 include_all:1;
@@ -55,6 +55,9 @@ extern struct list_head dmar_drhd_units;

extern int dmar_table_init(void);
extern int dmar_dev_scope_init(void);
+extern int dmar_match_scope(struct acpi_dmar_device_scope **, int,
+ struct pci_dev *, u16);
+extern struct pci_dev *dmar_get_scope_dev(struct acpi_dmar_device_scope *, u16);

/* Intel IOMMU detection */
extern int detect_intel_iommu(void);
@@ -72,6 +75,20 @@ static inline int dmar_table_init(void)
{
return -ENODEV;
}
+
+static inline int dmar_match_scope(struct acpi_dmar_device_scope **scopes,
+ int cnt, struct pci_dev *dev, u16 segment)
+{
+ return 0;
+}
+
+static inline struct pci_dev *dmar_get_scope_dev(
+ struct acpi_dmar_device_scope *scope,
+ u16 segment)
+{
+ return NULL;
+}
+
static inline int enable_drhd_fault_handling(void)
{
return -1;
@@ -212,8 +229,8 @@ struct dmar_rmrr_unit {
struct acpi_dmar_header *hdr; /* ACPI header */
u64 base_address; /* reserved base address*/
u64 end_address; /* reserved end address */
- struct pci_dev **devices; /* target devices */
- int devices_cnt; /* target device count */
+ struct acpi_dmar_device_scope **scopes; /* target scope array */
+ int scopes_cnt; /* target scope count */
};

#define for_each_rmrr_units(rmrr) \
@@ -222,8 +239,8 @@ struct dmar_rmrr_unit {
struct dmar_atsr_unit {
struct list_head list; /* list of ATSR units */
struct acpi_dmar_header *hdr; /* ACPI header */
- struct pci_dev **devices; /* target devices */
- int devices_cnt; /* target device count */
+ struct acpi_dmar_device_scope **scopes; /* target scope array */
+ int scopes_cnt; /* target scope count */
u8 include_all:1; /* include all ports */
};

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/