diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/x86/kernel/cpu/intel_cacheinfo.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'arch/x86/kernel/cpu/intel_cacheinfo.c')
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 259 |
1 files changed, 115 insertions, 144 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index fe9edec6698..c105c533ed9 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -151,17 +151,28 @@ union _cpuid4_leaf_ecx { | |||
151 | u32 full; | 151 | u32 full; |
152 | }; | 152 | }; |
153 | 153 | ||
154 | struct _cpuid4_info_regs { | 154 | struct amd_l3_cache { |
155 | struct amd_northbridge *nb; | ||
156 | unsigned indices; | ||
157 | u8 subcaches[4]; | ||
158 | }; | ||
159 | |||
160 | struct _cpuid4_info { | ||
155 | union _cpuid4_leaf_eax eax; | 161 | union _cpuid4_leaf_eax eax; |
156 | union _cpuid4_leaf_ebx ebx; | 162 | union _cpuid4_leaf_ebx ebx; |
157 | union _cpuid4_leaf_ecx ecx; | 163 | union _cpuid4_leaf_ecx ecx; |
158 | unsigned long size; | 164 | unsigned long size; |
159 | struct amd_northbridge *nb; | 165 | struct amd_l3_cache *l3; |
166 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | ||
160 | }; | 167 | }; |
161 | 168 | ||
162 | struct _cpuid4_info { | 169 | /* subset of above _cpuid4_info w/o shared_cpu_map */ |
163 | struct _cpuid4_info_regs base; | 170 | struct _cpuid4_info_regs { |
164 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | 171 | union _cpuid4_leaf_eax eax; |
172 | union _cpuid4_leaf_ebx ebx; | ||
173 | union _cpuid4_leaf_ecx ecx; | ||
174 | unsigned long size; | ||
175 | struct amd_l3_cache *l3; | ||
165 | }; | 176 | }; |
166 | 177 | ||
167 | unsigned short num_cache_leaves; | 178 | unsigned short num_cache_leaves; |
@@ -303,41 +314,52 @@ struct _cache_attr { | |||
303 | /* | 314 | /* |
304 | * L3 cache descriptors | 315 | * L3 cache descriptors |
305 | */ | 316 | */ |
306 | static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) | 317 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) |
307 | { | 318 | { |
308 | struct amd_l3_cache *l3 = &nb->l3_cache; | ||
309 | unsigned int sc0, sc1, sc2, sc3; | 319 | unsigned int sc0, sc1, sc2, sc3; |
310 | u32 val = 0; | 320 | u32 val = 0; |
311 | 321 | ||
312 | pci_read_config_dword(nb->misc, 0x1C4, &val); | 322 | pci_read_config_dword(l3->nb->misc, 0x1C4, &val); |
313 | 323 | ||
314 | /* calculate subcache sizes */ | 324 | /* calculate subcache sizes */ |
315 | l3->subcaches[0] = sc0 = !(val & BIT(0)); | 325 | l3->subcaches[0] = sc0 = !(val & BIT(0)); |
316 | l3->subcaches[1] = sc1 = !(val & BIT(4)); | 326 | l3->subcaches[1] = sc1 = !(val & BIT(4)); |
317 | |||
318 | if (boot_cpu_data.x86 == 0x15) { | ||
319 | l3->subcaches[0] = sc0 += !(val & BIT(1)); | ||
320 | l3->subcaches[1] = sc1 += !(val & BIT(5)); | ||
321 | } | ||
322 | |||
323 | l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9)); | 327 | l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9)); |
324 | l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); | 328 | l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); |
325 | 329 | ||
326 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; | 330 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; |
327 | } | 331 | } |
328 | 332 | ||
329 | static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index) | 333 | static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, |
334 | int index) | ||
330 | { | 335 | { |
336 | static struct amd_l3_cache *__cpuinitdata l3_caches; | ||
331 | int node; | 337 | int node; |
332 | 338 | ||
333 | /* only for L3, and not in virtualized environments */ | 339 | /* only for L3, and not in virtualized environments */ |
334 | if (index < 3) | 340 | if (index < 3 || amd_nb_num() == 0) |
335 | return; | 341 | return; |
336 | 342 | ||
343 | /* | ||
344 | * Strictly speaking, the amount in @size below is leaked since it is | ||
345 | * never freed but this is done only on shutdown so it doesn't matter. | ||
346 | */ | ||
347 | if (!l3_caches) { | ||
348 | int size = amd_nb_num() * sizeof(struct amd_l3_cache); | ||
349 | |||
350 | l3_caches = kzalloc(size, GFP_ATOMIC); | ||
351 | if (!l3_caches) | ||
352 | return; | ||
353 | } | ||
354 | |||
337 | node = amd_get_nb_id(smp_processor_id()); | 355 | node = amd_get_nb_id(smp_processor_id()); |
338 | this_leaf->nb = node_to_amd_nb(node); | 356 | |
339 | if (this_leaf->nb && !this_leaf->nb->l3_cache.indices) | 357 | if (!l3_caches[node].nb) { |
340 | amd_calc_l3_indices(this_leaf->nb); | 358 | l3_caches[node].nb = node_to_amd_nb(node); |
359 | amd_calc_l3_indices(&l3_caches[node]); | ||
360 | } | ||
361 | |||
362 | this_leaf->l3 = &l3_caches[node]; | ||
341 | } | 363 | } |
342 | 364 | ||
343 | /* | 365 | /* |
@@ -347,11 +369,11 @@ static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int | |||
347 | * | 369 | * |
348 | * @returns: the disabled index if used or negative value if slot free. | 370 | * @returns: the disabled index if used or negative value if slot free. |
349 | */ | 371 | */ |
350 | int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot) | 372 | int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) |
351 | { | 373 | { |
352 | unsigned int reg = 0; | 374 | unsigned int reg = 0; |
353 | 375 | ||
354 | pci_read_config_dword(nb->misc, 0x1BC + slot * 4, ®); | 376 | pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, ®); |
355 | 377 | ||
356 | /* check whether this slot is activated already */ | 378 | /* check whether this slot is activated already */ |
357 | if (reg & (3UL << 30)) | 379 | if (reg & (3UL << 30)) |
@@ -365,10 +387,11 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | |||
365 | { | 387 | { |
366 | int index; | 388 | int index; |
367 | 389 | ||
368 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | 390 | if (!this_leaf->l3 || |
391 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
369 | return -EINVAL; | 392 | return -EINVAL; |
370 | 393 | ||
371 | index = amd_get_l3_disable_slot(this_leaf->base.nb, slot); | 394 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); |
372 | if (index >= 0) | 395 | if (index >= 0) |
373 | return sprintf(buf, "%d\n", index); | 396 | return sprintf(buf, "%d\n", index); |
374 | 397 | ||
@@ -385,7 +408,7 @@ show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \ | |||
385 | SHOW_CACHE_DISABLE(0) | 408 | SHOW_CACHE_DISABLE(0) |
386 | SHOW_CACHE_DISABLE(1) | 409 | SHOW_CACHE_DISABLE(1) |
387 | 410 | ||
388 | static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu, | 411 | static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, |
389 | unsigned slot, unsigned long idx) | 412 | unsigned slot, unsigned long idx) |
390 | { | 413 | { |
391 | int i; | 414 | int i; |
@@ -398,10 +421,10 @@ static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu, | |||
398 | for (i = 0; i < 4; i++) { | 421 | for (i = 0; i < 4; i++) { |
399 | u32 reg = idx | (i << 20); | 422 | u32 reg = idx | (i << 20); |
400 | 423 | ||
401 | if (!nb->l3_cache.subcaches[i]) | 424 | if (!l3->subcaches[i]) |
402 | continue; | 425 | continue; |
403 | 426 | ||
404 | pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg); | 427 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
405 | 428 | ||
406 | /* | 429 | /* |
407 | * We need to WBINVD on a core on the node containing the L3 | 430 | * We need to WBINVD on a core on the node containing the L3 |
@@ -411,7 +434,7 @@ static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu, | |||
411 | wbinvd_on_cpu(cpu); | 434 | wbinvd_on_cpu(cpu); |
412 | 435 | ||
413 | reg |= BIT(31); | 436 | reg |= BIT(31); |
414 | pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg); | 437 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
415 | } | 438 | } |
416 | } | 439 | } |
417 | 440 | ||
@@ -425,24 +448,24 @@ static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu, | |||
425 | * | 448 | * |
426 | * @return: 0 on success, error status on failure | 449 | * @return: 0 on success, error status on failure |
427 | */ | 450 | */ |
428 | int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot, | 451 | int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot, |
429 | unsigned long index) | 452 | unsigned long index) |
430 | { | 453 | { |
431 | int ret = 0; | 454 | int ret = 0; |
432 | 455 | ||
433 | /* check if @slot is already used or the index is already disabled */ | 456 | /* check if @slot is already used or the index is already disabled */ |
434 | ret = amd_get_l3_disable_slot(nb, slot); | 457 | ret = amd_get_l3_disable_slot(l3, slot); |
435 | if (ret >= 0) | 458 | if (ret >= 0) |
436 | return -EEXIST; | 459 | return -EINVAL; |
437 | 460 | ||
438 | if (index > nb->l3_cache.indices) | 461 | if (index > l3->indices) |
439 | return -EINVAL; | 462 | return -EINVAL; |
440 | 463 | ||
441 | /* check whether the other slot has disabled the same index already */ | 464 | /* check whether the other slot has disabled the same index already */ |
442 | if (index == amd_get_l3_disable_slot(nb, !slot)) | 465 | if (index == amd_get_l3_disable_slot(l3, !slot)) |
443 | return -EEXIST; | 466 | return -EINVAL; |
444 | 467 | ||
445 | amd_l3_disable_index(nb, cpu, slot, index); | 468 | amd_l3_disable_index(l3, cpu, slot, index); |
446 | 469 | ||
447 | return 0; | 470 | return 0; |
448 | } | 471 | } |
@@ -457,7 +480,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
457 | if (!capable(CAP_SYS_ADMIN)) | 480 | if (!capable(CAP_SYS_ADMIN)) |
458 | return -EPERM; | 481 | return -EPERM; |
459 | 482 | ||
460 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | 483 | if (!this_leaf->l3 || |
484 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
461 | return -EINVAL; | 485 | return -EINVAL; |
462 | 486 | ||
463 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 487 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
@@ -465,11 +489,11 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
465 | if (strict_strtoul(buf, 10, &val) < 0) | 489 | if (strict_strtoul(buf, 10, &val) < 0) |
466 | return -EINVAL; | 490 | return -EINVAL; |
467 | 491 | ||
468 | err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val); | 492 | err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val); |
469 | if (err) { | 493 | if (err) { |
470 | if (err == -EEXIST) | 494 | if (err == -EEXIST) |
471 | pr_warning("L3 slot %d in use/index already disabled!\n", | 495 | printk(KERN_WARNING "L3 disable slot %d in use!\n", |
472 | slot); | 496 | slot); |
473 | return err; | 497 | return err; |
474 | } | 498 | } |
475 | return count; | 499 | return count; |
@@ -494,7 +518,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | |||
494 | static ssize_t | 518 | static ssize_t |
495 | show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) | 519 | show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) |
496 | { | 520 | { |
497 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | 521 | if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) |
498 | return -EINVAL; | 522 | return -EINVAL; |
499 | 523 | ||
500 | return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); | 524 | return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); |
@@ -509,7 +533,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count, | |||
509 | if (!capable(CAP_SYS_ADMIN)) | 533 | if (!capable(CAP_SYS_ADMIN)) |
510 | return -EPERM; | 534 | return -EPERM; |
511 | 535 | ||
512 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | 536 | if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) |
513 | return -EINVAL; | 537 | return -EINVAL; |
514 | 538 | ||
515 | if (strict_strtoul(buf, 16, &val) < 0) | 539 | if (strict_strtoul(buf, 16, &val) < 0) |
@@ -538,11 +562,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
538 | unsigned edx; | 562 | unsigned edx; |
539 | 563 | ||
540 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 564 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
541 | if (cpu_has_topoext) | 565 | amd_cpuid4(index, &eax, &ebx, &ecx); |
542 | cpuid_count(0x8000001d, index, &eax.full, | ||
543 | &ebx.full, &ecx.full, &edx); | ||
544 | else | ||
545 | amd_cpuid4(index, &eax, &ebx, &ecx); | ||
546 | amd_init_l3_cache(this_leaf, index); | 566 | amd_init_l3_cache(this_leaf, index); |
547 | } else { | 567 | } else { |
548 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 568 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
@@ -561,39 +581,21 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
561 | return 0; | 581 | return 0; |
562 | } | 582 | } |
563 | 583 | ||
564 | static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c) | 584 | static int __cpuinit find_num_cache_leaves(void) |
565 | { | 585 | { |
566 | unsigned int eax, ebx, ecx, edx, op; | 586 | unsigned int eax, ebx, ecx, edx; |
567 | union _cpuid4_leaf_eax cache_eax; | 587 | union _cpuid4_leaf_eax cache_eax; |
568 | int i = -1; | 588 | int i = -1; |
569 | 589 | ||
570 | if (c->x86_vendor == X86_VENDOR_AMD) | ||
571 | op = 0x8000001d; | ||
572 | else | ||
573 | op = 4; | ||
574 | |||
575 | do { | 590 | do { |
576 | ++i; | 591 | ++i; |
577 | /* Do cpuid(op) loop to find out num_cache_leaves */ | 592 | /* Do cpuid(4) loop to find out num_cache_leaves */ |
578 | cpuid_count(op, i, &eax, &ebx, &ecx, &edx); | 593 | cpuid_count(4, i, &eax, &ebx, &ecx, &edx); |
579 | cache_eax.full = eax; | 594 | cache_eax.full = eax; |
580 | } while (cache_eax.split.type != CACHE_TYPE_NULL); | 595 | } while (cache_eax.split.type != CACHE_TYPE_NULL); |
581 | return i; | 596 | return i; |
582 | } | 597 | } |
583 | 598 | ||
584 | void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c) | ||
585 | { | ||
586 | |||
587 | if (cpu_has_topoext) { | ||
588 | num_cache_leaves = find_num_cache_leaves(c); | ||
589 | } else if (c->extended_cpuid_level >= 0x80000006) { | ||
590 | if (cpuid_edx(0x80000006) & 0xf000) | ||
591 | num_cache_leaves = 4; | ||
592 | else | ||
593 | num_cache_leaves = 3; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | 599 | unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) |
598 | { | 600 | { |
599 | /* Cache sizes */ | 601 | /* Cache sizes */ |
@@ -610,7 +612,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
610 | 612 | ||
611 | if (is_initialized == 0) { | 613 | if (is_initialized == 0) { |
612 | /* Init num_cache_leaves from boot CPU */ | 614 | /* Init num_cache_leaves from boot CPU */ |
613 | num_cache_leaves = find_num_cache_leaves(c); | 615 | num_cache_leaves = find_num_cache_leaves(); |
614 | is_initialized++; | 616 | is_initialized++; |
615 | } | 617 | } |
616 | 618 | ||
@@ -637,14 +639,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
637 | new_l2 = this_leaf.size/1024; | 639 | new_l2 = this_leaf.size/1024; |
638 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; | 640 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; |
639 | index_msb = get_count_order(num_threads_sharing); | 641 | index_msb = get_count_order(num_threads_sharing); |
640 | l2_id = c->apicid & ~((1 << index_msb) - 1); | 642 | l2_id = c->apicid >> index_msb; |
641 | break; | 643 | break; |
642 | case 3: | 644 | case 3: |
643 | new_l3 = this_leaf.size/1024; | 645 | new_l3 = this_leaf.size/1024; |
644 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; | 646 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; |
645 | index_msb = get_count_order( | 647 | index_msb = get_count_order( |
646 | num_threads_sharing); | 648 | num_threads_sharing); |
647 | l3_id = c->apicid & ~((1 << index_msb) - 1); | 649 | l3_id = c->apicid >> index_msb; |
648 | break; | 650 | break; |
649 | default: | 651 | default: |
650 | break; | 652 | break; |
@@ -746,40 +748,14 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info); | |||
746 | #define CPUID4_INFO_IDX(x, y) (&((per_cpu(ici_cpuid4_info, x))[y])) | 748 | #define CPUID4_INFO_IDX(x, y) (&((per_cpu(ici_cpuid4_info, x))[y])) |
747 | 749 | ||
748 | #ifdef CONFIG_SMP | 750 | #ifdef CONFIG_SMP |
749 | 751 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | |
750 | static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) | ||
751 | { | 752 | { |
752 | struct _cpuid4_info *this_leaf; | 753 | struct _cpuid4_info *this_leaf, *sibling_leaf; |
753 | int i, sibling; | 754 | unsigned long num_threads_sharing; |
754 | 755 | int index_msb, i, sibling; | |
755 | if (cpu_has_topoext) { | 756 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
756 | unsigned int apicid, nshared, first, last; | ||
757 | |||
758 | if (!per_cpu(ici_cpuid4_info, cpu)) | ||
759 | return 0; | ||
760 | |||
761 | this_leaf = CPUID4_INFO_IDX(cpu, index); | ||
762 | nshared = this_leaf->base.eax.split.num_threads_sharing + 1; | ||
763 | apicid = cpu_data(cpu).apicid; | ||
764 | first = apicid - (apicid % nshared); | ||
765 | last = first + nshared - 1; | ||
766 | |||
767 | for_each_online_cpu(i) { | ||
768 | apicid = cpu_data(i).apicid; | ||
769 | if ((apicid < first) || (apicid > last)) | ||
770 | continue; | ||
771 | if (!per_cpu(ici_cpuid4_info, i)) | ||
772 | continue; | ||
773 | this_leaf = CPUID4_INFO_IDX(i, index); | ||
774 | 757 | ||
775 | for_each_online_cpu(sibling) { | 758 | if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) { |
776 | apicid = cpu_data(sibling).apicid; | ||
777 | if ((apicid < first) || (apicid > last)) | ||
778 | continue; | ||
779 | set_bit(sibling, this_leaf->shared_cpu_map); | ||
780 | } | ||
781 | } | ||
782 | } else if (index == 3) { | ||
783 | for_each_cpu(i, cpu_llc_shared_mask(cpu)) { | 759 | for_each_cpu(i, cpu_llc_shared_mask(cpu)) { |
784 | if (!per_cpu(ici_cpuid4_info, i)) | 760 | if (!per_cpu(ici_cpuid4_info, i)) |
785 | continue; | 761 | continue; |
@@ -790,26 +766,10 @@ static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) | |||
790 | set_bit(sibling, this_leaf->shared_cpu_map); | 766 | set_bit(sibling, this_leaf->shared_cpu_map); |
791 | } | 767 | } |
792 | } | 768 | } |
793 | } else | 769 | return; |
794 | return 0; | ||
795 | |||
796 | return 1; | ||
797 | } | ||
798 | |||
799 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | ||
800 | { | ||
801 | struct _cpuid4_info *this_leaf, *sibling_leaf; | ||
802 | unsigned long num_threads_sharing; | ||
803 | int index_msb, i; | ||
804 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
805 | |||
806 | if (c->x86_vendor == X86_VENDOR_AMD) { | ||
807 | if (cache_shared_amd_cpu_map_setup(cpu, index)) | ||
808 | return; | ||
809 | } | 770 | } |
810 | |||
811 | this_leaf = CPUID4_INFO_IDX(cpu, index); | 771 | this_leaf = CPUID4_INFO_IDX(cpu, index); |
812 | num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing; | 772 | num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; |
813 | 773 | ||
814 | if (num_threads_sharing == 1) | 774 | if (num_threads_sharing == 1) |
815 | cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map)); | 775 | cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map)); |
@@ -860,19 +820,29 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) | |||
860 | for (i = 0; i < num_cache_leaves; i++) | 820 | for (i = 0; i < num_cache_leaves; i++) |
861 | cache_remove_shared_cpu_map(cpu, i); | 821 | cache_remove_shared_cpu_map(cpu, i); |
862 | 822 | ||
823 | kfree(per_cpu(ici_cpuid4_info, cpu)->l3); | ||
863 | kfree(per_cpu(ici_cpuid4_info, cpu)); | 824 | kfree(per_cpu(ici_cpuid4_info, cpu)); |
864 | per_cpu(ici_cpuid4_info, cpu) = NULL; | 825 | per_cpu(ici_cpuid4_info, cpu) = NULL; |
865 | } | 826 | } |
866 | 827 | ||
828 | static int | ||
829 | __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) | ||
830 | { | ||
831 | struct _cpuid4_info_regs *leaf_regs = | ||
832 | (struct _cpuid4_info_regs *)this_leaf; | ||
833 | |||
834 | return cpuid4_cache_lookup_regs(index, leaf_regs); | ||
835 | } | ||
836 | |||
867 | static void __cpuinit get_cpu_leaves(void *_retval) | 837 | static void __cpuinit get_cpu_leaves(void *_retval) |
868 | { | 838 | { |
869 | int j, *retval = _retval, cpu = smp_processor_id(); | 839 | int j, *retval = _retval, cpu = smp_processor_id(); |
870 | 840 | ||
871 | /* Do cpuid and store the results */ | 841 | /* Do cpuid and store the results */ |
872 | for (j = 0; j < num_cache_leaves; j++) { | 842 | for (j = 0; j < num_cache_leaves; j++) { |
873 | struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j); | 843 | struct _cpuid4_info *this_leaf; |
874 | 844 | this_leaf = CPUID4_INFO_IDX(cpu, j); | |
875 | *retval = cpuid4_cache_lookup_regs(j, &this_leaf->base); | 845 | *retval = cpuid4_cache_lookup(j, this_leaf); |
876 | if (unlikely(*retval < 0)) { | 846 | if (unlikely(*retval < 0)) { |
877 | int i; | 847 | int i; |
878 | 848 | ||
@@ -907,7 +877,8 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) | |||
907 | 877 | ||
908 | #include <linux/kobject.h> | 878 | #include <linux/kobject.h> |
909 | #include <linux/sysfs.h> | 879 | #include <linux/sysfs.h> |
910 | #include <linux/cpu.h> | 880 | |
881 | extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */ | ||
911 | 882 | ||
912 | /* pointer to kobject for cpuX/cache */ | 883 | /* pointer to kobject for cpuX/cache */ |
913 | static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject); | 884 | static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject); |
@@ -929,16 +900,16 @@ static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \ | |||
929 | return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \ | 900 | return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \ |
930 | } | 901 | } |
931 | 902 | ||
932 | show_one_plus(level, base.eax.split.level, 0); | 903 | show_one_plus(level, eax.split.level, 0); |
933 | show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1); | 904 | show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1); |
934 | show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1); | 905 | show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1); |
935 | show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1); | 906 | show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1); |
936 | show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1); | 907 | show_one_plus(number_of_sets, ecx.split.number_of_sets, 1); |
937 | 908 | ||
938 | static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf, | 909 | static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf, |
939 | unsigned int cpu) | 910 | unsigned int cpu) |
940 | { | 911 | { |
941 | return sprintf(buf, "%luK\n", this_leaf->base.size / 1024); | 912 | return sprintf(buf, "%luK\n", this_leaf->size / 1024); |
942 | } | 913 | } |
943 | 914 | ||
944 | static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf, | 915 | static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf, |
@@ -975,7 +946,7 @@ static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf, | |||
975 | static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf, | 946 | static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf, |
976 | unsigned int cpu) | 947 | unsigned int cpu) |
977 | { | 948 | { |
978 | switch (this_leaf->base.eax.split.type) { | 949 | switch (this_leaf->eax.split.type) { |
979 | case CACHE_TYPE_DATA: | 950 | case CACHE_TYPE_DATA: |
980 | return sprintf(buf, "Data\n"); | 951 | return sprintf(buf, "Data\n"); |
981 | case CACHE_TYPE_INST: | 952 | case CACHE_TYPE_INST: |
@@ -1026,7 +997,7 @@ static struct attribute ** __cpuinit amd_l3_attrs(void) | |||
1026 | if (attrs) | 997 | if (attrs) |
1027 | return attrs; | 998 | return attrs; |
1028 | 999 | ||
1029 | n = ARRAY_SIZE(default_attrs); | 1000 | n = sizeof (default_attrs) / sizeof (struct attribute *); |
1030 | 1001 | ||
1031 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | 1002 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) |
1032 | n += 2; | 1003 | n += 2; |
@@ -1135,9 +1106,9 @@ err_out: | |||
1135 | static DECLARE_BITMAP(cache_dev_map, NR_CPUS); | 1106 | static DECLARE_BITMAP(cache_dev_map, NR_CPUS); |
1136 | 1107 | ||
1137 | /* Add/Remove cache interface for CPU device */ | 1108 | /* Add/Remove cache interface for CPU device */ |
1138 | static int __cpuinit cache_add_dev(struct device *dev) | 1109 | static int __cpuinit cache_add_dev(struct sys_device * sys_dev) |
1139 | { | 1110 | { |
1140 | unsigned int cpu = dev->id; | 1111 | unsigned int cpu = sys_dev->id; |
1141 | unsigned long i, j; | 1112 | unsigned long i, j; |
1142 | struct _index_kobject *this_object; | 1113 | struct _index_kobject *this_object; |
1143 | struct _cpuid4_info *this_leaf; | 1114 | struct _cpuid4_info *this_leaf; |
@@ -1149,7 +1120,7 @@ static int __cpuinit cache_add_dev(struct device *dev) | |||
1149 | 1120 | ||
1150 | retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu), | 1121 | retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu), |
1151 | &ktype_percpu_entry, | 1122 | &ktype_percpu_entry, |
1152 | &dev->kobj, "%s", "cache"); | 1123 | &sys_dev->kobj, "%s", "cache"); |
1153 | if (retval < 0) { | 1124 | if (retval < 0) { |
1154 | cpuid4_cache_sysfs_exit(cpu); | 1125 | cpuid4_cache_sysfs_exit(cpu); |
1155 | return retval; | 1126 | return retval; |
@@ -1164,7 +1135,7 @@ static int __cpuinit cache_add_dev(struct device *dev) | |||
1164 | 1135 | ||
1165 | ktype_cache.default_attrs = default_attrs; | 1136 | ktype_cache.default_attrs = default_attrs; |
1166 | #ifdef CONFIG_AMD_NB | 1137 | #ifdef CONFIG_AMD_NB |
1167 | if (this_leaf->base.nb) | 1138 | if (this_leaf->l3) |
1168 | ktype_cache.default_attrs = amd_l3_attrs(); | 1139 | ktype_cache.default_attrs = amd_l3_attrs(); |
1169 | #endif | 1140 | #endif |
1170 | retval = kobject_init_and_add(&(this_object->kobj), | 1141 | retval = kobject_init_and_add(&(this_object->kobj), |
@@ -1186,9 +1157,9 @@ static int __cpuinit cache_add_dev(struct device *dev) | |||
1186 | return 0; | 1157 | return 0; |
1187 | } | 1158 | } |
1188 | 1159 | ||
1189 | static void __cpuinit cache_remove_dev(struct device *dev) | 1160 | static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) |
1190 | { | 1161 | { |
1191 | unsigned int cpu = dev->id; | 1162 | unsigned int cpu = sys_dev->id; |
1192 | unsigned long i; | 1163 | unsigned long i; |
1193 | 1164 | ||
1194 | if (per_cpu(ici_cpuid4_info, cpu) == NULL) | 1165 | if (per_cpu(ici_cpuid4_info, cpu) == NULL) |
@@ -1207,17 +1178,17 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, | |||
1207 | unsigned long action, void *hcpu) | 1178 | unsigned long action, void *hcpu) |
1208 | { | 1179 | { |
1209 | unsigned int cpu = (unsigned long)hcpu; | 1180 | unsigned int cpu = (unsigned long)hcpu; |
1210 | struct device *dev; | 1181 | struct sys_device *sys_dev; |
1211 | 1182 | ||
1212 | dev = get_cpu_device(cpu); | 1183 | sys_dev = get_cpu_sysdev(cpu); |
1213 | switch (action) { | 1184 | switch (action) { |
1214 | case CPU_ONLINE: | 1185 | case CPU_ONLINE: |
1215 | case CPU_ONLINE_FROZEN: | 1186 | case CPU_ONLINE_FROZEN: |
1216 | cache_add_dev(dev); | 1187 | cache_add_dev(sys_dev); |
1217 | break; | 1188 | break; |
1218 | case CPU_DEAD: | 1189 | case CPU_DEAD: |
1219 | case CPU_DEAD_FROZEN: | 1190 | case CPU_DEAD_FROZEN: |
1220 | cache_remove_dev(dev); | 1191 | cache_remove_dev(sys_dev); |
1221 | break; | 1192 | break; |
1222 | } | 1193 | } |
1223 | return NOTIFY_OK; | 1194 | return NOTIFY_OK; |
@@ -1236,9 +1207,9 @@ static int __cpuinit cache_sysfs_init(void) | |||
1236 | 1207 | ||
1237 | for_each_online_cpu(i) { | 1208 | for_each_online_cpu(i) { |
1238 | int err; | 1209 | int err; |
1239 | struct device *dev = get_cpu_device(i); | 1210 | struct sys_device *sys_dev = get_cpu_sysdev(i); |
1240 | 1211 | ||
1241 | err = cache_add_dev(dev); | 1212 | err = cache_add_dev(sys_dev); |
1242 | if (err) | 1213 | if (err) |
1243 | return err; | 1214 | return err; |
1244 | } | 1215 | } |