Lines Matching +full:block +full:- +full:offset

1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
27 u32 offset; member
45 prestera_counter_is_ready(struct prestera_counter_block *block, u32 id) in prestera_counter_is_ready() argument
47 return block->counter_flag[id - block->offset] == COUNTER_FLAG_READY; in prestera_counter_is_ready()
52 mutex_lock(&counter->mtx); in prestera_counter_lock()
57 mutex_unlock(&counter->mtx); in prestera_counter_unlock()
60 static void prestera_counter_block_lock(struct prestera_counter_block *block) in prestera_counter_block_lock() argument
62 mutex_lock(&block->mtx); in prestera_counter_block_lock()
65 static void prestera_counter_block_unlock(struct prestera_counter_block *block) in prestera_counter_block_unlock() argument
67 mutex_unlock(&block->mtx); in prestera_counter_block_unlock()
70 static bool prestera_counter_block_incref(struct prestera_counter_block *block) in prestera_counter_block_incref() argument
72 return refcount_inc_not_zero(&block->refcnt); in prestera_counter_block_incref()
75 static bool prestera_counter_block_decref(struct prestera_counter_block *block) in prestera_counter_block_decref() argument
77 return refcount_dec_and_test(&block->refcnt); in prestera_counter_block_decref()
81 static void prestera_counter_stats_clear(struct prestera_counter_block *block, in prestera_counter_stats_clear() argument
84 memset(&block->stats[counter_id - block->offset], 0, in prestera_counter_stats_clear()
85 sizeof(*block->stats)); in prestera_counter_stats_clear()
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()
101 return counter->block_list[i]; in prestera_counter_block_lookup_not_full()
110 struct prestera_counter_block *block) in prestera_counter_block_list_add() argument
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()
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()
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()
143 struct prestera_counter_block *block; in prestera_counter_block_get() local
146 block = prestera_counter_block_lookup_not_full(counter, client); in prestera_counter_block_get()
147 if (block) in prestera_counter_block_get()
148 return block; in prestera_counter_block_get()
150 block = kzalloc(sizeof(*block), GFP_KERNEL); in prestera_counter_block_get()
151 if (!block) 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()
184 return 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()
195 kfree(block); in prestera_counter_block_get()
200 struct prestera_counter_block *block) in prestera_counter_block_put() argument
204 if (!prestera_counter_block_decref(block)) 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()
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()
223 kfree(block); in prestera_counter_block_put()
226 static int prestera_counter_get_vacant(struct prestera_counter_block *block, in prestera_counter_get_vacant() argument
231 if (block->full) in prestera_counter_get_vacant()
232 return -ENOSPC; in prestera_counter_get_vacant()
234 prestera_counter_block_lock(block); 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()
239 if (free_id == -ENOSPC) in prestera_counter_get_vacant()
240 block->full = true; in prestera_counter_get_vacant()
242 prestera_counter_block_unlock(block); in prestera_counter_get_vacant()
246 prestera_counter_block_unlock(block); in prestera_counter_get_vacant()
254 struct prestera_counter_block *block; in prestera_counter_get() local
259 block = prestera_counter_block_get(counter, client); in prestera_counter_get()
260 if (IS_ERR(block)) in prestera_counter_get()
261 return PTR_ERR(block); in prestera_counter_get()
263 err = prestera_counter_get_vacant(block, &id); in prestera_counter_get()
265 prestera_counter_block_put(counter, block); in prestera_counter_get()
267 if (err == -ENOSPC) in prestera_counter_get()
273 prestera_counter_block_lock(block); 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()
276 prestera_counter_block_unlock(block); in prestera_counter_get()
279 *bl = block; in prestera_counter_get()
285 struct prestera_counter_block *block, u32 counter_id) in prestera_counter_put() argument
287 if (!block) in prestera_counter_put()
290 prestera_counter_block_lock(block); in prestera_counter_put()
291 idr_remove(&block->counter_idr, counter_id); in prestera_counter_put()
292 block->full = false; in prestera_counter_put()
293 prestera_counter_stats_clear(block, counter_id); in prestera_counter_put()
294 prestera_counter_block_unlock(block); 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()
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()
322 if (idx >= counter->block_list_len) 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()
334 return counter->block_list[idx]; in prestera_counter_block_get_by_idx()
343 struct prestera_counter_block *block; in prestera_counter_stats_work() local
350 block = prestera_counter_block_get_by_idx(counter, counter->curr_idx); in prestera_counter_stats_work()
351 if (!block) { 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()
363 prestera_counter_block_lock(block); in prestera_counter_stats_work()
364 block->is_updating = true; in prestera_counter_stats_work()
365 prestera_counter_block_unlock(block); 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()
373 prestera_counter_block_lock(block); 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()
377 prestera_counter_block_unlock(block); 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()
389 prestera_counter_block_lock(block); 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()
392 prestera_counter_block_unlock(block); in prestera_counter_stats_work()
396 prestera_counter_block_lock(block); in prestera_counter_stats_work()
397 block->is_updating = false; in prestera_counter_stats_work()
398 prestera_counter_block_unlock(block); 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()
408 if (block) 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()
418 struct prestera_counter_block *block, in prestera_counter_stats_get() argument
421 if (!block || !prestera_counter_is_ready(block, counter_id)) { in prestera_counter_stats_get()
427 prestera_counter_block_lock(block); 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()
431 prestera_counter_stats_clear(block, counter_id); in prestera_counter_stats_get()
432 prestera_counter_block_unlock(block); in prestera_counter_stats_get()
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()
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()
464 struct prestera_counter *counter = sw->counter; in prestera_counter_fini()
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()