* acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache
  * @table_hdr: Pointer to the head of the PPTT table
  * @local_level: passed res reflects this cache level
+ * @split_levels: Number of split cache levels (data/instruction).
  * @res: cache resource in the PPTT we want to walk
  * @found: returns a pointer to the requested level if found
  * @level: the requested cache level
  */
 static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr,
                                         unsigned int local_level,
+                                        unsigned int *split_levels,
                                         struct acpi_subtable_header *res,
                                         struct acpi_pptt_cache **found,
                                         unsigned int level, int type)
        while (cache) {
                local_level++;
 
+               if (!(cache->flags & ACPI_PPTT_CACHE_TYPE_VALID)) {
+                       cache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache);
+                       continue;
+               }
+
+               if (split_levels &&
+                   (acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_DATA) ||
+                    acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_INSTR)))
+                       *split_levels = local_level;
+
                if (local_level == level &&
-                   cache->flags & ACPI_PPTT_CACHE_TYPE_VALID &&
                    acpi_pptt_match_type(cache->attributes, type)) {
                        if (*found != NULL && cache != *found)
                                pr_warn("Found duplicate cache level/type unable to determine uniqueness\n");
 static struct acpi_pptt_cache *
 acpi_find_cache_level(struct acpi_table_header *table_hdr,
                      struct acpi_pptt_processor *cpu_node,
-                     unsigned int *starting_level, unsigned int level,
-                     int type)
+                     unsigned int *starting_level, unsigned int *split_levels,
+                     unsigned int level, int type)
 {
        struct acpi_subtable_header *res;
        unsigned int number_of_levels = *starting_level;
                resource++;
 
                local_level = acpi_pptt_walk_cache(table_hdr, *starting_level,
-                                                  res, &ret, level, type);
+                                                  split_levels, res, &ret,
+                                                  level, type);
                /*
                 * we are looking for the max depth. Since its potentially
                 * possible for a given node to have resources with differing
 }
 
 /**
- * acpi_count_levels() - Given a PPTT table, and a CPU node, count the caches
+ * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cache
+ * levels and split cache levels (data/instruction).
  * @table_hdr: Pointer to the head of the PPTT table
  * @cpu_node: processor node we wish to count caches for
+ * @levels: Number of levels if success.
+ * @split_levels:      Number of split cache levels (data/instruction) if
+ *                     success. Can by NULL.
  *
  * Given a processor node containing a processing unit, walk into it and count
  * how many levels exist solely for it, and then walk up each level until we hit
  * the root node (ignore the package level because it may be possible to have
- * caches that exist across packages). Count the number of cache levels that
- * exist at each level on the way up.
- *
- * Return: Total number of levels found.
+ * caches that exist across packages). Count the number of cache levels and
+ * split cache levels (data/instruction) that exist at each level on the way
+ * up.
  */
-static int acpi_count_levels(struct acpi_table_header *table_hdr,
-                            struct acpi_pptt_processor *cpu_node)
+static void acpi_count_levels(struct acpi_table_header *table_hdr,
+                             struct acpi_pptt_processor *cpu_node,
+                             unsigned int *levels, unsigned int *split_levels)
 {
-       int total_levels = 0;
-
        do {
-               acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0);
+               acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0);
                cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
        } while (cpu_node);
-
-       return total_levels;
 }
 
 /**
 
        while (cpu_node && !found) {
                found = acpi_find_cache_level(table_hdr, cpu_node,
-                                             &total_levels, level, acpi_type);
+                                             &total_levels, NULL, level, acpi_type);
                *node = cpu_node;
                cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
        }
 }
 
 /**
- * acpi_find_last_cache_level() - Determines the number of cache levels for a PE
+ * acpi_get_cache_info() - Determine the number of cache levels and
+ * split cache levels (data/instruction) and for a PE.
  * @cpu: Kernel logical CPU number
+ * @levels: Number of levels if success.
+ * @split_levels:      Number of levels being split (i.e. data/instruction)
+ *                     if success. Can by NULL.
  *
  * Given a logical CPU number, returns the number of levels of cache represented
  * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0
  * indicating we didn't find any cache levels.
  *
- * Return: Cache levels visible to this core.
+ * Return: -ENOENT if no PPTT table or no PPTT processor struct found.
+ *        0 on success.
  */
-int acpi_find_last_cache_level(unsigned int cpu)
+int acpi_get_cache_info(unsigned int cpu, unsigned int *levels,
+                       unsigned int *split_levels)
 {
        struct acpi_pptt_processor *cpu_node;
        struct acpi_table_header *table;
-       int number_of_levels = 0;
        u32 acpi_cpu_id;
 
+       *levels = 0;
+       if (split_levels)
+               *split_levels = 0;
+
        table = acpi_get_pptt();
        if (!table)
                return -ENOENT;
 
-       pr_debug("Cache Setup find last level CPU=%d\n", cpu);
+       pr_debug("Cache Setup: find cache levels for CPU=%d\n", cpu);
 
        acpi_cpu_id = get_acpi_id_for_cpu(cpu);
        cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
-       if (cpu_node)
-               number_of_levels = acpi_count_levels(table, cpu_node);
+       if (!cpu_node)
+               return -ENOENT;
 
-       pr_debug("Cache Setup find last level level=%d\n", number_of_levels);
+       acpi_count_levels(table, cpu_node, levels, split_levels);
 
-       return number_of_levels;
+       pr_debug("Cache Setup: last_level=%d split_levels=%d\n",
+                *levels, split_levels ? *split_levels : -1);
+
+       return 0;
 }
 
 /**