The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ofed/drivers/infiniband/ulp/sdp/sdp_bcopy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * Copyright (c) 2006 Mellanox Technologies Ltd.  All rights reserved.
    5  *
    6  * This software is available to you under a choice of one of two
    7  * licenses.  You may choose to be licensed under the terms of the GNU
    8  * General Public License (GPL) Version 2, available from the file
    9  * COPYING in the main directory of this source tree, or the
   10  * OpenIB.org BSD license below:
   11  *
   12  *     Redistribution and use in source and binary forms, with or
   13  *     without modification, are permitted provided that the following
   14  *     conditions are met:
   15  *
   16  *      - Redistributions of source code must retain the above
   17  *        copyright notice, this list of conditions and the following
   18  *        disclaimer.
   19  *
   20  *      - Redistributions in binary form must reproduce the above
   21  *        copyright notice, this list of conditions and the following
   22  *        disclaimer in the documentation and/or other materials
   23  *        provided with the distribution.
   24  *
   25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   32  * SOFTWARE.
   33  *
   34  * $Id$
   35  */
   36 #include "sdp.h"
   37 
   38 static void sdp_nagle_timeout(void *data);
   39 
   40 #ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA
   41 void _dump_packet(const char *func, int line, struct socket *sk, char *str,
   42                 struct mbuf *mb, const struct sdp_bsdh *h)
   43 {
   44         struct sdp_hh *hh;
   45         struct sdp_hah *hah;
   46         struct sdp_chrecvbuf *req_size;
   47         struct sdp_rrch *rrch;
   48         struct sdp_srcah *srcah;
   49         int len = 0;
   50         char buf[256];
   51         len += snprintf(buf, 255-len, "%s mb: %p mid: %2x:%-20s flags: 0x%x "
   52                         "bufs: 0x%x len: 0x%x mseq: 0x%x mseq_ack: 0x%x | ",
   53                         str, mb, h->mid, mid2str(h->mid), h->flags,
   54                         ntohs(h->bufs), ntohl(h->len), ntohl(h->mseq),
   55                         ntohl(h->mseq_ack));
   56 
   57         switch (h->mid) {
   58         case SDP_MID_HELLO:
   59                 hh = (struct sdp_hh *)h;
   60                 len += snprintf(buf + len, 255-len,
   61                                 "max_adverts: %d  majv_minv: 0x%x "
   62                                 "localrcvsz: 0x%x desremrcvsz: 0x%x |",
   63                                 hh->max_adverts, hh->majv_minv,
   64                                 ntohl(hh->localrcvsz),
   65                                 ntohl(hh->desremrcvsz));
   66                 break;
   67         case SDP_MID_HELLO_ACK:
   68                 hah = (struct sdp_hah *)h;
   69                 len += snprintf(buf + len, 255-len, "actrcvz: 0x%x |",
   70                                 ntohl(hah->actrcvsz));
   71                 break;
   72         case SDP_MID_CHRCVBUF:
   73         case SDP_MID_CHRCVBUF_ACK:
   74                 req_size = (struct sdp_chrecvbuf *)(h+1);
   75                 len += snprintf(buf + len, 255-len, "req_size: 0x%x |",
   76                                 ntohl(req_size->size));
   77                 break;
   78         case SDP_MID_DATA:
   79                 len += snprintf(buf + len, 255-len, "data_len: 0x%lx |",
   80                         ntohl(h->len) - sizeof(struct sdp_bsdh));
   81                 break;
   82         case SDP_MID_RDMARDCOMPL:
   83                 rrch = (struct sdp_rrch *)(h+1);
   84 
   85                 len += snprintf(buf + len, 255-len, " | len: 0x%x |",
   86                                 ntohl(rrch->len));
   87                 break;
   88         case SDP_MID_SRCAVAIL:
   89                 srcah = (struct sdp_srcah *)(h+1);
   90 
   91                 len += snprintf(buf + len, 255-len, " | payload: 0x%lx, "
   92                                 "len: 0x%x, rkey: 0x%x, vaddr: 0x%jx |",
   93                                 ntohl(h->len) - sizeof(struct sdp_bsdh) - 
   94                                 sizeof(struct sdp_srcah),
   95                                 ntohl(srcah->len), ntohl(srcah->rkey),
   96                                 be64_to_cpu(srcah->vaddr));
   97                 break;
   98         default:
   99                 break;
  100         }
  101         buf[len] = 0;
  102         _sdp_printk(func, line, KERN_WARNING, sk, "%s: %s\n", str, buf);
  103 }
  104 #endif
  105 
  106 static inline int
  107 sdp_nagle_off(struct sdp_sock *ssk, struct mbuf *mb)
  108 {
  109 
  110         struct sdp_bsdh *h;
  111 
  112         h = mtod(mb, struct sdp_bsdh *);
  113         int send_now =
  114 #ifdef SDP_ZCOPY
  115                 BZCOPY_STATE(mb) ||
  116 #endif
  117                 unlikely(h->mid != SDP_MID_DATA) ||
  118                 (ssk->flags & SDP_NODELAY) ||
  119                 !ssk->nagle_last_unacked ||
  120                 mb->m_pkthdr.len >= ssk->xmit_size_goal / 4 ||
  121                 (mb->m_flags & M_PUSH);
  122 
  123         if (send_now) {
  124                 unsigned long mseq = ring_head(ssk->tx_ring);
  125                 ssk->nagle_last_unacked = mseq;
  126         } else {
  127                 if (!callout_pending(&ssk->nagle_timer)) {
  128                         callout_reset(&ssk->nagle_timer, SDP_NAGLE_TIMEOUT,
  129                             sdp_nagle_timeout, ssk);
  130                         sdp_dbg_data(ssk->socket, "Starting nagle timer\n");
  131                 }
  132         }
  133         sdp_dbg_data(ssk->socket, "send_now = %d last_unacked = %ld\n",
  134                 send_now, ssk->nagle_last_unacked);
  135 
  136         return send_now;
  137 }
  138 
  139 static void
  140 sdp_nagle_timeout(void *data)
  141 {
  142         struct sdp_sock *ssk = (struct sdp_sock *)data;
  143         struct socket *sk = ssk->socket;
  144 
  145         sdp_dbg_data(sk, "last_unacked = %ld\n", ssk->nagle_last_unacked);
  146 
  147         if (!callout_active(&ssk->nagle_timer))
  148                 return;
  149         callout_deactivate(&ssk->nagle_timer);
  150 
  151         if (!ssk->nagle_last_unacked)
  152                 goto out;
  153         if (ssk->state == TCPS_CLOSED)
  154                 return;
  155         ssk->nagle_last_unacked = 0;
  156         sdp_post_sends(ssk, M_NOWAIT);
  157 
  158         sowwakeup(ssk->socket);
  159 out:
  160         if (sk->so_snd.sb_sndptr)
  161                 callout_reset(&ssk->nagle_timer, SDP_NAGLE_TIMEOUT,
  162                     sdp_nagle_timeout, ssk);
  163 }
  164 
  165 void
  166 sdp_post_sends(struct sdp_sock *ssk, int wait)
  167 {
  168         struct mbuf *mb;
  169         int post_count = 0;
  170         struct socket *sk;
  171         int low;
  172 
  173         sk = ssk->socket;
  174         if (unlikely(!ssk->id)) {
  175                 if (sk->so_snd.sb_sndptr) {
  176                         sdp_dbg(ssk->socket,
  177                                 "Send on socket without cmid ECONNRESET.\n");
  178                         sdp_notify(ssk, ECONNRESET);
  179                 }
  180                 return;
  181         }
  182 again:
  183         if (sdp_tx_ring_slots_left(ssk) < SDP_TX_SIZE / 2)
  184                 sdp_xmit_poll(ssk,  1);
  185 
  186         if (ssk->recv_request &&
  187             ring_tail(ssk->rx_ring) >= ssk->recv_request_head &&
  188             tx_credits(ssk) >= SDP_MIN_TX_CREDITS &&
  189             sdp_tx_ring_slots_left(ssk)) {
  190                 mb = sdp_alloc_mb_chrcvbuf_ack(sk,
  191                     ssk->recv_bytes - SDP_HEAD_SIZE, wait);
  192                 if (mb == NULL)
  193                         goto allocfail;
  194                 ssk->recv_request = 0;
  195                 sdp_post_send(ssk, mb);
  196                 post_count++;
  197         }
  198 
  199         if (tx_credits(ssk) <= SDP_MIN_TX_CREDITS &&
  200             sdp_tx_ring_slots_left(ssk) && sk->so_snd.sb_sndptr &&
  201             sdp_nagle_off(ssk, sk->so_snd.sb_sndptr)) {
  202                 SDPSTATS_COUNTER_INC(send_miss_no_credits);
  203         }
  204 
  205         while (tx_credits(ssk) > SDP_MIN_TX_CREDITS &&
  206             sdp_tx_ring_slots_left(ssk) && (mb = sk->so_snd.sb_sndptr) &&
  207             sdp_nagle_off(ssk, mb)) {
  208                 struct mbuf *n;
  209 
  210                 SOCKBUF_LOCK(&sk->so_snd);
  211                 sk->so_snd.sb_sndptr = mb->m_nextpkt;
  212                 sk->so_snd.sb_mb = mb->m_nextpkt;
  213                 mb->m_nextpkt = NULL;
  214                 SB_EMPTY_FIXUP(&sk->so_snd);
  215                 for (n = mb; n != NULL; n = n->m_next)
  216                         sbfree(&sk->so_snd, n);
  217                 SOCKBUF_UNLOCK(&sk->so_snd);
  218                 sdp_post_send(ssk, mb);
  219                 post_count++;
  220         }
  221 
  222         if (credit_update_needed(ssk) && ssk->state >= TCPS_ESTABLISHED &&
  223             ssk->state < TCPS_FIN_WAIT_2) {
  224                 mb = sdp_alloc_mb_data(ssk->socket, wait);
  225                 if (mb == NULL)
  226                         goto allocfail;
  227                 sdp_post_send(ssk, mb);
  228 
  229                 SDPSTATS_COUNTER_INC(post_send_credits);
  230                 post_count++;
  231         }
  232 
  233         /* send DisConn if needed
  234          * Do not send DisConn if there is only 1 credit. Compliance with CA4-82
  235          * If one credit is available, an implementation shall only send SDP
  236          * messages that provide additional credits and also do not contain ULP
  237          * payload. */
  238         if ((ssk->flags & SDP_NEEDFIN) && !sk->so_snd.sb_sndptr &&
  239             tx_credits(ssk) > 1) {
  240                 mb = sdp_alloc_mb_disconnect(sk, wait);
  241                 if (mb == NULL)
  242                         goto allocfail;
  243                 ssk->flags &= ~SDP_NEEDFIN;
  244                 sdp_post_send(ssk, mb);
  245                 post_count++;
  246         }
  247         low = (sdp_tx_ring_slots_left(ssk) <= SDP_MIN_TX_CREDITS);
  248         if (post_count || low) {
  249                 if (low)
  250                         sdp_arm_tx_cq(ssk);
  251                 if (sdp_xmit_poll(ssk, low))
  252                         goto again;
  253         }
  254         return;
  255 
  256 allocfail:
  257         ssk->nagle_last_unacked = -1;
  258         callout_reset(&ssk->nagle_timer, 1, sdp_nagle_timeout, ssk);
  259         return;
  260 }

Cache object: e025cd24d60ce876538e926c662afe5d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.