X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_sw_stats.c;h=81bd531a17ee09858923d5cf4f4bcc5e2fdc1556;hb=63abf8d29225;hp=0f9309150067b0e4209045c3e07a6d82b73fd5d5;hpb=c704e5df3d8fc75c74235943efa68f7e0f1109f1;p=dpdk.git diff --git a/drivers/net/sfc/sfc_sw_stats.c b/drivers/net/sfc/sfc_sw_stats.c index 0f93091500..81bd531a17 100644 --- a/drivers/net/sfc/sfc_sw_stats.c +++ b/drivers/net/sfc/sfc_sw_stats.c @@ -10,55 +10,73 @@ #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_stat_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_stat_descr { const char *name; enum sfc_sw_stats_type type; sfc_get_sw_stat_val_t *get_val; + bool provide_total; }; static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_rx_dbells; -static uint64_t -sfc_get_sw_stat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid) +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_stat_val_t sfc_get_sw_stat_val_tx_dbells; -static uint64_t -sfc_get_sw_stat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid) +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; } +/* + * 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_stat_val_rx_dbells, + .provide_total = true, }, { .name = "dbells", .type = SFC_SW_STATS_TX, .get_val = sfc_get_sw_stat_val_tx_dbells, + .provide_total = true, } }; @@ -83,7 +101,7 @@ sfc_sw_stat_get_name(struct sfc_adapter *sa, return -EINVAL; } - if (id_off == 0) { + if (sw_stat->provide_total && id_off == 0) { ret = snprintf(name, name_size, "%s_%s", prefix, sw_stat->name); if (ret < 0 || ret >= (int)name_size) { @@ -92,7 +110,7 @@ sfc_sw_stat_get_name(struct sfc_adapter *sa, 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_stat->name); if (ret < 0 || ret >= (int)name_size) { @@ -124,10 +142,11 @@ sfc_sw_stat_get_queue_count(struct sfc_adapter *sa, } 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 total xstat of all queues */ - return nb_queues > 0 ? 1 + nb_queues : 0; + return nb_queues > 0 ? sw_stat->provide_total + nb_queues : 0; } static unsigned int @@ -137,7 +156,7 @@ sfc_sw_xstat_get_nb_supported(struct sfc_adapter *sa, unsigned int nb_queues; nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat); - return sfc_sw_xstat_per_queue_get_count(nb_queues); + return sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues); } static int @@ -157,13 +176,13 @@ sfc_sw_stat_get_names(struct sfc_adapter *sa, 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 total xstat * followed by per-queue xstats. */ - if (*nb_written < xstats_names_sz) { + 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); @@ -196,6 +215,7 @@ 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; @@ -203,14 +223,15 @@ sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa, 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 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) { + 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); @@ -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_stat_descr *sw_stat, + unsigned int sw_stat_idx, struct rte_eth_xstat *xstats, unsigned int xstats_size, unsigned int *nb_written, @@ -239,13 +304,13 @@ sfc_sw_xstat_get_values(struct sfc_adapter *sa, 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 total xstat * followed by per-queue xstats. */ - if (*nb_written < xstats_size) { + if (*nb_written < xstats_size && sw_stat->provide_total) { count_total_value = true; total_xstat = &xstats[*nb_written]; xstats[*nb_written].id = *nb_written; @@ -254,7 +319,7 @@ sfc_sw_xstat_get_values(struct sfc_adapter *sa, } for (qid = 0; qid < nb_queues; ++qid) { - value = sw_stat->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; @@ -270,6 +335,7 @@ sfc_sw_xstat_get_values(struct sfc_adapter *sa, static void sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, const struct sfc_sw_stat_descr *sw_stat, + unsigned int sw_stat_idx, const uint64_t *ids, uint64_t *values, unsigned int ids_size, @@ -278,6 +344,8 @@ sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, 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; + unsigned int id_base_q; + unsigned int id_end; bool count_total_value = false; unsigned int total_value_idx; uint64_t total_value = 0; @@ -291,21 +359,24 @@ sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, 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 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 */ + 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_stat->get_val(sa, qid); + 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); @@ -317,7 +388,9 @@ sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa, for (qid = 0; qid < nb_queues; ++qid) { if (rte_bitmap_get(bmp, qid) != 0) continue; - values[total_value_idx] += sw_stat->get_val(sa, qid); + values[total_value_idx] += sfc_sw_stat_get_val(sa, + sw_stat_idx, + qid); } values[total_value_idx] += total_value; } @@ -333,6 +406,16 @@ sfc_sw_xstats_get_nb_supported(struct sfc_adapter *sa) return sa->sw_stats.xstats_count; } +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; + + RTE_BUILD_BUG_ON(UINT64_C(0xffffffffffffffff) != SFC_SW_STAT_INVALID); + memset(cache, 0xff, cache_count * sizeof(*cache)); +} + void sfc_sw_xstats_get_vals(struct sfc_adapter *sa, struct rte_eth_xstat *xstats, @@ -341,16 +424,19 @@ sfc_sw_xstats_get_vals(struct sfc_adapter *sa, unsigned int *nb_supported) { 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_stats_descr); i++) { - sfc_sw_xstat_get_values(sa, &sfc_sw_stats_descr[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++) @@ -366,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_stats_descr); i++) { - ret = sfc_sw_stat_get_names(sa, &sfc_sw_stats_descr[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) { @@ -394,16 +481,19 @@ sfc_sw_xstats_get_vals_by_id(struct sfc_adapter *sa, unsigned int *nb_supported) { 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_stats_descr); i++) { - sfc_sw_xstat_get_values_by_id(sa, &sfc_sw_stats_descr[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++) { @@ -421,13 +511,14 @@ 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_stats_descr); i++) { - ret = sfc_sw_xstat_get_names_by_id(sa, &sfc_sw_stats_descr[i], + 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) { @@ -445,11 +536,12 @@ sfc_sw_xstats_get_names_by_id(struct sfc_adapter *sa, static void 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 *total_xstat_reset; + uint64_t *total_xstat_reset = NULL; SFC_ASSERT(sfc_adapter_is_locked(sa)); @@ -461,13 +553,16 @@ sfc_sw_xstat_reset(struct sfc_adapter *sa, * The order of each software xstat type is the total xstat * followed by per-queue xstats. */ - total_xstat_reset = reset_vals; - *total_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_stat->get_val(sa, qid); - *total_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]; } } @@ -475,15 +570,17 @@ void sfc_sw_xstats_reset(struct sfc_adapter *sa) { uint64_t *reset_vals = sa->sw_stats.reset_vals; - const struct sfc_sw_stat_descr *sw_stat; + 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_stats_descr); i++) { - sw_stat = &sfc_sw_stats_descr[i]; - sfc_sw_xstat_reset(sa, sw_stat, reset_vals); - reset_vals += sfc_sw_xstat_get_nb_supported(sa, sw_stat); + 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); } } @@ -491,22 +588,67 @@ int sfc_sw_xstats_configure(struct sfc_adapter *sa) { 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; - for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) + 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 < sw_stats->supp_count; i++) { nb_supported += sfc_sw_xstat_get_nb_supported(sa, - &sfc_sw_stats_descr[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 @@ -552,6 +694,10 @@ int sfc_sw_xstats_init(struct sfc_adapter *sa) { 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); @@ -561,7 +707,13 @@ void sfc_sw_xstats_close(struct sfc_adapter *sa) { sfc_sw_xstats_free_queues_bitmap(sa); - rte_free(sa->sw_stats.reset_vals); 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; }