cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

commonring.c (5503B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (c) 2014 Broadcom Corporation
      4 */
      5
      6#include <linux/types.h>
      7#include <linux/netdevice.h>
      8
      9#include <brcmu_utils.h>
     10#include <brcmu_wifi.h>
     11
     12#include "core.h"
     13#include "commonring.h"
     14
     15void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
     16				  int (*cr_ring_bell)(void *ctx),
     17				  int (*cr_update_rptr)(void *ctx),
     18				  int (*cr_update_wptr)(void *ctx),
     19				  int (*cr_write_rptr)(void *ctx),
     20				  int (*cr_write_wptr)(void *ctx), void *ctx)
     21{
     22	commonring->cr_ring_bell = cr_ring_bell;
     23	commonring->cr_update_rptr = cr_update_rptr;
     24	commonring->cr_update_wptr = cr_update_wptr;
     25	commonring->cr_write_rptr = cr_write_rptr;
     26	commonring->cr_write_wptr = cr_write_wptr;
     27	commonring->cr_ctx = ctx;
     28}
     29
     30
     31void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
     32			     u16 item_len, void *buf_addr)
     33{
     34	commonring->depth = depth;
     35	commonring->item_len = item_len;
     36	commonring->buf_addr = buf_addr;
     37	if (!commonring->inited) {
     38		spin_lock_init(&commonring->lock);
     39		commonring->inited = true;
     40	}
     41	commonring->r_ptr = 0;
     42	if (commonring->cr_write_rptr)
     43		commonring->cr_write_rptr(commonring->cr_ctx);
     44	commonring->w_ptr = 0;
     45	if (commonring->cr_write_wptr)
     46		commonring->cr_write_wptr(commonring->cr_ctx);
     47	commonring->f_ptr = 0;
     48}
     49
     50
     51void brcmf_commonring_lock(struct brcmf_commonring *commonring)
     52		__acquires(&commonring->lock)
     53{
     54	unsigned long flags;
     55
     56	spin_lock_irqsave(&commonring->lock, flags);
     57	commonring->flags = flags;
     58}
     59
     60
     61void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
     62		__releases(&commonring->lock)
     63{
     64	spin_unlock_irqrestore(&commonring->lock, commonring->flags);
     65}
     66
     67
     68bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
     69{
     70	u16 available;
     71	bool retry = true;
     72
     73again:
     74	if (commonring->r_ptr <= commonring->w_ptr)
     75		available = commonring->depth - commonring->w_ptr +
     76			    commonring->r_ptr;
     77	else
     78		available = commonring->r_ptr - commonring->w_ptr;
     79
     80	if (available > 1) {
     81		if (!commonring->was_full)
     82			return true;
     83		if (available > commonring->depth / 8) {
     84			commonring->was_full = false;
     85			return true;
     86		}
     87		if (retry) {
     88			if (commonring->cr_update_rptr)
     89				commonring->cr_update_rptr(commonring->cr_ctx);
     90			retry = false;
     91			goto again;
     92		}
     93		return false;
     94	}
     95
     96	if (retry) {
     97		if (commonring->cr_update_rptr)
     98			commonring->cr_update_rptr(commonring->cr_ctx);
     99		retry = false;
    100		goto again;
    101	}
    102
    103	commonring->was_full = true;
    104	return false;
    105}
    106
    107
    108void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
    109{
    110	void *ret_ptr;
    111	u16 available;
    112	bool retry = true;
    113
    114again:
    115	if (commonring->r_ptr <= commonring->w_ptr)
    116		available = commonring->depth - commonring->w_ptr +
    117			    commonring->r_ptr;
    118	else
    119		available = commonring->r_ptr - commonring->w_ptr;
    120
    121	if (available > 1) {
    122		ret_ptr = commonring->buf_addr +
    123			  (commonring->w_ptr * commonring->item_len);
    124		commonring->w_ptr++;
    125		if (commonring->w_ptr == commonring->depth)
    126			commonring->w_ptr = 0;
    127		return ret_ptr;
    128	}
    129
    130	if (retry) {
    131		if (commonring->cr_update_rptr)
    132			commonring->cr_update_rptr(commonring->cr_ctx);
    133		retry = false;
    134		goto again;
    135	}
    136
    137	commonring->was_full = true;
    138	return NULL;
    139}
    140
    141
    142void *
    143brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
    144					    u16 n_items, u16 *alloced)
    145{
    146	void *ret_ptr;
    147	u16 available;
    148	bool retry = true;
    149
    150again:
    151	if (commonring->r_ptr <= commonring->w_ptr)
    152		available = commonring->depth - commonring->w_ptr +
    153			    commonring->r_ptr;
    154	else
    155		available = commonring->r_ptr - commonring->w_ptr;
    156
    157	if (available > 1) {
    158		ret_ptr = commonring->buf_addr +
    159			  (commonring->w_ptr * commonring->item_len);
    160		*alloced = min_t(u16, n_items, available - 1);
    161		if (*alloced + commonring->w_ptr > commonring->depth)
    162			*alloced = commonring->depth - commonring->w_ptr;
    163		commonring->w_ptr += *alloced;
    164		if (commonring->w_ptr == commonring->depth)
    165			commonring->w_ptr = 0;
    166		return ret_ptr;
    167	}
    168
    169	if (retry) {
    170		if (commonring->cr_update_rptr)
    171			commonring->cr_update_rptr(commonring->cr_ctx);
    172		retry = false;
    173		goto again;
    174	}
    175
    176	commonring->was_full = true;
    177	return NULL;
    178}
    179
    180
    181int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
    182{
    183	if (commonring->f_ptr > commonring->w_ptr)
    184		commonring->f_ptr = 0;
    185
    186	commonring->f_ptr = commonring->w_ptr;
    187
    188	if (commonring->cr_write_wptr)
    189		commonring->cr_write_wptr(commonring->cr_ctx);
    190	if (commonring->cr_ring_bell)
    191		return commonring->cr_ring_bell(commonring->cr_ctx);
    192
    193	return -EIO;
    194}
    195
    196
    197void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
    198				   u16 n_items)
    199{
    200	if (commonring->w_ptr == 0)
    201		commonring->w_ptr = commonring->depth - n_items;
    202	else
    203		commonring->w_ptr -= n_items;
    204}
    205
    206
    207void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
    208				    u16 *n_items)
    209{
    210	if (commonring->cr_update_wptr)
    211		commonring->cr_update_wptr(commonring->cr_ctx);
    212
    213	*n_items = (commonring->w_ptr >= commonring->r_ptr) ?
    214				(commonring->w_ptr - commonring->r_ptr) :
    215				(commonring->depth - commonring->r_ptr);
    216
    217	if (*n_items == 0)
    218		return NULL;
    219
    220	return commonring->buf_addr +
    221	       (commonring->r_ptr * commonring->item_len);
    222}
    223
    224
    225int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
    226				   u16 n_items)
    227{
    228	commonring->r_ptr += n_items;
    229	if (commonring->r_ptr == commonring->depth)
    230		commonring->r_ptr = 0;
    231
    232	if (commonring->cr_write_rptr)
    233		return commonring->cr_write_rptr(commonring->cr_ctx);
    234
    235	return -EIO;
    236}