* [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug [not found] ` <1331018040-30725-1-git-send-email-yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> @ 2012-03-06 7:13 ` Yinghai Lu 2012-03-09 1:06 ` Bjorn Helgaas 2012-03-06 7:13 ` [PATCH 09/23] IOMMU: Fix tboot force iommu logic Yinghai Lu 1 sibling, 1 reply; 8+ messages in thread From: Yinghai Lu @ 2012-03-06 7:13 UTC (permalink / raw) To: Jesse Barnes, x86 Cc: Vinod Koul, linux-pci-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Yinghai Lu, Dan Williams, David Woodhouse When do pci remove/rescan on system that have more iommus, got [ 894.089745] Set context mapping for c4:00.0 [ 894.110890] mpt2sas3: Allocated physical memory: size(4293 kB) [ 894.112556] mpt2sas3: Current Controller Queue Depth(1883), Max Controller Queue Depth(2144) [ 894.127278] mpt2sas3: Scatter Gather Elements per IO(128) [ 894.361295] DRHD: handling fault status reg 2 [ 894.364053] DMAR:[DMA Read] Request device [c4:00.0] fault addr fffbe000 [ 894.364056] DMAR:[fault reason 02] Present bit in context entry is cl it turns out when remove/rescan, pci dev will be freed and will get another new dev. but drhd units still keep old one... so dmar_find_matched_drhd_unit will return wrong drhd and iommu for the device that is not on first iommu. So need to update devices in drhd_units during pci remove/rescan. Could save domain/bus/device/function aside in the list and according that info restore new dev to drhd_units later. Then dmar_find_matched_drdh_unit and device_to_iommu could return right drhd and iommu. Add remove_dev_from_drhd/restore_dev_to_drhd functions to do the real work. call them in device ADD_DEVICE and UNBOUND_DRIVER Need to do the samething to atsr. (expose dmar_atsr_units and add atsru->segment) After patch, will right iommu for the new dev and will not get DMAR error any more. -v2: add pci_dev_put/pci_dev_get to make refcount consistent. Signed-off-by: Yinghai Lu <yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> Cc: David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org> Cc: Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Cc: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org --- drivers/iommu/intel-iommu.c | 187 ++++++++++++++++++++++++++++++++++++++++--- include/linux/dmar.h | 4 + 2 files changed, 181 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c9c6053..39ef2ce 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -665,6 +665,159 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) return NULL; } +#ifdef CONFIG_HOTPLUG +struct dev_dmaru { + struct list_head list; + void *dmaru; + int index; + int segment; + unsigned char bus; + unsigned int devfn; +}; + +static int +save_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, + void *dmaru, int index, struct list_head *lh) +{ + struct dev_dmaru *m; + + m = kzalloc(sizeof(*m), GFP_KERNEL); + if (!m) + return -ENOMEM; + + m->segment = segment; + m->bus = bus; + m->devfn = devfn; + m->dmaru = dmaru; + m->index = index; + + list_add(&m->list, lh); + + return 0; +} + +static void +*get_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, + int *index, struct list_head *lh) +{ + struct dev_dmaru *m; + void *dmaru = NULL; + + list_for_each_entry(m, lh, list) { + if (m->segment == segment && + m->bus == bus && m->devfn == devfn) { + *index = m->index; + dmaru = m->dmaru; + list_del(&m->list); + kfree(m); + break; + } + } + + return dmaru; +} + +static LIST_HEAD(saved_dev_drhd_list); + +static void remove_dev_from_drhd(struct pci_dev *dev) +{ + struct dmar_drhd_unit *drhd = NULL; + int segment = pci_domain_nr(dev->bus); + int i; + + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + if (segment != drhd->segment) + continue; + + for (i = 0; i < drhd->devices_cnt; i++) { + if (drhd->devices[i] == dev) { + /* save it at first if it is in drhd */ + save_dev_dmaru(segment, dev->bus->number, + dev->devfn, drhd, i, + &saved_dev_drhd_list); + /* always remove it */ + pci_dev_put(dev); + drhd->devices[i] = NULL; + return; + } + } + } +} + +static void restore_dev_to_drhd(struct pci_dev *dev) +{ + struct dmar_drhd_unit *drhd = NULL; + int i; + + /* find the stored drhd */ + drhd = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, + dev->devfn, &i, &saved_dev_drhd_list); + /* restore that into drhd */ + if (drhd) + drhd->devices[i] = pci_dev_get(dev); +} +#else +static void remove_dev_from_drhd(struct pci_dev *dev) +{ +} + +static void restore_dev_to_drhd(struct pci_dev *dev) +{ +} +#endif + +#if defined(CONFIG_DMAR) && defined(CONFIG_HOTPLUG) +static LIST_HEAD(saved_dev_atsr_list); + +static void remove_dev_from_atsr(struct pci_dev *dev) +{ + struct dmar_atsr_unit *atsr = NULL; + int segment = pci_domain_nr(dev->bus); + int i; + + for_each_atsr_unit(atsr) { + if (segment != atsr->segment) + continue; + + for (i = 0; i < atsr->devices_cnt; i++) { + if (atsr->devices[i] == dev) { + /* save it at first if it is in drhd */ + save_dev_dmaru(segment, dev->bus->number, + dev->devfn, atsr, i, + &saved_dev_atsr_list); + /* always remove it */ + pci_dev_put(dev); + atsr->devices[i] = NULL; + return; + } + } + } +} + +static void restore_dev_to_atsr(struct pci_dev *dev) +{ + struct dmar_atsr_unit *atsr = NULL; + int i; + + /* find the stored atsr */ + atsr = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, + dev->devfn, &i, &saved_dev_atsr_list); + /* restore that into atsr */ + if (atsr) + atsr->devices[i] = pci_dev_get(dev); +} +#else +static void remove_dev_from_atsr(struct pci_dev *dev) +{ +} + +static void restore_dev_to_atsr(struct pci_dev *dev) +{ +} +#endif + static void domain_flush_cache(struct dmar_domain *domain, void *addr, int size) { @@ -3474,6 +3627,7 @@ int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr) atsru->hdr = hdr; atsru->include_all = atsr->flags & 0x1; + atsru->segment = atsr->segment; list_add(&atsru->list, &dmar_atsr_units); @@ -3505,16 +3659,13 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) { int i; struct pci_bus *bus; - struct acpi_dmar_atsr *atsr; struct dmar_atsr_unit *atsru; dev = pci_physfn(dev); - list_for_each_entry(atsru, &dmar_atsr_units, list) { - atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); - if (atsr->segment == pci_domain_nr(dev->bus)) + list_for_each_entry(atsru, &dmar_atsr_units, list) + if (atsru->segment == pci_domain_nr(dev->bus)) goto found; - } return 0; @@ -3574,20 +3725,36 @@ static int device_notifier(struct notifier_block *nb, struct pci_dev *pdev = to_pci_dev(dev); struct dmar_domain *domain; - if (iommu_no_mapping(dev)) + if (unlikely(dev->bus != &pci_bus_type)) return 0; - domain = find_domain(pdev); - if (!domain) - return 0; + switch (action) { + case BUS_NOTIFY_UNBOUND_DRIVER: + if (iommu_no_mapping(dev)) + goto out; + + if (iommu_pass_through) + goto out; + + domain = find_domain(pdev); + if (!domain) + goto out; - if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) { domain_remove_one_dev_info(domain, pdev); if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && list_empty(&domain->devices)) domain_exit(domain); +out: + remove_dev_from_drhd(pdev); + remove_dev_from_atsr(pdev); + + break; + case BUS_NOTIFY_ADD_DEVICE: + restore_dev_to_drhd(pdev); + restore_dev_to_atsr(pdev); + break; } return 0; diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 731a609..57e1375 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -236,9 +236,13 @@ struct dmar_atsr_unit { struct acpi_dmar_header *hdr; /* ACPI header */ struct pci_dev **devices; /* target devices */ int devices_cnt; /* target device count */ + u16 segment; /* PCI domain */ u8 include_all:1; /* include all ports */ }; +#define for_each_atsr_unit(atsr) \ + list_for_each_entry(atsr, &dmar_atsr_units, list) + int dmar_parse_rmrr_atsr_dev(void); extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); -- 1.7.7 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-06 7:13 ` [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug Yinghai Lu @ 2012-03-09 1:06 ` Bjorn Helgaas 2012-03-09 7:06 ` Yinghai Lu 0 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2012-03-09 1:06 UTC (permalink / raw) To: Yinghai Lu Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Tue, Mar 6, 2012 at 12:13 AM, Yinghai Lu <yinghai@kernel.org> wrote: > When do pci remove/rescan on system that have more iommus, got > > [ 894.089745] Set context mapping for c4:00.0 > [ 894.110890] mpt2sas3: Allocated physical memory: size(4293 kB) > [ 894.112556] mpt2sas3: Current Controller Queue Depth(1883), Max Controller Queue Depth(2144) > [ 894.127278] mpt2sas3: Scatter Gather Elements per IO(128) > [ 894.361295] DRHD: handling fault status reg 2 > [ 894.364053] DMAR:[DMA Read] Request device [c4:00.0] fault addr fffbe000 > [ 894.364056] DMAR:[fault reason 02] Present bit in context entry is cl > > it turns out when remove/rescan, pci dev will be freed and will get another new dev. > but drhd units still keep old one... so dmar_find_matched_drhd_unit will > return wrong drhd and iommu for the device that is not on first iommu. > > So need to update devices in drhd_units during pci remove/rescan. > > Could save domain/bus/device/function aside in the list and according that info > restore new dev to drhd_units later. > Then dmar_find_matched_drdh_unit and device_to_iommu could return right drhd and iommu. > > Add remove_dev_from_drhd/restore_dev_to_drhd functions to do the real work. > call them in device ADD_DEVICE and UNBOUND_DRIVER > > Need to do the samething to atsr. (expose dmar_atsr_units and add atsru->segment) > > After patch, will right iommu for the new dev and will not get DMAR error any more. > > -v2: add pci_dev_put/pci_dev_get to make refcount consistent. > > Signed-off-by: Yinghai Lu <yinghai@kernel.org> > Cc: David Woodhouse <dwmw2@infradead.org> > Cc: Vinod Koul <vinod.koul@intel.com> > Cc: Dan Williams <dan.j.williams@intel.com> > Cc: iommu@lists.linux-foundation.org > --- > drivers/iommu/intel-iommu.c | 187 ++++++++++++++++++++++++++++++++++++++++--- > include/linux/dmar.h | 4 + > 2 files changed, 181 insertions(+), 10 deletions(-) > > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index c9c6053..39ef2ce 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -665,6 +665,159 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) > return NULL; > } > > +#ifdef CONFIG_HOTPLUG > +struct dev_dmaru { > + struct list_head list; > + void *dmaru; > + int index; > + int segment; > + unsigned char bus; > + unsigned int devfn; > +}; > + > +static int > +save_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, > + void *dmaru, int index, struct list_head *lh) Follow the indentation style used elsewhere in the file: as much of the declaration on one line as will fit (here and below). I think the callers would read more naturally if you passed in the struct pci_dev * to save_dev_dmaru() and extracted the segment/bus/devfn here rather than in the callers. > +{ > + struct dev_dmaru *m; > + > + m = kzalloc(sizeof(*m), GFP_KERNEL); > + if (!m) > + return -ENOMEM; > + > + m->segment = segment; > + m->bus = bus; > + m->devfn = devfn; > + m->dmaru = dmaru; > + m->index = index; > + > + list_add(&m->list, lh); > + > + return 0; > +} > + > +static void > +*get_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, > + int *index, struct list_head *lh) > +{ > + struct dev_dmaru *m; > + void *dmaru = NULL; > + > + list_for_each_entry(m, lh, list) { > + if (m->segment == segment && > + m->bus == bus && m->devfn == devfn) { > + *index = m->index; > + dmaru = m->dmaru; > + list_del(&m->list); > + kfree(m); > + break; > + } > + } > + > + return dmaru; > +} > + > +static LIST_HEAD(saved_dev_drhd_list); > + > +static void remove_dev_from_drhd(struct pci_dev *dev) > +{ > + struct dmar_drhd_unit *drhd = NULL; > + int segment = pci_domain_nr(dev->bus); > + int i; > + > + for_each_drhd_unit(drhd) { > + if (drhd->ignored) > + continue; > + if (segment != drhd->segment) > + continue; > + > + for (i = 0; i < drhd->devices_cnt; i++) { > + if (drhd->devices[i] == dev) { > + /* save it at first if it is in drhd */ > + save_dev_dmaru(segment, dev->bus->number, > + dev->devfn, drhd, i, > + &saved_dev_drhd_list); > + /* always remove it */ > + pci_dev_put(dev); > + drhd->devices[i] = NULL; > + return; > + } > + } > + } > +} > + > +static void restore_dev_to_drhd(struct pci_dev *dev) > +{ > + struct dmar_drhd_unit *drhd = NULL; > + int i; > + > + /* find the stored drhd */ > + drhd = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, > + dev->devfn, &i, &saved_dev_drhd_list); > + /* restore that into drhd */ > + if (drhd) > + drhd->devices[i] = pci_dev_get(dev); > +} > +#else > +static void remove_dev_from_drhd(struct pci_dev *dev) > +{ > +} > + > +static void restore_dev_to_drhd(struct pci_dev *dev) > +{ > +} > +#endif > + > +#if defined(CONFIG_DMAR) && defined(CONFIG_HOTPLUG) > +static LIST_HEAD(saved_dev_atsr_list); > + > +static void remove_dev_from_atsr(struct pci_dev *dev) > +{ > + struct dmar_atsr_unit *atsr = NULL; > + int segment = pci_domain_nr(dev->bus); > + int i; > + > + for_each_atsr_unit(atsr) { > + if (segment != atsr->segment) > + continue; > + > + for (i = 0; i < atsr->devices_cnt; i++) { > + if (atsr->devices[i] == dev) { > + /* save it at first if it is in drhd */ > + save_dev_dmaru(segment, dev->bus->number, > + dev->devfn, atsr, i, > + &saved_dev_atsr_list); > + /* always remove it */ > + pci_dev_put(dev); > + atsr->devices[i] = NULL; > + return; > + } > + } > + } > +} > + > +static void restore_dev_to_atsr(struct pci_dev *dev) > +{ > + struct dmar_atsr_unit *atsr = NULL; > + int i; > + > + /* find the stored atsr */ > + atsr = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, > + dev->devfn, &i, &saved_dev_atsr_list); > + /* restore that into atsr */ > + if (atsr) > + atsr->devices[i] = pci_dev_get(dev); > +} > +#else > +static void remove_dev_from_atsr(struct pci_dev *dev) > +{ > +} > + > +static void restore_dev_to_atsr(struct pci_dev *dev) > +{ > +} > +#endif > + > static void domain_flush_cache(struct dmar_domain *domain, > void *addr, int size) > { > @@ -3474,6 +3627,7 @@ int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr) > > atsru->hdr = hdr; > atsru->include_all = atsr->flags & 0x1; > + atsru->segment = atsr->segment; > > list_add(&atsru->list, &dmar_atsr_units); > > @@ -3505,16 +3659,13 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) > { > int i; > struct pci_bus *bus; > - struct acpi_dmar_atsr *atsr; > struct dmar_atsr_unit *atsru; > > dev = pci_physfn(dev); > > - list_for_each_entry(atsru, &dmar_atsr_units, list) { > - atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); > - if (atsr->segment == pci_domain_nr(dev->bus)) > + list_for_each_entry(atsru, &dmar_atsr_units, list) > + if (atsru->segment == pci_domain_nr(dev->bus)) > goto found; > - } > > return 0; > > @@ -3574,20 +3725,36 @@ static int device_notifier(struct notifier_block *nb, > struct pci_dev *pdev = to_pci_dev(dev); > struct dmar_domain *domain; > > - if (iommu_no_mapping(dev)) > + if (unlikely(dev->bus != &pci_bus_type)) > return 0; > > - domain = find_domain(pdev); > - if (!domain) > - return 0; > + switch (action) { > + case BUS_NOTIFY_UNBOUND_DRIVER: > + if (iommu_no_mapping(dev)) > + goto out; > + > + if (iommu_pass_through) > + goto out; > + > + domain = find_domain(pdev); > + if (!domain) > + goto out; > > - if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) { > domain_remove_one_dev_info(domain, pdev); > > if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && > !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && > list_empty(&domain->devices)) > domain_exit(domain); > +out: > + remove_dev_from_drhd(pdev); > + remove_dev_from_atsr(pdev); > + > + break; > + case BUS_NOTIFY_ADD_DEVICE: > + restore_dev_to_drhd(pdev); > + restore_dev_to_atsr(pdev); > + break; > } > > return 0; > diff --git a/include/linux/dmar.h b/include/linux/dmar.h > index 731a609..57e1375 100644 > --- a/include/linux/dmar.h > +++ b/include/linux/dmar.h > @@ -236,9 +236,13 @@ struct dmar_atsr_unit { > struct acpi_dmar_header *hdr; /* ACPI header */ > struct pci_dev **devices; /* target devices */ > int devices_cnt; /* target device count */ > + u16 segment; /* PCI domain */ > u8 include_all:1; /* include all ports */ > }; > > +#define for_each_atsr_unit(atsr) \ > + list_for_each_entry(atsr, &dmar_atsr_units, list) > + > int dmar_parse_rmrr_atsr_dev(void); > extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); > extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); > -- > 1.7.7 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-pci" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-09 1:06 ` Bjorn Helgaas @ 2012-03-09 7:06 ` Yinghai Lu 2012-03-09 17:25 ` Bjorn Helgaas 0 siblings, 1 reply; 8+ messages in thread From: Yinghai Lu @ 2012-03-09 7:06 UTC (permalink / raw) To: Bjorn Helgaas Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Thu, Mar 8, 2012 at 5:06 PM, Bjorn Helgaas <bhelgaas@google.com> wrote: > On Tue, Mar 6, 2012 at 12:13 AM, Yinghai Lu <yinghai@kernel.org> wrote: >> When do pci remove/rescan on system that have more iommus, got >> >> [ 894.089745] Set context mapping for c4:00.0 >> [ 894.110890] mpt2sas3: Allocated physical memory: size(4293 kB) >> [ 894.112556] mpt2sas3: Current Controller Queue Depth(1883), Max Controller Queue Depth(2144) >> [ 894.127278] mpt2sas3: Scatter Gather Elements per IO(128) >> [ 894.361295] DRHD: handling fault status reg 2 >> [ 894.364053] DMAR:[DMA Read] Request device [c4:00.0] fault addr fffbe000 >> [ 894.364056] DMAR:[fault reason 02] Present bit in context entry is cl >> >> it turns out when remove/rescan, pci dev will be freed and will get another new dev. >> but drhd units still keep old one... so dmar_find_matched_drhd_unit will >> return wrong drhd and iommu for the device that is not on first iommu. >> >> So need to update devices in drhd_units during pci remove/rescan. >> >> Could save domain/bus/device/function aside in the list and according that info >> restore new dev to drhd_units later. >> Then dmar_find_matched_drdh_unit and device_to_iommu could return right drhd and iommu. >> >> Add remove_dev_from_drhd/restore_dev_to_drhd functions to do the real work. >> call them in device ADD_DEVICE and UNBOUND_DRIVER >> >> Need to do the samething to atsr. (expose dmar_atsr_units and add atsru->segment) >> >> After patch, will right iommu for the new dev and will not get DMAR error any more. >> >> -v2: add pci_dev_put/pci_dev_get to make refcount consistent. >> >> Signed-off-by: Yinghai Lu <yinghai@kernel.org> >> Cc: David Woodhouse <dwmw2@infradead.org> >> Cc: Vinod Koul <vinod.koul@intel.com> >> Cc: Dan Williams <dan.j.williams@intel.com> >> Cc: iommu@lists.linux-foundation.org >> --- >> drivers/iommu/intel-iommu.c | 187 ++++++++++++++++++++++++++++++++++++++++--- >> include/linux/dmar.h | 4 + >> 2 files changed, 181 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c >> index c9c6053..39ef2ce 100644 >> --- a/drivers/iommu/intel-iommu.c >> +++ b/drivers/iommu/intel-iommu.c >> @@ -665,6 +665,159 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) >> return NULL; >> } >> >> +#ifdef CONFIG_HOTPLUG >> +struct dev_dmaru { >> + struct list_head list; >> + void *dmaru; >> + int index; >> + int segment; >> + unsigned char bus; >> + unsigned int devfn; >> +}; >> + >> +static int >> +save_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, >> + void *dmaru, int index, struct list_head *lh) > > Follow the indentation style used elsewhere in the file: as much of > the declaration on one line as will fit (here and below). > > I think the callers would read more naturally if you passed in the > struct pci_dev * to save_dev_dmaru() and extracted the > segment/bus/devfn here rather than in the callers. Just want to keep save_dev_dmaru more consistent to get_dev_dmaru... Anyway, will change to pass struct pci_dev *dev instead. Yinghai ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-09 7:06 ` Yinghai Lu @ 2012-03-09 17:25 ` Bjorn Helgaas 2012-03-09 17:32 ` Yinghai Lu 0 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2012-03-09 17:25 UTC (permalink / raw) To: Yinghai Lu Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Fri, Mar 9, 2012 at 12:06 AM, Yinghai Lu <yinghai@kernel.org> wrote: > On Thu, Mar 8, 2012 at 5:06 PM, Bjorn Helgaas <bhelgaas@google.com> wrote: >> On Tue, Mar 6, 2012 at 12:13 AM, Yinghai Lu <yinghai@kernel.org> wrote: >>> When do pci remove/rescan on system that have more iommus, got >>> >>> [ 894.089745] Set context mapping for c4:00.0 >>> [ 894.110890] mpt2sas3: Allocated physical memory: size(4293 kB) >>> [ 894.112556] mpt2sas3: Current Controller Queue Depth(1883), Max Controller Queue Depth(2144) >>> [ 894.127278] mpt2sas3: Scatter Gather Elements per IO(128) >>> [ 894.361295] DRHD: handling fault status reg 2 >>> [ 894.364053] DMAR:[DMA Read] Request device [c4:00.0] fault addr fffbe000 >>> [ 894.364056] DMAR:[fault reason 02] Present bit in context entry is cl >>> >>> it turns out when remove/rescan, pci dev will be freed and will get another new dev. >>> but drhd units still keep old one... so dmar_find_matched_drhd_unit will >>> return wrong drhd and iommu for the device that is not on first iommu. >>> >>> So need to update devices in drhd_units during pci remove/rescan. >>> >>> Could save domain/bus/device/function aside in the list and according that info >>> restore new dev to drhd_units later. >>> Then dmar_find_matched_drdh_unit and device_to_iommu could return right drhd and iommu. >>> >>> Add remove_dev_from_drhd/restore_dev_to_drhd functions to do the real work. >>> call them in device ADD_DEVICE and UNBOUND_DRIVER >>> >>> Need to do the samething to atsr. (expose dmar_atsr_units and add atsru->segment) >>> >>> After patch, will right iommu for the new dev and will not get DMAR error any more. >>> >>> -v2: add pci_dev_put/pci_dev_get to make refcount consistent. >>> >>> Signed-off-by: Yinghai Lu <yinghai@kernel.org> >>> Cc: David Woodhouse <dwmw2@infradead.org> >>> Cc: Vinod Koul <vinod.koul@intel.com> >>> Cc: Dan Williams <dan.j.williams@intel.com> >>> Cc: iommu@lists.linux-foundation.org >>> --- >>> drivers/iommu/intel-iommu.c | 187 ++++++++++++++++++++++++++++++++++++++++--- >>> include/linux/dmar.h | 4 + >>> 2 files changed, 181 insertions(+), 10 deletions(-) >>> >>> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c >>> index c9c6053..39ef2ce 100644 >>> --- a/drivers/iommu/intel-iommu.c >>> +++ b/drivers/iommu/intel-iommu.c >>> @@ -665,6 +665,159 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) >>> return NULL; >>> } >>> >>> +#ifdef CONFIG_HOTPLUG >>> +struct dev_dmaru { >>> + struct list_head list; >>> + void *dmaru; >>> + int index; >>> + int segment; >>> + unsigned char bus; >>> + unsigned int devfn; >>> +}; >>> + >>> +static int >>> +save_dev_dmaru(int segment, unsigned char bus, unsigned int devfn, >>> + void *dmaru, int index, struct list_head *lh) >> >> Follow the indentation style used elsewhere in the file: as much of >> the declaration on one line as will fit (here and below). >> >> I think the callers would read more naturally if you passed in the >> struct pci_dev * to save_dev_dmaru() and extracted the >> segment/bus/devfn here rather than in the callers. > > Just want to keep save_dev_dmaru more consistent to get_dev_dmaru... Well, it looks like you can change both save_dev_dmaru() *and* get_dev_dmaru() to take a struct pci_dev *. I assumed that would be obvious. Bjorn ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-09 17:25 ` Bjorn Helgaas @ 2012-03-09 17:32 ` Yinghai Lu 2012-03-09 17:37 ` Bjorn Helgaas 0 siblings, 1 reply; 8+ messages in thread From: Yinghai Lu @ 2012-03-09 17:32 UTC (permalink / raw) To: Bjorn Helgaas Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Fri, Mar 9, 2012 at 9:25 AM, Bjorn Helgaas <bhelgaas@google.com> wrote: > > Well, it looks like you can change both save_dev_dmaru() *and* > get_dev_dmaru() to take a struct pci_dev *. I assumed that would be > obvious. no. get_dev_dmaru() have to use bus/devfn to retrieve the dev pointer. Yinghai ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-09 17:32 ` Yinghai Lu @ 2012-03-09 17:37 ` Bjorn Helgaas 2012-03-09 18:29 ` Yinghai Lu 0 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2012-03-09 17:37 UTC (permalink / raw) To: Yinghai Lu Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Fri, Mar 9, 2012 at 10:32 AM, Yinghai Lu <yinghai@kernel.org> wrote: > On Fri, Mar 9, 2012 at 9:25 AM, Bjorn Helgaas <bhelgaas@google.com> wrote: >> >> Well, it looks like you can change both save_dev_dmaru() *and* >> get_dev_dmaru() to take a struct pci_dev *. I assumed that would be >> obvious. > > no. > > get_dev_dmaru() have to use bus/devfn to retrieve the dev pointer. I expected something like that, but all I see in the patch is this: +static void restore_dev_to_drhd(struct pci_dev *dev) + drhd = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, + dev->devfn, &i, &saved_dev_drhd_list); +static void restore_dev_to_atsr(struct pci_dev *dev) + atsr = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, + dev->devfn, &i, &saved_dev_atsr_list); In both those cases, you have the struct pci_dev *. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug 2012-03-09 17:37 ` Bjorn Helgaas @ 2012-03-09 18:29 ` Yinghai Lu 0 siblings, 0 replies; 8+ messages in thread From: Yinghai Lu @ 2012-03-09 18:29 UTC (permalink / raw) To: Bjorn Helgaas Cc: Jesse Barnes, x86, linux-pci, linux-kernel, David Woodhouse, Vinod Koul, Dan Williams, iommu On Fri, Mar 9, 2012 at 9:37 AM, Bjorn Helgaas <bhelgaas@google.com> wrote: > On Fri, Mar 9, 2012 at 10:32 AM, Yinghai Lu <yinghai@kernel.org> wrote: >> On Fri, Mar 9, 2012 at 9:25 AM, Bjorn Helgaas <bhelgaas@google.com> wrote: >>> >>> Well, it looks like you can change both save_dev_dmaru() *and* >>> get_dev_dmaru() to take a struct pci_dev *. I assumed that would be >>> obvious. >> >> no. >> >> get_dev_dmaru() have to use bus/devfn to retrieve the dev pointer. > > I expected something like that, but all I see in the patch is this: > > +static void restore_dev_to_drhd(struct pci_dev *dev) > + drhd = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, > + dev->devfn, &i, &saved_dev_drhd_list); > > +static void restore_dev_to_atsr(struct pci_dev *dev) > + atsr = get_dev_dmaru(pci_domain_nr(dev->bus), dev->bus->number, > + dev->devfn, &i, &saved_dev_atsr_list); > > In both those cases, you have the struct pci_dev *. OK, i missed that. will update that accordingly. Thanks Yinghai ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 09/23] IOMMU: Fix tboot force iommu logic [not found] ` <1331018040-30725-1-git-send-email-yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> 2012-03-06 7:13 ` [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug Yinghai Lu @ 2012-03-06 7:13 ` Yinghai Lu 1 sibling, 0 replies; 8+ messages in thread From: Yinghai Lu @ 2012-03-06 7:13 UTC (permalink / raw) To: Jesse Barnes, x86 Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, David Woodhouse, Yinghai Lu, linux-kernel-u79uwXL29TY76Z2rM5mHXA Should check dmar_disabled just after tboot_force_iommu. otherwise when tboot is not used, and intel_iommu=off, and nointrmap still get dmar_table_init() called. that will cause some get_device calling, and it will have some device refcount leaking. Signed-off-by: Yinghai Lu <yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> Cc: David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org> Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org --- drivers/iommu/intel-iommu.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 39ef2ce..f1879d3 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3771,6 +3771,9 @@ int __init intel_iommu_init(void) /* VT-d is required for a TXT/tboot launch, so enforce that */ force_on = tboot_force_iommu(); + if (no_iommu || dmar_disabled) + return -ENODEV; + if (dmar_table_init()) { if (force_on) panic("tboot: Failed to initialize DMAR table\n"); @@ -3783,9 +3786,6 @@ int __init intel_iommu_init(void) return -ENODEV; } - if (no_iommu || dmar_disabled) - return -ENODEV; - if (iommu_init_mempool()) { if (force_on) panic("tboot: Failed to initialize iommu memory\n"); -- 1.7.7 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-03-09 18:29 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1331018040-30725-1-git-send-email-yinghai@kernel.org>
[not found] ` <1331018040-30725-1-git-send-email-yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2012-03-06 7:13 ` [PATCH 07/23] pci, dmar: Update dmar units devices list during hotplug Yinghai Lu
2012-03-09 1:06 ` Bjorn Helgaas
2012-03-09 7:06 ` Yinghai Lu
2012-03-09 17:25 ` Bjorn Helgaas
2012-03-09 17:32 ` Yinghai Lu
2012-03-09 17:37 ` Bjorn Helgaas
2012-03-09 18:29 ` Yinghai Lu
2012-03-06 7:13 ` [PATCH 09/23] IOMMU: Fix tboot force iommu logic Yinghai Lu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).