aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/palinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/palinfo.c')
-rw-r--r--arch/ia64/kernel/palinfo.c502
1 files changed, 238 insertions, 264 deletions
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 79521d5499f9..b17129e3b7c8 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -22,6 +22,7 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/proc_fs.h> 24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
25#include <linux/mm.h> 26#include <linux/mm.h>
26#include <linux/module.h> 27#include <linux/module.h>
27#include <linux/efi.h> 28#include <linux/efi.h>
@@ -41,7 +42,7 @@ MODULE_LICENSE("GPL");
41 42
42#define PALINFO_VERSION "0.5" 43#define PALINFO_VERSION "0.5"
43 44
44typedef int (*palinfo_func_t)(char*); 45typedef int (*palinfo_func_t)(struct seq_file *);
45 46
46typedef struct { 47typedef struct {
47 const char *name; /* name of the proc entry */ 48 const char *name; /* name of the proc entry */
@@ -54,7 +55,7 @@ typedef struct {
54 * A bunch of string array to get pretty printing 55 * A bunch of string array to get pretty printing
55 */ 56 */
56 57
57static char *cache_types[] = { 58static const char *cache_types[] = {
58 "", /* not used */ 59 "", /* not used */
59 "Instruction", 60 "Instruction",
60 "Data", 61 "Data",
@@ -122,19 +123,16 @@ static const char *mem_attrib[]={
122 * - a pointer to the end of the buffer 123 * - a pointer to the end of the buffer
123 * 124 *
124 */ 125 */
125static char * 126static void bitvector_process(struct seq_file *m, u64 vector)
126bitvector_process(char *p, u64 vector)
127{ 127{
128 int i,j; 128 int i,j;
129 const char *units[]={ "", "K", "M", "G", "T" }; 129 static const char *units[]={ "", "K", "M", "G", "T" };
130 130
131 for (i=0, j=0; i < 64; i++ , j=i/10) { 131 for (i=0, j=0; i < 64; i++ , j=i/10) {
132 if (vector & 0x1) { 132 if (vector & 0x1)
133 p += sprintf(p, "%d%s ", 1 << (i-j*10), units[j]); 133 seq_printf(m, "%d%s ", 1 << (i-j*10), units[j]);
134 }
135 vector >>= 1; 134 vector >>= 1;
136 } 135 }
137 return p;
138} 136}
139 137
140/* 138/*
@@ -149,8 +147,7 @@ bitvector_process(char *p, u64 vector)
149 * - a pointer to the end of the buffer 147 * - a pointer to the end of the buffer
150 * 148 *
151 */ 149 */
152static char * 150static void bitregister_process(struct seq_file *m, u64 *reg_info, int max)
153bitregister_process(char *p, u64 *reg_info, int max)
154{ 151{
155 int i, begin, skip = 0; 152 int i, begin, skip = 0;
156 u64 value = reg_info[0]; 153 u64 value = reg_info[0];
@@ -163,9 +160,9 @@ bitregister_process(char *p, u64 *reg_info, int max)
163 160
164 if ((value & 0x1) == 0 && skip == 0) { 161 if ((value & 0x1) == 0 && skip == 0) {
165 if (begin <= i - 2) 162 if (begin <= i - 2)
166 p += sprintf(p, "%d-%d ", begin, i-1); 163 seq_printf(m, "%d-%d ", begin, i-1);
167 else 164 else
168 p += sprintf(p, "%d ", i-1); 165 seq_printf(m, "%d ", i-1);
169 skip = 1; 166 skip = 1;
170 begin = -1; 167 begin = -1;
171 } else if ((value & 0x1) && skip == 1) { 168 } else if ((value & 0x1) && skip == 1) {
@@ -176,19 +173,15 @@ bitregister_process(char *p, u64 *reg_info, int max)
176 } 173 }
177 if (begin > -1) { 174 if (begin > -1) {
178 if (begin < 127) 175 if (begin < 127)
179 p += sprintf(p, "%d-127", begin); 176 seq_printf(m, "%d-127", begin);
180 else 177 else
181 p += sprintf(p, "127"); 178 seq_puts(m, "127");
182 } 179 }
183
184 return p;
185} 180}
186 181
187static int 182static int power_info(struct seq_file *m)
188power_info(char *page)
189{ 183{
190 s64 status; 184 s64 status;
191 char *p = page;
192 u64 halt_info_buffer[8]; 185 u64 halt_info_buffer[8];
193 pal_power_mgmt_info_u_t *halt_info =(pal_power_mgmt_info_u_t *)halt_info_buffer; 186 pal_power_mgmt_info_u_t *halt_info =(pal_power_mgmt_info_u_t *)halt_info_buffer;
194 int i; 187 int i;
@@ -198,26 +191,25 @@ power_info(char *page)
198 191
199 for (i=0; i < 8 ; i++ ) { 192 for (i=0; i < 8 ; i++ ) {
200 if (halt_info[i].pal_power_mgmt_info_s.im == 1) { 193 if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
201 p += sprintf(p, "Power level %d:\n" 194 seq_printf(m,
202 "\tentry_latency : %d cycles\n" 195 "Power level %d:\n"
203 "\texit_latency : %d cycles\n" 196 "\tentry_latency : %d cycles\n"
204 "\tpower consumption : %d mW\n" 197 "\texit_latency : %d cycles\n"
205 "\tCache+TLB coherency : %s\n", i, 198 "\tpower consumption : %d mW\n"
206 halt_info[i].pal_power_mgmt_info_s.entry_latency, 199 "\tCache+TLB coherency : %s\n", i,
207 halt_info[i].pal_power_mgmt_info_s.exit_latency, 200 halt_info[i].pal_power_mgmt_info_s.entry_latency,
208 halt_info[i].pal_power_mgmt_info_s.power_consumption, 201 halt_info[i].pal_power_mgmt_info_s.exit_latency,
209 halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No"); 202 halt_info[i].pal_power_mgmt_info_s.power_consumption,
203 halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
210 } else { 204 } else {
211 p += sprintf(p,"Power level %d: not implemented\n",i); 205 seq_printf(m,"Power level %d: not implemented\n", i);
212 } 206 }
213 } 207 }
214 return p - page; 208 return 0;
215} 209}
216 210
217static int 211static int cache_info(struct seq_file *m)
218cache_info(char *page)
219{ 212{
220 char *p = page;
221 unsigned long i, levels, unique_caches; 213 unsigned long i, levels, unique_caches;
222 pal_cache_config_info_t cci; 214 pal_cache_config_info_t cci;
223 int j, k; 215 int j, k;
@@ -228,73 +220,74 @@ cache_info(char *page)
228 return 0; 220 return 0;
229 } 221 }
230 222
231 p += sprintf(p, "Cache levels : %ld\nUnique caches : %ld\n\n", levels, unique_caches); 223 seq_printf(m, "Cache levels : %ld\nUnique caches : %ld\n\n",
224 levels, unique_caches);
232 225
233 for (i=0; i < levels; i++) { 226 for (i=0; i < levels; i++) {
234
235 for (j=2; j >0 ; j--) { 227 for (j=2; j >0 ; j--) {
236
237 /* even without unification some level may not be present */ 228 /* even without unification some level may not be present */
238 if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) { 229 if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0)
239 continue; 230 continue;
240 } 231
241 p += sprintf(p, 232 seq_printf(m,
242 "%s Cache level %lu:\n" 233 "%s Cache level %lu:\n"
243 "\tSize : %u bytes\n" 234 "\tSize : %u bytes\n"
244 "\tAttributes : ", 235 "\tAttributes : ",
245 cache_types[j+cci.pcci_unified], i+1, 236 cache_types[j+cci.pcci_unified], i+1,
246 cci.pcci_cache_size); 237 cci.pcci_cache_size);
247 238
248 if (cci.pcci_unified) p += sprintf(p, "Unified "); 239 if (cci.pcci_unified)
249 240 seq_puts(m, "Unified ");
250 p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]); 241
251 242 seq_printf(m, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
252 p += sprintf(p, 243
253 "\tAssociativity : %d\n" 244 seq_printf(m,
254 "\tLine size : %d bytes\n" 245 "\tAssociativity : %d\n"
255 "\tStride : %d bytes\n", 246 "\tLine size : %d bytes\n"
256 cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride); 247 "\tStride : %d bytes\n",
248 cci.pcci_assoc,
249 1<<cci.pcci_line_size,
250 1<<cci.pcci_stride);
257 if (j == 1) 251 if (j == 1)
258 p += sprintf(p, "\tStore latency : N/A\n"); 252 seq_puts(m, "\tStore latency : N/A\n");
259 else 253 else
260 p += sprintf(p, "\tStore latency : %d cycle(s)\n", 254 seq_printf(m, "\tStore latency : %d cycle(s)\n",
261 cci.pcci_st_latency); 255 cci.pcci_st_latency);
262 256
263 p += sprintf(p, 257 seq_printf(m,
264 "\tLoad latency : %d cycle(s)\n" 258 "\tLoad latency : %d cycle(s)\n"
265 "\tStore hints : ", cci.pcci_ld_latency); 259 "\tStore hints : ", cci.pcci_ld_latency);
266 260
267 for(k=0; k < 8; k++ ) { 261 for(k=0; k < 8; k++ ) {
268 if ( cci.pcci_st_hints & 0x1) 262 if ( cci.pcci_st_hints & 0x1)
269 p += sprintf(p, "[%s]", cache_st_hints[k]); 263 seq_printf(m, "[%s]", cache_st_hints[k]);
270 cci.pcci_st_hints >>=1; 264 cci.pcci_st_hints >>=1;
271 } 265 }
272 p += sprintf(p, "\n\tLoad hints : "); 266 seq_puts(m, "\n\tLoad hints : ");
273 267
274 for(k=0; k < 8; k++ ) { 268 for(k=0; k < 8; k++ ) {
275 if (cci.pcci_ld_hints & 0x1) 269 if (cci.pcci_ld_hints & 0x1)
276 p += sprintf(p, "[%s]", cache_ld_hints[k]); 270 seq_printf(m, "[%s]", cache_ld_hints[k]);
277 cci.pcci_ld_hints >>=1; 271 cci.pcci_ld_hints >>=1;
278 } 272 }
279 p += sprintf(p, 273 seq_printf(m,
280 "\n\tAlias boundary : %d byte(s)\n" 274 "\n\tAlias boundary : %d byte(s)\n"
281 "\tTag LSB : %d\n" 275 "\tTag LSB : %d\n"
282 "\tTag MSB : %d\n", 276 "\tTag MSB : %d\n",
283 1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb, 277 1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
284 cci.pcci_tag_msb); 278 cci.pcci_tag_msb);
285 279
286 /* when unified, data(j=2) is enough */ 280 /* when unified, data(j=2) is enough */
287 if (cci.pcci_unified) break; 281 if (cci.pcci_unified)
282 break;
288 } 283 }
289 } 284 }
290 return p - page; 285 return 0;
291} 286}
292 287
293 288
294static int 289static int vm_info(struct seq_file *m)
295vm_info(char *page)
296{ 290{
297 char *p = page;
298 u64 tr_pages =0, vw_pages=0, tc_pages; 291 u64 tr_pages =0, vw_pages=0, tc_pages;
299 u64 attrib; 292 u64 attrib;
300 pal_vm_info_1_u_t vm_info_1; 293 pal_vm_info_1_u_t vm_info_1;
@@ -309,7 +302,7 @@ vm_info(char *page)
309 printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status); 302 printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
310 } else { 303 } else {
311 304
312 p += sprintf(p, 305 seq_printf(m,
313 "Physical Address Space : %d bits\n" 306 "Physical Address Space : %d bits\n"
314 "Virtual Address Space : %d bits\n" 307 "Virtual Address Space : %d bits\n"
315 "Protection Key Registers(PKR) : %d\n" 308 "Protection Key Registers(PKR) : %d\n"
@@ -324,49 +317,49 @@ vm_info(char *page)
324 vm_info_1.pal_vm_info_1_s.hash_tag_id, 317 vm_info_1.pal_vm_info_1_s.hash_tag_id,
325 vm_info_2.pal_vm_info_2_s.rid_size); 318 vm_info_2.pal_vm_info_2_s.rid_size);
326 if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES) 319 if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
327 p += sprintf(p, "unlimited\n"); 320 seq_puts(m, "unlimited\n");
328 else 321 else
329 p += sprintf(p, "%d\n", 322 seq_printf(m, "%d\n",
330 vm_info_2.pal_vm_info_2_s.max_purges ? 323 vm_info_2.pal_vm_info_2_s.max_purges ?
331 vm_info_2.pal_vm_info_2_s.max_purges : 1); 324 vm_info_2.pal_vm_info_2_s.max_purges : 1);
332 } 325 }
333 326
334 if (ia64_pal_mem_attrib(&attrib) == 0) { 327 if (ia64_pal_mem_attrib(&attrib) == 0) {
335 p += sprintf(p, "Supported memory attributes : "); 328 seq_puts(m, "Supported memory attributes : ");
336 sep = ""; 329 sep = "";
337 for (i = 0; i < 8; i++) { 330 for (i = 0; i < 8; i++) {
338 if (attrib & (1 << i)) { 331 if (attrib & (1 << i)) {
339 p += sprintf(p, "%s%s", sep, mem_attrib[i]); 332 seq_printf(m, "%s%s", sep, mem_attrib[i]);
340 sep = ", "; 333 sep = ", ";
341 } 334 }
342 } 335 }
343 p += sprintf(p, "\n"); 336 seq_putc(m, '\n');
344 } 337 }
345 338
346 if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) { 339 if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
347 printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status); 340 printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
348 } else { 341 } else {
349 342
350 p += sprintf(p, 343 seq_printf(m,
351 "\nTLB walker : %simplemented\n" 344 "\nTLB walker : %simplemented\n"
352 "Number of DTR : %d\n" 345 "Number of DTR : %d\n"
353 "Number of ITR : %d\n" 346 "Number of ITR : %d\n"
354 "TLB insertable page sizes : ", 347 "TLB insertable page sizes : ",
355 vm_info_1.pal_vm_info_1_s.vw ? "" : "not ", 348 vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
356 vm_info_1.pal_vm_info_1_s.max_dtr_entry+1, 349 vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
357 vm_info_1.pal_vm_info_1_s.max_itr_entry+1); 350 vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
358
359 351
360 p = bitvector_process(p, tr_pages); 352 bitvector_process(m, tr_pages);
361 353
362 p += sprintf(p, "\nTLB purgeable page sizes : "); 354 seq_puts(m, "\nTLB purgeable page sizes : ");
363 355
364 p = bitvector_process(p, vw_pages); 356 bitvector_process(m, vw_pages);
365 } 357 }
366 if ((status=ia64_get_ptce(&ptce)) != 0) { 358
359 if ((status = ia64_get_ptce(&ptce)) != 0) {
367 printk(KERN_ERR "ia64_get_ptce=%ld\n", status); 360 printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
368 } else { 361 } else {
369 p += sprintf(p, 362 seq_printf(m,
370 "\nPurge base address : 0x%016lx\n" 363 "\nPurge base address : 0x%016lx\n"
371 "Purge outer loop count : %d\n" 364 "Purge outer loop count : %d\n"
372 "Purge inner loop count : %d\n" 365 "Purge inner loop count : %d\n"
@@ -375,7 +368,7 @@ vm_info(char *page)
375 ptce.base, ptce.count[0], ptce.count[1], 368 ptce.base, ptce.count[0], ptce.count[1],
376 ptce.stride[0], ptce.stride[1]); 369 ptce.stride[0], ptce.stride[1]);
377 370
378 p += sprintf(p, 371 seq_printf(m,
379 "TC Levels : %d\n" 372 "TC Levels : %d\n"
380 "Unique TC(s) : %d\n", 373 "Unique TC(s) : %d\n",
381 vm_info_1.pal_vm_info_1_s.num_tc_levels, 374 vm_info_1.pal_vm_info_1_s.num_tc_levels,
@@ -385,13 +378,11 @@ vm_info(char *page)
385 for (j=2; j>0 ; j--) { 378 for (j=2; j>0 ; j--) {
386 tc_pages = 0; /* just in case */ 379 tc_pages = 0; /* just in case */
387 380
388
389 /* even without unification, some levels may not be present */ 381 /* even without unification, some levels may not be present */
390 if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) { 382 if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0)
391 continue; 383 continue;
392 }
393 384
394 p += sprintf(p, 385 seq_printf(m,
395 "\n%s Translation Cache Level %d:\n" 386 "\n%s Translation Cache Level %d:\n"
396 "\tHash sets : %d\n" 387 "\tHash sets : %d\n"
397 "\tAssociativity : %d\n" 388 "\tAssociativity : %d\n"
@@ -403,15 +394,15 @@ vm_info(char *page)
403 tc_info.tc_num_entries); 394 tc_info.tc_num_entries);
404 395
405 if (tc_info.tc_pf) 396 if (tc_info.tc_pf)
406 p += sprintf(p, "PreferredPageSizeOptimized "); 397 seq_puts(m, "PreferredPageSizeOptimized ");
407 if (tc_info.tc_unified) 398 if (tc_info.tc_unified)
408 p += sprintf(p, "Unified "); 399 seq_puts(m, "Unified ");
409 if (tc_info.tc_reduce_tr) 400 if (tc_info.tc_reduce_tr)
410 p += sprintf(p, "TCReduction"); 401 seq_puts(m, "TCReduction");
411 402
412 p += sprintf(p, "\n\tSupported page sizes: "); 403 seq_puts(m, "\n\tSupported page sizes: ");
413 404
414 p = bitvector_process(p, tc_pages); 405 bitvector_process(m, tc_pages);
415 406
416 /* when unified date (j=2) is enough */ 407 /* when unified date (j=2) is enough */
417 if (tc_info.tc_unified) 408 if (tc_info.tc_unified)
@@ -419,16 +410,14 @@ vm_info(char *page)
419 } 410 }
420 } 411 }
421 } 412 }
422 p += sprintf(p, "\n");
423 413
424 return p - page; 414 seq_putc(m, '\n');
415 return 0;
425} 416}
426 417
427 418
428static int 419static int register_info(struct seq_file *m)
429register_info(char *page)
430{ 420{
431 char *p = page;
432 u64 reg_info[2]; 421 u64 reg_info[2];
433 u64 info; 422 u64 info;
434 unsigned long phys_stacked; 423 unsigned long phys_stacked;
@@ -442,35 +431,31 @@ register_info(char *page)
442 }; 431 };
443 432
444 for(info=0; info < 4; info++) { 433 for(info=0; info < 4; info++) {
445 434 if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0)
446 if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0) return 0; 435 return 0;
447 436 seq_printf(m, "%-32s : ", info_type[info]);
448 p += sprintf(p, "%-32s : ", info_type[info]); 437 bitregister_process(m, reg_info, 128);
449 438 seq_putc(m, '\n');
450 p = bitregister_process(p, reg_info, 128);
451
452 p += sprintf(p, "\n");
453 } 439 }
454 440
455 if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) { 441 if (ia64_pal_rse_info(&phys_stacked, &hints) == 0)
442 seq_printf(m,
443 "RSE stacked physical registers : %ld\n"
444 "RSE load/store hints : %ld (%s)\n",
445 phys_stacked, hints.ph_data,
446 hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
456 447
457 p += sprintf(p,
458 "RSE stacked physical registers : %ld\n"
459 "RSE load/store hints : %ld (%s)\n",
460 phys_stacked, hints.ph_data,
461 hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
462 }
463 if (ia64_pal_debug_info(&iregs, &dregs)) 448 if (ia64_pal_debug_info(&iregs, &dregs))
464 return 0; 449 return 0;
465 450
466 p += sprintf(p, 451 seq_printf(m,
467 "Instruction debug register pairs : %ld\n" 452 "Instruction debug register pairs : %ld\n"
468 "Data debug register pairs : %ld\n", iregs, dregs); 453 "Data debug register pairs : %ld\n", iregs, dregs);
469 454
470 return p - page; 455 return 0;
471} 456}
472 457
473static char *proc_features_0[]={ /* Feature set 0 */ 458static const char *const proc_features_0[]={ /* Feature set 0 */
474 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 459 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
475 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL, 460 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
476 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 461 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -502,7 +487,7 @@ static char *proc_features_0[]={ /* Feature set 0 */
502 "Enable BERR promotion" 487 "Enable BERR promotion"
503}; 488};
504 489
505static char *proc_features_16[]={ /* Feature set 16 */ 490static const char *const proc_features_16[]={ /* Feature set 16 */
506 "Disable ETM", 491 "Disable ETM",
507 "Enable ETM", 492 "Enable ETM",
508 "Enable MCA on half-way timer", 493 "Enable MCA on half-way timer",
@@ -522,7 +507,7 @@ static char *proc_features_16[]={ /* Feature set 16 */
522 NULL, NULL, NULL, NULL, NULL 507 NULL, NULL, NULL, NULL, NULL
523}; 508};
524 509
525static char **proc_features[]={ 510static const char *const *const proc_features[]={
526 proc_features_0, 511 proc_features_0,
527 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 512 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
528 NULL, NULL, NULL, NULL, 513 NULL, NULL, NULL, NULL,
@@ -530,11 +515,10 @@ static char **proc_features[]={
530 NULL, NULL, NULL, NULL, 515 NULL, NULL, NULL, NULL,
531}; 516};
532 517
533static char * feature_set_info(char *page, u64 avail, u64 status, u64 control, 518static void feature_set_info(struct seq_file *m, u64 avail, u64 status, u64 control,
534 unsigned long set) 519 unsigned long set)
535{ 520{
536 char *p = page; 521 const char *const *vf, *const *v;
537 char **vf, **v;
538 int i; 522 int i;
539 523
540 vf = v = proc_features[set]; 524 vf = v = proc_features[set];
@@ -547,13 +531,13 @@ static char * feature_set_info(char *page, u64 avail, u64 status, u64 control,
547 if (vf) 531 if (vf)
548 v = vf + i; 532 v = vf + i;
549 if ( v && *v ) { 533 if ( v && *v ) {
550 p += sprintf(p, "%-40s : %s %s\n", *v, 534 seq_printf(m, "%-40s : %s %s\n", *v,
551 avail & 0x1 ? (status & 0x1 ? 535 avail & 0x1 ? (status & 0x1 ?
552 "On " : "Off"): "", 536 "On " : "Off"): "",
553 avail & 0x1 ? (control & 0x1 ? 537 avail & 0x1 ? (control & 0x1 ?
554 "Ctrl" : "NoCtrl"): ""); 538 "Ctrl" : "NoCtrl"): "");
555 } else { 539 } else {
556 p += sprintf(p, "Feature set %2ld bit %2d\t\t\t" 540 seq_printf(m, "Feature set %2ld bit %2d\t\t\t"
557 " : %s %s\n", 541 " : %s %s\n",
558 set, i, 542 set, i,
559 avail & 0x1 ? (status & 0x1 ? 543 avail & 0x1 ? (status & 0x1 ?
@@ -562,36 +546,32 @@ static char * feature_set_info(char *page, u64 avail, u64 status, u64 control,
562 "Ctrl" : "NoCtrl"): ""); 546 "Ctrl" : "NoCtrl"): "");
563 } 547 }
564 } 548 }
565 return p;
566} 549}
567 550
568static int 551static int processor_info(struct seq_file *m)
569processor_info(char *page)
570{ 552{
571 char *p = page;
572 u64 avail=1, status=1, control=1, feature_set=0; 553 u64 avail=1, status=1, control=1, feature_set=0;
573 s64 ret; 554 s64 ret;
574 555
575 do { 556 do {
576 ret = ia64_pal_proc_get_features(&avail, &status, &control, 557 ret = ia64_pal_proc_get_features(&avail, &status, &control,
577 feature_set); 558 feature_set);
578 if (ret < 0) { 559 if (ret < 0)
579 return p - page; 560 return 0;
580 } 561
581 if (ret == 1) { 562 if (ret == 1) {
582 feature_set++; 563 feature_set++;
583 continue; 564 continue;
584 } 565 }
585 566
586 p = feature_set_info(p, avail, status, control, feature_set); 567 feature_set_info(m, avail, status, control, feature_set);
587
588 feature_set++; 568 feature_set++;
589 } while(1); 569 } while(1);
590 570
591 return p - page; 571 return 0;
592} 572}
593 573
594static const char *bus_features[]={ 574static const char *const bus_features[]={
595 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 575 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
596 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL, 576 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
597 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 577 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -617,125 +597,118 @@ static const char *bus_features[]={
617}; 597};
618 598
619 599
620static int 600static int bus_info(struct seq_file *m)
621bus_info(char *page)
622{ 601{
623 char *p = page; 602 const char *const *v = bus_features;
624 const char **v = bus_features;
625 pal_bus_features_u_t av, st, ct; 603 pal_bus_features_u_t av, st, ct;
626 u64 avail, status, control; 604 u64 avail, status, control;
627 int i; 605 int i;
628 s64 ret; 606 s64 ret;
629 607
630 if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0) return 0; 608 if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0)
609 return 0;
631 610
632 avail = av.pal_bus_features_val; 611 avail = av.pal_bus_features_val;
633 status = st.pal_bus_features_val; 612 status = st.pal_bus_features_val;
634 control = ct.pal_bus_features_val; 613 control = ct.pal_bus_features_val;
635 614
636 for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) { 615 for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
637 if ( ! *v ) continue; 616 if ( ! *v )
638 p += sprintf(p, "%-48s : %s%s %s\n", *v, 617 continue;
639 avail & 0x1 ? "" : "NotImpl", 618 seq_printf(m, "%-48s : %s%s %s\n", *v,
640 avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "", 619 avail & 0x1 ? "" : "NotImpl",
641 avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): ""); 620 avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
621 avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
642 } 622 }
643 return p - page; 623 return 0;
644} 624}
645 625
646static int 626static int version_info(struct seq_file *m)
647version_info(char *page)
648{ 627{
649 pal_version_u_t min_ver, cur_ver; 628 pal_version_u_t min_ver, cur_ver;
650 char *p = page;
651 629
652 if (ia64_pal_version(&min_ver, &cur_ver) != 0) 630 if (ia64_pal_version(&min_ver, &cur_ver) != 0)
653 return 0; 631 return 0;
654 632
655 p += sprintf(p, 633 seq_printf(m,
656 "PAL_vendor : 0x%02x (min=0x%02x)\n" 634 "PAL_vendor : 0x%02x (min=0x%02x)\n"
657 "PAL_A : %02x.%02x (min=%02x.%02x)\n" 635 "PAL_A : %02x.%02x (min=%02x.%02x)\n"
658 "PAL_B : %02x.%02x (min=%02x.%02x)\n", 636 "PAL_B : %02x.%02x (min=%02x.%02x)\n",
659 cur_ver.pal_version_s.pv_pal_vendor, 637 cur_ver.pal_version_s.pv_pal_vendor,
660 min_ver.pal_version_s.pv_pal_vendor, 638 min_ver.pal_version_s.pv_pal_vendor,
661 cur_ver.pal_version_s.pv_pal_a_model, 639 cur_ver.pal_version_s.pv_pal_a_model,
662 cur_ver.pal_version_s.pv_pal_a_rev, 640 cur_ver.pal_version_s.pv_pal_a_rev,
663 min_ver.pal_version_s.pv_pal_a_model, 641 min_ver.pal_version_s.pv_pal_a_model,
664 min_ver.pal_version_s.pv_pal_a_rev, 642 min_ver.pal_version_s.pv_pal_a_rev,
665 cur_ver.pal_version_s.pv_pal_b_model, 643 cur_ver.pal_version_s.pv_pal_b_model,
666 cur_ver.pal_version_s.pv_pal_b_rev, 644 cur_ver.pal_version_s.pv_pal_b_rev,
667 min_ver.pal_version_s.pv_pal_b_model, 645 min_ver.pal_version_s.pv_pal_b_model,
668 min_ver.pal_version_s.pv_pal_b_rev); 646 min_ver.pal_version_s.pv_pal_b_rev);
669 return p - page; 647 return 0;
670} 648}
671 649
672static int 650static int perfmon_info(struct seq_file *m)
673perfmon_info(char *page)
674{ 651{
675 char *p = page;
676 u64 pm_buffer[16]; 652 u64 pm_buffer[16];
677 pal_perf_mon_info_u_t pm_info; 653 pal_perf_mon_info_u_t pm_info;
678 654
679 if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0; 655 if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0)
680 656 return 0;
681 p += sprintf(p,
682 "PMC/PMD pairs : %d\n"
683 "Counter width : %d bits\n"
684 "Cycle event number : %d\n"
685 "Retired event number : %d\n"
686 "Implemented PMC : ",
687 pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
688 pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
689 657
690 p = bitregister_process(p, pm_buffer, 256); 658 seq_printf(m,
691 p += sprintf(p, "\nImplemented PMD : "); 659 "PMC/PMD pairs : %d\n"
692 p = bitregister_process(p, pm_buffer+4, 256); 660 "Counter width : %d bits\n"
693 p += sprintf(p, "\nCycles count capable : "); 661 "Cycle event number : %d\n"
694 p = bitregister_process(p, pm_buffer+8, 256); 662 "Retired event number : %d\n"
695 p += sprintf(p, "\nRetired bundles count capable : "); 663 "Implemented PMC : ",
664 pm_info.pal_perf_mon_info_s.generic,
665 pm_info.pal_perf_mon_info_s.width,
666 pm_info.pal_perf_mon_info_s.cycles,
667 pm_info.pal_perf_mon_info_s.retired);
668
669 bitregister_process(m, pm_buffer, 256);
670 seq_puts(m, "\nImplemented PMD : ");
671 bitregister_process(m, pm_buffer+4, 256);
672 seq_puts(m, "\nCycles count capable : ");
673 bitregister_process(m, pm_buffer+8, 256);
674 seq_puts(m, "\nRetired bundles count capable : ");
696 675
697#ifdef CONFIG_ITANIUM 676#ifdef CONFIG_ITANIUM
698 /* 677 /*
699 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES 678 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
700 * which is wrong, both PMC4 and PMD5 support it. 679 * which is wrong, both PMC4 and PMD5 support it.
701 */ 680 */
702 if (pm_buffer[12] == 0x10) pm_buffer[12]=0x30; 681 if (pm_buffer[12] == 0x10)
682 pm_buffer[12]=0x30;
703#endif 683#endif
704 684
705 p = bitregister_process(p, pm_buffer+12, 256); 685 bitregister_process(m, pm_buffer+12, 256);
706 686 seq_putc(m, '\n');
707 p += sprintf(p, "\n"); 687 return 0;
708
709 return p - page;
710} 688}
711 689
712static int 690static int frequency_info(struct seq_file *m)
713frequency_info(char *page)
714{ 691{
715 char *p = page;
716 struct pal_freq_ratio proc, itc, bus; 692 struct pal_freq_ratio proc, itc, bus;
717 unsigned long base; 693 unsigned long base;
718 694
719 if (ia64_pal_freq_base(&base) == -1) 695 if (ia64_pal_freq_base(&base) == -1)
720 p += sprintf(p, "Output clock : not implemented\n"); 696 seq_puts(m, "Output clock : not implemented\n");
721 else 697 else
722 p += sprintf(p, "Output clock : %ld ticks/s\n", base); 698 seq_printf(m, "Output clock : %ld ticks/s\n", base);
723 699
724 if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; 700 if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
725 701
726 p += sprintf(p, 702 seq_printf(m,
727 "Processor/Clock ratio : %d/%d\n" 703 "Processor/Clock ratio : %d/%d\n"
728 "Bus/Clock ratio : %d/%d\n" 704 "Bus/Clock ratio : %d/%d\n"
729 "ITC/Clock ratio : %d/%d\n", 705 "ITC/Clock ratio : %d/%d\n",
730 proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); 706 proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
731 707 return 0;
732 return p - page;
733} 708}
734 709
735static int 710static int tr_info(struct seq_file *m)
736tr_info(char *page)
737{ 711{
738 char *p = page;
739 long status; 712 long status;
740 pal_tr_valid_u_t tr_valid; 713 pal_tr_valid_u_t tr_valid;
741 u64 tr_buffer[4]; 714 u64 tr_buffer[4];
@@ -794,39 +767,40 @@ tr_info(char *page)
794 767
795 ifa_reg = (struct ifa_reg *)&tr_buffer[2]; 768 ifa_reg = (struct ifa_reg *)&tr_buffer[2];
796 769
797 if (ifa_reg->valid == 0) continue; 770 if (ifa_reg->valid == 0)
771 continue;
798 772
799 gr_reg = (struct gr_reg *)tr_buffer; 773 gr_reg = (struct gr_reg *)tr_buffer;
800 itir_reg = (struct itir_reg *)&tr_buffer[1]; 774 itir_reg = (struct itir_reg *)&tr_buffer[1];
801 rid_reg = (struct rid_reg *)&tr_buffer[3]; 775 rid_reg = (struct rid_reg *)&tr_buffer[3];
802 776
803 pgm = -1 << (itir_reg->ps - 12); 777 pgm = -1 << (itir_reg->ps - 12);
804 p += sprintf(p, 778 seq_printf(m,
805 "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n" 779 "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
806 "\tppn : 0x%lx\n" 780 "\tppn : 0x%lx\n"
807 "\tvpn : 0x%lx\n" 781 "\tvpn : 0x%lx\n"
808 "\tps : ", 782 "\tps : ",
809 "ID"[i], j, 783 "ID"[i], j,
810 tr_valid.pal_tr_valid_s.access_rights_valid, 784 tr_valid.pal_tr_valid_s.access_rights_valid,
811 tr_valid.pal_tr_valid_s.priv_level_valid, 785 tr_valid.pal_tr_valid_s.priv_level_valid,
812 tr_valid.pal_tr_valid_s.dirty_bit_valid, 786 tr_valid.pal_tr_valid_s.dirty_bit_valid,
813 tr_valid.pal_tr_valid_s.mem_attr_valid, 787 tr_valid.pal_tr_valid_s.mem_attr_valid,
814 (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12); 788 (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
815 789
816 p = bitvector_process(p, 1<< itir_reg->ps); 790 bitvector_process(m, 1<< itir_reg->ps);
817 791
818 p += sprintf(p, 792 seq_printf(m,
819 "\n\tpl : %d\n" 793 "\n\tpl : %d\n"
820 "\tar : %d\n" 794 "\tar : %d\n"
821 "\trid : %x\n" 795 "\trid : %x\n"
822 "\tp : %d\n" 796 "\tp : %d\n"
823 "\tma : %d\n" 797 "\tma : %d\n"
824 "\td : %d\n", 798 "\td : %d\n",
825 gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma, 799 gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
826 gr_reg->d); 800 gr_reg->d);
827 } 801 }
828 } 802 }
829 return p - page; 803 return 0;
830} 804}
831 805
832 806
@@ -834,7 +808,7 @@ tr_info(char *page)
834/* 808/*
835 * List {name,function} pairs for every entry in /proc/palinfo/cpu* 809 * List {name,function} pairs for every entry in /proc/palinfo/cpu*
836 */ 810 */
837static palinfo_entry_t palinfo_entries[]={ 811static const palinfo_entry_t palinfo_entries[]={
838 { "version_info", version_info, }, 812 { "version_info", version_info, },
839 { "vm_info", vm_info, }, 813 { "vm_info", vm_info, },
840 { "cache_info", cache_info, }, 814 { "cache_info", cache_info, },
@@ -876,7 +850,7 @@ typedef union {
876 */ 850 */
877typedef struct { 851typedef struct {
878 palinfo_func_t func; /* pointer to function to call */ 852 palinfo_func_t func; /* pointer to function to call */
879 char *page; /* buffer to store results */ 853 struct seq_file *m; /* buffer to store results */
880 int ret; /* return value from call */ 854 int ret; /* return value from call */
881} palinfo_smp_data_t; 855} palinfo_smp_data_t;
882 856
@@ -889,7 +863,7 @@ static void
889palinfo_smp_call(void *info) 863palinfo_smp_call(void *info)
890{ 864{
891 palinfo_smp_data_t *data = (palinfo_smp_data_t *)info; 865 palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
892 data->ret = (*data->func)(data->page); 866 data->ret = (*data->func)(data->m);
893} 867}
894 868
895/* 869/*
@@ -899,13 +873,13 @@ palinfo_smp_call(void *info)
899 * otherwise how many bytes in the "page" buffer were written 873 * otherwise how many bytes in the "page" buffer were written
900 */ 874 */
901static 875static
902int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page) 876int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
903{ 877{
904 palinfo_smp_data_t ptr; 878 palinfo_smp_data_t ptr;
905 int ret; 879 int ret;
906 880
907 ptr.func = palinfo_entries[f->func_id].proc_read; 881 ptr.func = palinfo_entries[f->func_id].proc_read;
908 ptr.page = page; 882 ptr.m = m;
909 ptr.ret = 0; /* just in case */ 883 ptr.ret = 0; /* just in case */
910 884
911 885
@@ -919,7 +893,7 @@ int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
919} 893}
920#else /* ! CONFIG_SMP */ 894#else /* ! CONFIG_SMP */
921static 895static
922int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page) 896int palinfo_handle_smp(struct seq_file *m, pal_func_cpu_u_t *f)
923{ 897{
924 printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n"); 898 printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n");
925 return 0; 899 return 0;
@@ -929,34 +903,35 @@ int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
929/* 903/*
930 * Entry point routine: all calls go through this function 904 * Entry point routine: all calls go through this function
931 */ 905 */
932static int 906static int proc_palinfo_show(struct seq_file *m, void *v)
933palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
934{ 907{
935 int len=0; 908 pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&m->private;
936 pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&data;
937 909
938 /* 910 /*
939 * in SMP mode, we may need to call another CPU to get correct 911 * in SMP mode, we may need to call another CPU to get correct
940 * information. PAL, by definition, is processor specific 912 * information. PAL, by definition, is processor specific
941 */ 913 */
942 if (f->req_cpu == get_cpu()) 914 if (f->req_cpu == get_cpu())
943 len = (*palinfo_entries[f->func_id].proc_read)(page); 915 (*palinfo_entries[f->func_id].proc_read)(m);
944 else 916 else
945 len = palinfo_handle_smp(f, page); 917 palinfo_handle_smp(m, f);
946 918
947 put_cpu(); 919 put_cpu();
920 return 0;
921}
948 922
949 if (len <= off+count) *eof = 1; 923static int proc_palinfo_open(struct inode *inode, struct file *file)
950 924{
951 *start = page + off; 925 return single_open(file, proc_palinfo_show, PDE_DATA(inode));
952 len -= off;
953
954 if (len>count) len = count;
955 if (len<0) len = 0;
956
957 return len;
958} 926}
959 927
928static const struct file_operations proc_palinfo_fops = {
929 .open = proc_palinfo_open,
930 .read = seq_read,
931 .llseek = seq_lseek,
932 .release = seq_release,
933};
934
960static void __cpuinit 935static void __cpuinit
961create_palinfo_proc_entries(unsigned int cpu) 936create_palinfo_proc_entries(unsigned int cpu)
962{ 937{
@@ -974,9 +949,8 @@ create_palinfo_proc_entries(unsigned int cpu)
974 949
975 for (j=0; j < NR_PALINFO_ENTRIES; j++) { 950 for (j=0; j < NR_PALINFO_ENTRIES; j++) {
976 f.func_id = j; 951 f.func_id = j;
977 create_proc_read_entry( 952 proc_create_data(palinfo_entries[j].name, 0, cpu_dir,
978 palinfo_entries[j].name, 0, cpu_dir, 953 &proc_palinfo_fops, (void *)f.value);
979 palinfo_read_entry, (void *)f.value);
980 } 954 }
981} 955}
982 956