File Index
Files and directories
Sign in
FILE

repository.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/ps3/repository.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  PS3 repository routines.
   4 *
   5 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
   6 *  Copyright 2006 Sony Corp.
   7 */
   8
   9#include <asm/lv1call.h>
  10
  11#include "platform.h"
  12
  13enum ps3_vendor_id {
  14	PS3_VENDOR_ID_NONE = 0,
  15	PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
  16};
  17
  18enum ps3_lpar_id {
  19	PS3_LPAR_ID_CURRENT = 0,
  20	PS3_LPAR_ID_PME = 1,
  21};
  22
  23#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
  24static void _dump_field(const char *hdr, u64 n, const char *func, int line)
  25{
  26#if defined(DEBUG)
  27	char s[16];
  28	const char *const in = (const char *)&n;
  29	unsigned int i;
  30
  31	for (i = 0; i < 8; i++)
  32		s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
  33	s[i] = 0;
  34
  35	pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
  36#endif
  37}
  38
  39#define dump_node_name(_a, _b, _c, _d, _e) \
  40	_dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
  41static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
  42	u64 n4, const char *func, int line)
  43{
  44	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
  45	_dump_field("n1: ", n1, func, line);
  46	_dump_field("n2: ", n2, func, line);
  47	_dump_field("n3: ", n3, func, line);
  48	_dump_field("n4: ", n4, func, line);
  49}
  50
  51#define dump_node(_a, _b, _c, _d, _e, _f, _g) \
  52	_dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
  53static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
  54	u64 v1, u64 v2, const char *func, int line)
  55{
  56	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
  57	_dump_field("n1: ", n1, func, line);
  58	_dump_field("n2: ", n2, func, line);
  59	_dump_field("n3: ", n3, func, line);
  60	_dump_field("n4: ", n4, func, line);
  61	pr_devel("%s:%d: v1: %016llx\n", func, line, v1);
  62	pr_devel("%s:%d: v2: %016llx\n", func, line, v2);
  63}
  64
  65/**
  66 * make_first_field - Make the first field of a repository node name.
  67 * @text: Text portion of the field.
  68 * @index: Numeric index portion of the field.  Use zero for 'don't care'.
  69 *
  70 * This routine sets the vendor id to zero (non-vendor specific).
  71 * Returns field value.
  72 */
  73
  74static u64 make_first_field(const char *text, u64 index)
  75{
  76	u64 n = 0;
  77
  78	memcpy((char *)&n, text, strnlen(text, sizeof(n)));
  79	return PS3_VENDOR_ID_NONE + (n >> 32) + index;
  80}
  81
  82/**
  83 * make_field - Make subsequent fields of a repository node name.
  84 * @text: Text portion of the field.  Use "" for 'don't care'.
  85 * @index: Numeric index portion of the field.  Use zero for 'don't care'.
  86 *
  87 * Returns field value.
  88 */
  89
  90static u64 make_field(const char *text, u64 index)
  91{
  92	u64 n = 0;
  93
  94	memcpy((char *)&n, text, strnlen(text, sizeof(n)));
  95	return n + index;
  96}
  97
  98/**
  99 * read_node - Read a repository node from raw fields.
 100 * @n1: First field of node name.
 101 * @n2: Second field of node name.  Use zero for 'don't care'.
 102 * @n3: Third field of node name.  Use zero for 'don't care'.
 103 * @n4: Fourth field of node name.  Use zero for 'don't care'.
 104 * @v1: First repository value (high word).
 105 * @v2: Second repository value (low word).  Optional parameter, use zero
 106 *      for 'don't care'.
 107 */
 108
 109static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
 110	u64 *_v1, u64 *_v2)
 111{
 112	int result;
 113	u64 v1;
 114	u64 v2;
 115
 116	if (lpar_id == PS3_LPAR_ID_CURRENT) {
 117		u64 id;
 118		lv1_get_logical_partition_id(&id);
 119		lpar_id = id;
 120	}
 121
 122	result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1,
 123		&v2);
 124
 125	if (result) {
 126		pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",
 127			__func__, __LINE__, ps3_result(result));
 128		dump_node_name(lpar_id, n1, n2, n3, n4);
 129		return -ENOENT;
 130	}
 131
 132	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
 133
 134	if (_v1)
 135		*_v1 = v1;
 136	if (_v2)
 137		*_v2 = v2;
 138
 139	if (v1 && !_v1)
 140		pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",
 141			__func__, __LINE__, v1);
 142	if (v2 && !_v2)
 143		pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",
 144			__func__, __LINE__, v2);
 145
 146	return 0;
 147}
 148
 149int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
 150	u64 *value)
 151{
 152	return read_node(PS3_LPAR_ID_PME,
 153		make_first_field("bus", bus_index),
 154		make_field(bus_str, 0),
 155		0, 0,
 156		value, NULL);
 157}
 158
 159int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
 160{
 161	return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
 162			 make_field("id", 0), 0, 0, bus_id, NULL);
 163}
 164
 165int ps3_repository_read_bus_type(unsigned int bus_index,
 166	enum ps3_bus_type *bus_type)
 167{
 168	int result;
 169	u64 v1 = 0;
 170
 171	result = read_node(PS3_LPAR_ID_PME,
 172		make_first_field("bus", bus_index),
 173		make_field("type", 0),
 174		0, 0,
 175		&v1, NULL);
 176	*bus_type = v1;
 177	return result;
 178}
 179
 180int ps3_repository_read_bus_num_dev(unsigned int bus_index,
 181	unsigned int *num_dev)
 182{
 183	int result;
 184	u64 v1 = 0;
 185
 186	result = read_node(PS3_LPAR_ID_PME,
 187		make_first_field("bus", bus_index),
 188		make_field("num_dev", 0),
 189		0, 0,
 190		&v1, NULL);
 191	*num_dev = v1;
 192	return result;
 193}
 194
 195int ps3_repository_read_dev_str(unsigned int bus_index,
 196	unsigned int dev_index, const char *dev_str, u64 *value)
 197{
 198	return read_node(PS3_LPAR_ID_PME,
 199		make_first_field("bus", bus_index),
 200		make_field("dev", dev_index),
 201		make_field(dev_str, 0),
 202		0,
 203		value, NULL);
 204}
 205
 206int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
 207	u64 *dev_id)
 208{
 209	return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
 210			 make_field("dev", dev_index), make_field("id", 0), 0,
 211			 dev_id, NULL);
 212}
 213
 214int ps3_repository_read_dev_type(unsigned int bus_index,
 215	unsigned int dev_index, enum ps3_dev_type *dev_type)
 216{
 217	int result;
 218	u64 v1 = 0;
 219
 220	result = read_node(PS3_LPAR_ID_PME,
 221		make_first_field("bus", bus_index),
 222		make_field("dev", dev_index),
 223		make_field("type", 0),
 224		0,
 225		&v1, NULL);
 226	*dev_type = v1;
 227	return result;
 228}
 229
 230int ps3_repository_read_dev_intr(unsigned int bus_index,
 231	unsigned int dev_index, unsigned int intr_index,
 232	enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
 233{
 234	int result;
 235	u64 v1 = 0;
 236	u64 v2 = 0;
 237
 238	result = read_node(PS3_LPAR_ID_PME,
 239		make_first_field("bus", bus_index),
 240		make_field("dev", dev_index),
 241		make_field("intr", intr_index),
 242		0,
 243		&v1, &v2);
 244	*intr_type = v1;
 245	*interrupt_id = v2;
 246	return result;
 247}
 248
 249int ps3_repository_read_dev_reg_type(unsigned int bus_index,
 250	unsigned int dev_index, unsigned int reg_index,
 251	enum ps3_reg_type *reg_type)
 252{
 253	int result;
 254	u64 v1 = 0;
 255
 256	result = read_node(PS3_LPAR_ID_PME,
 257		make_first_field("bus", bus_index),
 258		make_field("dev", dev_index),
 259		make_field("reg", reg_index),
 260		make_field("type", 0),
 261		&v1, NULL);
 262	*reg_type = v1;
 263	return result;
 264}
 265
 266int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
 267	unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
 268{
 269	return read_node(PS3_LPAR_ID_PME,
 270		make_first_field("bus", bus_index),
 271		make_field("dev", dev_index),
 272		make_field("reg", reg_index),
 273		make_field("data", 0),
 274		bus_addr, len);
 275}
 276
 277int ps3_repository_read_dev_reg(unsigned int bus_index,
 278	unsigned int dev_index, unsigned int reg_index,
 279	enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
 280{
 281	int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
 282		reg_index, reg_type);
 283	return result ? result
 284		: ps3_repository_read_dev_reg_addr(bus_index, dev_index,
 285		reg_index, bus_addr, len);
 286}
 287
 288
 289
 290int ps3_repository_find_device(struct ps3_repository_device *repo)
 291{
 292	int result;
 293	struct ps3_repository_device tmp = *repo;
 294	unsigned int num_dev;
 295
 296	BUG_ON(repo->bus_index > 10);
 297	BUG_ON(repo->dev_index > 10);
 298
 299	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 300
 301	if (result) {
 302		pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
 303		return result;
 304	}
 305
 306	pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
 307		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
 308		num_dev);
 309
 310	if (tmp.dev_index >= num_dev) {
 311		pr_devel("%s:%d: no device found\n", __func__, __LINE__);
 312		return -ENODEV;
 313	}
 314
 315	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
 316		&tmp.dev_type);
 317
 318	if (result) {
 319		pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);
 320		return result;
 321	}
 322
 323	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
 324		&tmp.dev_id);
 325
 326	if (result) {
 327		pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,
 328		__LINE__);
 329		return result;
 330	}
 331
 332	pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
 333		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
 334
 335	*repo = tmp;
 336	return 0;
 337}
 338
 339int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
 340				     u64 bus_id, u64 dev_id)
 341{
 342	int result = -ENODEV;
 343	struct ps3_repository_device tmp;
 344	unsigned int num_dev;
 345
 346	pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
 347		 bus_id, dev_id);
 348
 349	for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
 350		result = ps3_repository_read_bus_id(tmp.bus_index,
 351						    &tmp.bus_id);
 352		if (result) {
 353			pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,
 354				 __LINE__, tmp.bus_index);
 355			return result;
 356		}
 357
 358		if (tmp.bus_id == bus_id)
 359			goto found_bus;
 360
 361		pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
 362			 tmp.bus_id);
 363	}
 364	pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
 365	return result;
 366
 367found_bus:
 368	result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
 369	if (result) {
 370		pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,
 371			 __LINE__, tmp.bus_index);
 372		return result;
 373	}
 374
 375	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 376	if (result) {
 377		pr_devel("%s:%u read_bus_num_dev failed\n", __func__,
 378			 __LINE__);
 379		return result;
 380	}
 381
 382	for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
 383		result = ps3_repository_read_dev_id(tmp.bus_index,
 384						    tmp.dev_index,
 385						    &tmp.dev_id);
 386		if (result) {
 387			pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,
 388				 __LINE__, tmp.bus_index, tmp.dev_index);
 389			return result;
 390		}
 391
 392		if (tmp.dev_id == dev_id)
 393			goto found_dev;
 394
 395		pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
 396			 tmp.dev_id);
 397	}
 398	pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);
 399	return result;
 400
 401found_dev:
 402	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
 403					      &tmp.dev_type);
 404	if (result) {
 405		pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);
 406		return result;
 407	}
 408
 409	pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
 410		 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
 411		 tmp.dev_index, tmp.bus_id, tmp.dev_id);
 412	*repo = tmp;
 413	return 0;
 414}
 415
 416int __init ps3_repository_find_devices(enum ps3_bus_type bus_type,
 417	int (*callback)(const struct ps3_repository_device *repo))
 418{
 419	int result = 0;
 420	struct ps3_repository_device repo;
 421
 422	pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 423
 424	repo.bus_type = bus_type;
 425	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
 426	if (result) {
 427		pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
 428		return result;
 429	}
 430
 431	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
 432	if (result) {
 433		pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
 434			 repo.bus_index);
 435		return result;
 436	}
 437
 438	for (repo.dev_index = 0; ; repo.dev_index++) {
 439		result = ps3_repository_find_device(&repo);
 440		if (result == -ENODEV) {
 441			result = 0;
 442			break;
 443		} else if (result)
 444			break;
 445
 446		result = callback(&repo);
 447		if (result) {
 448			pr_devel("%s:%d: abort at callback\n", __func__,
 449				__LINE__);
 450			break;
 451		}
 452	}
 453
 454	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 455	return result;
 456}
 457
 458int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
 459	unsigned int *bus_index)
 460{
 461	unsigned int i;
 462	enum ps3_bus_type type;
 463	int error;
 464
 465	for (i = from; i < 10; i++) {
 466		error = ps3_repository_read_bus_type(i, &type);
 467		if (error) {
 468			pr_devel("%s:%d read_bus_type failed\n",
 469				__func__, __LINE__);
 470			*bus_index = UINT_MAX;
 471			return error;
 472		}
 473		if (type == bus_type) {
 474			*bus_index = i;
 475			return 0;
 476		}
 477	}
 478	*bus_index = UINT_MAX;
 479	return -ENODEV;
 480}
 481
 482int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 483	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
 484{
 485	int result = 0;
 486	unsigned int res_index;
 487
 488	pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
 489
 490	*interrupt_id = UINT_MAX;
 491
 492	for (res_index = 0; res_index < 10; res_index++) {
 493		enum ps3_interrupt_type t;
 494		unsigned int id;
 495
 496		result = ps3_repository_read_dev_intr(repo->bus_index,
 497			repo->dev_index, res_index, &t, &id);
 498
 499		if (result) {
 500			pr_devel("%s:%d read_dev_intr failed\n",
 501				__func__, __LINE__);
 502			return result;
 503		}
 504
 505		if (t == intr_type) {
 506			*interrupt_id = id;
 507			break;
 508		}
 509	}
 510
 511	if (res_index == 10)
 512		return -ENODEV;
 513
 514	pr_devel("%s:%d: found intr_type %u at res_index %u\n",
 515		__func__, __LINE__, intr_type, res_index);
 516
 517	return result;
 518}
 519
 520int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 521	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
 522{
 523	int result = 0;
 524	unsigned int res_index;
 525
 526	pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
 527
 528	*bus_addr = *len = 0;
 529
 530	for (res_index = 0; res_index < 10; res_index++) {
 531		enum ps3_reg_type t;
 532		u64 a;
 533		u64 l;
 534
 535		result = ps3_repository_read_dev_reg(repo->bus_index,
 536			repo->dev_index, res_index, &t, &a, &l);
 537
 538		if (result) {
 539			pr_devel("%s:%d read_dev_reg failed\n",
 540				__func__, __LINE__);
 541			return result;
 542		}
 543
 544		if (t == reg_type) {
 545			*bus_addr = a;
 546			*len = l;
 547			break;
 548		}
 549	}
 550
 551	if (res_index == 10)
 552		return -ENODEV;
 553
 554	pr_devel("%s:%d: found reg_type %u at res_index %u\n",
 555		__func__, __LINE__, reg_type, res_index);
 556
 557	return result;
 558}
 559
 560int ps3_repository_read_stor_dev_port(unsigned int bus_index,
 561	unsigned int dev_index, u64 *port)
 562{
 563	return read_node(PS3_LPAR_ID_PME,
 564		make_first_field("bus", bus_index),
 565		make_field("dev", dev_index),
 566		make_field("port", 0),
 567		0, port, NULL);
 568}
 569
 570int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
 571	unsigned int dev_index, u64 *blk_size)
 572{
 573	return read_node(PS3_LPAR_ID_PME,
 574		make_first_field("bus", bus_index),
 575		make_field("dev", dev_index),
 576		make_field("blk_size", 0),
 577		0, blk_size, NULL);
 578}
 579
 580int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
 581	unsigned int dev_index, u64 *num_blocks)
 582{
 583	return read_node(PS3_LPAR_ID_PME,
 584		make_first_field("bus", bus_index),
 585		make_field("dev", dev_index),
 586		make_field("n_blocks", 0),
 587		0, num_blocks, NULL);
 588}
 589
 590int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
 591	unsigned int dev_index, unsigned int *num_regions)
 592{
 593	int result;
 594	u64 v1 = 0;
 595
 596	result = read_node(PS3_LPAR_ID_PME,
 597		make_first_field("bus", bus_index),
 598		make_field("dev", dev_index),
 599		make_field("n_regs", 0),
 600		0, &v1, NULL);
 601	*num_regions = v1;
 602	return result;
 603}
 604
 605int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
 606	unsigned int dev_index, unsigned int region_index,
 607	unsigned int *region_id)
 608{
 609	int result;
 610	u64 v1 = 0;
 611
 612	result = read_node(PS3_LPAR_ID_PME,
 613	    make_first_field("bus", bus_index),
 614	    make_field("dev", dev_index),
 615	    make_field("region", region_index),
 616	    make_field("id", 0),
 617	    &v1, NULL);
 618	*region_id = v1;
 619	return result;
 620}
 621
 622int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
 623	unsigned int dev_index,	unsigned int region_index, u64 *region_size)
 624{
 625	return read_node(PS3_LPAR_ID_PME,
 626	    make_first_field("bus", bus_index),
 627	    make_field("dev", dev_index),
 628	    make_field("region", region_index),
 629	    make_field("size", 0),
 630	    region_size, NULL);
 631}
 632
 633int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
 634	unsigned int dev_index, unsigned int region_index, u64 *region_start)
 635{
 636	return read_node(PS3_LPAR_ID_PME,
 637	    make_first_field("bus", bus_index),
 638	    make_field("dev", dev_index),
 639	    make_field("region", region_index),
 640	    make_field("start", 0),
 641	    region_start, NULL);
 642}
 643
 644int ps3_repository_read_stor_dev_info(unsigned int bus_index,
 645	unsigned int dev_index, u64 *port, u64 *blk_size,
 646	u64 *num_blocks, unsigned int *num_regions)
 647{
 648	int result;
 649
 650	result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
 651	if (result)
 652	    return result;
 653
 654	result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
 655		blk_size);
 656	if (result)
 657	    return result;
 658
 659	result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
 660		num_blocks);
 661	if (result)
 662	    return result;
 663
 664	result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
 665		num_regions);
 666	return result;
 667}
 668
 669int ps3_repository_read_stor_dev_region(unsigned int bus_index,
 670	unsigned int dev_index, unsigned int region_index,
 671	unsigned int *region_id, u64 *region_start, u64 *region_size)
 672{
 673	int result;
 674
 675	result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
 676		region_index, region_id);
 677	if (result)
 678	    return result;
 679
 680	result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
 681		region_index, region_start);
 682	if (result)
 683	    return result;
 684
 685	result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
 686		region_index, region_size);
 687	return result;
 688}
 689
 690/**
 691 * ps3_repository_read_num_pu - Number of logical PU processors for this lpar.
 692 */
 693
 694int ps3_repository_read_num_pu(u64 *num_pu)
 695{
 696	*num_pu = 0;
 697	return read_node(PS3_LPAR_ID_CURRENT,
 698			   make_first_field("bi", 0),
 699			   make_field("pun", 0),
 700			   0, 0,
 701			   num_pu, NULL);
 702}
 703
 704/**
 705 * ps3_repository_read_pu_id - Read the logical PU id.
 706 * @pu_index: Zero based index.
 707 * @pu_id: The logical PU id.
 708 */
 709
 710int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
 711{
 712	return read_node(PS3_LPAR_ID_CURRENT,
 713		make_first_field("bi", 0),
 714		make_field("pu", pu_index),
 715		0, 0,
 716		pu_id, NULL);
 717}
 718
 719int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
 720{
 721	return read_node(PS3_LPAR_ID_CURRENT,
 722		make_first_field("bi", 0),
 723		make_field("pu", 0),
 724		ppe_id,
 725		make_field("rm_size", 0),
 726		rm_size, NULL);
 727}
 728
 729int ps3_repository_read_region_total(u64 *region_total)
 730{
 731	return read_node(PS3_LPAR_ID_CURRENT,
 732		make_first_field("bi", 0),
 733		make_field("rgntotal", 0),
 734		0, 0,
 735		region_total, NULL);
 736}
 737
 738/**
 739 * ps3_repository_read_mm_info - Read mm info for single pu system.
 740 * @rm_base: Real mode memory base address.
 741 * @rm_size: Real mode memory size.
 742 * @region_total: Maximum memory region size.
 743 */
 744
 745int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
 746{
 747	int result;
 748	u64 ppe_id;
 749
 750	lv1_get_logical_ppe_id(&ppe_id);
 751	*rm_base = 0;
 752	result = ps3_repository_read_rm_size(ppe_id, rm_size);
 753	return result ? result
 754		: ps3_repository_read_region_total(region_total);
 755}
 756
 757/**
 758 * ps3_repository_read_highmem_region_count - Read the number of highmem regions
 759 *
 760 * Bootloaders must arrange the repository nodes such that regions are indexed
 761 * with a region_index from 0 to region_count-1.
 762 */
 763
 764int ps3_repository_read_highmem_region_count(unsigned int *region_count)
 765{
 766	int result;
 767	u64 v1 = 0;
 768
 769	result = read_node(PS3_LPAR_ID_CURRENT,
 770		make_first_field("highmem", 0),
 771		make_field("region", 0),
 772		make_field("count", 0),
 773		0,
 774		&v1, NULL);
 775	*region_count = v1;
 776	return result;
 777}
 778
 779
 780int ps3_repository_read_highmem_base(unsigned int region_index,
 781	u64 *highmem_base)
 782{
 783	return read_node(PS3_LPAR_ID_CURRENT,
 784		make_first_field("highmem", 0),
 785		make_field("region", region_index),
 786		make_field("base", 0),
 787		0,
 788		highmem_base, NULL);
 789}
 790
 791int ps3_repository_read_highmem_size(unsigned int region_index,
 792	u64 *highmem_size)
 793{
 794	return read_node(PS3_LPAR_ID_CURRENT,
 795		make_first_field("highmem", 0),
 796		make_field("region", region_index),
 797		make_field("size", 0),
 798		0,
 799		highmem_size, NULL);
 800}
 801
 802/**
 803 * ps3_repository_read_highmem_info - Read high memory region info
 804 * @region_index: Region index, {0,..,region_count-1}.
 805 * @highmem_base: High memory base address.
 806 * @highmem_size: High memory size.
 807 *
 808 * Bootloaders that preallocate highmem regions must place the
 809 * region info into the repository at these well known nodes.
 810 */
 811
 812int ps3_repository_read_highmem_info(unsigned int region_index,
 813	u64 *highmem_base, u64 *highmem_size)
 814{
 815	int result;
 816
 817	*highmem_base = 0;
 818	result = ps3_repository_read_highmem_base(region_index, highmem_base);
 819	return result ? result
 820		: ps3_repository_read_highmem_size(region_index, highmem_size);
 821}
 822
 823/**
 824 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
 825 * @num_spu: Number of physical spus.
 826 */
 827
 828int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 829{
 830	int result;
 831	u64 v1 = 0;
 832
 833	result = read_node(PS3_LPAR_ID_CURRENT,
 834		make_first_field("bi", 0),
 835		make_field("spun", 0),
 836		0, 0,
 837		&v1, NULL);
 838	*num_spu_reserved = v1;
 839	return result;
 840}
 841
 842/**
 843 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
 844 * @num_resource_id: Number of spu resource ids.
 845 */
 846
 847int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
 848{
 849	int result;
 850	u64 v1 = 0;
 851
 852	result = read_node(PS3_LPAR_ID_CURRENT,
 853		make_first_field("bi", 0),
 854		make_field("spursvn", 0),
 855		0, 0,
 856		&v1, NULL);
 857	*num_resource_id = v1;
 858	return result;
 859}
 860
 861/**
 862 * ps3_repository_read_spu_resource_id - spu resource reservation id value.
 863 * @res_index: Resource reservation index.
 864 * @resource_type: Resource reservation type.
 865 * @resource_id: Resource reservation id.
 866 */
 867
 868int ps3_repository_read_spu_resource_id(unsigned int res_index,
 869	enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
 870{
 871	int result;
 872	u64 v1 = 0;
 873	u64 v2 = 0;
 874
 875	result = read_node(PS3_LPAR_ID_CURRENT,
 876		make_first_field("bi", 0),
 877		make_field("spursv", 0),
 878		res_index,
 879		0,
 880		&v1, &v2);
 881	*resource_type = v1;
 882	*resource_id = v2;
 883	return result;
 884}
 885
 886static int ps3_repository_read_boot_dat_address(u64 *address)
 887{
 888	return read_node(PS3_LPAR_ID_CURRENT,
 889		make_first_field("bi", 0),
 890		make_field("boot_dat", 0),
 891		make_field("address", 0),
 892		0,
 893		address, NULL);
 894}
 895
 896int ps3_repository_read_boot_dat_size(unsigned int *size)
 897{
 898	int result;
 899	u64 v1 = 0;
 900
 901	result = read_node(PS3_LPAR_ID_CURRENT,
 902		make_first_field("bi", 0),
 903		make_field("boot_dat", 0),
 904		make_field("size", 0),
 905		0,
 906		&v1, NULL);
 907	*size = v1;
 908	return result;
 909}
 910
 911int __init ps3_repository_read_vuart_av_port(unsigned int *port)
 912{
 913	int result;
 914	u64 v1 = 0;
 915
 916	result = read_node(PS3_LPAR_ID_CURRENT,
 917		make_first_field("bi", 0),
 918		make_field("vir_uart", 0),
 919		make_field("port", 0),
 920		make_field("avset", 0),
 921		&v1, NULL);
 922	*port = v1;
 923	return result;
 924}
 925
 926int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
 927{
 928	int result;
 929	u64 v1 = 0;
 930
 931	result = read_node(PS3_LPAR_ID_CURRENT,
 932		make_first_field("bi", 0),
 933		make_field("vir_uart", 0),
 934		make_field("port", 0),
 935		make_field("sysmgr", 0),
 936		&v1, NULL);
 937	*port = v1;
 938	return result;
 939}
 940
 941/**
 942  * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
 943  * @lpar_addr: lpar address of cell_ext_os_area
 944  * @size: size of cell_ext_os_area
 945  */
 946
 947int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
 948{
 949	int result;
 950
 951	*size = 0;
 952	result = ps3_repository_read_boot_dat_address(lpar_addr);
 953	return result ? result
 954		: ps3_repository_read_boot_dat_size(size);
 955}
 956
 957/**
 958 * ps3_repository_read_num_be - Number of physical BE processors in the system.
 959 */
 960
 961int ps3_repository_read_num_be(unsigned int *num_be)
 962{
 963	int result;
 964	u64 v1 = 0;
 965
 966	result = read_node(PS3_LPAR_ID_PME,
 967		make_first_field("ben", 0),
 968		0,
 969		0,
 970		0,
 971		&v1, NULL);
 972	*num_be = v1;
 973	return result;
 974}
 975
 976/**
 977 * ps3_repository_read_be_node_id - Read the physical BE processor node id.
 978 * @be_index: Zero based index.
 979 * @node_id: The BE processor node id.
 980 */
 981
 982int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
 983{
 984	return read_node(PS3_LPAR_ID_PME,
 985		make_first_field("be", be_index),
 986		0,
 987		0,
 988		0,
 989		node_id, NULL);
 990}
 991
 992/**
 993 * ps3_repository_read_be_id - Read the physical BE processor id.
 994 * @node_id: The BE processor node id.
 995 * @be_id: The BE processor id.
 996 */
 997
 998int ps3_repository_read_be_id(u64 node_id, u64 *be_id)
 999{
1000	return read_node(PS3_LPAR_ID_PME,
1001		make_first_field("be", 0),
1002		node_id,
1003		0,
1004		0,
1005		be_id, NULL);
1006}
1007
1008int __init ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
1009{
1010	return read_node(PS3_LPAR_ID_PME,
1011		make_first_field("be", 0),
1012		node_id,
1013		make_field("clock", 0),
1014		0,
1015		tb_freq, NULL);
1016}
1017
1018int __init ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
1019{
1020	int result;
1021	u64 node_id;
1022
1023	*tb_freq = 0;
1024	result = ps3_repository_read_be_node_id(be_index, &node_id);
1025	return result ? result
1026		: ps3_repository_read_tb_freq(node_id, tb_freq);
1027}
1028
1029int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
1030	u64 *rights)
1031{
1032	int result;
1033	u64 node_id;
1034
1035	*lpar = 0;
1036	*rights = 0;
1037	result = ps3_repository_read_be_node_id(be_index, &node_id);
1038	return result ? result
1039		: read_node(PS3_LPAR_ID_PME,
1040			    make_first_field("be", 0),
1041			    node_id,
1042			    make_field("lpm", 0),
1043			    make_field("priv", 0),
1044			    lpar, rights);
1045}
1046
1047#if defined(CONFIG_PS3_REPOSITORY_WRITE)
1048
1049static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1050{
1051	int result;
1052
1053	dump_node(0, n1, n2, n3, n4, v1, v2);
1054
1055	result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);
1056
1057	if (result) {
1058		pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",
1059			__func__, __LINE__, ps3_result(result));
1060		return -ENOENT;
1061	}
1062
1063	return 0;
1064}
1065
1066static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)
1067{
1068	int result;
1069
1070	dump_node(0, n1, n2, n3, n4, 0, 0);
1071
1072	result = lv1_delete_repository_node(n1, n2, n3, n4);
1073
1074	if (result) {
1075		pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",
1076			__func__, __LINE__, ps3_result(result));
1077		return -ENOENT;
1078	}
1079
1080	return 0;
1081}
1082
1083static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1084{
1085	int result;
1086
1087	result = create_node(n1, n2, n3, n4, v1, v2);
1088
1089	if (!result)
1090		return 0;
1091
1092	result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);
1093
1094	if (result) {
1095		pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",
1096			__func__, __LINE__, ps3_result(result));
1097		return -ENOENT;
1098	}
1099
1100	return 0;
1101}
1102
1103int ps3_repository_write_highmem_region_count(unsigned int region_count)
1104{
1105	int result;
1106	u64 v1 = (u64)region_count;
1107
1108	result = write_node(
1109		make_first_field("highmem", 0),
1110		make_field("region", 0),
1111		make_field("count", 0),
1112		0,
1113		v1, 0);
1114	return result;
1115}
1116
1117int ps3_repository_write_highmem_base(unsigned int region_index,
1118	u64 highmem_base)
1119{
1120	return write_node(
1121		make_first_field("highmem", 0),
1122		make_field("region", region_index),
1123		make_field("base", 0),
1124		0,
1125		highmem_base, 0);
1126}
1127
1128int ps3_repository_write_highmem_size(unsigned int region_index,
1129	u64 highmem_size)
1130{
1131	return write_node(
1132		make_first_field("highmem", 0),
1133		make_field("region", region_index),
1134		make_field("size", 0),
1135		0,
1136		highmem_size, 0);
1137}
1138
1139int ps3_repository_write_highmem_info(unsigned int region_index,
1140	u64 highmem_base, u64 highmem_size)
1141{
1142	int result;
1143
1144	result = ps3_repository_write_highmem_base(region_index, highmem_base);
1145	return result ? result
1146		: ps3_repository_write_highmem_size(region_index, highmem_size);
1147}
1148
1149static int ps3_repository_delete_highmem_base(unsigned int region_index)
1150{
1151	return delete_node(
1152		make_first_field("highmem", 0),
1153		make_field("region", region_index),
1154		make_field("base", 0),
1155		0);
1156}
1157
1158static int ps3_repository_delete_highmem_size(unsigned int region_index)
1159{
1160	return delete_node(
1161		make_first_field("highmem", 0),
1162		make_field("region", region_index),
1163		make_field("size", 0),
1164		0);
1165}
1166
1167int ps3_repository_delete_highmem_info(unsigned int region_index)
1168{
1169	int result;
1170
1171	result = ps3_repository_delete_highmem_base(region_index);
1172	result += ps3_repository_delete_highmem_size(region_index);
1173
1174	return result ? -1 : 0;
1175}
1176
1177#endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */
1178
1179#if defined(DEBUG)
1180
1181int __init ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
1182{
1183	int result = 0;
1184	unsigned int res_index;
1185
1186	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1187		repo->bus_index, repo->dev_index);
1188
1189	for (res_index = 0; res_index < 10; res_index++) {
1190		enum ps3_interrupt_type intr_type;
1191		unsigned int interrupt_id;
1192
1193		result = ps3_repository_read_dev_intr(repo->bus_index,
1194			repo->dev_index, res_index, &intr_type, &interrupt_id);
1195
1196		if (result) {
1197			if (result !=  LV1_NO_ENTRY)
1198				pr_devel("%s:%d ps3_repository_read_dev_intr"
1199					" (%u:%u) failed\n", __func__, __LINE__,
1200					repo->bus_index, repo->dev_index);
1201			break;
1202		}
1203
1204		pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
1205			__func__, __LINE__, repo->bus_index, repo->dev_index,
1206			intr_type, interrupt_id);
1207	}
1208
1209	for (res_index = 0; res_index < 10; res_index++) {
1210		enum ps3_reg_type reg_type;
1211		u64 bus_addr;
1212		u64 len;
1213
1214		result = ps3_repository_read_dev_reg(repo->bus_index,
1215			repo->dev_index, res_index, &reg_type, &bus_addr, &len);
1216
1217		if (result) {
1218			if (result !=  LV1_NO_ENTRY)
1219				pr_devel("%s:%d ps3_repository_read_dev_reg"
1220					" (%u:%u) failed\n", __func__, __LINE__,
1221					repo->bus_index, repo->dev_index);
1222			break;
1223		}
1224
1225		pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n",
1226			__func__, __LINE__, repo->bus_index, repo->dev_index,
1227			reg_type, bus_addr, len);
1228	}
1229
1230	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1231	return result;
1232}
1233
1234static int __init dump_stor_dev_info(struct ps3_repository_device *repo)
1235{
1236	int result = 0;
1237	unsigned int num_regions, region_index;
1238	u64 port, blk_size, num_blocks;
1239
1240	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1241		repo->bus_index, repo->dev_index);
1242
1243	result = ps3_repository_read_stor_dev_info(repo->bus_index,
1244		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
1245	if (result) {
1246		pr_devel("%s:%d ps3_repository_read_stor_dev_info"
1247			" (%u:%u) failed\n", __func__, __LINE__,
1248			repo->bus_index, repo->dev_index);
1249		goto out;
1250	}
1251
1252	pr_devel("%s:%d  (%u:%u): port %llu, blk_size %llu, num_blocks "
1253		 "%llu, num_regions %u\n",
1254		 __func__, __LINE__, repo->bus_index, repo->dev_index,
1255		port, blk_size, num_blocks, num_regions);
1256
1257	for (region_index = 0; region_index < num_regions; region_index++) {
1258		unsigned int region_id;
1259		u64 region_start, region_size;
1260
1261		result = ps3_repository_read_stor_dev_region(repo->bus_index,
1262			repo->dev_index, region_index, &region_id,
1263			&region_start, &region_size);
1264		if (result) {
1265			 pr_devel("%s:%d ps3_repository_read_stor_dev_region"
1266				  " (%u:%u) failed\n", __func__, __LINE__,
1267				  repo->bus_index, repo->dev_index);
1268			break;
1269		}
1270
1271		pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
1272			__func__, __LINE__, repo->bus_index, repo->dev_index,
1273			region_id, (unsigned long)region_start,
1274			(unsigned long)region_size);
1275	}
1276
1277out:
1278	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1279	return result;
1280}
1281
1282static int __init dump_device_info(struct ps3_repository_device *repo,
1283	unsigned int num_dev)
1284{
1285	int result = 0;
1286
1287	pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
1288
1289	for (repo->dev_index = 0; repo->dev_index < num_dev;
1290		repo->dev_index++) {
1291
1292		result = ps3_repository_read_dev_type(repo->bus_index,
1293			repo->dev_index, &repo->dev_type);
1294
1295		if (result) {
1296			pr_devel("%s:%d ps3_repository_read_dev_type"
1297				" (%u:%u) failed\n", __func__, __LINE__,
1298				repo->bus_index, repo->dev_index);
1299			break;
1300		}
1301
1302		result = ps3_repository_read_dev_id(repo->bus_index,
1303			repo->dev_index, &repo->dev_id);
1304
1305		if (result) {
1306			pr_devel("%s:%d ps3_repository_read_dev_id"
1307				" (%u:%u) failed\n", __func__, __LINE__,
1308				repo->bus_index, repo->dev_index);
1309			continue;
1310		}
1311
1312		pr_devel("%s:%d  (%u:%u): dev_type %u, dev_id %lu\n", __func__,
1313			__LINE__, repo->bus_index, repo->dev_index,
1314			repo->dev_type, (unsigned long)repo->dev_id);
1315
1316		ps3_repository_dump_resource_info(repo);
1317
1318		if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
1319			dump_stor_dev_info(repo);
1320	}
1321
1322	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1323	return result;
1324}
1325
1326int __init ps3_repository_dump_bus_info(void)
1327{
1328	int result = 0;
1329	struct ps3_repository_device repo;
1330
1331	pr_devel(" -> %s:%d\n", __func__, __LINE__);
1332
1333	memset(&repo, 0, sizeof(repo));
1334
1335	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
1336		unsigned int num_dev;
1337
1338		result = ps3_repository_read_bus_type(repo.bus_index,
1339			&repo.bus_type);
1340
1341		if (result) {
1342			pr_devel("%s:%d read_bus_type(%u) failed\n",
1343				__func__, __LINE__, repo.bus_index);
1344			break;
1345		}
1346
1347		result = ps3_repository_read_bus_id(repo.bus_index,
1348			&repo.bus_id);
1349
1350		if (result) {
1351			pr_devel("%s:%d read_bus_id(%u) failed\n",
1352				__func__, __LINE__, repo.bus_index);
1353			continue;
1354		}
1355
1356		if (repo.bus_index != repo.bus_id)
1357			pr_devel("%s:%d bus_index != bus_id\n",
1358				__func__, __LINE__);
1359
1360		result = ps3_repository_read_bus_num_dev(repo.bus_index,
1361			&num_dev);
1362
1363		if (result) {
1364			pr_devel("%s:%d read_bus_num_dev(%u) failed\n",
1365				__func__, __LINE__, repo.bus_index);
1366			continue;
1367		}
1368
1369		pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
1370			__func__, __LINE__, repo.bus_index, repo.bus_type,
1371			(unsigned long)repo.bus_id, num_dev);
1372
1373		dump_device_info(&repo, num_dev);
1374	}
1375
1376	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1377	return result;
1378}
1379
1380#endif /* defined(DEBUG) */
~/ Read-only file preview.