|
21 | 21 | * - if all enabled ports are in linked
|
22 | 22 | * - if all linked ports are in full lane
|
23 | 23 | * - CRC error count sum
|
| 24 | + * |
| 25 | + * - Retrieve all HCCS types used on the platform. |
24 | 26 | */
|
25 | 27 | #include <linux/acpi.h>
|
26 | 28 | #include <linux/iopoll.h>
|
27 | 29 | #include <linux/platform_device.h>
|
28 | 30 | #include <linux/sysfs.h>
|
| 31 | +#include <linux/types.h> |
29 | 32 |
|
30 | 33 | #include <acpi/pcc.h>
|
31 | 34 |
|
@@ -53,6 +56,15 @@ static struct hccs_chip_info *kobj_to_chip_info(struct kobject *k)
|
53 | 56 | return container_of(k, struct hccs_chip_info, kobj);
|
54 | 57 | }
|
55 | 58 |
|
| 59 | +static struct hccs_dev *device_kobj_to_hccs_dev(struct kobject *k) |
| 60 | +{ |
| 61 | + struct device *dev = container_of(k, struct device, kobj); |
| 62 | + struct platform_device *pdev = |
| 63 | + container_of(dev, struct platform_device, dev); |
| 64 | + |
| 65 | + return platform_get_drvdata(pdev); |
| 66 | +} |
| 67 | + |
56 | 68 | struct hccs_register_ctx {
|
57 | 69 | struct device *dev;
|
58 | 70 | u8 chan_id;
|
@@ -670,6 +682,55 @@ static int hccs_get_hw_info(struct hccs_dev *hdev)
|
670 | 682 | return 0;
|
671 | 683 | }
|
672 | 684 |
|
| 685 | +static u16 hccs_calc_used_type_num(struct hccs_dev *hdev, |
| 686 | + unsigned long *hccs_ver) |
| 687 | +{ |
| 688 | + struct hccs_chip_info *chip; |
| 689 | + struct hccs_port_info *port; |
| 690 | + struct hccs_die_info *die; |
| 691 | + u16 used_type_num = 0; |
| 692 | + u16 i, j, k; |
| 693 | + |
| 694 | + for (i = 0; i < hdev->chip_num; i++) { |
| 695 | + chip = &hdev->chips[i]; |
| 696 | + for (j = 0; j < chip->die_num; j++) { |
| 697 | + die = &chip->dies[j]; |
| 698 | + for (k = 0; k < die->port_num; k++) { |
| 699 | + port = &die->ports[k]; |
| 700 | + set_bit(port->port_type, hccs_ver); |
| 701 | + } |
| 702 | + } |
| 703 | + } |
| 704 | + |
| 705 | + for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1) |
| 706 | + used_type_num++; |
| 707 | + |
| 708 | + return used_type_num; |
| 709 | +} |
| 710 | + |
| 711 | +static int hccs_init_type_name_maps(struct hccs_dev *hdev) |
| 712 | +{ |
| 713 | + DECLARE_BITMAP(hccs_ver, HCCS_IP_MAX + 1) = {}; |
| 714 | + unsigned int i; |
| 715 | + u16 idx = 0; |
| 716 | + |
| 717 | + hdev->used_type_num = hccs_calc_used_type_num(hdev, hccs_ver); |
| 718 | + hdev->type_name_maps = devm_kcalloc(hdev->dev, hdev->used_type_num, |
| 719 | + sizeof(struct hccs_type_name_map), |
| 720 | + GFP_KERNEL); |
| 721 | + if (!hdev->type_name_maps) |
| 722 | + return -ENOMEM; |
| 723 | + |
| 724 | + for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1) { |
| 725 | + hdev->type_name_maps[idx].type = i; |
| 726 | + sprintf(hdev->type_name_maps[idx].name, |
| 727 | + "%s%u", HCCS_IP_PREFIX, i); |
| 728 | + idx++; |
| 729 | + } |
| 730 | + |
| 731 | + return 0; |
| 732 | +} |
| 733 | + |
673 | 734 | static int hccs_query_port_link_status(struct hccs_dev *hdev,
|
674 | 735 | const struct hccs_port_info *port,
|
675 | 736 | struct hccs_link_status *link_status)
|
@@ -830,7 +891,7 @@ static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
|
830 | 891 | {
|
831 | 892 | const struct hccs_port_info *port = kobj_to_port_info(kobj);
|
832 | 893 |
|
833 |
| - return sysfs_emit(buf, "HCCS-v%u\n", port->port_type); |
| 894 | + return sysfs_emit(buf, "%s%u\n", HCCS_IP_PREFIX, port->port_type); |
834 | 895 | }
|
835 | 896 | static struct kobj_attribute hccs_type_attr = __ATTR_RO(type);
|
836 | 897 |
|
@@ -1134,6 +1195,33 @@ static const struct kobj_type hccs_chip_type = {
|
1134 | 1195 | .default_groups = hccs_chip_default_groups,
|
1135 | 1196 | };
|
1136 | 1197 |
|
| 1198 | + |
| 1199 | +static ssize_t used_types_show(struct kobject *kobj, |
| 1200 | + struct kobj_attribute *attr, char *buf) |
| 1201 | +{ |
| 1202 | + struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj); |
| 1203 | + int len = 0; |
| 1204 | + u16 i; |
| 1205 | + |
| 1206 | + for (i = 0; i < hdev->used_type_num - 1; i++) |
| 1207 | + len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name); |
| 1208 | + len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name); |
| 1209 | + |
| 1210 | + return len; |
| 1211 | +} |
| 1212 | +static struct kobj_attribute used_types_attr = |
| 1213 | + __ATTR(used_types, 0444, used_types_show, NULL); |
| 1214 | + |
| 1215 | +static void hccs_remove_misc_sysfs(struct hccs_dev *hdev) |
| 1216 | +{ |
| 1217 | + sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr); |
| 1218 | +} |
| 1219 | + |
| 1220 | +static int hccs_add_misc_sysfs(struct hccs_dev *hdev) |
| 1221 | +{ |
| 1222 | + return sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr); |
| 1223 | +} |
| 1224 | + |
1137 | 1225 | static void hccs_remove_die_dir(struct hccs_die_info *die)
|
1138 | 1226 | {
|
1139 | 1227 | struct hccs_port_info *port;
|
@@ -1168,6 +1256,8 @@ static void hccs_remove_topo_dirs(struct hccs_dev *hdev)
|
1168 | 1256 |
|
1169 | 1257 | for (i = 0; i < hdev->chip_num; i++)
|
1170 | 1258 | hccs_remove_chip_dir(&hdev->chips[i]);
|
| 1259 | + |
| 1260 | + hccs_remove_misc_sysfs(hdev); |
1171 | 1261 | }
|
1172 | 1262 |
|
1173 | 1263 | static int hccs_create_hccs_dir(struct hccs_dev *hdev,
|
@@ -1263,6 +1353,12 @@ static int hccs_create_topo_dirs(struct hccs_dev *hdev)
|
1263 | 1353 | }
|
1264 | 1354 | }
|
1265 | 1355 |
|
| 1356 | + ret = hccs_add_misc_sysfs(hdev); |
| 1357 | + if (ret) { |
| 1358 | + dev_err(hdev->dev, "create misc sysfs interface failed, ret = %d\n", ret); |
| 1359 | + goto err; |
| 1360 | + } |
| 1361 | + |
1266 | 1362 | return 0;
|
1267 | 1363 | err:
|
1268 | 1364 | for (k = 0; k < id; k++)
|
@@ -1313,6 +1409,10 @@ static int hccs_probe(struct platform_device *pdev)
|
1313 | 1409 | if (rc)
|
1314 | 1410 | goto unregister_pcc_chan;
|
1315 | 1411 |
|
| 1412 | + rc = hccs_init_type_name_maps(hdev); |
| 1413 | + if (rc) |
| 1414 | + goto unregister_pcc_chan; |
| 1415 | + |
1316 | 1416 | rc = hccs_create_topo_dirs(hdev);
|
1317 | 1417 | if (rc)
|
1318 | 1418 | goto unregister_pcc_chan;
|
|
0 commit comments