kunpeng_hccs.c (23fe8112a23106e7dfc2b73fc52a60ea3eb64c20) kunpeng_hccs.c (e3c289c0916e2a3d7859a0cf851ea242fa23ec1e)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * The Huawei Cache Coherence System (HCCS) is a multi-chip interconnection
4 * bus protocol.
5 *
6 * Copyright (c) 2023 Hisilicon Limited.
7 * Author: Huisong Li <lihuisong@huawei.com>
8 *

--- 9 unchanged lines hidden (view full) ---

18 *
19 * - Retrieve the following information about all the ports on the chip or
20 * the die:
21 * - if all enabled ports are in linked
22 * - if all linked ports are in full lane
23 * - CRC error count sum
24 *
25 * - Retrieve all HCCS types used on the platform.
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * The Huawei Cache Coherence System (HCCS) is a multi-chip interconnection
4 * bus protocol.
5 *
6 * Copyright (c) 2023 Hisilicon Limited.
7 * Author: Huisong Li <lihuisong@huawei.com>
8 *

--- 9 unchanged lines hidden (view full) ---

18 *
19 * - Retrieve the following information about all the ports on the chip or
20 * the die:
21 * - if all enabled ports are in linked
22 * - if all linked ports are in full lane
23 * - CRC error count sum
24 *
25 * - Retrieve all HCCS types used on the platform.
26 *
27 * - Support low power feature for all specified HCCS type ports, and
28 * provide the following interface:
29 * - query HCCS types supported increasing and decreasing lane number.
30 * - decrease lane number of all specified HCCS type ports on idle state.
31 * - increase lane number of all specified HCCS type ports.
26 */
27#include <linux/acpi.h>
32 */
33#include <linux/acpi.h>
34#include <linux/delay.h>
28#include <linux/iopoll.h>
29#include <linux/platform_device.h>
35#include <linux/iopoll.h>
36#include <linux/platform_device.h>
37#include <linux/stringify.h>
30#include <linux/sysfs.h>
31#include <linux/types.h>
32
33#include <acpi/pcc.h>
34
35#include "kunpeng_hccs.h"
36
37/*

--- 22 unchanged lines hidden (view full) ---

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
38#include <linux/sysfs.h>
39#include <linux/types.h>
40
41#include <acpi/pcc.h>
42
43#include "kunpeng_hccs.h"
44
45/*

--- 22 unchanged lines hidden (view full) ---

68{
69 struct device *dev = container_of(k, struct device, kobj);
70 struct platform_device *pdev =
71 container_of(dev, struct platform_device, dev);
72
73 return platform_get_drvdata(pdev);
74}
75
76static char *hccs_port_type_to_name(struct hccs_dev *hdev, u8 type)
77{
78 u16 i;
79
80 for (i = 0; i < hdev->used_type_num; i++) {
81 if (hdev->type_name_maps[i].type == type)
82 return hdev->type_name_maps[i].name;
83 }
84
85 return NULL;
86}
87
88static int hccs_name_to_port_type(struct hccs_dev *hdev,
89 const char *name, u8 *type)
90{
91 u16 i;
92
93 for (i = 0; i < hdev->used_type_num; i++) {
94 if (strcmp(hdev->type_name_maps[i].name, name) == 0) {
95 *type = hdev->type_name_maps[i].type;
96 return 0;
97 }
98 }
99
100 return -EINVAL;
101}
102
68struct hccs_register_ctx {
69 struct device *dev;
70 u8 chan_id;
71 int err;
72};
73
74static acpi_status hccs_get_register_cb(struct acpi_resource *ares,
75 void *context)

--- 1114 unchanged lines hidden (view full) ---

1190};
1191ATTRIBUTE_GROUPS(hccs_chip_default);
1192
1193static const struct kobj_type hccs_chip_type = {
1194 .sysfs_ops = &hccs_comm_ops,
1195 .default_groups = hccs_chip_default_groups,
1196};
1197
103struct hccs_register_ctx {
104 struct device *dev;
105 u8 chan_id;
106 int err;
107};
108
109static acpi_status hccs_get_register_cb(struct acpi_resource *ares,
110 void *context)

--- 1114 unchanged lines hidden (view full) ---

1225};
1226ATTRIBUTE_GROUPS(hccs_chip_default);
1227
1228static const struct kobj_type hccs_chip_type = {
1229 .sysfs_ops = &hccs_comm_ops,
1230 .default_groups = hccs_chip_default_groups,
1231};
1232
1233static int hccs_parse_pm_port_type(struct hccs_dev *hdev, const char *buf,
1234 u8 *port_type)
1235{
1236 char hccs_name[HCCS_NAME_MAX_LEN + 1] = "";
1237 u8 type;
1238 int ret;
1198
1239
1240 ret = sscanf(buf, "%" __stringify(HCCS_NAME_MAX_LEN) "s", hccs_name);
1241 if (ret != 1)
1242 return -EINVAL;
1243
1244 ret = hccs_name_to_port_type(hdev, hccs_name, &type);
1245 if (ret) {
1246 dev_dbg(hdev->dev, "input invalid, please get the available types from 'used_types'.\n");
1247 return ret;
1248 }
1249
1250 if (type == HCCS_V2 && hdev->caps & HCCS_CAPS_HCCS_V2_PM) {
1251 *port_type = type;
1252 return 0;
1253 }
1254
1255 dev_dbg(hdev->dev, "%s doesn't support for increasing and decreasing lane.\n",
1256 hccs_name);
1257
1258 return -EOPNOTSUPP;
1259}
1260
1261static int hccs_query_port_idle_status(struct hccs_dev *hdev,
1262 struct hccs_port_info *port, u8 *idle)
1263{
1264 const struct hccs_die_info *die = port->die;
1265 const struct hccs_chip_info *chip = die->chip;
1266 struct hccs_port_comm_req_param *req_param;
1267 struct hccs_desc desc;
1268 int ret;
1269
1270 hccs_init_req_desc(&desc);
1271 req_param = (struct hccs_port_comm_req_param *)desc.req.data;
1272 req_param->chip_id = chip->chip_id;
1273 req_param->die_id = die->die_id;
1274 req_param->port_id = port->port_id;
1275 ret = hccs_pcc_cmd_send(hdev, HCCS_GET_PORT_IDLE_STATUS, &desc);
1276 if (ret) {
1277 dev_err(hdev->dev,
1278 "get port idle status failed, ret = %d.\n", ret);
1279 return ret;
1280 }
1281
1282 *idle = *((u8 *)desc.rsp.data);
1283 return 0;
1284}
1285
1286static int hccs_get_all_spec_port_idle_sta(struct hccs_dev *hdev, u8 port_type,
1287 bool *all_idle)
1288{
1289 struct hccs_chip_info *chip;
1290 struct hccs_port_info *port;
1291 struct hccs_die_info *die;
1292 int ret = 0;
1293 u8 i, j, k;
1294 u8 idle;
1295
1296 *all_idle = false;
1297 for (i = 0; i < hdev->chip_num; i++) {
1298 chip = &hdev->chips[i];
1299 for (j = 0; j < chip->die_num; j++) {
1300 die = &chip->dies[j];
1301 for (k = 0; k < die->port_num; k++) {
1302 port = &die->ports[k];
1303 if (port->port_type != port_type)
1304 continue;
1305 ret = hccs_query_port_idle_status(hdev, port,
1306 &idle);
1307 if (ret) {
1308 dev_err(hdev->dev,
1309 "hccs%u on chip%u/die%u get idle status failed, ret = %d.\n",
1310 k, i, j, ret);
1311 return ret;
1312 } else if (idle == 0) {
1313 dev_info(hdev->dev, "hccs%u on chip%u/die%u is busy.\n",
1314 k, i, j);
1315 return 0;
1316 }
1317 }
1318 }
1319 }
1320 *all_idle = true;
1321
1322 return 0;
1323}
1324
1325static int hccs_get_all_spec_port_full_lane_sta(struct hccs_dev *hdev,
1326 u8 port_type, bool *full_lane)
1327{
1328 struct hccs_link_status status = {0};
1329 struct hccs_chip_info *chip;
1330 struct hccs_port_info *port;
1331 struct hccs_die_info *die;
1332 u8 i, j, k;
1333 int ret;
1334
1335 *full_lane = false;
1336 for (i = 0; i < hdev->chip_num; i++) {
1337 chip = &hdev->chips[i];
1338 for (j = 0; j < chip->die_num; j++) {
1339 die = &chip->dies[j];
1340 for (k = 0; k < die->port_num; k++) {
1341 port = &die->ports[k];
1342 if (port->port_type != port_type)
1343 continue;
1344 ret = hccs_query_port_link_status(hdev, port,
1345 &status);
1346 if (ret)
1347 return ret;
1348 if (status.lane_num != port->max_lane_num)
1349 return 0;
1350 }
1351 }
1352 }
1353 *full_lane = true;
1354
1355 return 0;
1356}
1357
1358static int hccs_prepare_inc_lane(struct hccs_dev *hdev, u8 type)
1359{
1360 struct hccs_inc_lane_req_param *req_param;
1361 struct hccs_desc desc;
1362 int ret;
1363
1364 hccs_init_req_desc(&desc);
1365 req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
1366 req_param->port_type = type;
1367 req_param->opt_type = HCCS_PREPARE_INC_LANE;
1368 ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
1369 if (ret)
1370 dev_err(hdev->dev, "prepare for increasing lane failed, ret = %d.\n",
1371 ret);
1372
1373 return ret;
1374}
1375
1376static int hccs_wait_serdes_adapt_completed(struct hccs_dev *hdev, u8 type)
1377{
1378#define HCCS_MAX_WAIT_CNT_FOR_ADAPT 10
1379#define HCCS_QUERY_ADAPT_RES_DELAY_MS 100
1380#define HCCS_SERDES_ADAPT_OK 0
1381
1382 struct hccs_inc_lane_req_param *req_param;
1383 u8 wait_cnt = HCCS_MAX_WAIT_CNT_FOR_ADAPT;
1384 struct hccs_desc desc;
1385 u8 adapt_res;
1386 int ret;
1387
1388 do {
1389 hccs_init_req_desc(&desc);
1390 req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
1391 req_param->port_type = type;
1392 req_param->opt_type = HCCS_GET_ADAPT_RES;
1393 ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
1394 if (ret) {
1395 dev_err(hdev->dev, "query adapting result failed, ret = %d.\n",
1396 ret);
1397 return ret;
1398 }
1399 adapt_res = *((u8 *)&desc.rsp.data);
1400 if (adapt_res == HCCS_SERDES_ADAPT_OK)
1401 return 0;
1402
1403 msleep(HCCS_QUERY_ADAPT_RES_DELAY_MS);
1404 } while (--wait_cnt);
1405
1406 dev_err(hdev->dev, "wait for adapting completed timeout.\n");
1407
1408 return -ETIMEDOUT;
1409}
1410
1411static int hccs_start_hpcs_retraining(struct hccs_dev *hdev, u8 type)
1412{
1413 struct hccs_inc_lane_req_param *req_param;
1414 struct hccs_desc desc;
1415 int ret;
1416
1417 hccs_init_req_desc(&desc);
1418 req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
1419 req_param->port_type = type;
1420 req_param->opt_type = HCCS_START_RETRAINING;
1421 ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
1422 if (ret)
1423 dev_err(hdev->dev, "start hpcs retraining failed, ret = %d.\n",
1424 ret);
1425
1426 return ret;
1427}
1428
1429static int hccs_start_inc_lane(struct hccs_dev *hdev, u8 type)
1430{
1431 int ret;
1432
1433 ret = hccs_prepare_inc_lane(hdev, type);
1434 if (ret)
1435 return ret;
1436
1437 ret = hccs_wait_serdes_adapt_completed(hdev, type);
1438 if (ret)
1439 return ret;
1440
1441 return hccs_start_hpcs_retraining(hdev, type);
1442}
1443
1444static int hccs_start_dec_lane(struct hccs_dev *hdev, u8 type)
1445{
1446 struct hccs_desc desc;
1447 u8 *port_type;
1448 int ret;
1449
1450 hccs_init_req_desc(&desc);
1451 port_type = (u8 *)desc.req.data;
1452 *port_type = type;
1453 ret = hccs_pcc_cmd_send(hdev, HCCS_PM_DEC_LANE, &desc);
1454 if (ret)
1455 dev_err(hdev->dev, "start to decrease lane failed, ret = %d.\n",
1456 ret);
1457
1458 return ret;
1459}
1460
1461static ssize_t dec_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr,
1462 const char *buf, size_t count)
1463{
1464 struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
1465 bool all_in_idle;
1466 u8 port_type;
1467 int ret;
1468
1469 ret = hccs_parse_pm_port_type(hdev, buf, &port_type);
1470 if (ret)
1471 return ret;
1472
1473 mutex_lock(&hdev->lock);
1474 ret = hccs_get_all_spec_port_idle_sta(hdev, port_type, &all_in_idle);
1475 if (ret)
1476 goto out;
1477 if (!all_in_idle) {
1478 ret = -EBUSY;
1479 dev_err(hdev->dev, "please don't decrese lanes on high load with %s, ret = %d.\n",
1480 hccs_port_type_to_name(hdev, port_type), ret);
1481 goto out;
1482 }
1483
1484 ret = hccs_start_dec_lane(hdev, port_type);
1485out:
1486 mutex_unlock(&hdev->lock);
1487
1488 return ret == 0 ? count : ret;
1489}
1490static struct kobj_attribute dec_lane_of_type_attr =
1491 __ATTR(dec_lane_of_type, 0200, NULL, dec_lane_of_type_store);
1492
1493static ssize_t inc_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr,
1494 const char *buf, size_t count)
1495{
1496 struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
1497 bool full_lane;
1498 u8 port_type;
1499 int ret;
1500
1501 ret = hccs_parse_pm_port_type(hdev, buf, &port_type);
1502 if (ret)
1503 return ret;
1504
1505 mutex_lock(&hdev->lock);
1506 ret = hccs_get_all_spec_port_full_lane_sta(hdev, port_type, &full_lane);
1507 if (ret || full_lane)
1508 goto out;
1509
1510 ret = hccs_start_inc_lane(hdev, port_type);
1511out:
1512 mutex_unlock(&hdev->lock);
1513 return ret == 0 ? count : ret;
1514}
1515static struct kobj_attribute inc_lane_of_type_attr =
1516 __ATTR(inc_lane_of_type, 0200, NULL, inc_lane_of_type_store);
1517
1518static ssize_t available_inc_dec_lane_types_show(struct kobject *kobj,
1519 struct kobj_attribute *attr,
1520 char *buf)
1521{
1522 struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
1523
1524 if (hdev->caps & HCCS_CAPS_HCCS_V2_PM)
1525 return sysfs_emit(buf, "%s\n",
1526 hccs_port_type_to_name(hdev, HCCS_V2));
1527
1528 return -EINVAL;
1529}
1530static struct kobj_attribute available_inc_dec_lane_types_attr =
1531 __ATTR(available_inc_dec_lane_types, 0444,
1532 available_inc_dec_lane_types_show, NULL);
1533
1199static 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}
1212static struct kobj_attribute used_types_attr =
1213 __ATTR(used_types, 0444, used_types_show, NULL);
1214
1215static void hccs_remove_misc_sysfs(struct hccs_dev *hdev)
1216{
1217 sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr);
1534static ssize_t used_types_show(struct kobject *kobj,
1535 struct kobj_attribute *attr, char *buf)
1536{
1537 struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
1538 int len = 0;
1539 u16 i;
1540
1541 for (i = 0; i < hdev->used_type_num - 1; i++)
1542 len += sysfs_emit(&buf[len], "%s ", hdev->type_name_maps[i].name);
1543 len += sysfs_emit(&buf[len], "%s\n", hdev->type_name_maps[i].name);
1544
1545 return len;
1546}
1547static struct kobj_attribute used_types_attr =
1548 __ATTR(used_types, 0444, used_types_show, NULL);
1549
1550static void hccs_remove_misc_sysfs(struct hccs_dev *hdev)
1551{
1552 sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr);
1553
1554 if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM))
1555 return;
1556
1557 sysfs_remove_file(&hdev->dev->kobj,
1558 &available_inc_dec_lane_types_attr.attr);
1559 sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
1560 sysfs_remove_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr);
1218}
1219
1220static int hccs_add_misc_sysfs(struct hccs_dev *hdev)
1221{
1561}
1562
1563static int hccs_add_misc_sysfs(struct hccs_dev *hdev)
1564{
1222 return sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr);
1565 int ret;
1566
1567 ret = sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr);
1568 if (ret)
1569 return ret;
1570
1571 if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM))
1572 return 0;
1573
1574 ret = sysfs_create_file(&hdev->dev->kobj,
1575 &available_inc_dec_lane_types_attr.attr);
1576 if (ret)
1577 goto used_types_remove;
1578
1579 ret = sysfs_create_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
1580 if (ret)
1581 goto inc_dec_lane_types_remove;
1582
1583 ret = sysfs_create_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr);
1584 if (ret)
1585 goto dec_lane_of_type_remove;
1586
1587 return 0;
1588
1589dec_lane_of_type_remove:
1590 sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
1591inc_dec_lane_types_remove:
1592 sysfs_remove_file(&hdev->dev->kobj,
1593 &available_inc_dec_lane_types_attr.attr);
1594used_types_remove:
1595 sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr);
1596 return ret;
1223}
1224
1225static void hccs_remove_die_dir(struct hccs_die_info *die)
1226{
1227 struct hccs_port_info *port;
1228 u8 i;
1229
1230 for (i = 0; i < die->port_num; i++) {

--- 242 unchanged lines hidden ---
1597}
1598
1599static void hccs_remove_die_dir(struct hccs_die_info *die)
1600{
1601 struct hccs_port_info *port;
1602 u8 i;
1603
1604 for (i = 0; i < die->port_num; i++) {

--- 242 unchanged lines hidden ---