aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-09-23 20:43:11 -0400
committerTejun Heo <tj@kernel.org>2009-09-28 20:17:57 -0400
commit635b75fc18858d3522e481c043de764766db923c (patch)
tree0bd2dc916bac8d0188bdd3ba15d0a1b00aa86e48 /mm
parent6ea529a2037ce662fc6bfa572b46d47407d08805 (diff)
percpu: make pcpu_setup_first_chunk() failures more verbose
The parameters to pcpu_setup_first_chunk() come from different sources depending on architecture and can be quite complex. The function runs various sanity checks on the parameters and triggers BUG() if something isn't right. However, this is very early during the boot and not reporting exactly what the problem is makes debugging even harder. Add PCPU_SETUP_BUG() macro which prints out enough information about the parameters. As the macro still puts separate BUG() for each check, it won't lose any information even on the situations where only the program counter can be retrieved. While at it, also bump pcpu_dump_alloc_info() message to KERN_INFO so that it's visible on the console if boot fails to complete. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/percpu.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index c43da8c024d1..83617ca3ba52 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1578,6 +1578,7 @@ static void pcpu_dump_alloc_info(const char *lvl,
1578int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, 1578int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1579 void *base_addr) 1579 void *base_addr)
1580{ 1580{
1581 static char cpus_buf[4096] __initdata;
1581 static int smap[2], dmap[2]; 1582 static int smap[2], dmap[2];
1582 size_t dyn_size = ai->dyn_size; 1583 size_t dyn_size = ai->dyn_size;
1583 size_t size_sum = ai->static_size + ai->reserved_size + dyn_size; 1584 size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
@@ -1589,17 +1590,26 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1589 int *unit_map; 1590 int *unit_map;
1590 int group, unit, i; 1591 int group, unit, i;
1591 1592
1593 cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
1594
1595#define PCPU_SETUP_BUG_ON(cond) do { \
1596 if (unlikely(cond)) { \
1597 pr_emerg("PERCPU: failed to initialize, %s", #cond); \
1598 pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf); \
1599 pcpu_dump_alloc_info(KERN_EMERG, ai); \
1600 BUG(); \
1601 } \
1602} while (0)
1603
1592 /* sanity checks */ 1604 /* sanity checks */
1593 BUILD_BUG_ON(ARRAY_SIZE(smap) >= PCPU_DFL_MAP_ALLOC || 1605 BUILD_BUG_ON(ARRAY_SIZE(smap) >= PCPU_DFL_MAP_ALLOC ||
1594 ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC); 1606 ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC);
1595 BUG_ON(ai->nr_groups <= 0); 1607 PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
1596 BUG_ON(!ai->static_size); 1608 PCPU_SETUP_BUG_ON(!ai->static_size);
1597 BUG_ON(!base_addr); 1609 PCPU_SETUP_BUG_ON(!base_addr);
1598 BUG_ON(ai->unit_size < size_sum); 1610 PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
1599 BUG_ON(ai->unit_size & ~PAGE_MASK); 1611 PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
1600 BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE); 1612 PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);
1601
1602 pcpu_dump_alloc_info(KERN_DEBUG, ai);
1603 1613
1604 /* process group information and build config tables accordingly */ 1614 /* process group information and build config tables accordingly */
1605 group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0])); 1615 group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
@@ -1622,8 +1632,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1622 if (cpu == NR_CPUS) 1632 if (cpu == NR_CPUS)
1623 continue; 1633 continue;
1624 1634
1625 BUG_ON(cpu > nr_cpu_ids || !cpu_possible(cpu)); 1635 PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);
1626 BUG_ON(unit_map[cpu] != UINT_MAX); 1636 PCPU_SETUP_BUG_ON(!cpu_possible(cpu));
1637 PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);
1627 1638
1628 unit_map[cpu] = unit + i; 1639 unit_map[cpu] = unit + i;
1629 unit_off[cpu] = gi->base_offset + i * ai->unit_size; 1640 unit_off[cpu] = gi->base_offset + i * ai->unit_size;
@@ -1636,7 +1647,11 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1636 pcpu_nr_units = unit; 1647 pcpu_nr_units = unit;
1637 1648
1638 for_each_possible_cpu(cpu) 1649 for_each_possible_cpu(cpu)
1639 BUG_ON(unit_map[cpu] == UINT_MAX); 1650 PCPU_SETUP_BUG_ON(unit_map[cpu] == UINT_MAX);
1651
1652 /* we're done parsing the input, undefine BUG macro and dump config */
1653#undef PCPU_SETUP_BUG_ON
1654 pcpu_dump_alloc_info(KERN_INFO, ai);
1640 1655
1641 pcpu_nr_groups = ai->nr_groups; 1656 pcpu_nr_groups = ai->nr_groups;
1642 pcpu_group_offsets = group_offsets; 1657 pcpu_group_offsets = group_offsets;