Lines Matching +full:counter +full:- +full:0

1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
40 COUNTER_FLAG_READY = 0,
47 return block->counter_flag[id - block->offset] == COUNTER_FLAG_READY; in prestera_counter_is_ready()
50 static void prestera_counter_lock(struct prestera_counter *counter) in prestera_counter_lock() argument
52 mutex_lock(&counter->mtx); in prestera_counter_lock()
55 static void prestera_counter_unlock(struct prestera_counter *counter) in prestera_counter_unlock() argument
57 mutex_unlock(&counter->mtx); in prestera_counter_unlock()
62 mutex_lock(&block->mtx); in prestera_counter_block_lock()
67 mutex_unlock(&block->mtx); in prestera_counter_block_unlock()
72 return refcount_inc_not_zero(&block->refcnt); in prestera_counter_block_incref()
77 return refcount_dec_and_test(&block->refcnt); in prestera_counter_block_decref()
84 memset(&block->stats[counter_id - block->offset], 0, in prestera_counter_stats_clear()
85 sizeof(*block->stats)); in prestera_counter_stats_clear()
89 prestera_counter_block_lookup_not_full(struct prestera_counter *counter, in prestera_counter_block_lookup_not_full() argument
94 prestera_counter_lock(counter); in prestera_counter_block_lookup_not_full()
95 for (i = 0; i < counter->block_list_len; i++) { in prestera_counter_block_lookup_not_full()
96 if (counter->block_list[i] && in prestera_counter_block_lookup_not_full()
97 counter->block_list[i]->client == client && in prestera_counter_block_lookup_not_full()
98 !counter->block_list[i]->full && in prestera_counter_block_lookup_not_full()
99 prestera_counter_block_incref(counter->block_list[i])) { in prestera_counter_block_lookup_not_full()
100 prestera_counter_unlock(counter); in prestera_counter_block_lookup_not_full()
101 return counter->block_list[i]; in prestera_counter_block_lookup_not_full()
104 prestera_counter_unlock(counter); in prestera_counter_block_lookup_not_full()
109 static int prestera_counter_block_list_add(struct prestera_counter *counter, in prestera_counter_block_list_add() argument
115 prestera_counter_lock(counter); in prestera_counter_block_list_add()
117 for (i = 0; i < counter->block_list_len; i++) { in prestera_counter_block_list_add()
118 if (counter->block_list[i]) in prestera_counter_block_list_add()
121 counter->block_list[i] = block; in prestera_counter_block_list_add()
122 prestera_counter_unlock(counter); in prestera_counter_block_list_add()
123 return 0; in prestera_counter_block_list_add()
126 arr = krealloc(counter->block_list, (counter->block_list_len + 1) * in prestera_counter_block_list_add()
127 sizeof(*counter->block_list), GFP_KERNEL); in prestera_counter_block_list_add()
129 prestera_counter_unlock(counter); in prestera_counter_block_list_add()
130 return -ENOMEM; in prestera_counter_block_list_add()
133 counter->block_list = arr; in prestera_counter_block_list_add()
134 counter->block_list[counter->block_list_len] = block; in prestera_counter_block_list_add()
135 counter->block_list_len++; in prestera_counter_block_list_add()
136 prestera_counter_unlock(counter); in prestera_counter_block_list_add()
137 return 0; in prestera_counter_block_list_add()
141 prestera_counter_block_get(struct prestera_counter *counter, u32 client) in prestera_counter_block_get() argument
146 block = prestera_counter_block_lookup_not_full(counter, client); in prestera_counter_block_get()
152 return ERR_PTR(-ENOMEM); in prestera_counter_block_get()
154 err = prestera_hw_counter_block_get(counter->sw, client, in prestera_counter_block_get()
155 &block->id, &block->offset, in prestera_counter_block_get()
156 &block->num_counters); in prestera_counter_block_get()
160 block->stats = kcalloc(block->num_counters, in prestera_counter_block_get()
161 sizeof(*block->stats), GFP_KERNEL); in prestera_counter_block_get()
162 if (!block->stats) { in prestera_counter_block_get()
163 err = -ENOMEM; in prestera_counter_block_get()
167 block->counter_flag = kcalloc(block->num_counters, in prestera_counter_block_get()
168 sizeof(*block->counter_flag), in prestera_counter_block_get()
170 if (!block->counter_flag) { in prestera_counter_block_get()
171 err = -ENOMEM; in prestera_counter_block_get()
175 block->client = client; in prestera_counter_block_get()
176 mutex_init(&block->mtx); in prestera_counter_block_get()
177 refcount_set(&block->refcnt, 1); in prestera_counter_block_get()
178 idr_init_base(&block->counter_idr, block->offset); in prestera_counter_block_get()
180 err = prestera_counter_block_list_add(counter, block); in prestera_counter_block_get()
187 idr_destroy(&block->counter_idr); in prestera_counter_block_get()
188 mutex_destroy(&block->mtx); in prestera_counter_block_get()
189 kfree(block->counter_flag); in prestera_counter_block_get()
191 kfree(block->stats); in prestera_counter_block_get()
193 prestera_hw_counter_block_release(counter->sw, block->id); in prestera_counter_block_get()
199 static void prestera_counter_block_put(struct prestera_counter *counter, in prestera_counter_block_put() argument
207 prestera_counter_lock(counter); in prestera_counter_block_put()
208 for (i = 0; i < counter->block_list_len; i++) { in prestera_counter_block_put()
209 if (counter->block_list[i] && in prestera_counter_block_put()
210 counter->block_list[i]->id == block->id) { in prestera_counter_block_put()
211 counter->block_list[i] = NULL; in prestera_counter_block_put()
215 prestera_counter_unlock(counter); in prestera_counter_block_put()
217 WARN_ON(!idr_is_empty(&block->counter_idr)); in prestera_counter_block_put()
219 prestera_hw_counter_block_release(counter->sw, block->id); in prestera_counter_block_put()
220 idr_destroy(&block->counter_idr); in prestera_counter_block_put()
221 mutex_destroy(&block->mtx); in prestera_counter_block_put()
222 kfree(block->stats); in prestera_counter_block_put()
231 if (block->full) in prestera_counter_get_vacant()
232 return -ENOSPC; in prestera_counter_get_vacant()
235 free_id = idr_alloc_cyclic(&block->counter_idr, NULL, block->offset, in prestera_counter_get_vacant()
236 block->offset + block->num_counters, in prestera_counter_get_vacant()
238 if (free_id < 0) { in prestera_counter_get_vacant()
239 if (free_id == -ENOSPC) in prestera_counter_get_vacant()
240 block->full = true; in prestera_counter_get_vacant()
248 return 0; in prestera_counter_get_vacant()
251 int prestera_counter_get(struct prestera_counter *counter, u32 client, in prestera_counter_get() argument
259 block = prestera_counter_block_get(counter, client); in prestera_counter_get()
265 prestera_counter_block_put(counter, block); in prestera_counter_get()
267 if (err == -ENOSPC) in prestera_counter_get()
274 if (block->is_updating) in prestera_counter_get()
275 block->counter_flag[id - block->offset] = COUNTER_FLAG_INVALID; in prestera_counter_get()
281 return 0; in prestera_counter_get()
284 void prestera_counter_put(struct prestera_counter *counter, in prestera_counter_put() argument
291 idr_remove(&block->counter_idr, counter_id); in prestera_counter_put()
292 block->full = false; in prestera_counter_put()
296 prestera_hw_counter_clear(counter->sw, block->id, counter_id); in prestera_counter_put()
297 prestera_counter_block_put(counter, block); in prestera_counter_put()
300 static u32 prestera_counter_block_idx_next(struct prestera_counter *counter, in prestera_counter_block_idx_next() argument
305 prestera_counter_lock(counter); in prestera_counter_block_idx_next()
306 for (i = 0; i < counter->block_list_len; i++) { in prestera_counter_block_idx_next()
307 idx = (start + i) % counter->block_list_len; in prestera_counter_block_idx_next()
308 if (!counter->block_list[idx]) in prestera_counter_block_idx_next()
311 prestera_counter_unlock(counter); in prestera_counter_block_idx_next()
314 prestera_counter_unlock(counter); in prestera_counter_block_idx_next()
316 return 0; in prestera_counter_block_idx_next()
320 prestera_counter_block_get_by_idx(struct prestera_counter *counter, u32 idx) in prestera_counter_block_get_by_idx() argument
322 if (idx >= counter->block_list_len) in prestera_counter_block_get_by_idx()
325 prestera_counter_lock(counter); in prestera_counter_block_get_by_idx()
327 if (!counter->block_list[idx] || in prestera_counter_block_get_by_idx()
328 !prestera_counter_block_incref(counter->block_list[idx])) { in prestera_counter_block_get_by_idx()
329 prestera_counter_unlock(counter); in prestera_counter_block_get_by_idx()
333 prestera_counter_unlock(counter); in prestera_counter_block_get_by_idx()
334 return counter->block_list[idx]; in prestera_counter_block_get_by_idx()
341 struct prestera_counter *counter = in prestera_counter_stats_work() local
350 block = prestera_counter_block_get_by_idx(counter, counter->curr_idx); in prestera_counter_stats_work()
352 if (counter->is_fetching) in prestera_counter_stats_work()
358 if (!counter->is_fetching) { in prestera_counter_stats_work()
359 err = prestera_hw_counter_trigger(counter->sw, block->id); in prestera_counter_stats_work()
364 block->is_updating = true; in prestera_counter_stats_work()
367 counter->is_fetching = true; in prestera_counter_stats_work()
368 counter->total_read = 0; in prestera_counter_stats_work()
374 err = prestera_hw_counters_get(counter->sw, counter->total_read, in prestera_counter_stats_work()
376 &block->stats[counter->total_read]); in prestera_counter_stats_work()
381 counter->total_read += count; in prestera_counter_stats_work()
382 if (!done || counter->total_read < block->num_counters) { in prestera_counter_stats_work()
387 for (i = 0; i < block->num_counters; i++) { in prestera_counter_stats_work()
388 if (block->counter_flag[i] == COUNTER_FLAG_INVALID) { in prestera_counter_stats_work()
390 block->counter_flag[i] = COUNTER_FLAG_READY; in prestera_counter_stats_work()
391 memset(&block->stats[i], 0, sizeof(*block->stats)); in prestera_counter_stats_work()
397 block->is_updating = false; in prestera_counter_stats_work()
402 prestera_hw_counter_abort(counter->sw); in prestera_counter_stats_work()
404 counter->is_fetching = false; in prestera_counter_stats_work()
405 counter->curr_idx = in prestera_counter_stats_work()
406 prestera_counter_block_idx_next(counter, counter->curr_idx); in prestera_counter_stats_work()
409 prestera_counter_block_put(counter, block); in prestera_counter_stats_work()
411 schedule_delayed_work(&counter->stats_dw, resched_time); in prestera_counter_stats_work()
417 int prestera_counter_stats_get(struct prestera_counter *counter, in prestera_counter_stats_get() argument
422 *packets = 0; in prestera_counter_stats_get()
423 *bytes = 0; in prestera_counter_stats_get()
424 return 0; in prestera_counter_stats_get()
428 *packets = block->stats[counter_id - block->offset].packets; in prestera_counter_stats_get()
429 *bytes = block->stats[counter_id - block->offset].bytes; in prestera_counter_stats_get()
434 return 0; in prestera_counter_stats_get()
439 struct prestera_counter *counter; in prestera_counter_init() local
441 counter = kzalloc(sizeof(*counter), GFP_KERNEL); in prestera_counter_init()
442 if (!counter) in prestera_counter_init()
443 return -ENOMEM; in prestera_counter_init()
445 counter->block_list = kzalloc(sizeof(*counter->block_list), GFP_KERNEL); in prestera_counter_init()
446 if (!counter->block_list) { in prestera_counter_init()
447 kfree(counter); in prestera_counter_init()
448 return -ENOMEM; in prestera_counter_init()
451 mutex_init(&counter->mtx); in prestera_counter_init()
452 counter->block_list_len = 1; in prestera_counter_init()
453 counter->sw = sw; in prestera_counter_init()
454 sw->counter = counter; in prestera_counter_init()
456 INIT_DELAYED_WORK(&counter->stats_dw, prestera_counter_stats_work); in prestera_counter_init()
457 schedule_delayed_work(&counter->stats_dw, COUNTER_POLL_TIME); in prestera_counter_init()
459 return 0; in prestera_counter_init()
464 struct prestera_counter *counter = sw->counter; in prestera_counter_fini() local
467 cancel_delayed_work_sync(&counter->stats_dw); in prestera_counter_fini()
469 for (i = 0; i < counter->block_list_len; i++) in prestera_counter_fini()
470 WARN_ON(counter->block_list[i]); in prestera_counter_fini()
472 mutex_destroy(&counter->mtx); in prestera_counter_fini()
473 kfree(counter->block_list); in prestera_counter_fini()
474 kfree(counter); in prestera_counter_fini()