0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/device.h>
0012 #include <linux/slab.h>
0013 #include <linux/kobject.h>
0014 #include <asm/uv/bios.h>
0015 #include <asm/uv/uv.h>
0016 #include <asm/uv/uv_hub.h>
0017 #include <asm/uv/uv_geo.h>
0018
0019 #define INVALID_CNODE -1
0020
0021 struct kobject *sgi_uv_kobj;
0022 static struct kset *uv_pcibus_kset;
0023 static struct kset *uv_hubs_kset;
0024 static struct uv_bios_hub_info *hub_buf;
0025 static struct uv_bios_port_info **port_buf;
0026 static struct uv_hub **uv_hubs;
0027 static struct uv_pci_top_obj **uv_pci_objs;
0028 static int num_pci_lines;
0029 static int num_cnodes;
0030 static int *prev_obj_to_cnode;
0031 static int uv_bios_obj_cnt;
0032 static signed short uv_master_nasid = -1;
0033 static void *uv_biosheap;
0034
0035 static const char *uv_type_string(void)
0036 {
0037 if (is_uv5_hub())
0038 return "9.0";
0039 else if (is_uv4a_hub())
0040 return "7.1";
0041 else if (is_uv4_hub())
0042 return "7.0";
0043 else if (is_uv3_hub())
0044 return "5.0";
0045 else if (is_uv2_hub())
0046 return "3.0";
0047 else if (uv_get_hubless_system())
0048 return "0.1";
0049 else
0050 return "unknown";
0051 }
0052
0053 static int ordinal_to_nasid(int ordinal)
0054 {
0055 if (ordinal < num_cnodes && ordinal >= 0)
0056 return UV_PNODE_TO_NASID(uv_blade_to_pnode(ordinal));
0057 else
0058 return -1;
0059 }
0060
0061 static union geoid_u cnode_to_geoid(int cnode)
0062 {
0063 union geoid_u geoid;
0064
0065 uv_bios_get_geoinfo(ordinal_to_nasid(cnode), (u64)sizeof(union geoid_u), (u64 *)&geoid);
0066 return geoid;
0067 }
0068
0069 static int location_to_bpos(char *location, int *rack, int *slot, int *blade)
0070 {
0071 char type, r, b, h;
0072 int idb, idh;
0073
0074 if (sscanf(location, "%c%03d%c%02d%c%2d%c%d",
0075 &r, rack, &type, slot, &b, &idb, &h, &idh) != 8)
0076 return -1;
0077 *blade = idb * 2 + idh;
0078
0079 return 0;
0080 }
0081
0082 static int cache_obj_to_cnode(struct uv_bios_hub_info *obj)
0083 {
0084 int cnode;
0085 union geoid_u geoid;
0086 int obj_rack, obj_slot, obj_blade;
0087 int rack, slot, blade;
0088
0089 if (!obj->f.fields.this_part && !obj->f.fields.is_shared)
0090 return 0;
0091
0092 if (location_to_bpos(obj->location, &obj_rack, &obj_slot, &obj_blade))
0093 return -1;
0094
0095 for (cnode = 0; cnode < num_cnodes; cnode++) {
0096 geoid = cnode_to_geoid(cnode);
0097 rack = geo_rack(geoid);
0098 slot = geo_slot(geoid);
0099 blade = geo_blade(geoid);
0100 if (obj_rack == rack && obj_slot == slot && obj_blade == blade)
0101 prev_obj_to_cnode[obj->id] = cnode;
0102 }
0103
0104 return 0;
0105 }
0106
0107 static int get_obj_to_cnode(int obj_id)
0108 {
0109 return prev_obj_to_cnode[obj_id];
0110 }
0111
0112 struct uv_hub {
0113 struct kobject kobj;
0114 struct uv_bios_hub_info *hub_info;
0115 struct uv_port **ports;
0116 };
0117
0118 #define to_uv_hub(kobj_ptr) container_of(kobj_ptr, struct uv_hub, kobj)
0119
0120 static ssize_t hub_name_show(struct uv_bios_hub_info *hub_info, char *buf)
0121 {
0122 return scnprintf(buf, PAGE_SIZE, "%s\n", hub_info->name);
0123 }
0124
0125 static ssize_t hub_location_show(struct uv_bios_hub_info *hub_info, char *buf)
0126 {
0127 return scnprintf(buf, PAGE_SIZE, "%s\n", hub_info->location);
0128 }
0129
0130 static ssize_t hub_partition_show(struct uv_bios_hub_info *hub_info, char *buf)
0131 {
0132 return sprintf(buf, "%d\n", hub_info->f.fields.this_part);
0133 }
0134
0135 static ssize_t hub_shared_show(struct uv_bios_hub_info *hub_info, char *buf)
0136 {
0137 return sprintf(buf, "%d\n", hub_info->f.fields.is_shared);
0138 }
0139 static ssize_t hub_nasid_show(struct uv_bios_hub_info *hub_info, char *buf)
0140 {
0141 int cnode = get_obj_to_cnode(hub_info->id);
0142
0143 return sprintf(buf, "%d\n", ordinal_to_nasid(cnode));
0144 }
0145 static ssize_t hub_cnode_show(struct uv_bios_hub_info *hub_info, char *buf)
0146 {
0147 return sprintf(buf, "%d\n", get_obj_to_cnode(hub_info->id));
0148 }
0149
0150 struct hub_sysfs_entry {
0151 struct attribute attr;
0152 ssize_t (*show)(struct uv_bios_hub_info *hub_info, char *buf);
0153 ssize_t (*store)(struct uv_bios_hub_info *hub_info, const char *buf, size_t sz);
0154 };
0155
0156 static struct hub_sysfs_entry name_attribute =
0157 __ATTR(name, 0444, hub_name_show, NULL);
0158 static struct hub_sysfs_entry location_attribute =
0159 __ATTR(location, 0444, hub_location_show, NULL);
0160 static struct hub_sysfs_entry partition_attribute =
0161 __ATTR(this_partition, 0444, hub_partition_show, NULL);
0162 static struct hub_sysfs_entry shared_attribute =
0163 __ATTR(shared, 0444, hub_shared_show, NULL);
0164 static struct hub_sysfs_entry nasid_attribute =
0165 __ATTR(nasid, 0444, hub_nasid_show, NULL);
0166 static struct hub_sysfs_entry cnode_attribute =
0167 __ATTR(cnode, 0444, hub_cnode_show, NULL);
0168
0169 static struct attribute *uv_hub_attrs[] = {
0170 &name_attribute.attr,
0171 &location_attribute.attr,
0172 &partition_attribute.attr,
0173 &shared_attribute.attr,
0174 &nasid_attribute.attr,
0175 &cnode_attribute.attr,
0176 NULL,
0177 };
0178 ATTRIBUTE_GROUPS(uv_hub);
0179
0180 static void hub_release(struct kobject *kobj)
0181 {
0182 struct uv_hub *hub = to_uv_hub(kobj);
0183
0184 kfree(hub);
0185 }
0186
0187 static ssize_t hub_type_show(struct kobject *kobj, struct attribute *attr,
0188 char *buf)
0189 {
0190 struct uv_hub *hub = to_uv_hub(kobj);
0191 struct uv_bios_hub_info *bios_hub_info = hub->hub_info;
0192 struct hub_sysfs_entry *entry;
0193
0194 entry = container_of(attr, struct hub_sysfs_entry, attr);
0195
0196 if (!entry->show)
0197 return -EIO;
0198
0199 return entry->show(bios_hub_info, buf);
0200 }
0201
0202 static const struct sysfs_ops hub_sysfs_ops = {
0203 .show = hub_type_show,
0204 };
0205
0206 static struct kobj_type hub_attr_type = {
0207 .release = hub_release,
0208 .sysfs_ops = &hub_sysfs_ops,
0209 .default_groups = uv_hub_groups,
0210 };
0211
0212 static int uv_hubs_init(void)
0213 {
0214 s64 biosr;
0215 u64 sz;
0216 int i, ret;
0217
0218 prev_obj_to_cnode = kmalloc_array(uv_bios_obj_cnt, sizeof(*prev_obj_to_cnode),
0219 GFP_KERNEL);
0220 if (!prev_obj_to_cnode)
0221 return -ENOMEM;
0222
0223 for (i = 0; i < uv_bios_obj_cnt; i++)
0224 prev_obj_to_cnode[i] = INVALID_CNODE;
0225
0226 uv_hubs_kset = kset_create_and_add("hubs", NULL, sgi_uv_kobj);
0227 if (!uv_hubs_kset) {
0228 ret = -ENOMEM;
0229 goto err_hubs_kset;
0230 }
0231 sz = uv_bios_obj_cnt * sizeof(*hub_buf);
0232 hub_buf = kzalloc(sz, GFP_KERNEL);
0233 if (!hub_buf) {
0234 ret = -ENOMEM;
0235 goto err_hub_buf;
0236 }
0237
0238 biosr = uv_bios_enum_objs((u64)uv_master_nasid, sz, (u64 *)hub_buf);
0239 if (biosr) {
0240 ret = -EINVAL;
0241 goto err_enum_objs;
0242 }
0243
0244 uv_hubs = kcalloc(uv_bios_obj_cnt, sizeof(*uv_hubs), GFP_KERNEL);
0245 if (!uv_hubs) {
0246 ret = -ENOMEM;
0247 goto err_enum_objs;
0248 }
0249
0250 for (i = 0; i < uv_bios_obj_cnt; i++) {
0251 uv_hubs[i] = kzalloc(sizeof(*uv_hubs[i]), GFP_KERNEL);
0252 if (!uv_hubs[i]) {
0253 i--;
0254 ret = -ENOMEM;
0255 goto err_hubs;
0256 }
0257
0258 uv_hubs[i]->hub_info = &hub_buf[i];
0259 cache_obj_to_cnode(uv_hubs[i]->hub_info);
0260
0261 uv_hubs[i]->kobj.kset = uv_hubs_kset;
0262
0263 ret = kobject_init_and_add(&uv_hubs[i]->kobj, &hub_attr_type,
0264 NULL, "hub_%u", hub_buf[i].id);
0265 if (ret)
0266 goto err_hubs;
0267 kobject_uevent(&uv_hubs[i]->kobj, KOBJ_ADD);
0268 }
0269 return 0;
0270
0271 err_hubs:
0272 for (; i >= 0; i--)
0273 kobject_put(&uv_hubs[i]->kobj);
0274 kfree(uv_hubs);
0275 err_enum_objs:
0276 kfree(hub_buf);
0277 err_hub_buf:
0278 kset_unregister(uv_hubs_kset);
0279 err_hubs_kset:
0280 kfree(prev_obj_to_cnode);
0281 return ret;
0282
0283 }
0284
0285 static void uv_hubs_exit(void)
0286 {
0287 int i;
0288
0289 for (i = 0; i < uv_bios_obj_cnt; i++)
0290 kobject_put(&uv_hubs[i]->kobj);
0291
0292 kfree(uv_hubs);
0293 kfree(hub_buf);
0294 kset_unregister(uv_hubs_kset);
0295 kfree(prev_obj_to_cnode);
0296 }
0297
0298 struct uv_port {
0299 struct kobject kobj;
0300 struct uv_bios_port_info *port_info;
0301 };
0302
0303 #define to_uv_port(kobj_ptr) container_of(kobj_ptr, struct uv_port, kobj)
0304
0305 static ssize_t uv_port_conn_hub_show(struct uv_bios_port_info *port, char *buf)
0306 {
0307 return sprintf(buf, "%d\n", port->conn_id);
0308 }
0309
0310 static ssize_t uv_port_conn_port_show(struct uv_bios_port_info *port, char *buf)
0311 {
0312 return sprintf(buf, "%d\n", port->conn_port);
0313 }
0314
0315 struct uv_port_sysfs_entry {
0316 struct attribute attr;
0317 ssize_t (*show)(struct uv_bios_port_info *port_info, char *buf);
0318 ssize_t (*store)(struct uv_bios_port_info *port_info, const char *buf, size_t size);
0319 };
0320
0321 static struct uv_port_sysfs_entry uv_port_conn_hub_attribute =
0322 __ATTR(conn_hub, 0444, uv_port_conn_hub_show, NULL);
0323 static struct uv_port_sysfs_entry uv_port_conn_port_attribute =
0324 __ATTR(conn_port, 0444, uv_port_conn_port_show, NULL);
0325
0326 static struct attribute *uv_port_attrs[] = {
0327 &uv_port_conn_hub_attribute.attr,
0328 &uv_port_conn_port_attribute.attr,
0329 NULL,
0330 };
0331 ATTRIBUTE_GROUPS(uv_port);
0332
0333 static void uv_port_release(struct kobject *kobj)
0334 {
0335 struct uv_port *port = to_uv_port(kobj);
0336
0337 kfree(port);
0338 }
0339
0340 static ssize_t uv_port_type_show(struct kobject *kobj, struct attribute *attr,
0341 char *buf)
0342 {
0343 struct uv_port *port = to_uv_port(kobj);
0344 struct uv_bios_port_info *port_info = port->port_info;
0345 struct uv_port_sysfs_entry *entry;
0346
0347 entry = container_of(attr, struct uv_port_sysfs_entry, attr);
0348
0349 if (!entry->show)
0350 return -EIO;
0351
0352 return entry->show(port_info, buf);
0353 }
0354
0355 static const struct sysfs_ops uv_port_sysfs_ops = {
0356 .show = uv_port_type_show,
0357 };
0358
0359 static struct kobj_type uv_port_attr_type = {
0360 .release = uv_port_release,
0361 .sysfs_ops = &uv_port_sysfs_ops,
0362 .default_groups = uv_port_groups,
0363 };
0364
0365 static int uv_ports_init(void)
0366 {
0367 s64 biosr;
0368 int j = 0, k = 0, ret, sz;
0369
0370 port_buf = kcalloc(uv_bios_obj_cnt, sizeof(*port_buf), GFP_KERNEL);
0371 if (!port_buf)
0372 return -ENOMEM;
0373
0374 for (j = 0; j < uv_bios_obj_cnt; j++) {
0375 sz = hub_buf[j].ports * sizeof(*port_buf[j]);
0376 port_buf[j] = kzalloc(sz, GFP_KERNEL);
0377 if (!port_buf[j]) {
0378 ret = -ENOMEM;
0379 j--;
0380 goto err_port_info;
0381 }
0382 biosr = uv_bios_enum_ports((u64)uv_master_nasid, (u64)hub_buf[j].id, sz,
0383 (u64 *)port_buf[j]);
0384 if (biosr) {
0385 ret = -EINVAL;
0386 goto err_port_info;
0387 }
0388 }
0389 for (j = 0; j < uv_bios_obj_cnt; j++) {
0390 uv_hubs[j]->ports = kcalloc(hub_buf[j].ports,
0391 sizeof(*uv_hubs[j]->ports), GFP_KERNEL);
0392 if (!uv_hubs[j]->ports) {
0393 ret = -ENOMEM;
0394 j--;
0395 goto err_ports;
0396 }
0397 }
0398 for (j = 0; j < uv_bios_obj_cnt; j++) {
0399 for (k = 0; k < hub_buf[j].ports; k++) {
0400 uv_hubs[j]->ports[k] = kzalloc(sizeof(*uv_hubs[j]->ports[k]), GFP_KERNEL);
0401 if (!uv_hubs[j]->ports[k]) {
0402 ret = -ENOMEM;
0403 k--;
0404 goto err_kobj_ports;
0405 }
0406 uv_hubs[j]->ports[k]->port_info = &port_buf[j][k];
0407 ret = kobject_init_and_add(&uv_hubs[j]->ports[k]->kobj, &uv_port_attr_type,
0408 &uv_hubs[j]->kobj, "port_%d", port_buf[j][k].port);
0409 if (ret)
0410 goto err_kobj_ports;
0411 kobject_uevent(&uv_hubs[j]->ports[k]->kobj, KOBJ_ADD);
0412 }
0413 }
0414 return 0;
0415
0416 err_kobj_ports:
0417 for (; j >= 0; j--) {
0418 for (; k >= 0; k--)
0419 kobject_put(&uv_hubs[j]->ports[k]->kobj);
0420 if (j > 0)
0421 k = hub_buf[j-1].ports - 1;
0422 }
0423 j = uv_bios_obj_cnt - 1;
0424 err_ports:
0425 for (; j >= 0; j--)
0426 kfree(uv_hubs[j]->ports);
0427 j = uv_bios_obj_cnt - 1;
0428 err_port_info:
0429 for (; j >= 0; j--)
0430 kfree(port_buf[j]);
0431 kfree(port_buf);
0432 return ret;
0433 }
0434
0435 static void uv_ports_exit(void)
0436 {
0437 int j, k;
0438
0439 for (j = 0; j < uv_bios_obj_cnt; j++) {
0440 for (k = hub_buf[j].ports - 1; k >= 0; k--)
0441 kobject_put(&uv_hubs[j]->ports[k]->kobj);
0442 }
0443 for (j = 0; j < uv_bios_obj_cnt; j++) {
0444 kfree(uv_hubs[j]->ports);
0445 kfree(port_buf[j]);
0446 }
0447 kfree(port_buf);
0448 }
0449
0450 struct uv_pci_top_obj {
0451 struct kobject kobj;
0452 char *type;
0453 char *location;
0454 int iio_stack;
0455 char *ppb_addr;
0456 int slot;
0457 };
0458
0459 #define to_uv_pci_top_obj(kobj_ptr) container_of(kobj_ptr, struct uv_pci_top_obj, kobj)
0460
0461 static ssize_t uv_pci_type_show(struct uv_pci_top_obj *top_obj, char *buf)
0462 {
0463 return scnprintf(buf, PAGE_SIZE, "%s\n", top_obj->type);
0464 }
0465
0466 static ssize_t uv_pci_location_show(struct uv_pci_top_obj *top_obj, char *buf)
0467 {
0468 return scnprintf(buf, PAGE_SIZE, "%s\n", top_obj->location);
0469 }
0470
0471 static ssize_t uv_pci_iio_stack_show(struct uv_pci_top_obj *top_obj, char *buf)
0472 {
0473 return sprintf(buf, "%d\n", top_obj->iio_stack);
0474 }
0475
0476 static ssize_t uv_pci_ppb_addr_show(struct uv_pci_top_obj *top_obj, char *buf)
0477 {
0478 return scnprintf(buf, PAGE_SIZE, "%s\n", top_obj->ppb_addr);
0479 }
0480
0481 static ssize_t uv_pci_slot_show(struct uv_pci_top_obj *top_obj, char *buf)
0482 {
0483 return sprintf(buf, "%d\n", top_obj->slot);
0484 }
0485
0486 struct uv_pci_top_sysfs_entry {
0487 struct attribute attr;
0488 ssize_t (*show)(struct uv_pci_top_obj *top_obj, char *buf);
0489 ssize_t (*store)(struct uv_pci_top_obj *top_obj, const char *buf, size_t size);
0490 };
0491
0492 static struct uv_pci_top_sysfs_entry uv_pci_type_attribute =
0493 __ATTR(type, 0444, uv_pci_type_show, NULL);
0494 static struct uv_pci_top_sysfs_entry uv_pci_location_attribute =
0495 __ATTR(location, 0444, uv_pci_location_show, NULL);
0496 static struct uv_pci_top_sysfs_entry uv_pci_iio_stack_attribute =
0497 __ATTR(iio_stack, 0444, uv_pci_iio_stack_show, NULL);
0498 static struct uv_pci_top_sysfs_entry uv_pci_ppb_addr_attribute =
0499 __ATTR(ppb_addr, 0444, uv_pci_ppb_addr_show, NULL);
0500 static struct uv_pci_top_sysfs_entry uv_pci_slot_attribute =
0501 __ATTR(slot, 0444, uv_pci_slot_show, NULL);
0502
0503 static void uv_pci_top_release(struct kobject *kobj)
0504 {
0505 struct uv_pci_top_obj *top_obj = to_uv_pci_top_obj(kobj);
0506
0507 kfree(top_obj->type);
0508 kfree(top_obj->location);
0509 kfree(top_obj->ppb_addr);
0510 kfree(top_obj);
0511 }
0512
0513 static ssize_t pci_top_type_show(struct kobject *kobj,
0514 struct attribute *attr, char *buf)
0515 {
0516 struct uv_pci_top_obj *top_obj = to_uv_pci_top_obj(kobj);
0517 struct uv_pci_top_sysfs_entry *entry;
0518
0519 entry = container_of(attr, struct uv_pci_top_sysfs_entry, attr);
0520
0521 if (!entry->show)
0522 return -EIO;
0523
0524 return entry->show(top_obj, buf);
0525 }
0526
0527 static const struct sysfs_ops uv_pci_top_sysfs_ops = {
0528 .show = pci_top_type_show,
0529 };
0530
0531 static struct kobj_type uv_pci_top_attr_type = {
0532 .release = uv_pci_top_release,
0533 .sysfs_ops = &uv_pci_top_sysfs_ops,
0534 };
0535
0536 static int init_pci_top_obj(struct uv_pci_top_obj *top_obj, char *line)
0537 {
0538 char *start;
0539 char type[11], location[14], ppb_addr[15];
0540 int str_cnt, ret;
0541 unsigned int tmp_match[2];
0542
0543
0544 if (strlen(line) < 36)
0545 return -EINVAL;
0546
0547
0548 str_cnt = sscanf(line, "pcibus %4x:%2x", &tmp_match[0], &tmp_match[1]);
0549 if (str_cnt < 2)
0550 return -EINVAL;
0551
0552
0553
0554
0555
0556 line[6] = '_';
0557
0558
0559
0560
0561 line[14] = '\0';
0562
0563
0564 start = &line[15];
0565
0566 top_obj->iio_stack = -1;
0567 top_obj->slot = -1;
0568
0569
0570
0571
0572
0573
0574
0575
0576 if (start[0] == 'r') {
0577 str_cnt = sscanf(start, "%13s %10[^(] %*s %*s %d)",
0578 location, type, &top_obj->iio_stack);
0579 if (str_cnt < 2)
0580 return -EINVAL;
0581 top_obj->type = kstrdup(type, GFP_KERNEL);
0582 if (!top_obj->type)
0583 return -ENOMEM;
0584 top_obj->location = kstrdup(location, GFP_KERNEL);
0585 if (!top_obj->location) {
0586 kfree(top_obj->type);
0587 return -ENOMEM;
0588 }
0589 }
0590
0591
0592
0593 else if (start[0] == 'P') {
0594 str_cnt = sscanf(start, "%10s %*s %14s %*s %d)",
0595 type, ppb_addr, &top_obj->slot);
0596 if (str_cnt < 2)
0597 return -EINVAL;
0598 top_obj->type = kstrdup(type, GFP_KERNEL);
0599 if (!top_obj->type)
0600 return -ENOMEM;
0601 top_obj->ppb_addr = kstrdup(ppb_addr, GFP_KERNEL);
0602 if (!top_obj->ppb_addr) {
0603 kfree(top_obj->type);
0604 return -ENOMEM;
0605 }
0606 } else
0607 return -EINVAL;
0608
0609 top_obj->kobj.kset = uv_pcibus_kset;
0610
0611 ret = kobject_init_and_add(&top_obj->kobj, &uv_pci_top_attr_type, NULL, "%s", line);
0612 if (ret)
0613 goto err_add_sysfs;
0614
0615 if (top_obj->type) {
0616 ret = sysfs_create_file(&top_obj->kobj, &uv_pci_type_attribute.attr);
0617 if (ret)
0618 goto err_add_sysfs;
0619 }
0620 if (top_obj->location) {
0621 ret = sysfs_create_file(&top_obj->kobj, &uv_pci_location_attribute.attr);
0622 if (ret)
0623 goto err_add_sysfs;
0624 }
0625 if (top_obj->iio_stack >= 0) {
0626 ret = sysfs_create_file(&top_obj->kobj, &uv_pci_iio_stack_attribute.attr);
0627 if (ret)
0628 goto err_add_sysfs;
0629 }
0630 if (top_obj->ppb_addr) {
0631 ret = sysfs_create_file(&top_obj->kobj, &uv_pci_ppb_addr_attribute.attr);
0632 if (ret)
0633 goto err_add_sysfs;
0634 }
0635 if (top_obj->slot >= 0) {
0636 ret = sysfs_create_file(&top_obj->kobj, &uv_pci_slot_attribute.attr);
0637 if (ret)
0638 goto err_add_sysfs;
0639 }
0640
0641 kobject_uevent(&top_obj->kobj, KOBJ_ADD);
0642 return 0;
0643
0644 err_add_sysfs:
0645 kobject_put(&top_obj->kobj);
0646 return ret;
0647 }
0648
0649 static int pci_topology_init(void)
0650 {
0651 char *pci_top_str, *start, *found, *count;
0652 size_t sz;
0653 s64 biosr;
0654 int l = 0, k = 0;
0655 int len, ret;
0656
0657 uv_pcibus_kset = kset_create_and_add("pcibuses", NULL, sgi_uv_kobj);
0658 if (!uv_pcibus_kset)
0659 return -ENOMEM;
0660
0661 for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
0662 pci_top_str = kmalloc(sz, GFP_KERNEL);
0663 if (!pci_top_str) {
0664 ret = -ENOMEM;
0665 goto err_pci_top_str;
0666 }
0667 biosr = uv_bios_get_pci_topology((u64)sz, (u64 *)pci_top_str);
0668 if (biosr == BIOS_STATUS_SUCCESS) {
0669 len = strnlen(pci_top_str, sz);
0670 for (count = pci_top_str; count < pci_top_str + len; count++) {
0671 if (*count == '\n')
0672 l++;
0673 }
0674 num_pci_lines = l;
0675
0676 uv_pci_objs = kcalloc(num_pci_lines,
0677 sizeof(*uv_pci_objs), GFP_KERNEL);
0678 if (!uv_pci_objs) {
0679 kfree(pci_top_str);
0680 ret = -ENOMEM;
0681 goto err_pci_top_str;
0682 }
0683 start = pci_top_str;
0684 while ((found = strsep(&start, "\n")) != NULL) {
0685 uv_pci_objs[k] = kzalloc(sizeof(*uv_pci_objs[k]), GFP_KERNEL);
0686 if (!uv_pci_objs[k]) {
0687 ret = -ENOMEM;
0688 goto err_pci_obj;
0689 }
0690 ret = init_pci_top_obj(uv_pci_objs[k], found);
0691 if (ret)
0692 goto err_pci_obj;
0693 k++;
0694 if (k == num_pci_lines)
0695 break;
0696 }
0697 }
0698 kfree(pci_top_str);
0699 if (biosr == BIOS_STATUS_SUCCESS || biosr == BIOS_STATUS_UNIMPLEMENTED)
0700 break;
0701 }
0702
0703 return 0;
0704 err_pci_obj:
0705 k--;
0706 for (; k >= 0; k--)
0707 kobject_put(&uv_pci_objs[k]->kobj);
0708 kfree(uv_pci_objs);
0709 kfree(pci_top_str);
0710 err_pci_top_str:
0711 kset_unregister(uv_pcibus_kset);
0712 return ret;
0713 }
0714
0715 static void pci_topology_exit(void)
0716 {
0717 int k;
0718
0719 for (k = 0; k < num_pci_lines; k++)
0720 kobject_put(&uv_pci_objs[k]->kobj);
0721 kset_unregister(uv_pcibus_kset);
0722 kfree(uv_pci_objs);
0723 }
0724
0725 static ssize_t partition_id_show(struct kobject *kobj,
0726 struct kobj_attribute *attr, char *buf)
0727 {
0728 return sprintf(buf, "%ld\n", sn_partition_id);
0729 }
0730
0731 static ssize_t coherence_id_show(struct kobject *kobj,
0732 struct kobj_attribute *attr, char *buf)
0733 {
0734 return sprintf(buf, "%ld\n", sn_coherency_id);
0735 }
0736
0737 static ssize_t uv_type_show(struct kobject *kobj,
0738 struct kobj_attribute *attr, char *buf)
0739 {
0740 return scnprintf(buf, PAGE_SIZE, "%s\n", uv_type_string());
0741 }
0742
0743 static ssize_t uv_archtype_show(struct kobject *kobj,
0744 struct kobj_attribute *attr, char *buf)
0745 {
0746 return uv_get_archtype(buf, PAGE_SIZE);
0747 }
0748
0749 static ssize_t uv_hub_type_show(struct kobject *kobj,
0750 struct kobj_attribute *attr, char *buf)
0751 {
0752 return scnprintf(buf, PAGE_SIZE, "0x%x\n", uv_hub_type());
0753 }
0754
0755 static ssize_t uv_hubless_show(struct kobject *kobj,
0756 struct kobj_attribute *attr, char *buf)
0757 {
0758 return scnprintf(buf, PAGE_SIZE, "0x%x\n", uv_get_hubless_system());
0759 }
0760
0761 static struct kobj_attribute partition_id_attr =
0762 __ATTR(partition_id, 0444, partition_id_show, NULL);
0763 static struct kobj_attribute coherence_id_attr =
0764 __ATTR(coherence_id, 0444, coherence_id_show, NULL);
0765 static struct kobj_attribute uv_type_attr =
0766 __ATTR(uv_type, 0444, uv_type_show, NULL);
0767 static struct kobj_attribute uv_archtype_attr =
0768 __ATTR(archtype, 0444, uv_archtype_show, NULL);
0769 static struct kobj_attribute uv_hub_type_attr =
0770 __ATTR(hub_type, 0444, uv_hub_type_show, NULL);
0771 static struct kobj_attribute uv_hubless_attr =
0772 __ATTR(hubless, 0444, uv_hubless_show, NULL);
0773
0774 static struct attribute *base_attrs[] = {
0775 &partition_id_attr.attr,
0776 &coherence_id_attr.attr,
0777 &uv_type_attr.attr,
0778 &uv_archtype_attr.attr,
0779 &uv_hub_type_attr.attr,
0780 NULL,
0781 };
0782
0783 static const struct attribute_group base_attr_group = {
0784 .attrs = base_attrs
0785 };
0786
0787 static int initial_bios_setup(void)
0788 {
0789 u64 v;
0790 s64 biosr;
0791
0792 biosr = uv_bios_get_master_nasid((u64)sizeof(uv_master_nasid), (u64 *)&uv_master_nasid);
0793 if (biosr)
0794 return -EINVAL;
0795
0796 biosr = uv_bios_get_heapsize((u64)uv_master_nasid, (u64)sizeof(u64), &v);
0797 if (biosr)
0798 return -EINVAL;
0799
0800 uv_biosheap = vmalloc(v);
0801 if (!uv_biosheap)
0802 return -ENOMEM;
0803
0804 biosr = uv_bios_install_heap((u64)uv_master_nasid, v, (u64 *)uv_biosheap);
0805 if (biosr) {
0806 vfree(uv_biosheap);
0807 return -EINVAL;
0808 }
0809
0810 biosr = uv_bios_obj_count((u64)uv_master_nasid, sizeof(u64), &v);
0811 if (biosr) {
0812 vfree(uv_biosheap);
0813 return -EINVAL;
0814 }
0815 uv_bios_obj_cnt = (int)v;
0816
0817 return 0;
0818 }
0819
0820 static struct attribute *hubless_base_attrs[] = {
0821 &partition_id_attr.attr,
0822 &uv_type_attr.attr,
0823 &uv_archtype_attr.attr,
0824 &uv_hubless_attr.attr,
0825 NULL,
0826 };
0827
0828 static const struct attribute_group hubless_base_attr_group = {
0829 .attrs = hubless_base_attrs
0830 };
0831
0832
0833 static int __init uv_sysfs_hubless_init(void)
0834 {
0835 int ret;
0836
0837 ret = sysfs_create_group(sgi_uv_kobj, &hubless_base_attr_group);
0838 if (ret) {
0839 pr_warn("sysfs_create_group hubless_base_attr_group failed\n");
0840 kobject_put(sgi_uv_kobj);
0841 }
0842 return ret;
0843 }
0844
0845 static int __init uv_sysfs_init(void)
0846 {
0847 int ret = 0;
0848
0849 if (!is_uv_system() && !uv_get_hubless_system())
0850 return -ENODEV;
0851
0852 num_cnodes = uv_num_possible_blades();
0853
0854 if (!sgi_uv_kobj)
0855 sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj);
0856 if (!sgi_uv_kobj) {
0857 pr_warn("kobject_create_and_add sgi_uv failed\n");
0858 return -EINVAL;
0859 }
0860
0861 if (uv_get_hubless_system())
0862 return uv_sysfs_hubless_init();
0863
0864 ret = sysfs_create_group(sgi_uv_kobj, &base_attr_group);
0865 if (ret) {
0866 pr_warn("sysfs_create_group base_attr_group failed\n");
0867 goto err_create_group;
0868 }
0869
0870 ret = initial_bios_setup();
0871 if (ret)
0872 goto err_bios_setup;
0873
0874 ret = uv_hubs_init();
0875 if (ret)
0876 goto err_hubs_init;
0877
0878 ret = uv_ports_init();
0879 if (ret)
0880 goto err_ports_init;
0881
0882 ret = pci_topology_init();
0883 if (ret)
0884 goto err_pci_init;
0885
0886 return 0;
0887
0888 err_pci_init:
0889 uv_ports_exit();
0890 err_ports_init:
0891 uv_hubs_exit();
0892 err_hubs_init:
0893 vfree(uv_biosheap);
0894 err_bios_setup:
0895 sysfs_remove_group(sgi_uv_kobj, &base_attr_group);
0896 err_create_group:
0897 kobject_put(sgi_uv_kobj);
0898 return ret;
0899 }
0900
0901 static void __exit uv_sysfs_hubless_exit(void)
0902 {
0903 sysfs_remove_group(sgi_uv_kobj, &hubless_base_attr_group);
0904 kobject_put(sgi_uv_kobj);
0905 }
0906
0907 static void __exit uv_sysfs_exit(void)
0908 {
0909 if (!is_uv_system()) {
0910 if (uv_get_hubless_system())
0911 uv_sysfs_hubless_exit();
0912 return;
0913 }
0914
0915 pci_topology_exit();
0916 uv_ports_exit();
0917 uv_hubs_exit();
0918 vfree(uv_biosheap);
0919 sysfs_remove_group(sgi_uv_kobj, &base_attr_group);
0920 kobject_put(sgi_uv_kobj);
0921 }
0922
0923 #ifndef MODULE
0924 device_initcall(uv_sysfs_init);
0925 #else
0926 module_init(uv_sysfs_init);
0927 #endif
0928 module_exit(uv_sysfs_exit);
0929
0930 MODULE_AUTHOR("Hewlett Packard Enterprise");
0931 MODULE_LICENSE("GPL");