in marvell/octeontx/otx_cptpf_ucode.c [1312:1454]
static ssize_t ucode_load_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct otx_cpt_engines engs[OTX_CPT_MAX_ETYPES_PER_GRP] = { {0} };
char *ucode_filename[OTX_CPT_MAX_ETYPES_PER_GRP];
char tmp_buf[OTX_CPT_UCODE_NAME_LENGTH] = { 0 };
char *start, *val, *err_msg, *tmp;
struct otx_cpt_eng_grps *eng_grps;
int grp_idx = 0, ret = -EINVAL;
bool has_se, has_ie, has_ae;
int del_grp_idx = -1;
int ucode_idx = 0;
if (strlen(buf) > OTX_CPT_UCODE_NAME_LENGTH)
return -EINVAL;
eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr);
err_msg = "Invalid engine group format";
strlcpy(tmp_buf, buf, OTX_CPT_UCODE_NAME_LENGTH);
start = tmp_buf;
has_se = has_ie = has_ae = false;
for (;;) {
val = strsep(&start, ";");
if (!val)
break;
val = strim(val);
if (!*val)
continue;
if (!strncasecmp(val, "engine_group", 12)) {
if (del_grp_idx != -1)
goto err_print;
tmp = strim(strsep(&val, ":"));
if (!val)
goto err_print;
if (strlen(tmp) != 13)
goto err_print;
if (kstrtoint((tmp + 12), 10, &del_grp_idx))
goto err_print;
val = strim(val);
if (strncasecmp(val, "null", 4))
goto err_print;
if (strlen(val) != 4)
goto err_print;
} else if (!strncasecmp(val, "se", 2) && strchr(val, ':')) {
if (has_se || ucode_idx)
goto err_print;
tmp = strim(strsep(&val, ":"));
if (!val)
goto err_print;
if (strlen(tmp) != 2)
goto err_print;
if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
goto err_print;
engs[grp_idx++].type = OTX_CPT_SE_TYPES;
has_se = true;
} else if (!strncasecmp(val, "ae", 2) && strchr(val, ':')) {
if (has_ae || ucode_idx)
goto err_print;
tmp = strim(strsep(&val, ":"));
if (!val)
goto err_print;
if (strlen(tmp) != 2)
goto err_print;
if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
goto err_print;
engs[grp_idx++].type = OTX_CPT_AE_TYPES;
has_ae = true;
} else {
if (ucode_idx > 1)
goto err_print;
if (!strlen(val))
goto err_print;
if (strnstr(val, " ", strlen(val)))
goto err_print;
ucode_filename[ucode_idx++] = val;
}
}
/* Validate input parameters */
if (del_grp_idx == -1) {
if (!(grp_idx && ucode_idx))
goto err_print;
if (ucode_idx > 1 && grp_idx < 2)
goto err_print;
if (grp_idx > OTX_CPT_MAX_ETYPES_PER_GRP) {
err_msg = "Error max 2 engine types can be attached";
goto err_print;
}
} else {
if (del_grp_idx < 0 ||
del_grp_idx >= OTX_CPT_MAX_ENGINE_GROUPS) {
dev_err(dev, "Invalid engine group index %d\n",
del_grp_idx);
ret = -EINVAL;
return ret;
}
if (!eng_grps->grp[del_grp_idx].is_enabled) {
dev_err(dev, "Error engine_group%d is not configured\n",
del_grp_idx);
ret = -EINVAL;
return ret;
}
if (grp_idx || ucode_idx)
goto err_print;
}
mutex_lock(&eng_grps->lock);
if (eng_grps->is_rdonly) {
dev_err(dev, "Disable VFs before modifying engine groups\n");
ret = -EACCES;
goto err_unlock;
}
if (del_grp_idx == -1)
/* create engine group */
ret = create_engine_group(dev, eng_grps, engs, grp_idx,
(void **) ucode_filename,
ucode_idx, false);
else
/* delete engine group */
ret = delete_engine_group(dev, &eng_grps->grp[del_grp_idx]);
if (ret)
goto err_unlock;
print_dbg_info(dev, eng_grps);
err_unlock:
mutex_unlock(&eng_grps->lock);
return ret ? ret : count;
err_print:
dev_err(dev, "%s\n", err_msg);
return ret;
}