Beispiel #1
0
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;
}