aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/init_32.c6
-rw-r--r--drivers/pci/intel-iommu.c51
-rw-r--r--include/linux/mm.h2
-rw-r--r--mm/page_alloc.c10
4 files changed, 49 insertions, 20 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 65d55056b6e7..a0484adbf59d 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -298,7 +298,7 @@ struct add_highpages_data {
298 unsigned long end_pfn; 298 unsigned long end_pfn;
299}; 299};
300 300
301static void __init add_highpages_work_fn(unsigned long start_pfn, 301static int __init add_highpages_work_fn(unsigned long start_pfn,
302 unsigned long end_pfn, void *datax) 302 unsigned long end_pfn, void *datax)
303{ 303{
304 int node_pfn; 304 int node_pfn;
@@ -311,7 +311,7 @@ static void __init add_highpages_work_fn(unsigned long start_pfn,
311 final_start_pfn = max(start_pfn, data->start_pfn); 311 final_start_pfn = max(start_pfn, data->start_pfn);
312 final_end_pfn = min(end_pfn, data->end_pfn); 312 final_end_pfn = min(end_pfn, data->end_pfn);
313 if (final_start_pfn >= final_end_pfn) 313 if (final_start_pfn >= final_end_pfn)
314 return; 314 return 0;
315 315
316 for (node_pfn = final_start_pfn; node_pfn < final_end_pfn; 316 for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
317 node_pfn++) { 317 node_pfn++) {
@@ -321,6 +321,8 @@ static void __init add_highpages_work_fn(unsigned long start_pfn,
321 add_one_highpage_init(page, node_pfn); 321 add_one_highpage_init(page, node_pfn);
322 } 322 }
323 323
324 return 0;
325
324} 326}
325 327
326void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn, 328void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 66c0fd21894b..bb0642318a95 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1637,12 +1637,43 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
1637} 1637}
1638 1638
1639#ifdef CONFIG_DMAR_GFX_WA 1639#ifdef CONFIG_DMAR_GFX_WA
1640extern int arch_get_ram_range(int slot, u64 *addr, u64 *size); 1640struct iommu_prepare_data {
1641 struct pci_dev *pdev;
1642 int ret;
1643};
1644
1645static int __init iommu_prepare_work_fn(unsigned long start_pfn,
1646 unsigned long end_pfn, void *datax)
1647{
1648 struct iommu_prepare_data *data;
1649
1650 data = (struct iommu_prepare_data *)datax;
1651
1652 data->ret = iommu_prepare_identity_map(data->pdev,
1653 start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
1654 return data->ret;
1655
1656}
1657
1658static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev)
1659{
1660 int nid;
1661 struct iommu_prepare_data data;
1662
1663 data.pdev = pdev;
1664 data.ret = 0;
1665
1666 for_each_online_node(nid) {
1667 work_with_active_regions(nid, iommu_prepare_work_fn, &data);
1668 if (data.ret)
1669 return data.ret;
1670 }
1671 return data.ret;
1672}
1673
1641static void __init iommu_prepare_gfx_mapping(void) 1674static void __init iommu_prepare_gfx_mapping(void)
1642{ 1675{
1643 struct pci_dev *pdev = NULL; 1676 struct pci_dev *pdev = NULL;
1644 u64 base, size;
1645 int slot;
1646 int ret; 1677 int ret;
1647 1678
1648 for_each_pci_dev(pdev) { 1679 for_each_pci_dev(pdev) {
@@ -1651,17 +1682,9 @@ static void __init iommu_prepare_gfx_mapping(void)
1651 continue; 1682 continue;
1652 printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", 1683 printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
1653 pci_name(pdev)); 1684 pci_name(pdev));
1654 slot = arch_get_ram_range(0, &base, &size); 1685 ret = iommu_prepare_with_active_regions(pdev);
1655 while (slot >= 0) { 1686 if (ret)
1656 ret = iommu_prepare_identity_map(pdev, 1687 printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
1657 base, base + size);
1658 if (ret)
1659 goto error;
1660 slot = arch_get_ram_range(slot, &base, &size);
1661 }
1662 continue;
1663error:
1664 printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
1665 } 1688 }
1666} 1689}
1667#endif 1690#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 3d647b24041f..cf1cd3a2ed78 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1011,7 +1011,7 @@ extern unsigned long find_min_pfn_with_active_regions(void);
1011extern unsigned long find_max_pfn_with_active_regions(void); 1011extern unsigned long find_max_pfn_with_active_regions(void);
1012extern void free_bootmem_with_active_regions(int nid, 1012extern void free_bootmem_with_active_regions(int nid,
1013 unsigned long max_low_pfn); 1013 unsigned long max_low_pfn);
1014typedef void (*work_fn_t)(unsigned long, unsigned long, void *); 1014typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
1015extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data); 1015extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
1016extern void sparse_memory_present_with_active_regions(int nid); 1016extern void sparse_memory_present_with_active_regions(int nid);
1017#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID 1017#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 41c6e3aa059f..e25b6b24f844 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2932,10 +2932,14 @@ void __init free_bootmem_with_active_regions(int nid,
2932void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data) 2932void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)
2933{ 2933{
2934 int i; 2934 int i;
2935 int ret;
2935 2936
2936 for_each_active_range_index_in_nid(i, nid) 2937 for_each_active_range_index_in_nid(i, nid) {
2937 work_fn(early_node_map[i].start_pfn, early_node_map[i].end_pfn, 2938 ret = work_fn(early_node_map[i].start_pfn,
2938 data); 2939 early_node_map[i].end_pfn, data);
2940 if (ret)
2941 break;
2942 }
2939} 2943}
2940/** 2944/**
2941 * sparse_memory_present_with_active_regions - Call memory_present for each active range 2945 * sparse_memory_present_with_active_regions - Call memory_present for each active range