17546a2cdSRobin Zhang /* SPDX-License-Identifier: BSD-3-Clause
27546a2cdSRobin Zhang * Copyright(c) 2022 Intel Corporation
37546a2cdSRobin Zhang */
47546a2cdSRobin Zhang
572b452c5SDmitry Kozlyuk #include <ctype.h>
67546a2cdSRobin Zhang #include <errno.h>
772b452c5SDmitry Kozlyuk #include <stdlib.h>
87546a2cdSRobin Zhang
97546a2cdSRobin Zhang #include "rte_ethdev.h"
107546a2cdSRobin Zhang #include <rte_common.h>
117546a2cdSRobin Zhang #include "sff_telemetry.h"
127546a2cdSRobin Zhang #include <telemetry_data.h>
137546a2cdSRobin Zhang
147546a2cdSRobin Zhang static void
sff_port_module_eeprom_parse(uint16_t port_id,struct rte_tel_data * d)157546a2cdSRobin Zhang sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d)
167546a2cdSRobin Zhang {
177546a2cdSRobin Zhang struct rte_eth_dev_module_info minfo;
187546a2cdSRobin Zhang struct rte_dev_eeprom_info einfo;
197546a2cdSRobin Zhang int ret;
207546a2cdSRobin Zhang
217546a2cdSRobin Zhang if (d == NULL) {
22*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Dict invalid");
237546a2cdSRobin Zhang return;
247546a2cdSRobin Zhang }
257546a2cdSRobin Zhang
267546a2cdSRobin Zhang ret = rte_eth_dev_get_module_info(port_id, &minfo);
277546a2cdSRobin Zhang if (ret != 0) {
287546a2cdSRobin Zhang switch (ret) {
297546a2cdSRobin Zhang case -ENODEV:
30*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Port index %d invalid", port_id);
317546a2cdSRobin Zhang break;
327546a2cdSRobin Zhang case -ENOTSUP:
33*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Operation not supported by device");
347546a2cdSRobin Zhang break;
357546a2cdSRobin Zhang case -EIO:
36*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Device is removed");
377546a2cdSRobin Zhang break;
387546a2cdSRobin Zhang default:
39*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Unable to get port module info, %d", ret);
407546a2cdSRobin Zhang break;
417546a2cdSRobin Zhang }
427546a2cdSRobin Zhang return;
437546a2cdSRobin Zhang }
447546a2cdSRobin Zhang
457546a2cdSRobin Zhang einfo.offset = 0;
467546a2cdSRobin Zhang einfo.length = minfo.eeprom_len;
477546a2cdSRobin Zhang einfo.data = calloc(1, minfo.eeprom_len);
487546a2cdSRobin Zhang if (einfo.data == NULL) {
49*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Allocation of port %u EEPROM data failed", port_id);
507546a2cdSRobin Zhang return;
517546a2cdSRobin Zhang }
527546a2cdSRobin Zhang
537546a2cdSRobin Zhang ret = rte_eth_dev_get_module_eeprom(port_id, &einfo);
547546a2cdSRobin Zhang if (ret != 0) {
557546a2cdSRobin Zhang switch (ret) {
567546a2cdSRobin Zhang case -ENODEV:
57*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Port index %d invalid", port_id);
587546a2cdSRobin Zhang break;
597546a2cdSRobin Zhang case -ENOTSUP:
60*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Operation not supported by device");
617546a2cdSRobin Zhang break;
627546a2cdSRobin Zhang case -EIO:
63*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Device is removed");
647546a2cdSRobin Zhang break;
657546a2cdSRobin Zhang default:
66*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Unable to get port module EEPROM, %d", ret);
677546a2cdSRobin Zhang break;
687546a2cdSRobin Zhang }
697546a2cdSRobin Zhang free(einfo.data);
707546a2cdSRobin Zhang return;
717546a2cdSRobin Zhang }
727546a2cdSRobin Zhang
737546a2cdSRobin Zhang switch (minfo.type) {
747546a2cdSRobin Zhang /* parsing module EEPROM data base on different module type */
75084b4880SRobin Zhang case RTE_ETH_MODULE_SFF_8079:
76084b4880SRobin Zhang sff_8079_show_all(einfo.data, d);
77084b4880SRobin Zhang break;
780caf7f37SRobin Zhang case RTE_ETH_MODULE_SFF_8472:
790caf7f37SRobin Zhang sff_8079_show_all(einfo.data, d);
800caf7f37SRobin Zhang sff_8472_show_all(einfo.data, d);
810caf7f37SRobin Zhang break;
82c42754fdSRobin Zhang case RTE_ETH_MODULE_SFF_8436:
83c42754fdSRobin Zhang case RTE_ETH_MODULE_SFF_8636:
84c42754fdSRobin Zhang sff_8636_show_all(einfo.data, einfo.length, d);
85c42754fdSRobin Zhang break;
867546a2cdSRobin Zhang default:
87*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(NOTICE, "Unsupported module type: %u", minfo.type);
887546a2cdSRobin Zhang break;
897546a2cdSRobin Zhang }
907546a2cdSRobin Zhang
917546a2cdSRobin Zhang free(einfo.data);
927546a2cdSRobin Zhang }
937546a2cdSRobin Zhang
94266c2bebSRobin Zhang void
ssf_add_dict_string(struct rte_tel_data * d,const char * name_str,const char * value_str)95266c2bebSRobin Zhang ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str)
96266c2bebSRobin Zhang {
97266c2bebSRobin Zhang struct tel_dict_entry *e = &d->data.dict[d->data_len];
98266c2bebSRobin Zhang
995a36d531SBruce Richardson if (d->type != TEL_DICT)
100266c2bebSRobin Zhang return;
101266c2bebSRobin Zhang if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) {
102*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "data_len has exceeded the maximum number of inserts");
103266c2bebSRobin Zhang return;
104266c2bebSRobin Zhang }
105266c2bebSRobin Zhang
106266c2bebSRobin Zhang e->type = RTE_TEL_STRING_VAL;
107266c2bebSRobin Zhang /* append different values for same keys */
108266c2bebSRobin Zhang if (d->data_len > 0) {
109266c2bebSRobin Zhang struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1];
110266c2bebSRobin Zhang if (strcmp(previous->name, name_str) == 0) {
111266c2bebSRobin Zhang strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN);
112266c2bebSRobin Zhang strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
113266c2bebSRobin Zhang goto end;
114266c2bebSRobin Zhang }
115266c2bebSRobin Zhang }
116266c2bebSRobin Zhang strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN);
117266c2bebSRobin Zhang strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN);
118266c2bebSRobin Zhang d->data_len++;
119266c2bebSRobin Zhang
120266c2bebSRobin Zhang end:
121266c2bebSRobin Zhang return;
122266c2bebSRobin Zhang }
123266c2bebSRobin Zhang
1247546a2cdSRobin Zhang int
eth_dev_handle_port_module_eeprom(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)1257546a2cdSRobin Zhang eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params,
1267546a2cdSRobin Zhang struct rte_tel_data *d)
1277546a2cdSRobin Zhang {
1287546a2cdSRobin Zhang char *end_param;
1296ca32611SJie Hai uint64_t port_id;
1307546a2cdSRobin Zhang
1317546a2cdSRobin Zhang if (params == NULL || strlen(params) == 0 || !isdigit(*params))
1327546a2cdSRobin Zhang return -1;
1337546a2cdSRobin Zhang
1347546a2cdSRobin Zhang errno = 0;
1357546a2cdSRobin Zhang port_id = strtoul(params, &end_param, 0);
1367546a2cdSRobin Zhang
1376ca32611SJie Hai if (errno != 0 || port_id >= UINT16_MAX) {
138*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Invalid argument, %d", errno);
1397546a2cdSRobin Zhang return -1;
1407546a2cdSRobin Zhang }
1417546a2cdSRobin Zhang
1427546a2cdSRobin Zhang if (*end_param != '\0')
143*0e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(NOTICE,
144*0e21c7c0SDavid Marchand "Extra parameters [%s] passed to ethdev telemetry command, ignoring",
1457546a2cdSRobin Zhang end_param);
1467546a2cdSRobin Zhang
1477546a2cdSRobin Zhang rte_tel_data_start_dict(d);
1487546a2cdSRobin Zhang
1497546a2cdSRobin Zhang sff_port_module_eeprom_parse(port_id, d);
1507546a2cdSRobin Zhang
1517546a2cdSRobin Zhang return 0;
1527546a2cdSRobin Zhang }
153