Commit 2be02f9f authored by Alessandro Rubini's avatar Alessandro Rubini

sdb: keep baseaddr, print absolute address; implement free_sdb

parent e538df7b
...@@ -61,17 +61,26 @@ static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc, ...@@ -61,17 +61,26 @@ static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc,
arr->level = level; arr->level = level;
arr->fmc = fmc; arr->fmc = fmc;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
union sdb_record *r;
for (j = 0; j < sizeof(arr->record[0]); j += 4) { for (j = 0; j < sizeof(arr->record[0]); j += 4) {
*(uint32_t *)((void *)(arr->record + i) + j) = *(uint32_t *)((void *)(arr->record + i) + j) =
__sdb_rd(fmc, address + (i * 64) + j, convert); __sdb_rd(fmc, address + (i * 64) + j, convert);
} }
r = &arr->record[i];
arr->subtree[i] = ERR_PTR(-ENODEV); arr->subtree[i] = ERR_PTR(-ENODEV);
if (arr->record[i].empty.record_type == sdb_type_bridge) { if (r->empty.record_type == sdb_type_bridge) {
uint64_t subaddr = arr->record[i].bridge.sdb_child; uint64_t subaddr = r->bridge.sdb_child;
struct sdb_component *c;
c = &r->bridge.sdb_component;
subaddr = __be64_to_cpu(subaddr); subaddr = __be64_to_cpu(subaddr);
sub = __fmc_scan_sdb_tree(fmc, subaddr, level + 1); sub = __fmc_scan_sdb_tree(fmc, subaddr, level + 1);
arr->subtree[i] = sub; /* may be error */ arr->subtree[i] = sub; /* may be error */
if (IS_ERR(sub))
continue;
sub->parent = arr;
sub->baseaddr = __be64_to_cpu(c->addr_first);
} }
} }
return arr; return arr;
...@@ -90,12 +99,37 @@ int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address) ...@@ -90,12 +99,37 @@ int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address)
} }
EXPORT_SYMBOL(fmc_scan_sdb_tree); EXPORT_SYMBOL(fmc_scan_sdb_tree);
static void __fmc_sdb_free(struct sdb_array *arr)
{
int i, n;
if (!arr) return;
n = arr->len;
for (i = 0; i < n; i++) {
if (IS_ERR(arr->subtree[i]))
continue;
__fmc_sdb_free(arr->subtree[i]);
}
kfree(arr->record);
kfree(arr->subtree);
kfree(arr);
}
int fmc_free_sdb_tree(struct fmc_device *fmc)
{
__fmc_sdb_free(fmc->sdb);
fmc->sdb = NULL;
return 0;
}
EXPORT_SYMBOL(fmc_free_sdb_tree);
static void __fmc_show_sdb_tree(struct sdb_array *arr) static void __fmc_show_sdb_tree(struct sdb_array *arr)
{ {
int i, j, n = arr->len, level = arr->level; int i, j, n = arr->len, level = arr->level;
struct sdb_array *ap;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
unsigned long base;
union sdb_record *r; union sdb_record *r;
struct sdb_product *p; struct sdb_product *p;
struct sdb_component *c; struct sdb_component *c;
...@@ -104,6 +138,9 @@ static void __fmc_show_sdb_tree(struct sdb_array *arr) ...@@ -104,6 +138,9 @@ static void __fmc_show_sdb_tree(struct sdb_array *arr)
r = &arr->record[i]; r = &arr->record[i];
c = &r->dev.sdb_component; c = &r->dev.sdb_component;
p = &c->product; p = &c->product;
base = 0;
for (ap = arr; ap; ap = ap->parent)
base += ap->baseaddr;
switch(r->empty.record_type) { switch(r->empty.record_type) {
case sdb_type_interconnect: case sdb_type_interconnect:
...@@ -117,14 +154,15 @@ static void __fmc_show_sdb_tree(struct sdb_array *arr) ...@@ -117,14 +154,15 @@ static void __fmc_show_sdb_tree(struct sdb_array *arr)
__be64_to_cpu(p->vendor_id), __be64_to_cpu(p->vendor_id),
__be32_to_cpu(p->device_id), __be32_to_cpu(p->device_id),
p->name, p->name,
__be64_to_cpu(c->addr_first), __be64_to_cpu(c->addr_first) + base,
__be64_to_cpu(c->addr_last)); __be64_to_cpu(c->addr_last) + base);
break; break;
case sdb_type_bridge: case sdb_type_bridge:
printk("%08llx:%08x %.19s (bridge)\n", printk("%08llx:%08x %.19s (bridge: %08llx)\n",
__be64_to_cpu(p->vendor_id), __be64_to_cpu(p->vendor_id),
__be32_to_cpu(p->device_id), __be32_to_cpu(p->device_id),
p->name); p->name,
__be64_to_cpu(c->addr_first) + base);
if (IS_ERR(arr->subtree[i])) { if (IS_ERR(arr->subtree[i])) {
printk("(bridge error %li)\n", printk("(bridge error %li)\n",
PTR_ERR(arr->subtree[i])); PTR_ERR(arr->subtree[i]));
......
...@@ -22,6 +22,7 @@ struct fmc_device; ...@@ -22,6 +22,7 @@ struct fmc_device;
struct sdb_array { struct sdb_array {
int len; int len;
int level; int level;
unsigned long baseaddr;
struct fmc_device *fmc; /* the device that hosts it */ struct fmc_device *fmc; /* the device that hosts it */
struct sdb_array *parent; /* NULL at root */ struct sdb_array *parent; /* NULL at root */
union sdb_record *record; /* copies of the struct */ union sdb_record *record; /* copies of the struct */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment