Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: cache_info: Kill the atomic allocation in amd_init_l3_cache()

It's not a good reason to allocate memory in the smp function call
just because someone thought it's the most conveniant place.

The AMD L3 data is coupled to the northbridge info by a pointer to the
corresponding north bridge data. So allocating it with the northbridge
data and referencing the northbridge in the cache_info code instead
uses less memory and gets rid of that atomic allocation hack in the
smp function call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Borislav Petkov <borislav.petkov@amd.com>
Cc: Hans Rosenfeld <hans.rosenfeld@amd.com>
Cc: Andreas Herrmann <andreas.herrmann3@amd.com>
Cc: Mike Travis <travis@sgi.com>
Link: http://lkml.kernel.org/r/20110723212626.688229918@linutronix.de
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Thomas Gleixner and committed by
Ingo Molnar
d2946041 b7d11a76

+32 -48
+6
arch/x86/include/asm/amd_nb.h
··· 19 19 extern int amd_get_subcaches(int); 20 20 extern int amd_set_subcaches(int, int); 21 21 22 + struct amd_l3_cache { 23 + unsigned indices; 24 + u8 subcaches[4]; 25 + }; 26 + 22 27 struct amd_northbridge { 23 28 struct pci_dev *misc; 24 29 struct pci_dev *link; 30 + struct amd_l3_cache l3_cache; 25 31 }; 26 32 27 33 struct amd_northbridge_info {
+26 -48
arch/x86/kernel/cpu/intel_cacheinfo.c
··· 151 151 u32 full; 152 152 }; 153 153 154 - struct amd_l3_cache { 155 - struct amd_northbridge *nb; 156 - unsigned indices; 157 - u8 subcaches[4]; 158 - }; 159 - 160 154 struct _cpuid4_info_regs { 161 155 union _cpuid4_leaf_eax eax; 162 156 union _cpuid4_leaf_ebx ebx; 163 157 union _cpuid4_leaf_ecx ecx; 164 158 unsigned long size; 165 - struct amd_l3_cache *l3; 159 + struct amd_northbridge *nb; 166 160 }; 167 161 168 162 struct _cpuid4_info { ··· 303 309 /* 304 310 * L3 cache descriptors 305 311 */ 306 - static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) 312 + static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) 307 313 { 314 + struct amd_l3_cache *l3 = &nb->l3_cache; 308 315 unsigned int sc0, sc1, sc2, sc3; 309 316 u32 val = 0; 310 317 311 - pci_read_config_dword(l3->nb->misc, 0x1C4, &val); 318 + pci_read_config_dword(nb->misc, 0x1C4, &val); 312 319 313 320 /* calculate subcache sizes */ 314 321 l3->subcaches[0] = sc0 = !(val & BIT(0)); ··· 323 328 static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, 324 329 int index) 325 330 { 326 - static struct amd_l3_cache *__cpuinitdata l3_caches; 327 331 int node; 328 332 329 333 /* only for L3, and not in virtualized environments */ 330 - if (index < 3 || amd_nb_num() == 0) 334 + if (index < 3) 331 335 return; 332 336 333 - /* 334 - * Strictly speaking, the amount in @size below is leaked since it is 335 - * never freed but this is done only on shutdown so it doesn't matter. 336 - */ 337 - if (!l3_caches) { 338 - int size = amd_nb_num() * sizeof(struct amd_l3_cache); 339 - 340 - l3_caches = kzalloc(size, GFP_ATOMIC); 341 - if (!l3_caches) 342 - return; 343 - } 344 - 345 337 node = amd_get_nb_id(smp_processor_id()); 346 - 347 - if (!l3_caches[node].nb) { 348 - l3_caches[node].nb = node_to_amd_nb(node); 349 - amd_calc_l3_indices(&l3_caches[node]); 350 - } 351 - 352 - this_leaf->l3 = &l3_caches[node]; 338 + this_leaf->nb = node_to_amd_nb(node); 339 + if (this_leaf->nb && !this_leaf->nb->l3_cache.indices) 340 + amd_calc_l3_indices(this_leaf->nb); 353 341 } 354 342 355 343 /* ··· 342 364 * 343 365 * @returns: the disabled index if used or negative value if slot free. 344 366 */ 345 - int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) 367 + int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot) 346 368 { 347 369 unsigned int reg = 0; 348 370 349 - pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg); 371 + pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg); 350 372 351 373 /* check whether this slot is activated already */ 352 374 if (reg & (3UL << 30)) ··· 360 382 { 361 383 int index; 362 384 363 - if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) 385 + if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) 364 386 return -EINVAL; 365 387 366 - index = amd_get_l3_disable_slot(this_leaf->base.l3, slot); 388 + index = amd_get_l3_disable_slot(this_leaf->base.nb, slot); 367 389 if (index >= 0) 368 390 return sprintf(buf, "%d\n", index); 369 391 ··· 380 402 SHOW_CACHE_DISABLE(0) 381 403 SHOW_CACHE_DISABLE(1) 382 404 383 - static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, 405 + static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu, 384 406 unsigned slot, unsigned long idx) 385 407 { 386 408 int i; ··· 393 415 for (i = 0; i < 4; i++) { 394 416 u32 reg = idx | (i << 20); 395 417 396 - if (!l3->subcaches[i]) 418 + if (!nb->l3_cache.subcaches[i]) 397 419 continue; 398 420 399 - pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); 421 + pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg); 400 422 401 423 /* 402 424 * We need to WBINVD on a core on the node containing the L3 ··· 406 428 wbinvd_on_cpu(cpu); 407 429 408 430 reg |= BIT(31); 409 - pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); 431 + pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg); 410 432 } 411 433 } 412 434 ··· 420 442 * 421 443 * @return: 0 on success, error status on failure 422 444 */ 423 - int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot, 445 + int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot, 424 446 unsigned long index) 425 447 { 426 448 int ret = 0; 427 449 428 450 /* check if @slot is already used or the index is already disabled */ 429 - ret = amd_get_l3_disable_slot(l3, slot); 451 + ret = amd_get_l3_disable_slot(nb, slot); 430 452 if (ret >= 0) 431 453 return -EINVAL; 432 454 433 - if (index > l3->indices) 455 + if (index > nb->l3_cache.indices) 434 456 return -EINVAL; 435 457 436 458 /* check whether the other slot has disabled the same index already */ 437 - if (index == amd_get_l3_disable_slot(l3, !slot)) 459 + if (index == amd_get_l3_disable_slot(nb, !slot)) 438 460 return -EINVAL; 439 461 440 - amd_l3_disable_index(l3, cpu, slot, index); 462 + amd_l3_disable_index(nb, cpu, slot, index); 441 463 442 464 return 0; 443 465 } ··· 452 474 if (!capable(CAP_SYS_ADMIN)) 453 475 return -EPERM; 454 476 455 - if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) 477 + if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) 456 478 return -EINVAL; 457 479 458 480 cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); ··· 460 482 if (strict_strtoul(buf, 10, &val) < 0) 461 483 return -EINVAL; 462 484 463 - err = amd_set_l3_disable_slot(this_leaf->base.l3, cpu, slot, val); 485 + err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val); 464 486 if (err) { 465 487 if (err == -EEXIST) 466 488 printk(KERN_WARNING "L3 disable slot %d in use!\n", ··· 489 511 static ssize_t 490 512 show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) 491 513 { 492 - if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 514 + if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 493 515 return -EINVAL; 494 516 495 517 return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); ··· 504 526 if (!capable(CAP_SYS_ADMIN)) 505 527 return -EPERM; 506 528 507 - if (!this_leaf->base.l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 529 + if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 508 530 return -EINVAL; 509 531 510 532 if (strict_strtoul(buf, 16, &val) < 0) ··· 1096 1118 1097 1119 ktype_cache.default_attrs = default_attrs; 1098 1120 #ifdef CONFIG_AMD_NB 1099 - if (this_leaf->base.l3) 1121 + if (this_leaf->base.nb) 1100 1122 ktype_cache.default_attrs = amd_l3_attrs(); 1101 1123 #endif 1102 1124 retval = kobject_init_and_add(&(this_object->kobj),