强制打开BIOS中禁用的I/OAT DCA(二)

上文提到打开R410中I/OAT DCA特性, 是通过在用户层控制.

还有一种可以直接修改内核DMA I/OAT 驱动可以做到.  google搜索到的 :)

首先打开内核支持:

Device Drivers  ---> DMA Engine support  ---> Intel I/OAT DMA support

 

添加修改寄存器函数, 详细可看前篇.

 

// 修改CPU MSR寄存器 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 // 修改PCI配置寄存器 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); }

以下是详细的patch, Kernel version 2.6.29.5

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 */

你可能感兴趣的:(struct,Module,header,null,each,patch)