Message ID | 1431724994-21601-4-git-send-email-Suravee.Suthikulpanit@amd.com (mailing list archive) |
---|---|
State | RFC, archived |
Headers | show |
On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: > This patch refactors of_pci_dma_configure() into a more generic > pci_dma_configure(), which can be reused by non-OF code. > Then, it adds support for setting up PCI device DMA coherency from > ACPI _CCA object that should normally be specified in the DSDT node > of its PCI host bridge.. > > Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> > CC: Bjorn Helgaas <bhelgaas@google.com> > CC: Catalin Marinas <catalin.marinas@arm.com> > CC: Rob Herring <robh+dt@kernel.org> > CC: Will Deacon <will.deacon@arm.com> > CC: Rafael J. Wysocki <rjw@rjwysocki.net> > CC: Murali Karicheri <m-karicheri2@ti.com> > --- > drivers/of/of_pci.c | 20 -------------------- > drivers/pci/probe.c | 35 +++++++++++++++++++++++++++++++++-- > include/linux/of_pci.h | 3 --- > 3 files changed, 33 insertions(+), 25 deletions(-) > > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c > index 5751dc5..b66ee4e 100644 > --- a/drivers/of/of_pci.c > +++ b/drivers/of/of_pci.c > @@ -117,26 +117,6 @@ int of_get_pci_domain_nr(struct device_node *node) > } > EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); > > -/** > - * of_pci_dma_configure - Setup DMA configuration > - * @dev: ptr to pci_dev struct of the PCI device > - * > - * Function to update PCI devices's DMA configuration using the same > - * info from the OF node of host bridge's parent (if any). > - */ > -void of_pci_dma_configure(struct pci_dev *pci_dev) > -{ > - struct device *dev = &pci_dev->dev; > - struct device *bridge = pci_get_host_bridge_device(pci_dev); > - > - if (!bridge->parent) > - return; > - > - of_dma_configure(dev, bridge->parent->of_node); > - pci_put_host_bridge_device(bridge); > -} > -EXPORT_SYMBOL_GPL(of_pci_dma_configure); > - > #if defined(CONFIG_OF_ADDRESS) > /** > * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c > index 6675a7a..3c6f2e5 100644 > --- a/drivers/pci/probe.c > +++ b/drivers/pci/probe.c > @@ -6,12 +6,14 @@ > #include <linux/delay.h> > #include <linux/init.h> > #include <linux/pci.h> > -#include <linux/of_pci.h> > +#include <linux/of_device.h> > #include <linux/pci_hotplug.h> > #include <linux/slab.h> > #include <linux/module.h> > #include <linux/cpumask.h> > #include <linux/pci-aspm.h> > +#include <linux/acpi.h> > +#include <linux/property.h> > #include <asm-generic/pci-bridge.h> > #include "pci.h" > > @@ -1508,6 +1510,35 @@ static void pci_init_capabilities(struct pci_dev *dev) > pci_enable_acs(dev); > } > > +/** > + * pci_dma_configure - Setup DMA configuration > + * @pci_dev: ptr to pci_dev struct of the PCI device > + * > + * Function to update PCI devices's DMA configuration using the same > + * info from the OF node or ACPI node of host bridge's parent (if any). > + */ > +static void pci_dma_configure(struct pci_dev *pci_dev) > +{ > + struct device *dev = &pci_dev->dev; > + struct device *bridge = pci_get_host_bridge_device(pci_dev); > + struct device *host = bridge->parent; > + struct acpi_device *adev; > + > + if (!host) > + return; > + > + if (acpi_disabled) { > + of_dma_configure(dev, host->of_node); I'd rather do if (IS_ENABLED(CONFIG_OF) && host->of_node) { of_dma_configure(dev, host->of_node); } else { struct acpi_device *adev = ACPI_COMPANION(host); if (adev && acpi_dma_is_supported(adev)) { > + } else if (has_acpi_companion(host)) { > + adev = acpi_node(host->fwnode); > + if (acpi_dma_is_supported(adev)) > + arch_setup_dma_ops(dev, 0, 0, NULL, > + acpi_dma_is_coherent(adev)); > + } > + > + pci_put_host_bridge_device(bridge); > +} > + > void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) > { > int ret; > @@ -1521,7 +1552,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) > dev->dev.dma_mask = &dev->dma_mask; > dev->dev.dma_parms = &dev->dma_parms; > dev->dev.coherent_dma_mask = 0xffffffffull; > - of_pci_dma_configure(dev); > + pci_dma_configure(dev); Also I'm not quite sure if that's actually OK. We should be handling the DMA setup on x86 in the ACPI case already without it. Or is this a NOP on x86? > > pci_set_dma_max_seg_size(dev, 65536); > pci_set_dma_seg_boundary(dev, 0xffffffff); > diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h > index 29fd3fe..ce0e5ab 100644 > --- a/include/linux/of_pci.h > +++ b/include/linux/of_pci.h > @@ -16,7 +16,6 @@ int of_pci_get_devfn(struct device_node *np); > int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin); > int of_pci_parse_bus_range(struct device_node *node, struct resource *res); > int of_get_pci_domain_nr(struct device_node *node); > -void of_pci_dma_configure(struct pci_dev *pci_dev); > #else > static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) > { > @@ -51,8 +50,6 @@ of_get_pci_domain_nr(struct device_node *node) > { > return -1; > } > - > -static inline void of_pci_dma_configure(struct pci_dev *pci_dev) { } > #endif > > #if defined(CONFIG_OF_ADDRESS) >
On Fri, May 15, 2015 at 4:23 PM, Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> wrote: > This patch refactors of_pci_dma_configure() into a more generic > pci_dma_configure(), which can be reused by non-OF code. > Then, it adds support for setting up PCI device DMA coherency from > ACPI _CCA object that should normally be specified in the DSDT node > of its PCI host bridge.. From the changelog, it sounds like you might be able to split this into two patches: 1) Refactor of_pci_dma_configure(), with no functional change 2) Add support for using _CCA If that's possible, please do so to make this easier to review. Bjorn -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Rafael, On 5/15/15, 18:59, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote: >On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: >> This patch refactors of_pci_dma_configure() into a more generic >> pci_dma_configure(), which can be reused by non-OF code. >> Then, it adds support for setting up PCI device DMA coherency from >> ACPI _CCA object that should normally be specified in the DSDT node >> of its PCI host bridge.. >> >> Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> >> CC: Bjorn Helgaas <bhelgaas@google.com> >> CC: Catalin Marinas <catalin.marinas@arm.com> >> CC: Rob Herring <robh+dt@kernel.org> >> CC: Will Deacon <will.deacon@arm.com> >> CC: Rafael J. Wysocki <rjw@rjwysocki.net> >> CC: Murali Karicheri <m-karicheri2@ti.com> >> --- >> drivers/of/of_pci.c | 20 -------------------- >> drivers/pci/probe.c | 35 +++++++++++++++++++++++++++++++++-- >> include/linux/of_pci.h | 3 --- >> 3 files changed, 33 insertions(+), 25 deletions(-) >> >> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c >> index 5751dc5..b66ee4e 100644 >> --- a/drivers/of/of_pci.c >> +++ b/drivers/of/of_pci.c >> @@ -117,26 +117,6 @@ int of_get_pci_domain_nr(struct device_node *node) >> } >> EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); >> >> -/** >> - * of_pci_dma_configure - Setup DMA configuration >> - * @dev: ptr to pci_dev struct of the PCI device >> - * >> - * Function to update PCI devices's DMA configuration using the same >> - * info from the OF node of host bridge's parent (if any). >> - */ >> -void of_pci_dma_configure(struct pci_dev *pci_dev) >> -{ >> - struct device *dev = &pci_dev->dev; >> - struct device *bridge = pci_get_host_bridge_device(pci_dev); >> - >> - if (!bridge->parent) >> - return; >> - >> - of_dma_configure(dev, bridge->parent->of_node); >> - pci_put_host_bridge_device(bridge); >> -} >> -EXPORT_SYMBOL_GPL(of_pci_dma_configure); >> - >> #if defined(CONFIG_OF_ADDRESS) >> /** >> * of_pci_get_host_bridge_resources - Parse PCI host bridge resources >>from DT >> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c >> index 6675a7a..3c6f2e5 100644 >> --- a/drivers/pci/probe.c >> +++ b/drivers/pci/probe.c >> @@ -6,12 +6,14 @@ >> #include <linux/delay.h> >> #include <linux/init.h> >> #include <linux/pci.h> >> -#include <linux/of_pci.h> >> +#include <linux/of_device.h> >> #include <linux/pci_hotplug.h> >> #include <linux/slab.h> >> #include <linux/module.h> >> #include <linux/cpumask.h> >> #include <linux/pci-aspm.h> >> +#include <linux/acpi.h> >> +#include <linux/property.h> >> #include <asm-generic/pci-bridge.h> >> #include "pci.h" >> >> @@ -1508,6 +1510,35 @@ static void pci_init_capabilities(struct pci_dev >>*dev) >> pci_enable_acs(dev); >> } >> >> +/** >> + * pci_dma_configure - Setup DMA configuration >> + * @pci_dev: ptr to pci_dev struct of the PCI device >> + * >> + * Function to update PCI devices's DMA configuration using the same >> + * info from the OF node or ACPI node of host bridge's parent (if any). >> + */ >> +static void pci_dma_configure(struct pci_dev *pci_dev) >> +{ >> + struct device *dev = &pci_dev->dev; >> + struct device *bridge = pci_get_host_bridge_device(pci_dev); >> + struct device *host = bridge->parent; >> + struct acpi_device *adev; >> + >> + if (!host) >> + return; >> + >> + if (acpi_disabled) { >> + of_dma_configure(dev, host->of_node); > >I'd rather do > > if (IS_ENABLED(CONFIG_OF) && host->of_node) { > of_dma_configure(dev, host->of_node); > } else { > struct acpi_device *adev = ACPI_COMPANION(host); > > if (adev && acpi_dma_is_supported(adev)) { Ok, I¹ll update this. > >> + } else if (has_acpi_companion(host)) { >> + adev = acpi_node(host->fwnode); >> + if (acpi_dma_is_supported(adev)) >> + arch_setup_dma_ops(dev, 0, 0, NULL, >> + acpi_dma_is_coherent(adev)); >> + } >> + >> + pci_put_host_bridge_device(bridge); >> +} >> + >> void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) >> { >> int ret; >> @@ -1521,7 +1552,7 @@ void pci_device_add(struct pci_dev *dev, struct >>pci_bus *bus) >> dev->dev.dma_mask = &dev->dma_mask; >> dev->dev.dma_parms = &dev->dma_parms; >> dev->dev.coherent_dma_mask = 0xffffffffull; >> - of_pci_dma_configure(dev); >> + pci_dma_configure(dev); > >Also I'm not quite sure if that's actually OK. > >We should be handling the DMA setup on x86 in the ACPI case already >without it. >Or is this a NOP on x86? You are correct. x86 doesn¹t implement the arch_setup_dma_ops(). Therefore, this is a NOP on x86. Thanks, Suravee -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Bjorn, On 5/16/15, 07:41, "Bjorn Helgaas" <bhelgaas@google.com> wrote: >On Fri, May 15, 2015 at 4:23 PM, Suravee Suthikulpanit ><Suravee.Suthikulpanit@amd.com> wrote: >> This patch refactors of_pci_dma_configure() into a more generic >> pci_dma_configure(), which can be reused by non-OF code. >> Then, it adds support for setting up PCI device DMA coherency from >> ACPI _CCA object that should normally be specified in the DSDT node >> of its PCI host bridge.. > >From the changelog, it sounds like you might be able to split this >into two patches: > >1) Refactor of_pci_dma_configure(), with no functional change >2) Add support for using _CCA > >If that's possible, please do so to make this easier to review. > >Bjorn Yes, I can separate the patch out. This would mainly affect ACPI+PCI support for ARM64 (which is in progress). Thanks, Surafvee -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sat, May 16, 2015 at 01:59:00AM +0200, Rafael J. Wysocki wrote: > On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: > > +/** > > + * pci_dma_configure - Setup DMA configuration > > + * @pci_dev: ptr to pci_dev struct of the PCI device > > + * > > + * Function to update PCI devices's DMA configuration using the same > > + * info from the OF node or ACPI node of host bridge's parent (if any). > > + */ > > +static void pci_dma_configure(struct pci_dev *pci_dev) > > +{ > > + struct device *dev = &pci_dev->dev; > > + struct device *bridge = pci_get_host_bridge_device(pci_dev); > > + struct device *host = bridge->parent; > > + struct acpi_device *adev; > > + > > + if (!host) > > + return; > > + > > + if (acpi_disabled) { > > + of_dma_configure(dev, host->of_node); > > I'd rather do > > if (IS_ENABLED(CONFIG_OF) && host->of_node) { > of_dma_configure(dev, host->of_node); Nitpick: do we need the CONFIG_OF check? If disabled, I don't think anyone would set host->of_node.
On Wednesday 20 May 2015 10:24:15 Catalin Marinas wrote: > On Sat, May 16, 2015 at 01:59:00AM +0200, Rafael J. Wysocki wrote: > > On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: > > > +/** > > > + * pci_dma_configure - Setup DMA configuration > > > + * @pci_dev: ptr to pci_dev struct of the PCI device > > > + * > > > + * Function to update PCI devices's DMA configuration using the same > > > + * info from the OF node or ACPI node of host bridge's parent (if any). > > > + */ > > > +static void pci_dma_configure(struct pci_dev *pci_dev) > > > +{ > > > + struct device *dev = &pci_dev->dev; > > > + struct device *bridge = pci_get_host_bridge_device(pci_dev); > > > + struct device *host = bridge->parent; > > > + struct acpi_device *adev; > > > + > > > + if (!host) > > > + return; > > > + > > > + if (acpi_disabled) { > > > + of_dma_configure(dev, host->of_node); > > > > I'd rather do > > > > if (IS_ENABLED(CONFIG_OF) && host->of_node) { > > of_dma_configure(dev, host->of_node); > > Nitpick: do we need the CONFIG_OF check? If disabled, I don't think > anyone would set host->of_node. > If of_dma_configure() is defined in a file that is built conditionally based on CONFIG_OF, you need it. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, May 20, 2015 at 10:24:15AM +0100, Catalin Marinas wrote: > On Sat, May 16, 2015 at 01:59:00AM +0200, Rafael J. Wysocki wrote: > > On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: > > > +/** > > > + * pci_dma_configure - Setup DMA configuration > > > + * @pci_dev: ptr to pci_dev struct of the PCI device > > > + * > > > + * Function to update PCI devices's DMA configuration using the same > > > + * info from the OF node or ACPI node of host bridge's parent (if any). > > > + */ > > > +static void pci_dma_configure(struct pci_dev *pci_dev) > > > +{ > > > + struct device *dev = &pci_dev->dev; > > > + struct device *bridge = pci_get_host_bridge_device(pci_dev); > > > + struct device *host = bridge->parent; > > > + struct acpi_device *adev; > > > + > > > + if (!host) > > > + return; > > > + > > > + if (acpi_disabled) { > > > + of_dma_configure(dev, host->of_node); > > > > I'd rather do > > > > if (IS_ENABLED(CONFIG_OF) && host->of_node) { > > of_dma_configure(dev, host->of_node); > > Nitpick: do we need the CONFIG_OF check? If disabled, I don't think > anyone would set host->of_node. Please ignore this, there is no point in checking host->of_node if CONFIG_OF is disabled (I was just thinking from an arm64 perspective where we always have CONFIG_OF enabled).
On Wed, May 20, 2015 at 11:27:54AM +0200, Arnd Bergmann wrote: > On Wednesday 20 May 2015 10:24:15 Catalin Marinas wrote: > > On Sat, May 16, 2015 at 01:59:00AM +0200, Rafael J. Wysocki wrote: > > > On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: > > > > +/** > > > > + * pci_dma_configure - Setup DMA configuration > > > > + * @pci_dev: ptr to pci_dev struct of the PCI device > > > > + * > > > > + * Function to update PCI devices's DMA configuration using the same > > > > + * info from the OF node or ACPI node of host bridge's parent (if any). > > > > + */ > > > > +static void pci_dma_configure(struct pci_dev *pci_dev) > > > > +{ > > > > + struct device *dev = &pci_dev->dev; > > > > + struct device *bridge = pci_get_host_bridge_device(pci_dev); > > > > + struct device *host = bridge->parent; > > > > + struct acpi_device *adev; > > > > + > > > > + if (!host) > > > > + return; > > > > + > > > > + if (acpi_disabled) { > > > > + of_dma_configure(dev, host->of_node); > > > > > > I'd rather do > > > > > > if (IS_ENABLED(CONFIG_OF) && host->of_node) { > > > of_dma_configure(dev, host->of_node); > > > > Nitpick: do we need the CONFIG_OF check? If disabled, I don't think > > anyone would set host->of_node. > > If of_dma_configure() is defined in a file that is built conditionally > based on CONFIG_OF, you need it. We have a dummy of_dma_configure() already when !CONFIG_OF, otherwise we would need #ifndef here. I already replied, I think for other architectures we need this check to avoid a useless host->of_node test.
On 5/20/2015 4:34 AM, Catalin Marinas wrote: > On Wed, May 20, 2015 at 11:27:54AM +0200, Arnd Bergmann wrote: >> On Wednesday 20 May 2015 10:24:15 Catalin Marinas wrote: >>> On Sat, May 16, 2015 at 01:59:00AM +0200, Rafael J. Wysocki wrote: >>>> On Friday, May 15, 2015 04:23:11 PM Suravee Suthikulpanit wrote: >>>>> +/** >>>>> + * pci_dma_configure - Setup DMA configuration >>>>> + * @pci_dev: ptr to pci_dev struct of the PCI device >>>>> + * >>>>> + * Function to update PCI devices's DMA configuration using the same >>>>> + * info from the OF node or ACPI node of host bridge's parent (if any). >>>>> + */ >>>>> +static void pci_dma_configure(struct pci_dev *pci_dev) >>>>> +{ >>>>> + struct device *dev = &pci_dev->dev; >>>>> + struct device *bridge = pci_get_host_bridge_device(pci_dev); >>>>> + struct device *host = bridge->parent; >>>>> + struct acpi_device *adev; >>>>> + >>>>> + if (!host) >>>>> + return; >>>>> + >>>>> + if (acpi_disabled) { >>>>> + of_dma_configure(dev, host->of_node); >>>> >>>> I'd rather do >>>> >>>> if (IS_ENABLED(CONFIG_OF) && host->of_node) { >>>> of_dma_configure(dev, host->of_node); >>> >>> Nitpick: do we need the CONFIG_OF check? If disabled, I don't think >>> anyone would set host->of_node. >> >> If of_dma_configure() is defined in a file that is built conditionally >> based on CONFIG_OF, you need it. > > We have a dummy of_dma_configure() already when !CONFIG_OF, otherwise > we would need #ifndef here. I already replied, I think for other > architectures we need this check to avoid a useless host->of_node test. > It seems that there are several places that have similar check. Would it be good to convert this into a macro? Something like: #define OF_NODE_ENABLED(dev) (IS_ENABLED(CONFIG_OF) && dev->of_node) Thanks all for the review feedback. Suravee -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wednesday 20 May 2015 07:00:25 Suravee Suthikulanit wrote: > It seems that there are several places that have similar check. Would it > be good to convert this into a macro? Something like: > > #define OF_NODE_ENABLED(dev) (IS_ENABLED(CONFIG_OF) && dev->of_node) > > Thanks all for the review feedback. > Better make that an inline function that returns the node: struct device_node *dev_of_node(struct device *) { if (IS_ENABLED(CONFIG_OF)) return dev->of_node; return NULL; } Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, May 20, 2015 at 07:00:25AM -0500, Suravee Suthikulanit wrote: > On 5/20/2015 4:34 AM, Catalin Marinas wrote: > >We have a dummy of_dma_configure() already when !CONFIG_OF, otherwise > >we would need #ifndef here. I already replied, I think for other > >architectures we need this check to avoid a useless host->of_node test. > > It seems that there are several places that have similar check. Would it be > good to convert this into a macro? Something like: > > #define OF_NODE_ENABLED(dev) (IS_ENABLED(CONFIG_OF) && dev->of_node) This /could/ be a useful compile-time optimisation: when CONFIG_OF is disabled, dev->of_node exists but will always be NULL - but the compiler doesn't know this. Your suggestion above would tell the compiler that when CONFIG_OF is disabled, OF_NODE_ENABLED() will evaluate to a constant false, which means it can eliminate code.
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index 5751dc5..b66ee4e 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -117,26 +117,6 @@ int of_get_pci_domain_nr(struct device_node *node) } EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); -/** - * of_pci_dma_configure - Setup DMA configuration - * @dev: ptr to pci_dev struct of the PCI device - * - * Function to update PCI devices's DMA configuration using the same - * info from the OF node of host bridge's parent (if any). - */ -void of_pci_dma_configure(struct pci_dev *pci_dev) -{ - struct device *dev = &pci_dev->dev; - struct device *bridge = pci_get_host_bridge_device(pci_dev); - - if (!bridge->parent) - return; - - of_dma_configure(dev, bridge->parent->of_node); - pci_put_host_bridge_device(bridge); -} -EXPORT_SYMBOL_GPL(of_pci_dma_configure); - #if defined(CONFIG_OF_ADDRESS) /** * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6675a7a..3c6f2e5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -6,12 +6,14 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/of_pci.h> +#include <linux/of_device.h> #include <linux/pci_hotplug.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/cpumask.h> #include <linux/pci-aspm.h> +#include <linux/acpi.h> +#include <linux/property.h> #include <asm-generic/pci-bridge.h> #include "pci.h" @@ -1508,6 +1510,35 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_enable_acs(dev); } +/** + * pci_dma_configure - Setup DMA configuration + * @pci_dev: ptr to pci_dev struct of the PCI device + * + * Function to update PCI devices's DMA configuration using the same + * info from the OF node or ACPI node of host bridge's parent (if any). + */ +static void pci_dma_configure(struct pci_dev *pci_dev) +{ + struct device *dev = &pci_dev->dev; + struct device *bridge = pci_get_host_bridge_device(pci_dev); + struct device *host = bridge->parent; + struct acpi_device *adev; + + if (!host) + return; + + if (acpi_disabled) { + of_dma_configure(dev, host->of_node); + } else if (has_acpi_companion(host)) { + adev = acpi_node(host->fwnode); + if (acpi_dma_is_supported(adev)) + arch_setup_dma_ops(dev, 0, 0, NULL, + acpi_dma_is_coherent(adev)); + } + + pci_put_host_bridge_device(bridge); +} + void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { int ret; @@ -1521,7 +1552,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_parms = &dev->dma_parms; dev->dev.coherent_dma_mask = 0xffffffffull; - of_pci_dma_configure(dev); + pci_dma_configure(dev); pci_set_dma_max_seg_size(dev, 65536); pci_set_dma_seg_boundary(dev, 0xffffffff); diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h index 29fd3fe..ce0e5ab 100644 --- a/include/linux/of_pci.h +++ b/include/linux/of_pci.h @@ -16,7 +16,6 @@ int of_pci_get_devfn(struct device_node *np); int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin); int of_pci_parse_bus_range(struct device_node *node, struct resource *res); int of_get_pci_domain_nr(struct device_node *node); -void of_pci_dma_configure(struct pci_dev *pci_dev); #else static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) { @@ -51,8 +50,6 @@ of_get_pci_domain_nr(struct device_node *node) { return -1; } - -static inline void of_pci_dma_configure(struct pci_dev *pci_dev) { } #endif #if defined(CONFIG_OF_ADDRESS)
This patch refactors of_pci_dma_configure() into a more generic pci_dma_configure(), which can be reused by non-OF code. Then, it adds support for setting up PCI device DMA coherency from ACPI _CCA object that should normally be specified in the DSDT node of its PCI host bridge.. Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> CC: Bjorn Helgaas <bhelgaas@google.com> CC: Catalin Marinas <catalin.marinas@arm.com> CC: Rob Herring <robh+dt@kernel.org> CC: Will Deacon <will.deacon@arm.com> CC: Rafael J. Wysocki <rjw@rjwysocki.net> CC: Murali Karicheri <m-karicheri2@ti.com> --- drivers/of/of_pci.c | 20 -------------------- drivers/pci/probe.c | 35 +++++++++++++++++++++++++++++++++-- include/linux/of_pci.h | 3 --- 3 files changed, 33 insertions(+), 25 deletions(-)