drivers/common/cnxk/roc_model.c | 152 +++++++++++++++++++++++++++----------
drivers/common/cnxk/roc_platform.h | 3 +
2 files changed, 113 insertions(+), 42 deletions(-)
diff --git a/drivers/common/cnxk/roc_model.c b/drivers/common/cnxk/roc_model.c
index a68baa6..791ffa6 100644
--- a/drivers/common/cnxk/roc_model.c
+++ b/drivers/common/cnxk/roc_model.c
@@ -2,6 +2,7 @@
* Copyright(C) 2021 Marvell.
*/
+#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
@@ -40,6 +41,16 @@ struct roc_model *roc_model;
#define MODEL_MINOR_SHIFT 0
#define MODEL_MINOR_MASK ((1 << MODEL_MINOR_BITS) - 1)
+#define MODEL_CN10K_PART_SHIFT 8
+#define MODEL_CN10K_PASS_BITS 4
+#define MODEL_CN10K_PASS_MASK ((1 << MODEL_CN10K_PASS_BITS) - 1)
+#define MODEL_CN10K_MAJOR_BITS 2
+#define MODEL_CN10K_MAJOR_SHIFT 2
+#define MODEL_CN10K_MAJOR_MASK ((1 << MODEL_CN10K_MAJOR_BITS) - 1)
+#define MODEL_CN10K_MINOR_BITS 2
+#define MODEL_CN10K_MINOR_SHIFT 0
+#define MODEL_CN10K_MINOR_MASK ((1 << MODEL_CN10K_MINOR_BITS) - 1)
+
static const struct model_db {
uint32_t impl;
uint32_t part;
@@ -66,55 +77,101 @@ static const struct model_db {
{VENDOR_CAVIUM, PART_95xxMM, 0, 0, ROC_MODEL_CNF95xxMM_A0,
"cnf95xxmm_a0"}};
-static uint32_t
-cn10k_part_get(void)
+/* Detect if RVU device */
+static bool
+is_rvu_device(unsigned long val)
{
- uint32_t soc = 0x0;
- char buf[BUFSIZ];
- char *ptr;
- FILE *fd;
-
- /* Read the CPU compatible variant */
- fd = fopen("/proc/device-tree/compatible", "r");
- if (!fd) {
- plt_err("Failed to open /proc/device-tree/compatible");
- goto err;
- }
+ return (val == PCI_DEVID_CNXK_RVU_PF || val == PCI_DEVID_CNXK_RVU_VF ||
+ val == PCI_DEVID_CNXK_RVU_AF ||
+ val == PCI_DEVID_CNXK_RVU_AF_VF ||
+ val == PCI_DEVID_CNXK_RVU_NPA_PF ||
+ val == PCI_DEVID_CNXK_RVU_NPA_VF ||
+ val == PCI_DEVID_CNXK_RVU_SSO_TIM_PF ||
+ val == PCI_DEVID_CNXK_RVU_SSO_TIM_VF ||
+ val == PCI_DEVID_CN10K_RVU_CPT_PF ||
+ val == PCI_DEVID_CN10K_RVU_CPT_VF);
+}
- if (fgets(buf, sizeof(buf), fd) == NULL) {
- plt_err("Failed to read from /proc/device-tree/compatible");
- goto fclose;
- }
- ptr = strchr(buf, ',');
- if (!ptr) {
- plt_err("Malformed 'CPU compatible': <%s>", buf);
- goto fclose;
- }
- ptr++;
- if (strcmp("cn10ka", ptr) == 0) {
- soc = PART_106xx;
- } else if (strcmp("cnf10ka", ptr) == 0) {
- soc = PART_105xx;
- } else if (strcmp("cnf10kb", ptr) == 0) {
- soc = PART_105xxN;
- } else if (strcmp("cn10kb", ptr) == 0) {
- soc = PART_103xx;
- } else {
- plt_err("Unidentified 'CPU compatible': <%s>", ptr);
- goto fclose;
+static int
+rvu_device_lookup(const char *dirname, uint32_t *part, uint32_t *pass)
+{
+ char filename[PATH_MAX];
+ unsigned long val;
+
+ /* Check if vendor id is cavium */
+ snprintf(filename, sizeof(filename), "%s/vendor", dirname);
+ if (plt_sysfs_value_parse(filename, &val) < 0)
+ goto error;
+
+ if (val != PCI_VENDOR_ID_CAVIUM)
+ goto error;
+
+ /* Get device id */
+ snprintf(filename, sizeof(filename), "%s/device", dirname);
+ if (plt_sysfs_value_parse(filename, &val) < 0)
+ goto error;
+
+ /* Check if device ID belongs to any RVU device */
+ if (!is_rvu_device(val))
+ goto error;
+
+ /* Get subsystem_device id */
+ snprintf(filename, sizeof(filename), "%s/subsystem_device", dirname);
+ if (plt_sysfs_value_parse(filename, &val) < 0)
+ goto error;
+
+ *part = val >> MODEL_CN10K_PART_SHIFT;
+
+ /* Get revision for pass value*/
+ snprintf(filename, sizeof(filename), "%s/revision", dirname);
+ if (plt_sysfs_value_parse(filename, &val) < 0)
+ goto error;
+
+ *pass = val & MODEL_CN10K_PASS_MASK;
+
+ return 0;
+error:
+ return -EINVAL;
+}
+
+/* Scans through all PCI devices, detects RVU device and returns
+ * subsystem_device
+ */
+static int
+cn10k_part_pass_get(uint32_t *part, uint32_t *pass)
+{
+#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
+ char dirname[PATH_MAX];
+ struct dirent *e;
+ DIR *dir;
+
+ dir = opendir(SYSFS_PCI_DEVICES);
+ if (dir == NULL) {
+ plt_err("%s(): opendir failed: %s\n", __func__,
+ strerror(errno));
+ return -errno;
}
-fclose:
- fclose(fd);
+ while ((e = readdir(dir)) != NULL) {
+ if (e->d_name[0] == '.')
+ continue;
+
+ snprintf(dirname, sizeof(dirname), "%s/%s", SYSFS_PCI_DEVICES,
+ e->d_name);
+
+ /* Lookup for rvu device and get part pass information */
+ if (!rvu_device_lookup(dirname, part, pass))
+ break;
+ }
-err:
- return soc;
+ closedir(dir);
+ return 0;
}
static bool
populate_model(struct roc_model *model, uint32_t midr)
{
- uint32_t impl, major, part, minor;
+ uint32_t impl, major, part, minor, pass;
bool found = false;
size_t i;
@@ -124,8 +181,19 @@ populate_model(struct roc_model *model, uint32_t midr)
minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK;
/* Update part number for cn10k from device-tree */
- if (part == SOC_PART_CN10K)
- part = cn10k_part_get();
+ if (part == SOC_PART_CN10K) {
+ if (cn10k_part_pass_get(&part, &pass))
+ goto not_found;
+ /*
+ * Pass value format:
+ * Bits 0..1: minor pass
+ * Bits 3..2: major pass
+ */
+ minor = (pass >> MODEL_CN10K_MINOR_SHIFT) &
+ MODEL_CN10K_MINOR_MASK;
+ major = (pass >> MODEL_CN10K_MAJOR_SHIFT) &
+ MODEL_CN10K_MAJOR_MASK;
+ }
for (i = 0; i < PLT_DIM(model_db); i++)
if (model_db[i].impl == impl && model_db[i].part == part &&
@@ -136,7 +204,7 @@ populate_model(struct roc_model *model, uint32_t midr)
found = true;
break;
}
-
+not_found:
if (!found) {
model->flag = 0;
strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1);
diff --git a/drivers/common/cnxk/roc_platform.h
b/drivers/common/cnxk/roc_platform.h
index 502f243..3e7adfc 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -24,6 +24,8 @@
#include <rte_tailq.h>
#include <rte_telemetry.h>
+#include "eal_filesystem.h"
+
#include "roc_bits.h"
#if defined(__ARM_FEATURE_SVE)
@@ -94,6 +96,7 @@
#define plt_pci_device rte_pci_device
#define plt_pci_read_config rte_pci_read_config
#define plt_pci_find_ext_capability rte_pci_find_ext_capability
+#define plt_sysfs_value_parse eal_parse_sysfs_value
#define plt_log2_u32 rte_log2_u32
#define plt_cpu_to_be_16 rte_cpu_to_be_16
--
2.8.4