File Index
Files and directories
Sign in
FILE

commonring.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.c C
  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}
~/ Read-only file preview.