+/**
+ * Verify and store value for device argument.
+ *
+ * @param[in] key
+ * Key argument to verify.
+ * @param[in] val
+ * Value associated with key.
+ * @param opaque
+ * User data.
+ *
+ * @return
+ * 0 on success, negative errno value on failure.
+ */
+static int
+mlx5_args_check(const char *key, const char *val, void *opaque)
+{
+ struct mlx5_args *args = opaque;
+ unsigned long tmp;
+
+ errno = 0;
+ tmp = strtoul(val, NULL, 0);
+ if (errno) {
+ WARN("%s: \"%s\" is not a valid integer", key, val);
+ return errno;
+ }
+ if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) {
+ args->cqe_comp = !!tmp;
+ } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) {
+ args->txq_inline = tmp;
+ } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) {
+ args->txqs_inline = tmp;
+ } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) {
+ args->mps = !!tmp;
+ } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) {
+ args->mpw_hdr_dseg = !!tmp;
+ } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) {
+ args->inline_max_packet_sz = tmp;
+ } else if (strcmp(MLX5_TSO, key) == 0) {
+ args->tso = !!tmp;
+ } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) {
+ args->tx_vec_en = !!tmp;
+ } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) {
+ args->rx_vec_en = !!tmp;
+ } else {
+ WARN("%s: unknown parameter", key);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * Parse device parameters.
+ *
+ * @param priv
+ * Pointer to private structure.
+ * @param devargs
+ * Device arguments structure.
+ *
+ * @return
+ * 0 on success, errno value on failure.
+ */
+static int
+mlx5_args(struct mlx5_args *args, struct rte_devargs *devargs)
+{
+ const char **params = (const char *[]){
+ MLX5_RXQ_CQE_COMP_EN,
+ MLX5_TXQ_INLINE,
+ MLX5_TXQS_MIN_INLINE,
+ MLX5_TXQ_MPW_EN,
+ MLX5_TXQ_MPW_HDR_DSEG_EN,
+ MLX5_TXQ_MAX_INLINE_LEN,
+ MLX5_TSO,
+ MLX5_TX_VEC_EN,
+ MLX5_RX_VEC_EN,
+ NULL,
+ };
+ struct rte_kvargs *kvlist;
+ int ret = 0;
+ int i;
+
+ if (devargs == NULL)
+ return 0;
+ /* Following UGLY cast is done to pass checkpatch. */
+ kvlist = rte_kvargs_parse(devargs->args, params);
+ if (kvlist == NULL)
+ return 0;
+ /* Process parameters. */
+ for (i = 0; (params[i] != NULL); ++i) {
+ if (rte_kvargs_count(kvlist, params[i])) {
+ ret = rte_kvargs_process(kvlist, params[i],
+ mlx5_args_check, args);
+ if (ret != 0) {
+ rte_kvargs_free(kvlist);
+ return ret;
+ }
+ }
+ }
+ rte_kvargs_free(kvlist);
+ return 0;
+}
+
+static struct rte_pci_driver mlx5_driver;
+
+/**
+ * Assign parameters from args into priv, only non default
+ * values are considered.
+ *
+ * @param[out] priv
+ * Pointer to private structure.
+ * @param[in] args
+ * Pointer to args values.
+ */
+static void
+mlx5_args_assign(struct priv *priv, struct mlx5_args *args)
+{
+ if (args->cqe_comp != MLX5_ARG_UNSET)
+ priv->cqe_comp = args->cqe_comp;
+ if (args->txq_inline != MLX5_ARG_UNSET)
+ priv->txq_inline = args->txq_inline;
+ if (args->txqs_inline != MLX5_ARG_UNSET)
+ priv->txqs_inline = args->txqs_inline;
+ if (args->mps != MLX5_ARG_UNSET)
+ priv->mps = args->mps ? priv->mps : 0;
+ if (args->mpw_hdr_dseg != MLX5_ARG_UNSET)
+ priv->mpw_hdr_dseg = args->mpw_hdr_dseg;
+ if (args->inline_max_packet_sz != MLX5_ARG_UNSET)
+ priv->inline_max_packet_sz = args->inline_max_packet_sz;
+ if (args->tso != MLX5_ARG_UNSET)
+ priv->tso = args->tso;
+ if (args->tx_vec_en != MLX5_ARG_UNSET)
+ priv->tx_vec_en = args->tx_vec_en;
+ if (args->rx_vec_en != MLX5_ARG_UNSET)
+ priv->rx_vec_en = args->rx_vec_en;
+}