2009-03-30 22:04:58

by Brice Goglin

[permalink] [raw]
Subject: [RFC] ioat-dca: force I/OAT DCA when disabled in BIOS

Some machines (for instance Dell Poweredge servers) disable I/OAT DCA
support in the BIOS without any way to reenable it.
DCA may actually be enabled manually it in the processors' MSR and in
upstream bridge registers. We have been doing this with a hacky userspace
program, but we feel that the ioatdma driver may actually take care of it.

Here's a patch doing so, if the ioat_dca_force module parameter is set
to 1 on load.

There are some things to improve:
* Which pcidev should actually get DCA enabled? The patch below looks for
Intel upstream bridges. Do we need a check for pdev->is_pcie ? Or maybe
even look at pdev->pcie_type? It looks like the pcidev that need to be
configured on my machines are PCI_EXP_TYPE_ROOT_PORT, but I am not sure
it actually matters. Some Intel people will probably know how to fix this.
* Any better name for #defin'ing bit #6 at offset 0x64 in the config-space
of these bridges?

Signed-off-by: Brice Goglin <[email protected]>
Signed-off-by: Andrew Gallatin <[email protected]>

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index f4e505f..1e83796 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -85,6 +85,7 @@
#define MSR_P6_PERFCTR1 0x000000c2
#define MSR_P6_EVNTSEL0 0x00000186
#define MSR_P6_EVNTSEL1 0x00000187
+#define MSR_P6_DCA_CAP 0x000001f8

/* AMD64 MSRs. Not complete. See the architecture manual for a more
complete list. */
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index ed83dd9..8af1960 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -71,10 +71,16 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
static void __devexit ioat_remove(struct pci_dev *pdev);

+void dca_force(void);
+
static int ioat_dca_enabled = 1;
module_param(ioat_dca_enabled, int, 0644);
MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");

+static int ioat_dca_force = 0;
+module_param(ioat_dca_force, int, 0644);
+MODULE_PARM_DESC(ioat_dca_force, "enforce dca in upstream bridges and processors (default: 0)");
+
static struct pci_driver ioat_pci_driver = {
.name = "ioatdma",
.id_table = ioat_pci_tbl,
@@ -191,6 +197,9 @@ static void __devexit ioat_remove(struct pci_dev *pdev)

static int __init ioat_init_module(void)
{
+ if (ioat_dca_force)
+ dca_force();
+
return pci_register_driver(&ioat_pci_driver);
}
module_init(ioat_init_module);
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index c012a1e..3f45f78 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -88,6 +88,45 @@ static inline u16 dcaid_from_pcidev(struct pci_dev *pci)
return (pci->bus->number << 8) | pci->devfn;
}

+static void dca_force_msr(void *dummy)
+{
+ uint32_t data1, data2;
+ rdmsr(MSR_P6_DCA_CAP, data1, data2);
+ if (!(data1 & 1))
+ data1 |= 1;
+ wrmsr(MSR_P6_DCA_CAP, data1, data2);
+}
+
+#define INTEL_BRIDGE_DCAEN_OFFSET 0x64
+#define INTEL_BRIDGE_DCAEN_BIT 6
+
+void dca_force(void)
+{
+ struct pci_dev *pdev = NULL;
+
+ /* enable DCA in intel upstream bridges */
+ for_each_pci_dev(pdev) {
+ if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE
+ && pdev->vendor == PCI_VENDOR_ID_INTEL
+ && !pdev->bus->self) {
+ u32 val;
+ int ret;
+
+ ret = pci_read_config_dword(pdev, INTEL_BRIDGE_DCAEN_OFFSET, &val);
+ if (ret < 0)
+ continue;
+ if (!(val & (1<<INTEL_BRIDGE_DCAEN_BIT))) {
+ dev_printk(KERN_INFO, &pdev->dev, "enabling DCA in upstream bridge\n");
+ val |= 1<<INTEL_BRIDGE_DCAEN_BIT;
+ pci_write_config_dword(pdev, INTEL_BRIDGE_DCAEN_OFFSET, val);
+ }
+ }
+ }
+
+ /* enable DCA in processors */
+ on_each_cpu(dca_force_msr, NULL, 1);
+}
+
static int dca_enabled_in_bios(struct pci_dev *pdev)
{
/* CPUID level 9 returns DCA configuration */


2009-04-03 15:18:20

by Sosnowski, Maciej

[permalink] [raw]
Subject: RE: [RFC] ioat-dca: force I/OAT DCA when disabled in BIOS

Brice Goglin wrote:
> Some machines (for instance Dell Poweredge servers) disable I/OAT DCA
> support in the BIOS without any way to reenable it.
> DCA may actually be enabled manually it in the processors' MSR and in
> upstream bridge registers. We have been doing this with a hacky userspace
> program, but we feel that the ioatdma driver may actually take care of it.
>
> Here's a patch doing so, if the ioat_dca_force module parameter is set
> to 1 on load.
>
> There are some things to improve:
> * Which pcidev should actually get DCA enabled? The patch below looks for
> Intel upstream bridges. Do we need a check for pdev->is_pcie ? Or maybe
> even look at pdev->pcie_type? It looks like the pcidev that need to be
> configured on my machines are PCI_EXP_TYPE_ROOT_PORT, but I am not sure
> it actually matters. Some Intel people will probably know how to fix this.
> * Any better name for #defin'ing bit #6 at offset 0x64 in the config-space
> of these bridges?
>
> Signed-off-by: Brice Goglin <[email protected]>
> Signed-off-by: Andrew Gallatin <[email protected]>
>

Hi Brice,

While this patch should work for some platforms (with I/OAT devices of IDs: 0x1a38, 0x360b, 0x65ff) it is not a platform generic solution.
Generally enabling DCA, like this dca_force() routine does, requires other settings including the tag_map which should be set by BIOS.
Thus it should be BIOS responsibility to prepare the whole required configuration for DCA.
For these reasons we don't want to include this solution in the ioatdma driver.
Please continue to use the userspace application instead.

Regards,
Maciej-

2009-04-03 17:42:34

by Brice Goglin

[permalink] [raw]
Subject: Re: [RFC] ioat-dca: force I/OAT DCA when disabled in BIOS

Hello Maciej,

Thanks for at this.



Sosnowski, Maciej wrote:
> Brice Goglin wrote:
>
>> Some machines (for instance Dell Poweredge servers) disable I/OAT DCA
>> support in the BIOS without any way to reenable it.
>> DCA may actually be enabled manually it in the processors' MSR and in
>> upstream bridge registers. We have been doing this with a hacky userspace
>> program, but we feel that the ioatdma driver may actually take care of it.
>>
>> Here's a patch doing so, if the ioat_dca_force module parameter is set
>> to 1 on load.
>>
>> There are some things to improve:
>> * Which pcidev should actually get DCA enabled? The patch below looks for
>> Intel upstream bridges. Do we need a check for pdev->is_pcie ? Or maybe
>> even look at pdev->pcie_type? It looks like the pcidev that need to be
>> configured on my machines are PCI_EXP_TYPE_ROOT_PORT, but I am not sure
>> it actually matters. Some Intel people will probably know how to fix this.
>> * Any better name for #defin'ing bit #6 at offset 0x64 in the config-space
>> of these bridges?
>>
>> Signed-off-by: Brice Goglin <[email protected]>
>> Signed-off-by: Andrew Gallatin <[email protected]>
>>
>>
>
> Hi Brice,
>
> While this patch should work for some platforms (with I/OAT devices of IDs: 0x1a38, 0x360b, 0x65ff) it is not a platform generic solution.
> Generally enabling DCA, like this dca_force() routine does, requires other settings including the tag_map which should be set by BIOS.
> Thus it should be BIOS responsibility to prepare the whole required configuration for DCA.

Well, that's exactly the reason why the patch only enforces DCA when
ioat_dca_force=1 is given. We obviously don't want to tweak registers
like this by default, unless the admin knows what he is doing.

Having to run a custom script is really annoying for many Dell machine
users where the tag_map is already correctly set by the BIOS. And you
have to make sure that the script runs before ioatdma is loaded (which
means you cannot built ioatdma inside the kernel, by the way).

By the way, do you have some ideas about how to filter bridges better?
Maybe somebody at Intel has a whitelist of intel bridges that could be
involved here?

thanks,
Brice

2009-04-09 13:04:50

by Sosnowski, Maciej

[permalink] [raw]
Subject: RE: [RFC] ioat-dca: force I/OAT DCA when disabled in BIOS

Brice Goglin wrote:
>> While this patch should work for some platforms (with I/OAT devices of IDs: 0x1a38, 0x360b,
>> 0x65ff) it is not a platform generic solution. Generally enabling DCA, like this dca_force()
>> routine does, requires other settings including the tag_map which should be set by BIOS. Thus
>> it should be BIOS responsibility to prepare the whole required configuration for DCA.
>
> Well, that's exactly the reason why the patch only enforces DCA when
> ioat_dca_force=1 is given. We obviously don't want to tweak registers
> like this by default, unless the admin knows what he is doing.

As we can't guarantee that dca_force() should work on all platforms,
we can't accept adding this functionality as a part of the driver - even if it's disbled by default.
If an admin wishes to take a chance he can use the userspace program.

> Having to run a custom script is really annoying for many Dell machine
> users where the tag_map is already correctly set by the BIOS. And you
> have to make sure that the script runs before ioatdma is loaded (which
> means you cannot built ioatdma inside the kernel, by the way).
>
> By the way, do you have some ideas about how to filter bridges better?
> Maybe somebody at Intel has a whitelist of intel bridges that could be
> involved here?

What I found is that the list will be all root ports for the 5000-series chipset (Blackford),
5100-series chipset (San Clemente), 7300 chipset (Caneland).
The register does not exist for 5400 chipset (Seaburg).

Regards,
Maciej-