2 * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 static void sdp_nagle_timeout(void *data);
38 #ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA
39 void _dump_packet(const char *func, int line, struct socket *sk, char *str,
40 struct mbuf *mb, const struct sdp_bsdh *h)
44 struct sdp_chrecvbuf *req_size;
45 struct sdp_rrch *rrch;
46 struct sdp_srcah *srcah;
49 len += snprintf(buf, 255-len, "%s mb: %p mid: %2x:%-20s flags: 0x%x "
50 "bufs: 0x%x len: 0x%x mseq: 0x%x mseq_ack: 0x%x | ",
51 str, mb, h->mid, mid2str(h->mid), h->flags,
52 ntohs(h->bufs), ntohl(h->len), ntohl(h->mseq),
57 hh = (struct sdp_hh *)h;
58 len += snprintf(buf + len, 255-len,
59 "max_adverts: %d majv_minv: 0x%x "
60 "localrcvsz: 0x%x desremrcvsz: 0x%x |",
61 hh->max_adverts, hh->majv_minv,
62 ntohl(hh->localrcvsz),
63 ntohl(hh->desremrcvsz));
65 case SDP_MID_HELLO_ACK:
66 hah = (struct sdp_hah *)h;
67 len += snprintf(buf + len, 255-len, "actrcvz: 0x%x |",
68 ntohl(hah->actrcvsz));
70 case SDP_MID_CHRCVBUF:
71 case SDP_MID_CHRCVBUF_ACK:
72 req_size = (struct sdp_chrecvbuf *)(h+1);
73 len += snprintf(buf + len, 255-len, "req_size: 0x%x |",
74 ntohl(req_size->size));
77 len += snprintf(buf + len, 255-len, "data_len: 0x%lx |",
78 ntohl(h->len) - sizeof(struct sdp_bsdh));
80 case SDP_MID_RDMARDCOMPL:
81 rrch = (struct sdp_rrch *)(h+1);
83 len += snprintf(buf + len, 255-len, " | len: 0x%x |",
86 case SDP_MID_SRCAVAIL:
87 srcah = (struct sdp_srcah *)(h+1);
89 len += snprintf(buf + len, 255-len, " | payload: 0x%lx, "
90 "len: 0x%x, rkey: 0x%x, vaddr: 0x%jx |",
91 ntohl(h->len) - sizeof(struct sdp_bsdh) -
92 sizeof(struct sdp_srcah),
93 ntohl(srcah->len), ntohl(srcah->rkey),
94 be64_to_cpu(srcah->vaddr));
100 _sdp_printk(func, line, KERN_WARNING, sk, "%s: %s\n", str, buf);
105 sdp_nagle_off(struct sdp_sock *ssk, struct mbuf *mb)
110 h = mtod(mb, struct sdp_bsdh *);
115 unlikely(h->mid != SDP_MID_DATA) ||
116 (ssk->flags & SDP_NODELAY) ||
117 !ssk->nagle_last_unacked ||
118 mb->m_pkthdr.len >= ssk->xmit_size_goal / 4 ||
119 (mb->m_flags & M_PUSH);
122 unsigned long mseq = ring_head(ssk->tx_ring);
123 ssk->nagle_last_unacked = mseq;
125 if (!callout_pending(&ssk->nagle_timer)) {
126 callout_reset(&ssk->nagle_timer, SDP_NAGLE_TIMEOUT,
127 sdp_nagle_timeout, ssk);
128 sdp_dbg_data(ssk->socket, "Starting nagle timer\n");
131 sdp_dbg_data(ssk->socket, "send_now = %d last_unacked = %ld\n",
132 send_now, ssk->nagle_last_unacked);
138 sdp_nagle_timeout(void *data)
140 struct sdp_sock *ssk = (struct sdp_sock *)data;
141 struct socket *sk = ssk->socket;
143 sdp_dbg_data(sk, "last_unacked = %ld\n", ssk->nagle_last_unacked);
145 if (!callout_active(&ssk->nagle_timer))
147 callout_deactivate(&ssk->nagle_timer);
149 if (!ssk->nagle_last_unacked)
151 if (ssk->state == TCPS_CLOSED)
153 ssk->nagle_last_unacked = 0;
154 sdp_post_sends(ssk, M_NOWAIT);
156 sowwakeup(ssk->socket);
158 if (sk->so_snd.sb_sndptr)
159 callout_reset(&ssk->nagle_timer, SDP_NAGLE_TIMEOUT,
160 sdp_nagle_timeout, ssk);
164 sdp_post_sends(struct sdp_sock *ssk, int wait)
172 if (unlikely(!ssk->id)) {
173 if (sk->so_snd.sb_sndptr) {
175 "Send on socket without cmid ECONNRESET.\n");
176 sdp_notify(ssk, ECONNRESET);
181 if (sdp_tx_ring_slots_left(ssk) < SDP_TX_SIZE / 2)
182 sdp_xmit_poll(ssk, 1);
184 if (ssk->recv_request &&
185 ring_tail(ssk->rx_ring) >= ssk->recv_request_head &&
186 tx_credits(ssk) >= SDP_MIN_TX_CREDITS &&
187 sdp_tx_ring_slots_left(ssk)) {
188 mb = sdp_alloc_mb_chrcvbuf_ack(sk,
189 ssk->recv_bytes - SDP_HEAD_SIZE, wait);
192 ssk->recv_request = 0;
193 sdp_post_send(ssk, mb);
197 if (tx_credits(ssk) <= SDP_MIN_TX_CREDITS &&
198 sdp_tx_ring_slots_left(ssk) && sk->so_snd.sb_sndptr &&
199 sdp_nagle_off(ssk, sk->so_snd.sb_sndptr)) {
200 SDPSTATS_COUNTER_INC(send_miss_no_credits);
203 while (tx_credits(ssk) > SDP_MIN_TX_CREDITS &&
204 sdp_tx_ring_slots_left(ssk) && (mb = sk->so_snd.sb_sndptr) &&
205 sdp_nagle_off(ssk, mb)) {
208 SOCKBUF_LOCK(&sk->so_snd);
209 sk->so_snd.sb_sndptr = mb->m_nextpkt;
210 sk->so_snd.sb_mb = mb->m_nextpkt;
211 mb->m_nextpkt = NULL;
212 SB_EMPTY_FIXUP(&sk->so_snd);
213 for (n = mb; n != NULL; n = n->m_next)
214 sbfree(&sk->so_snd, n);
215 SOCKBUF_UNLOCK(&sk->so_snd);
216 sdp_post_send(ssk, mb);
220 if (credit_update_needed(ssk) && ssk->state >= TCPS_ESTABLISHED &&
221 ssk->state < TCPS_FIN_WAIT_2) {
222 mb = sdp_alloc_mb_data(ssk->socket, wait);
225 sdp_post_send(ssk, mb);
227 SDPSTATS_COUNTER_INC(post_send_credits);
231 /* send DisConn if needed
232 * Do not send DisConn if there is only 1 credit. Compliance with CA4-82
233 * If one credit is available, an implementation shall only send SDP
234 * messages that provide additional credits and also do not contain ULP
236 if ((ssk->flags & SDP_NEEDFIN) && !sk->so_snd.sb_sndptr &&
237 tx_credits(ssk) > 1) {
238 mb = sdp_alloc_mb_disconnect(sk, wait);
241 ssk->flags &= ~SDP_NEEDFIN;
242 sdp_post_send(ssk, mb);
245 low = (sdp_tx_ring_slots_left(ssk) <= SDP_MIN_TX_CREDITS);
246 if (post_count || low) {
249 if (sdp_xmit_poll(ssk, low))
255 ssk->nagle_last_unacked = -1;
256 callout_reset(&ssk->nagle_timer, 1, sdp_nagle_timeout, ssk);