X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_sw_stats.c;h=81bd531a17ee09858923d5cf4f4bcc5e2fdc1556;hb=63abf8d29225;hp=2b28ba29e6ce1a96e494a9a78fda58acfb5078af;hpb=67f1b4f1742a6f6d7b481e7641ce3c006cbf68e5;p=dpdk.git diff --git a/drivers/net/sfc/sfc_sw_stats.c b/drivers/net/sfc/sfc_sw_stats.c index 2b28ba29e6..81bd531a17 100644 --- a/drivers/net/sfc/sfc_sw_stats.c +++ b/drivers/net/sfc/sfc_sw_stats.c @@ -10,67 +10,85 @@ #include "sfc_tx.h" #include "sfc_sw_stats.h" +#define SFC_SW_STAT_INVALID UINT64_MAX + +#define SFC_SW_STATS_GROUP_SIZE_MAX 1U + enum sfc_sw_stats_type { SFC_SW_STATS_RX, SFC_SW_STATS_TX, }; -typedef uint64_t sfc_get_sw_xstat_val_t(struct sfc_adapter *sa, uint16_t qid); +typedef void sfc_get_sw_stat_val_t(struct sfc_adapter *sa, uint16_t qid, + uint64_t *values, unsigned int values_count); -struct sfc_sw_xstat_descr { +struct sfc_sw_stat_descr { const char *name; enum sfc_sw_stats_type type; - sfc_get_sw_xstat_val_t *get_val; + sfc_get_sw_stat_val_t *get_val; + bool provide_total; }; -static sfc_get_sw_xstat_val_t sfc_get_sw_xstat_val_rx_dbells; -static uint64_t -sfc_get_sw_xstat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid) +static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_rx_dbells; +static void +sfc_get_sw_stat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid, + uint64_t *values, unsigned int values_count) { struct sfc_adapter_shared *sas = sfc_sa2shared(sa); struct sfc_rxq_info *rxq_info; + RTE_SET_USED(values_count); + SFC_ASSERT(values_count == 1); rxq_info = sfc_rxq_info_by_ethdev_qid(sas, qid); - if (rxq_info->state & SFC_RXQ_INITIALIZED) - return rxq_info->dp->dpq.rx_dbells; - return 0; + values[0] = rxq_info->state & SFC_RXQ_INITIALIZED ? + rxq_info->dp->dpq.rx_dbells : 0; } -static sfc_get_sw_xstat_val_t sfc_get_sw_xstat_val_tx_dbells; -static uint64_t -sfc_get_sw_xstat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid) +static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_tx_dbells; +static void +sfc_get_sw_stat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid, + uint64_t *values, unsigned int values_count) { struct sfc_adapter_shared *sas = sfc_sa2shared(sa); struct sfc_txq_info *txq_info; + RTE_SET_USED(values_count); + SFC_ASSERT(values_count == 1); txq_info = sfc_txq_info_by_ethdev_qid(sas, qid); - if (txq_info->state & SFC_TXQ_INITIALIZED) - return txq_info->dp->dpq.tx_dbells; - return 0; + values[0] = txq_info->state & SFC_TXQ_INITIALIZED ? + txq_info->dp->dpq.tx_dbells : 0; } -struct sfc_sw_xstat_descr sfc_sw_xstats[] = { +/* + * SW stats can be grouped together. When stats are grouped the corresponding + * stats values for each queue are obtained during calling one get value + * callback. Stats of the same group are contiguous in the structure below. + * The start of the group is denoted by stat implementing get value callback. + */ +const struct sfc_sw_stat_descr sfc_sw_stats_descr[] = { { .name = "dbells", .type = SFC_SW_STATS_RX, - .get_val = sfc_get_sw_xstat_val_rx_dbells, + .get_val = sfc_get_sw_stat_val_rx_dbells, + .provide_total = true, }, { .name = "dbells", .type = SFC_SW_STATS_TX, - .get_val = sfc_get_sw_xstat_val_tx_dbells, + .get_val = sfc_get_sw_stat_val_tx_dbells, + .provide_total = true, } }; static int sfc_sw_stat_get_name(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat, char *name, + const struct sfc_sw_stat_descr *sw_stat, char *name, size_t name_size, unsigned int id_off) { const char *prefix; int ret; - switch (sw_xstat->type) { + switch (sw_stat->type) { case SFC_SW_STATS_RX: prefix = "rx"; break; @@ -79,25 +97,25 @@ sfc_sw_stat_get_name(struct sfc_adapter *sa, break; default: sfc_err(sa, "%s: unknown software statistics type %d", - __func__, sw_xstat->type); + __func__, sw_stat->type); return -EINVAL; } - if (id_off == 0) { + if (sw_stat->provide_total && id_off == 0) { ret = snprintf(name, name_size, "%s_%s", prefix, - sw_xstat->name); + sw_stat->name); if (ret < 0 || ret >= (int)name_size) { sfc_err(sa, "%s: failed to fill xstat name %s_%s, err %d", - __func__, prefix, sw_xstat->name, ret); + __func__, prefix, sw_stat->name, ret); return ret > 0 ? -EINVAL : ret; } } else { - uint16_t qid = id_off - 1; + uint16_t qid = id_off - sw_stat->provide_total; ret = snprintf(name, name_size, "%s_q%u_%s", prefix, qid, - sw_xstat->name); + sw_stat->name); if (ret < 0 || ret >= (int)name_size) { sfc_err(sa, "%s: failed to fill xstat name %s_q%u_%s, err %d", - __func__, prefix, qid, sw_xstat->name, ret); + __func__, prefix, qid, sw_stat->name, ret); return ret > 0 ? -EINVAL : ret; } } @@ -107,42 +125,43 @@ sfc_sw_stat_get_name(struct sfc_adapter *sa, static unsigned int sfc_sw_stat_get_queue_count(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat) + const struct sfc_sw_stat_descr *sw_stat) { struct sfc_adapter_shared *sas = sfc_sa2shared(sa); - switch (sw_xstat->type) { + switch (sw_stat->type) { case SFC_SW_STATS_RX: return sas->ethdev_rxq_count; case SFC_SW_STATS_TX: return sas->ethdev_txq_count; default: sfc_err(sa, "%s: unknown software statistics type %d", - __func__, sw_xstat->type); + __func__, sw_stat->type); return 0; } } static unsigned int -sfc_sw_xstat_per_queue_get_count(unsigned int nb_queues) +sfc_sw_xstat_per_queue_get_count(const struct sfc_sw_stat_descr *sw_stat, + unsigned int nb_queues) { - /* Take into account the accumulative xstat of all queues */ - return nb_queues > 0 ? 1 + nb_queues : 0; + /* Take into account the total xstat of all queues */ + return nb_queues > 0 ? sw_stat->provide_total + nb_queues : 0; } static unsigned int sfc_sw_xstat_get_nb_supported(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat) + const struct sfc_sw_stat_descr *sw_stat) { unsigned int nb_queues; - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); - return sfc_sw_xstat_per_queue_get_count(nb_queues); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); + return sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); } static int sfc_sw_stat_get_names(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat, + const struct sfc_sw_stat_descr *sw_stat, struct rte_eth_xstat_name *xstats_names, unsigned int xstats_names_sz, unsigned int *nb_written, @@ -154,17 +173,17 @@ sfc_sw_stat_get_names(struct sfc_adapter *sa, unsigned int qid; int rc; - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); if (nb_queues == 0) return 0; - *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues); + *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); /* - * The order of each software xstat type is the accumulative xstat + * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ - if (*nb_written < xstats_names_sz) { - rc = sfc_sw_stat_get_name(sa, sw_xstat, + if (*nb_written < xstats_names_sz && sw_stat->provide_total) { + rc = sfc_sw_stat_get_name(sa, sw_stat, xstats_names[*nb_written].name, name_size, *nb_written - id_base); if (rc != 0) @@ -174,7 +193,7 @@ sfc_sw_stat_get_names(struct sfc_adapter *sa, for (qid = 0; qid < nb_queues; ++qid) { if (*nb_written < xstats_names_sz) { - rc = sfc_sw_stat_get_name(sa, sw_xstat, + rc = sfc_sw_stat_get_name(sa, sw_stat, xstats_names[*nb_written].name, name_size, *nb_written - id_base); if (rc != 0) @@ -188,7 +207,7 @@ sfc_sw_stat_get_names(struct sfc_adapter *sa, static int sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat, + const struct sfc_sw_stat_descr *sw_stat, const uint64_t *ids, struct rte_eth_xstat_name *xstats_names, unsigned int size, @@ -196,22 +215,24 @@ sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa, { const size_t name_size = sizeof(xstats_names[0].name); unsigned int id_base = *nb_supported; + unsigned int id_end; unsigned int nb_queues; unsigned int i; int rc; - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); if (nb_queues == 0) return 0; - *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues); + *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); /* - * The order of each software xstat type is the accumulative xstat + * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ + id_end = id_base + sw_stat->provide_total + nb_queues; for (i = 0; i < size; i++) { - if (id_base <= ids[i] && ids[i] <= id_base + nb_queues) { - rc = sfc_sw_stat_get_name(sa, sw_xstat, + if (id_base <= ids[i] && ids[i] < id_end) { + rc = sfc_sw_stat_get_name(sa, sw_stat, xstats_names[i].name, name_size, ids[i] - id_base); if (rc != 0) @@ -222,9 +243,53 @@ sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa, return 0; } +static uint64_t +sfc_sw_stat_get_val(struct sfc_adapter *sa, + unsigned int sw_stat_idx, uint16_t qid) +{ + struct sfc_sw_stats *sw_stats = &sa->sw_stats; + uint64_t *res = &sw_stats->supp[sw_stat_idx].cache[qid]; + uint64_t values[SFC_SW_STATS_GROUP_SIZE_MAX]; + unsigned int group_start_idx; + unsigned int group_size; + unsigned int i; + + if (*res != SFC_SW_STAT_INVALID) + return *res; + + /* + * Search for the group start, i.e. the stat that implements + * get value callback. + */ + group_start_idx = sw_stat_idx; + while (sw_stats->supp[group_start_idx].descr->get_val == NULL) + group_start_idx--; + + /* + * Calculate number of elements in the group with loop till the next + * group start or the list end. + */ + group_size = 1; + for (i = sw_stat_idx + 1; i < sw_stats->supp_count; i++) { + if (sw_stats->supp[i].descr->get_val != NULL) + break; + group_size++; + } + group_size += sw_stat_idx - group_start_idx; + + SFC_ASSERT(group_size <= SFC_SW_STATS_GROUP_SIZE_MAX); + sw_stats->supp[group_start_idx].descr->get_val(sa, qid, values, + group_size); + for (i = group_start_idx; i < (group_start_idx + group_size); i++) + sw_stats->supp[i].cache[qid] = values[i - group_start_idx]; + + return *res; +} + static void sfc_sw_xstat_get_values(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat, + const struct sfc_sw_stat_descr *sw_stat, + unsigned int sw_stat_idx, struct rte_eth_xstat *xstats, unsigned int xstats_size, unsigned int *nb_written, @@ -232,29 +297,29 @@ sfc_sw_xstat_get_values(struct sfc_adapter *sa, { unsigned int qid; uint64_t value; - struct rte_eth_xstat *accum_xstat; - bool count_accum_value = false; + struct rte_eth_xstat *total_xstat; + bool count_total_value = false; unsigned int nb_queues; - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); if (nb_queues == 0) return; - *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues); + *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); /* - * The order of each software xstat type is the accumulative xstat + * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ - if (*nb_written < xstats_size) { - count_accum_value = true; - accum_xstat = &xstats[*nb_written]; + if (*nb_written < xstats_size && sw_stat->provide_total) { + count_total_value = true; + total_xstat = &xstats[*nb_written]; xstats[*nb_written].id = *nb_written; xstats[*nb_written].value = 0; (*nb_written)++; } for (qid = 0; qid < nb_queues; ++qid) { - value = sw_xstat->get_val(sa, qid); + value = sfc_sw_stat_get_val(sa, sw_stat_idx, qid); if (*nb_written < xstats_size) { xstats[*nb_written].id = *nb_written; @@ -262,25 +327,28 @@ sfc_sw_xstat_get_values(struct sfc_adapter *sa, (*nb_written)++; } - if (count_accum_value) - accum_xstat->value += value; + if (count_total_value) + total_xstat->value += value; } } static void sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, - const struct sfc_sw_xstat_descr *sw_xstat, + const struct sfc_sw_stat_descr *sw_stat, + unsigned int sw_stat_idx, const uint64_t *ids, uint64_t *values, unsigned int ids_size, unsigned int *nb_supported) { - rte_spinlock_t *bmp_lock = &sa->sw_xstats.queues_bitmap_lock; - struct rte_bitmap *bmp = sa->sw_xstats.queues_bitmap; + rte_spinlock_t *bmp_lock = &sa->sw_stats.queues_bitmap_lock; + struct rte_bitmap *bmp = sa->sw_stats.queues_bitmap; unsigned int id_base = *nb_supported; - bool count_accum_value = false; - unsigned int accum_value_idx; - uint64_t accum_value = 0; + unsigned int id_base_q; + unsigned int id_end; + bool count_total_value = false; + unsigned int total_value_idx; + uint64_t total_value = 0; unsigned int i, qid; unsigned int nb_queues; @@ -288,38 +356,43 @@ sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, rte_spinlock_lock(bmp_lock); rte_bitmap_reset(bmp); - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); if (nb_queues == 0) goto unlock; - *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues); + *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); /* - * The order of each software xstat type is the accumulative xstat + * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ + id_end = id_base + sw_stat->provide_total + nb_queues; for (i = 0; i < ids_size; i++) { - if (id_base <= ids[i] && ids[i] <= (id_base + nb_queues)) { - if (ids[i] == id_base) { /* Accumulative value */ - count_accum_value = true; - accum_value_idx = i; + if (id_base <= ids[i] && ids[i] < id_end) { + if (sw_stat->provide_total && ids[i] == id_base) { + /* Accumulative value */ + count_total_value = true; + total_value_idx = i; continue; } - qid = ids[i] - id_base - 1; - values[i] = sw_xstat->get_val(sa, qid); - accum_value += values[i]; + id_base_q = id_base + sw_stat->provide_total; + qid = ids[i] - id_base_q; + values[i] = sfc_sw_stat_get_val(sa, sw_stat_idx, qid); + total_value += values[i]; rte_bitmap_set(bmp, qid); } } - if (count_accum_value) { - values[accum_value_idx] = 0; + if (count_total_value) { + values[total_value_idx] = 0; for (qid = 0; qid < nb_queues; ++qid) { if (rte_bitmap_get(bmp, qid) != 0) continue; - values[accum_value_idx] += sw_xstat->get_val(sa, qid); + values[total_value_idx] += sfc_sw_stat_get_val(sa, + sw_stat_idx, + qid); } - values[accum_value_idx] += accum_value; + values[total_value_idx] += total_value; } unlock: @@ -329,17 +402,18 @@ unlock: unsigned int sfc_sw_xstats_get_nb_supported(struct sfc_adapter *sa) { - unsigned int nb_supported = 0; - unsigned int i; - SFC_ASSERT(sfc_adapter_is_locked(sa)); + return sa->sw_stats.xstats_count; +} - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - nb_supported += sfc_sw_xstat_get_nb_supported(sa, - &sfc_sw_xstats[i]); - } +static void +sfc_sw_stats_clear_cache(struct sfc_adapter *sa) +{ + unsigned int cache_count = sa->sw_stats.cache_count; + uint64_t *cache = sa->sw_stats.cache; - return nb_supported; + RTE_BUILD_BUG_ON(UINT64_C(0xffffffffffffffff) != SFC_SW_STAT_INVALID); + memset(cache, 0xff, cache_count * sizeof(*cache)); } void @@ -349,17 +423,20 @@ sfc_sw_xstats_get_vals(struct sfc_adapter *sa, unsigned int *nb_written, unsigned int *nb_supported) { - uint64_t *reset_vals = sa->sw_xstats.reset_vals; + uint64_t *reset_vals = sa->sw_stats.reset_vals; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; unsigned int sw_xstats_offset; unsigned int i; sfc_adapter_lock(sa); + sfc_sw_stats_clear_cache(sa); + sw_xstats_offset = *nb_supported; - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - sfc_sw_xstat_get_values(sa, &sfc_sw_xstats[i], xstats, - xstats_count, nb_written, nb_supported); + for (i = 0; i < sw_stats->supp_count; i++) { + sfc_sw_xstat_get_values(sa, sw_stats->supp[i].descr, i, + xstats, xstats_count, nb_written, nb_supported); } for (i = sw_xstats_offset; i < *nb_written; i++) @@ -375,13 +452,14 @@ sfc_sw_xstats_get_names(struct sfc_adapter *sa, unsigned int *nb_written, unsigned int *nb_supported) { + struct sfc_sw_stats *sw_stats = &sa->sw_stats; unsigned int i; int ret; sfc_adapter_lock(sa); - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - ret = sfc_sw_stat_get_names(sa, &sfc_sw_xstats[i], + for (i = 0; i < sw_stats->supp_count; i++) { + ret = sfc_sw_stat_get_names(sa, sw_stats->supp[i].descr, xstats_names, xstats_count, nb_written, nb_supported); if (ret != 0) { @@ -402,17 +480,20 @@ sfc_sw_xstats_get_vals_by_id(struct sfc_adapter *sa, unsigned int n, unsigned int *nb_supported) { - uint64_t *reset_vals = sa->sw_xstats.reset_vals; + uint64_t *reset_vals = sa->sw_stats.reset_vals; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; unsigned int sw_xstats_offset; unsigned int i; sfc_adapter_lock(sa); + sfc_sw_stats_clear_cache(sa); + sw_xstats_offset = *nb_supported; - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - sfc_sw_xstat_get_values_by_id(sa, &sfc_sw_xstats[i], ids, - values, n, nb_supported); + for (i = 0; i < sw_stats->supp_count; i++) { + sfc_sw_xstat_get_values_by_id(sa, sw_stats->supp[i].descr, i, + ids, values, n, nb_supported); } for (i = 0; i < n; i++) { @@ -430,14 +511,15 @@ sfc_sw_xstats_get_names_by_id(struct sfc_adapter *sa, unsigned int size, unsigned int *nb_supported) { + struct sfc_sw_stats *sw_stats = &sa->sw_stats; unsigned int i; int ret; sfc_adapter_lock(sa); - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - ret = sfc_sw_xstat_get_names_by_id(sa, &sfc_sw_xstats[i], ids, - xstats_names, size, + for (i = 0; i < sw_stats->supp_count; i++) { + ret = sfc_sw_xstat_get_names_by_id(sa, sw_stats->supp[i].descr, + ids, xstats_names, size, nb_supported); if (ret != 0) { sfc_adapter_unlock(sa); @@ -452,82 +534,135 @@ sfc_sw_xstats_get_names_by_id(struct sfc_adapter *sa, } static void -sfc_sw_xstat_reset(struct sfc_adapter *sa, struct sfc_sw_xstat_descr *sw_xstat, +sfc_sw_xstat_reset(struct sfc_adapter *sa, + const struct sfc_sw_stat_descr *sw_stat, + unsigned int sw_stat_idx, uint64_t *reset_vals) { unsigned int nb_queues; unsigned int qid; - uint64_t *accum_xstat_reset; + uint64_t *total_xstat_reset = NULL; SFC_ASSERT(sfc_adapter_is_locked(sa)); - nb_queues = sfc_sw_stat_get_queue_count(sa, sw_xstat); + nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); if (nb_queues == 0) return; /* - * The order of each software xstat type is the accumulative xstat + * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ - accum_xstat_reset = reset_vals; - *accum_xstat_reset = 0; - reset_vals++; + if (sw_stat->provide_total) { + total_xstat_reset = reset_vals; + *total_xstat_reset = 0; + reset_vals++; + } for (qid = 0; qid < nb_queues; ++qid) { - reset_vals[qid] = sw_xstat->get_val(sa, qid); - *accum_xstat_reset += reset_vals[qid]; + reset_vals[qid] = sfc_sw_stat_get_val(sa, sw_stat_idx, qid); + if (sw_stat->provide_total) + *total_xstat_reset += reset_vals[qid]; } } void sfc_sw_xstats_reset(struct sfc_adapter *sa) { - uint64_t *reset_vals = sa->sw_xstats.reset_vals; - struct sfc_sw_xstat_descr *sw_xstat; + uint64_t *reset_vals = sa->sw_stats.reset_vals; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; unsigned int i; SFC_ASSERT(sfc_adapter_is_locked(sa)); - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) { - sw_xstat = &sfc_sw_xstats[i]; - sfc_sw_xstat_reset(sa, sw_xstat, reset_vals); - reset_vals += sfc_sw_xstat_get_nb_supported(sa, sw_xstat); + sfc_sw_stats_clear_cache(sa); + + for (i = 0; i < sw_stats->supp_count; i++) { + sfc_sw_xstat_reset(sa, sw_stats->supp[i].descr, i, reset_vals); + reset_vals += sfc_sw_xstat_get_nb_supported(sa, + sw_stats->supp[i].descr); } } int sfc_sw_xstats_configure(struct sfc_adapter *sa) { - uint64_t **reset_vals = &sa->sw_xstats.reset_vals; + uint64_t **reset_vals = &sa->sw_stats.reset_vals; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; + unsigned int cache_count = 0; + uint64_t **cache = &sa->sw_stats.cache; + uint64_t *stat_cache; size_t nb_supported = 0; unsigned int i; + int rc; + + sw_stats->supp_count = RTE_DIM(sfc_sw_stats_descr); + if (sw_stats->supp == NULL) { + sw_stats->supp = rte_malloc(NULL, sw_stats->supp_count * + sizeof(*sw_stats->supp), 0); + if (sw_stats->supp == NULL) + return -ENOMEM; + } + for (i = 0; i < sw_stats->supp_count; i++) + sw_stats->supp[i].descr = &sfc_sw_stats_descr[i]; - for (i = 0; i < RTE_DIM(sfc_sw_xstats); i++) + for (i = 0; i < sw_stats->supp_count; i++) { nb_supported += sfc_sw_xstat_get_nb_supported(sa, - &sfc_sw_xstats[i]); + sw_stats->supp[i].descr); + cache_count += sfc_sw_stat_get_queue_count(sa, + sw_stats->supp[i].descr); + } + sa->sw_stats.xstats_count = nb_supported; *reset_vals = rte_realloc(*reset_vals, nb_supported * sizeof(**reset_vals), 0); - if (*reset_vals == NULL) - return ENOMEM; + if (*reset_vals == NULL) { + rc = -ENOMEM; + goto fail_reset_vals; + } memset(*reset_vals, 0, nb_supported * sizeof(**reset_vals)); + *cache = rte_realloc(*cache, cache_count * sizeof(*cache), 0); + if (*cache == NULL) { + rc = ENOMEM; + goto fail_cache; + } + sa->sw_stats.cache_count = cache_count; + stat_cache = *cache; + + for (i = 0; i < sw_stats->supp_count; i++) { + sw_stats->supp[i].cache = stat_cache; + stat_cache += sfc_sw_stat_get_queue_count(sa, + sw_stats->supp[i].descr); + } + return 0; + +fail_cache: + rte_free(*reset_vals); + *reset_vals = NULL; +fail_reset_vals: + sa->sw_stats.xstats_count = 0; + rte_free(sw_stats->supp); + sw_stats->supp = NULL; + sw_stats->supp_count = 0; + + return rc; } static void sfc_sw_xstats_free_queues_bitmap(struct sfc_adapter *sa) { - rte_bitmap_free(sa->sw_xstats.queues_bitmap); - rte_free(sa->sw_xstats.queues_bitmap_mem); + rte_bitmap_free(sa->sw_stats.queues_bitmap); + rte_free(sa->sw_stats.queues_bitmap_mem); } static int sfc_sw_xstats_alloc_queues_bitmap(struct sfc_adapter *sa) { - struct rte_bitmap **queues_bitmap = &sa->sw_xstats.queues_bitmap; - void **queues_bitmap_mem = &sa->sw_xstats.queues_bitmap_mem; + struct rte_bitmap **queues_bitmap = &sa->sw_stats.queues_bitmap; + void **queues_bitmap_mem = &sa->sw_stats.queues_bitmap_mem; uint32_t bmp_size; int rc; @@ -547,7 +682,7 @@ sfc_sw_xstats_alloc_queues_bitmap(struct sfc_adapter *sa) goto fail; } - rte_spinlock_init(&sa->sw_xstats.queues_bitmap_lock); + rte_spinlock_init(&sa->sw_stats.queues_bitmap_lock); return 0; fail: @@ -558,7 +693,12 @@ fail: int sfc_sw_xstats_init(struct sfc_adapter *sa) { - sa->sw_xstats.reset_vals = NULL; + sa->sw_stats.xstats_count = 0; + sa->sw_stats.supp = NULL; + sa->sw_stats.supp_count = 0; + sa->sw_stats.cache = NULL; + sa->sw_stats.cache_count = 0; + sa->sw_stats.reset_vals = NULL; return sfc_sw_xstats_alloc_queues_bitmap(sa); } @@ -566,8 +706,14 @@ sfc_sw_xstats_init(struct sfc_adapter *sa) void sfc_sw_xstats_close(struct sfc_adapter *sa) { - rte_free(sa->sw_xstats.reset_vals); - sa->sw_xstats.reset_vals = NULL; - sfc_sw_xstats_free_queues_bitmap(sa); + sa->sw_stats.reset_vals = NULL; + rte_free(sa->sw_stats.cache); + sa->sw_stats.cache = NULL; + sa->sw_stats.cache_count = 0; + rte_free(sa->sw_stats.reset_vals); + rte_free(sa->sw_stats.supp); + sa->sw_stats.supp = NULL; + sa->sw_stats.supp_count = 0; + sa->sw_stats.xstats_count = 0; }