static int efab_tcp_helper_more_bufs_rsop(ci_private_t* priv, void *unused) { if (priv->thr == NULL) return -EINVAL; return efab_tcp_helper_more_bufs(priv->thr); }
int efab_eplock_unlock_and_wake(ci_netif *ni, int in_dl_context) { int l = ni->state->lock.lock; tcp_helper_resource_t *rs = netif2tcp_helper_resource(ni); /* Allocate more packets if necessary. */ if( !in_dl_context && OO_STACK_NEEDS_MORE_PACKETS(ni) ) efab_tcp_helper_more_bufs(rs); /* We use in_dl_context from now on, and we should remove * CI_NETIF_FLAG_IN_DL_CONTEXT under the stack lock. */ if( in_dl_context ) ni->flags &= ~CI_NETIF_FLAG_IN_DL_CONTEXT; again: #ifndef NDEBUG if( (~l & CI_EPLOCK_LOCKED) || (l & CI_EPLOCK_UNLOCKED) ) { OO_DEBUG_ERR(ci_log("efab_eplock_unlock_and_wake: corrupt" " (value is %x)", (unsigned) l)); OO_DEBUG_ERR(dump_stack()); return -EIO; } #endif if( l & CI_EPLOCK_CALLBACK_FLAGS ) { /* Invoke the callback while we've still got the lock. The callback ** is responsible for either ** - dropping the lock using ef_eplock_try_unlock(), and returning ** the lock value prior to unlocking, OR ** - keeping the eplock locked and returning CI_EPLOCK_LOCKED */ l = efab_tcp_helper_netif_lock_callback(&ni->eplock_helper, l, in_dl_context); } else if( ci_cas32_fail(&ni->state->lock.lock, l, CI_EPLOCK_UNLOCKED) ) { /* Someone (probably) set a flag when we tried to unlock, so we'd ** better handle the flag(s). */ l = ni->state->lock.lock; goto again; } if( l & CI_EPLOCK_FL_NEED_WAKE ) { CITP_STATS_NETIF_INC(ni, lock_wakes); wake_up_interruptible(&ni->eplock_helper.wq); } return 0; }