static void get_max_cacheline_size (void) { unsigned long line_size, max = 1; u64 l, levels, unique_caches; pal_cache_config_info_t cci; s64 status; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", __FUNCTION__, status); max = SMP_CACHE_BYTES; goto out; } for (l = 0; l < levels; ++l) { status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", __FUNCTION__, l, status); max = SMP_CACHE_BYTES; } line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; } out: if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; }
/** * pci_cacheline_size - determine cacheline size for PCI devices * @dev: void * * We want to use the line-size of the outer-most cache. We assume * that this line-size is the same for all CPUs. * * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). * * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. */ static unsigned long pci_cacheline_size (void) { u64 levels, unique_caches; s64 status; pal_cache_config_info_t cci; static u8 cacheline_size; if (cacheline_size) return cacheline_size; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", __FUNCTION__, status); return SMP_CACHE_BYTES; } status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", __FUNCTION__, status); return SMP_CACHE_BYTES; } cacheline_size = 1 << cci.pcci_line_size; return cacheline_size; }
/* * Calculate the max. cache line size. * * In addition, the minimum of the i-cache stride sizes is calculated for * "flush_icache_range()". */ static void __cpuinit get_max_cacheline_size (void) { unsigned long line_size, max = 1; unsigned int cache_size = 0; u64 l, levels, unique_caches; pal_cache_config_info_t cci; s64 status; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", __FUNCTION__, status); max = SMP_CACHE_BYTES; /* Safest setup for "flush_icache_range()" */ ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; goto out; } for (l = 0; l < levels; ++l) { status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", __FUNCTION__, l, status); max = SMP_CACHE_BYTES; /* The safest setup for "flush_icache_range()" */ cci.pcci_stride = I_CACHE_STRIDE_SHIFT; cci.pcci_unified = 1; } line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; if (cache_size < cci.pcci_cache_size) cache_size = cci.pcci_cache_size; if (!cci.pcci_unified) { status = ia64_pal_cache_config_info(l, /* cache_type (instruction)= */ 1, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", __FUNCTION__, l, status); /* The safest setup for "flush_icache_range()" */ cci.pcci_stride = I_CACHE_STRIDE_SHIFT; } } if (cci.pcci_stride < ia64_i_cache_stride_shift) ia64_i_cache_stride_shift = cci.pcci_stride; } out: #ifdef CONFIG_SMP max_cache_size = max(max_cache_size, cache_size); #endif if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; }
/** * set_pci_cacheline_size - determine cacheline size for PCI devices * * We want to use the line-size of the outer-most cache. We assume * that this line-size is the same for all CPUs. * * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). */ static void __init set_pci_cacheline_size(void) { u64 levels, unique_caches; s64 status; pal_cache_config_info_t cci; status = ia64_pal_cache_summary(&levels, &unique_caches); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_summary() failed " "(status=%ld)\n", __func__, status); return; } status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed " "(status=%ld)\n", __func__, status); return; } pci_cache_line_size = (1 << cci.pcci_line_size) / 4; }
static int cache_info(char *page) { char *p = page; unsigned long i, levels, unique_caches; pal_cache_config_info_t cci; int j, k; long status; if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) { printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status); return 0; } p += sprintf(p, "Cache levels : %ld\nUnique caches : %ld\n\n", levels, unique_caches); for (i=0; i < levels; i++) { for (j=2; j >0 ; j--) { /* even without unification some level may not be present */ if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) { continue; } p += sprintf(p, "%s Cache level %lu:\n" "\tSize : %u bytes\n" "\tAttributes : ", cache_types[j+cci.pcci_unified], i+1, cci.pcci_cache_size); if (cci.pcci_unified) p += sprintf(p, "Unified "); p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]); p += sprintf(p, "\tAssociativity : %d\n" "\tLine size : %d bytes\n" "\tStride : %d bytes\n", cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride); if (j == 1) p += sprintf(p, "\tStore latency : N/A\n"); else p += sprintf(p, "\tStore latency : %d cycle(s)\n", cci.pcci_st_latency); p += sprintf(p, "\tLoad latency : %d cycle(s)\n" "\tStore hints : ", cci.pcci_ld_latency); for(k=0; k < 8; k++ ) { if ( cci.pcci_st_hints & 0x1) p += sprintf(p, "[%s]", cache_st_hints[k]); cci.pcci_st_hints >>=1; } p += sprintf(p, "\n\tLoad hints : "); for(k=0; k < 8; k++ ) { if (cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]); cci.pcci_ld_hints >>=1; } p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" "\tTag LSB : %d\n" "\tTag MSB : %d\n", 1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb, cci.pcci_tag_msb); /* when unified, data(j=2) is enough */ if (cci.pcci_unified) break; } } return p - page; }