1*2bfe3f2eSlogwang /*- 2*2bfe3f2eSlogwang * BSD LICENSE 3*2bfe3f2eSlogwang * 4*2bfe3f2eSlogwang * Copyright(c) 2017 Intel Corporation. All rights reserved. 5*2bfe3f2eSlogwang * 6*2bfe3f2eSlogwang * Redistribution and use in source and binary forms, with or without 7*2bfe3f2eSlogwang * modification, are permitted provided that the following conditions 8*2bfe3f2eSlogwang * are met: 9*2bfe3f2eSlogwang * 10*2bfe3f2eSlogwang * * Redistributions of source code must retain the above copyright 11*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer. 12*2bfe3f2eSlogwang * * Redistributions in binary form must reproduce the above copyright 13*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer in 14*2bfe3f2eSlogwang * the documentation and/or other materials provided with the 15*2bfe3f2eSlogwang * distribution. 16*2bfe3f2eSlogwang * * Neither the name of Intel Corporation nor the names of its 17*2bfe3f2eSlogwang * contributors may be used to endorse or promote products derived 18*2bfe3f2eSlogwang * from this software without specific prior written permission. 19*2bfe3f2eSlogwang * 20*2bfe3f2eSlogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*2bfe3f2eSlogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*2bfe3f2eSlogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23*2bfe3f2eSlogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24*2bfe3f2eSlogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25*2bfe3f2eSlogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26*2bfe3f2eSlogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27*2bfe3f2eSlogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28*2bfe3f2eSlogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29*2bfe3f2eSlogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30*2bfe3f2eSlogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31*2bfe3f2eSlogwang */ 32*2bfe3f2eSlogwang 33*2bfe3f2eSlogwang #include <sys/queue.h> 34*2bfe3f2eSlogwang #include <string.h> 35*2bfe3f2eSlogwang 36*2bfe3f2eSlogwang #include <rte_tailq.h> 37*2bfe3f2eSlogwang #include <rte_memzone.h> 38*2bfe3f2eSlogwang #include <rte_rwlock.h> 39*2bfe3f2eSlogwang #include <rte_eal_memconfig.h> 40*2bfe3f2eSlogwang #include "rte_event_ring.h" 41*2bfe3f2eSlogwang 42*2bfe3f2eSlogwang TAILQ_HEAD(rte_event_ring_list, rte_tailq_entry); 43*2bfe3f2eSlogwang 44*2bfe3f2eSlogwang static struct rte_tailq_elem rte_event_ring_tailq = { 45*2bfe3f2eSlogwang .name = RTE_TAILQ_EVENT_RING_NAME, 46*2bfe3f2eSlogwang }; 47*2bfe3f2eSlogwang EAL_REGISTER_TAILQ(rte_event_ring_tailq) 48*2bfe3f2eSlogwang 49*2bfe3f2eSlogwang int 50*2bfe3f2eSlogwang rte_event_ring_init(struct rte_event_ring *r, const char *name, 51*2bfe3f2eSlogwang unsigned int count, unsigned int flags) 52*2bfe3f2eSlogwang { 53*2bfe3f2eSlogwang /* compilation-time checks */ 54*2bfe3f2eSlogwang RTE_BUILD_BUG_ON((sizeof(struct rte_event_ring) & 55*2bfe3f2eSlogwang RTE_CACHE_LINE_MASK) != 0); 56*2bfe3f2eSlogwang 57*2bfe3f2eSlogwang /* init the ring structure */ 58*2bfe3f2eSlogwang return rte_ring_init(&r->r, name, count, flags); 59*2bfe3f2eSlogwang } 60*2bfe3f2eSlogwang 61*2bfe3f2eSlogwang /* create the ring */ 62*2bfe3f2eSlogwang struct rte_event_ring * 63*2bfe3f2eSlogwang rte_event_ring_create(const char *name, unsigned int count, int socket_id, 64*2bfe3f2eSlogwang unsigned int flags) 65*2bfe3f2eSlogwang { 66*2bfe3f2eSlogwang char mz_name[RTE_MEMZONE_NAMESIZE]; 67*2bfe3f2eSlogwang struct rte_event_ring *r; 68*2bfe3f2eSlogwang struct rte_tailq_entry *te; 69*2bfe3f2eSlogwang const struct rte_memzone *mz; 70*2bfe3f2eSlogwang ssize_t ring_size; 71*2bfe3f2eSlogwang int mz_flags = 0; 72*2bfe3f2eSlogwang struct rte_event_ring_list *ring_list = NULL; 73*2bfe3f2eSlogwang const unsigned int requested_count = count; 74*2bfe3f2eSlogwang int ret; 75*2bfe3f2eSlogwang 76*2bfe3f2eSlogwang ring_list = RTE_TAILQ_CAST(rte_event_ring_tailq.head, 77*2bfe3f2eSlogwang rte_event_ring_list); 78*2bfe3f2eSlogwang 79*2bfe3f2eSlogwang /* for an exact size ring, round up from count to a power of two */ 80*2bfe3f2eSlogwang if (flags & RING_F_EXACT_SZ) 81*2bfe3f2eSlogwang count = rte_align32pow2(count + 1); 82*2bfe3f2eSlogwang else if (!rte_is_power_of_2(count)) { 83*2bfe3f2eSlogwang rte_errno = EINVAL; 84*2bfe3f2eSlogwang return NULL; 85*2bfe3f2eSlogwang } 86*2bfe3f2eSlogwang 87*2bfe3f2eSlogwang ring_size = sizeof(*r) + (count * sizeof(struct rte_event)); 88*2bfe3f2eSlogwang 89*2bfe3f2eSlogwang ret = snprintf(mz_name, sizeof(mz_name), "%s%s", 90*2bfe3f2eSlogwang RTE_RING_MZ_PREFIX, name); 91*2bfe3f2eSlogwang if (ret < 0 || ret >= (int)sizeof(mz_name)) { 92*2bfe3f2eSlogwang rte_errno = ENAMETOOLONG; 93*2bfe3f2eSlogwang return NULL; 94*2bfe3f2eSlogwang } 95*2bfe3f2eSlogwang 96*2bfe3f2eSlogwang te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0); 97*2bfe3f2eSlogwang if (te == NULL) { 98*2bfe3f2eSlogwang RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n"); 99*2bfe3f2eSlogwang rte_errno = ENOMEM; 100*2bfe3f2eSlogwang return NULL; 101*2bfe3f2eSlogwang } 102*2bfe3f2eSlogwang 103*2bfe3f2eSlogwang rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); 104*2bfe3f2eSlogwang 105*2bfe3f2eSlogwang /* 106*2bfe3f2eSlogwang * reserve a memory zone for this ring. If we can't get rte_config or 107*2bfe3f2eSlogwang * we are secondary process, the memzone_reserve function will set 108*2bfe3f2eSlogwang * rte_errno for us appropriately - hence no check in this this function 109*2bfe3f2eSlogwang */ 110*2bfe3f2eSlogwang mz = rte_memzone_reserve(mz_name, ring_size, socket_id, mz_flags); 111*2bfe3f2eSlogwang if (mz != NULL) { 112*2bfe3f2eSlogwang r = mz->addr; 113*2bfe3f2eSlogwang /* 114*2bfe3f2eSlogwang * no need to check return value here, we already checked the 115*2bfe3f2eSlogwang * arguments above 116*2bfe3f2eSlogwang */ 117*2bfe3f2eSlogwang rte_event_ring_init(r, name, requested_count, flags); 118*2bfe3f2eSlogwang 119*2bfe3f2eSlogwang te->data = (void *) r; 120*2bfe3f2eSlogwang r->r.memzone = mz; 121*2bfe3f2eSlogwang 122*2bfe3f2eSlogwang TAILQ_INSERT_TAIL(ring_list, te, next); 123*2bfe3f2eSlogwang } else { 124*2bfe3f2eSlogwang r = NULL; 125*2bfe3f2eSlogwang RTE_LOG(ERR, RING, "Cannot reserve memory\n"); 126*2bfe3f2eSlogwang rte_free(te); 127*2bfe3f2eSlogwang } 128*2bfe3f2eSlogwang rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); 129*2bfe3f2eSlogwang 130*2bfe3f2eSlogwang return r; 131*2bfe3f2eSlogwang } 132*2bfe3f2eSlogwang 133*2bfe3f2eSlogwang 134*2bfe3f2eSlogwang struct rte_event_ring * 135*2bfe3f2eSlogwang rte_event_ring_lookup(const char *name) 136*2bfe3f2eSlogwang { 137*2bfe3f2eSlogwang struct rte_tailq_entry *te; 138*2bfe3f2eSlogwang struct rte_event_ring *r = NULL; 139*2bfe3f2eSlogwang struct rte_event_ring_list *ring_list; 140*2bfe3f2eSlogwang 141*2bfe3f2eSlogwang ring_list = RTE_TAILQ_CAST(rte_event_ring_tailq.head, 142*2bfe3f2eSlogwang rte_event_ring_list); 143*2bfe3f2eSlogwang 144*2bfe3f2eSlogwang rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); 145*2bfe3f2eSlogwang 146*2bfe3f2eSlogwang TAILQ_FOREACH(te, ring_list, next) { 147*2bfe3f2eSlogwang r = (struct rte_event_ring *) te->data; 148*2bfe3f2eSlogwang if (strncmp(name, r->r.name, RTE_RING_NAMESIZE) == 0) 149*2bfe3f2eSlogwang break; 150*2bfe3f2eSlogwang } 151*2bfe3f2eSlogwang 152*2bfe3f2eSlogwang rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); 153*2bfe3f2eSlogwang 154*2bfe3f2eSlogwang if (te == NULL) { 155*2bfe3f2eSlogwang rte_errno = ENOENT; 156*2bfe3f2eSlogwang return NULL; 157*2bfe3f2eSlogwang } 158*2bfe3f2eSlogwang 159*2bfe3f2eSlogwang return r; 160*2bfe3f2eSlogwang } 161*2bfe3f2eSlogwang 162*2bfe3f2eSlogwang /* free the ring */ 163*2bfe3f2eSlogwang void 164*2bfe3f2eSlogwang rte_event_ring_free(struct rte_event_ring *r) 165*2bfe3f2eSlogwang { 166*2bfe3f2eSlogwang struct rte_event_ring_list *ring_list = NULL; 167*2bfe3f2eSlogwang struct rte_tailq_entry *te; 168*2bfe3f2eSlogwang 169*2bfe3f2eSlogwang if (r == NULL) 170*2bfe3f2eSlogwang return; 171*2bfe3f2eSlogwang 172*2bfe3f2eSlogwang /* 173*2bfe3f2eSlogwang * Ring was not created with rte_event_ring_create, 174*2bfe3f2eSlogwang * therefore, there is no memzone to free. 175*2bfe3f2eSlogwang */ 176*2bfe3f2eSlogwang if (r->r.memzone == NULL) { 177*2bfe3f2eSlogwang RTE_LOG(ERR, RING, 178*2bfe3f2eSlogwang "Cannot free ring (not created with rte_event_ring_create()"); 179*2bfe3f2eSlogwang return; 180*2bfe3f2eSlogwang } 181*2bfe3f2eSlogwang 182*2bfe3f2eSlogwang if (rte_memzone_free(r->r.memzone) != 0) { 183*2bfe3f2eSlogwang RTE_LOG(ERR, RING, "Cannot free memory\n"); 184*2bfe3f2eSlogwang return; 185*2bfe3f2eSlogwang } 186*2bfe3f2eSlogwang 187*2bfe3f2eSlogwang ring_list = RTE_TAILQ_CAST(rte_event_ring_tailq.head, 188*2bfe3f2eSlogwang rte_event_ring_list); 189*2bfe3f2eSlogwang rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); 190*2bfe3f2eSlogwang 191*2bfe3f2eSlogwang /* find out tailq entry */ 192*2bfe3f2eSlogwang TAILQ_FOREACH(te, ring_list, next) { 193*2bfe3f2eSlogwang if (te->data == (void *) r) 194*2bfe3f2eSlogwang break; 195*2bfe3f2eSlogwang } 196*2bfe3f2eSlogwang 197*2bfe3f2eSlogwang if (te == NULL) { 198*2bfe3f2eSlogwang rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); 199*2bfe3f2eSlogwang return; 200*2bfe3f2eSlogwang } 201*2bfe3f2eSlogwang 202*2bfe3f2eSlogwang TAILQ_REMOVE(ring_list, te, next); 203*2bfe3f2eSlogwang 204*2bfe3f2eSlogwang rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); 205*2bfe3f2eSlogwang 206*2bfe3f2eSlogwang rte_free(te); 207*2bfe3f2eSlogwang } 208