Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * This file supports the /sys/firmware/sgi_uv topology tree on HPE UV.
0004  *
0005  *  Copyright (c) 2020 Hewlett Packard Enterprise.  All Rights Reserved.
0006  *  Copyright (c) Justin Ernst
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     // Minimum line length
0544     if (strlen(line) < 36)
0545         return -EINVAL;
0546 
0547     //Line must match format "pcibus %4x:%2x" to be valid
0548     str_cnt = sscanf(line, "pcibus %4x:%2x", &tmp_match[0], &tmp_match[1]);
0549     if (str_cnt < 2)
0550         return -EINVAL;
0551 
0552     /* Connect pcibus to segment:bus number with '_'
0553      * to concatenate name tokens.
0554      * pcibus 0000:00 ... -> pcibus_0000:00 ...
0555      */
0556     line[6] = '_';
0557 
0558     /* Null terminate after the concatencated name tokens
0559      * to produce kobj name string.
0560      */
0561     line[14] = '\0';
0562 
0563     // Use start to index after name tokens string for remainder of line info.
0564     start = &line[15];
0565 
0566     top_obj->iio_stack = -1;
0567     top_obj->slot = -1;
0568 
0569     /* r001i01b00h0 BASE IO (IIO Stack 0)
0570      * r001i01b00h1 PCIe IO (IIO Stack 1)
0571      * r001i01b03h1 PCIe SLOT
0572      * r001i01b00h0 NODE IO
0573      * r001i01b00h0 Riser
0574      * (IIO Stack #) may not be present.
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     /* PPB at 0000:80:00.00 (slot 3)
0591      * (slot #) may not be present.
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");