Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/ofed/drivers/infiniband/ulp/sdp/sdp_bcopy.c
39566 views
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
}
261
262