0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/kernel.h>
0034
0035 #include "rds.h"
0036 #include "ib.h"
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 DECLARE_WAIT_QUEUE_HEAD(rds_ib_ring_empty_wait);
0065
0066 void rds_ib_ring_init(struct rds_ib_work_ring *ring, u32 nr)
0067 {
0068 memset(ring, 0, sizeof(*ring));
0069 ring->w_nr = nr;
0070 rdsdebug("ring %p nr %u\n", ring, ring->w_nr);
0071 }
0072
0073 static inline u32 __rds_ib_ring_used(struct rds_ib_work_ring *ring)
0074 {
0075 u32 diff;
0076
0077
0078 diff = ring->w_alloc_ctr - (u32) atomic_read(&ring->w_free_ctr);
0079 BUG_ON(diff > ring->w_nr);
0080
0081 return diff;
0082 }
0083
0084 void rds_ib_ring_resize(struct rds_ib_work_ring *ring, u32 nr)
0085 {
0086
0087
0088 BUG_ON(__rds_ib_ring_used(ring));
0089 ring->w_nr = nr;
0090 }
0091
0092 static int __rds_ib_ring_empty(struct rds_ib_work_ring *ring)
0093 {
0094 return __rds_ib_ring_used(ring) == 0;
0095 }
0096
0097 u32 rds_ib_ring_alloc(struct rds_ib_work_ring *ring, u32 val, u32 *pos)
0098 {
0099 u32 ret = 0, avail;
0100
0101 avail = ring->w_nr - __rds_ib_ring_used(ring);
0102
0103 rdsdebug("ring %p val %u next %u free %u\n", ring, val,
0104 ring->w_alloc_ptr, avail);
0105
0106 if (val && avail) {
0107 ret = min(val, avail);
0108 *pos = ring->w_alloc_ptr;
0109
0110 ring->w_alloc_ptr = (ring->w_alloc_ptr + ret) % ring->w_nr;
0111 ring->w_alloc_ctr += ret;
0112 }
0113
0114 return ret;
0115 }
0116
0117 void rds_ib_ring_free(struct rds_ib_work_ring *ring, u32 val)
0118 {
0119 ring->w_free_ptr = (ring->w_free_ptr + val) % ring->w_nr;
0120 atomic_add(val, &ring->w_free_ctr);
0121
0122 if (__rds_ib_ring_empty(ring) &&
0123 waitqueue_active(&rds_ib_ring_empty_wait))
0124 wake_up(&rds_ib_ring_empty_wait);
0125 }
0126
0127 void rds_ib_ring_unalloc(struct rds_ib_work_ring *ring, u32 val)
0128 {
0129 ring->w_alloc_ptr = (ring->w_alloc_ptr - val) % ring->w_nr;
0130 ring->w_alloc_ctr -= val;
0131 }
0132
0133 int rds_ib_ring_empty(struct rds_ib_work_ring *ring)
0134 {
0135 return __rds_ib_ring_empty(ring);
0136 }
0137
0138 int rds_ib_ring_low(struct rds_ib_work_ring *ring)
0139 {
0140 return __rds_ib_ring_used(ring) <= (ring->w_nr >> 1);
0141 }
0142
0143
0144
0145
0146
0147 u32 rds_ib_ring_oldest(struct rds_ib_work_ring *ring)
0148 {
0149 return ring->w_free_ptr;
0150 }
0151
0152
0153
0154
0155
0156 u32 rds_ib_ring_completed(struct rds_ib_work_ring *ring, u32 wr_id, u32 oldest)
0157 {
0158 u32 ret;
0159
0160 if (oldest <= (unsigned long long)wr_id)
0161 ret = (unsigned long long)wr_id - oldest + 1;
0162 else
0163 ret = ring->w_nr - oldest + (unsigned long long)wr_id + 1;
0164
0165 rdsdebug("ring %p ret %u wr_id %u oldest %u\n", ring, ret,
0166 wr_id, oldest);
0167 return ret;
0168 }