~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/rds/ib_ring.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (c) 2006 Oracle.  All rights reserved.
  3  *
  4  * This software is available to you under a choice of one of two
  5  * licenses.  You may choose to be licensed under the terms of the GNU
  6  * General Public License (GPL) Version 2, available from the file
  7  * COPYING in the main directory of this source tree, or the
  8  * OpenIB.org BSD license below:
  9  *
 10  *     Redistribution and use in source and binary forms, with or
 11  *     without modification, are permitted provided that the following
 12  *     conditions are met:
 13  *
 14  *      - Redistributions of source code must retain the above
 15  *        copyright notice, this list of conditions and the following
 16  *        disclaimer.
 17  *
 18  *      - Redistributions in binary form must reproduce the above
 19  *        copyright notice, this list of conditions and the following
 20  *        disclaimer in the documentation and/or other materials
 21  *        provided with the distribution.
 22  *
 23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30  * SOFTWARE.
 31  *
 32  */
 33 #include <linux/kernel.h>
 34 
 35 #include "rds.h"
 36 #include "ib.h"
 37 
 38 /*
 39  * Locking for IB rings.
 40  * We assume that allocation is always protected by a mutex
 41  * in the caller (this is a valid assumption for the current
 42  * implementation).
 43  *
 44  * Freeing always happens in an interrupt, and hence only
 45  * races with allocations, but not with other free()s.
 46  *
 47  * The interaction between allocation and freeing is that
 48  * the alloc code has to determine the number of free entries.
 49  * To this end, we maintain two counters; an allocation counter
 50  * and a free counter. Both are allowed to run freely, and wrap
 51  * around.
 52  * The number of used entries is always (alloc_ctr - free_ctr) % NR.
 53  *
 54  * The current implementation makes free_ctr atomic. When the
 55  * caller finds an allocation fails, it should set an "alloc fail"
 56  * bit and retry the allocation. The "alloc fail" bit essentially tells
 57  * the CQ completion handlers to wake it up after freeing some
 58  * more entries.
 59  */
 60 
 61 /*
 62  * This only happens on shutdown.
 63  */
 64 DECLARE_WAIT_QUEUE_HEAD(rds_ib_ring_empty_wait);
 65 
 66 void rds_ib_ring_init(struct rds_ib_work_ring *ring, u32 nr)
 67 {
 68         memset(ring, 0, sizeof(*ring));
 69         ring->w_nr = nr;
 70         rdsdebug("ring %p nr %u\n", ring, ring->w_nr);
 71 }
 72 
 73 static inline u32 __rds_ib_ring_used(struct rds_ib_work_ring *ring)
 74 {
 75         u32 diff;
 76 
 77         /* This assumes that atomic_t has at least as many bits as u32 */
 78         diff = ring->w_alloc_ctr - (u32) atomic_read(&ring->w_free_ctr);
 79         BUG_ON(diff > ring->w_nr);
 80 
 81         return diff;
 82 }
 83 
 84 void rds_ib_ring_resize(struct rds_ib_work_ring *ring, u32 nr)
 85 {
 86         /* We only ever get called from the connection setup code,
 87          * prior to creating the QP. */
 88         BUG_ON(__rds_ib_ring_used(ring));
 89         ring->w_nr = nr;
 90 }
 91 
 92 static int __rds_ib_ring_empty(struct rds_ib_work_ring *ring)
 93 {
 94         return __rds_ib_ring_used(ring) == 0;
 95 }
 96 
 97 u32 rds_ib_ring_alloc(struct rds_ib_work_ring *ring, u32 val, u32 *pos)
 98 {
 99         u32 ret = 0, avail;
100 
101         avail = ring->w_nr - __rds_ib_ring_used(ring);
102 
103         rdsdebug("ring %p val %u next %u free %u\n", ring, val,
104                  ring->w_alloc_ptr, avail);
105 
106         if (val && avail) {
107                 ret = min(val, avail);
108                 *pos = ring->w_alloc_ptr;
109 
110                 ring->w_alloc_ptr = (ring->w_alloc_ptr + ret) % ring->w_nr;
111                 ring->w_alloc_ctr += ret;
112         }
113 
114         return ret;
115 }
116 
117 void rds_ib_ring_free(struct rds_ib_work_ring *ring, u32 val)
118 {
119         ring->w_free_ptr = (ring->w_free_ptr + val) % ring->w_nr;
120         atomic_add(val, &ring->w_free_ctr);
121 
122         if (__rds_ib_ring_empty(ring) &&
123             waitqueue_active(&rds_ib_ring_empty_wait))
124                 wake_up(&rds_ib_ring_empty_wait);
125 }
126 
127 void rds_ib_ring_unalloc(struct rds_ib_work_ring *ring, u32 val)
128 {
129         ring->w_alloc_ptr = (ring->w_alloc_ptr - val) % ring->w_nr;
130         ring->w_alloc_ctr -= val;
131 }
132 
133 int rds_ib_ring_empty(struct rds_ib_work_ring *ring)
134 {
135         return __rds_ib_ring_empty(ring);
136 }
137 
138 int rds_ib_ring_low(struct rds_ib_work_ring *ring)
139 {
140         return __rds_ib_ring_used(ring) <= (ring->w_nr >> 1);
141 }
142 
143 /*
144  * returns the oldest allocated ring entry.  This will be the next one
145  * freed.  This can't be called if there are none allocated.
146  */
147 u32 rds_ib_ring_oldest(struct rds_ib_work_ring *ring)
148 {
149         return ring->w_free_ptr;
150 }
151 
152 /*
153  * returns the number of completed work requests.
154  */
155 
156 u32 rds_ib_ring_completed(struct rds_ib_work_ring *ring, u32 wr_id, u32 oldest)
157 {
158         u32 ret;
159 
160         if (oldest <= (unsigned long long)wr_id)
161                 ret = (unsigned long long)wr_id - oldest + 1;
162         else
163                 ret = ring->w_nr - oldest + (unsigned long long)wr_id + 1;
164 
165         rdsdebug("ring %p ret %u wr_id %u oldest %u\n", ring, ret,
166                  wr_id, oldest);
167         return ret;
168 }
169 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php