PERFORCE change 129611 for review
Kip Macy
kmacy at FreeBSD.org
Mon Nov 26 22:36:38 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=129611
Change 129611 by kmacy at kmacy:storage:toestack on 2007/11/27 06:36:32
make locking a bit more consistent
fix socket buffer accounting in t3_push_frames by only skipping the last buffer
if sndptroff is not zero
Affected files ...
.. //depot/projects/toestack/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c#27 edit
Differences ...
==== //depot/projects/toestack/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c#27 (text+ko) ====
@@ -170,10 +170,13 @@
send_or_defer(struct socket *so, struct tcpcb *tp, struct mbuf *m, int through_l2t)
{
struct toepcb *toep = tp->t_toe;
+
- if (__predict_false(tp->t_state == TCPS_SYN_SENT))
+ if (__predict_false(tp->t_state == TCPS_SYN_SENT)) {
+ INP_LOCK(tp->t_inpcb);
mbufq_tail(&toep->out_of_order_queue, m); // defer
- else if (through_l2t)
+ INP_UNLOCK(tp->t_inpcb);
+ } else if (through_l2t)
l2t_send(T3C_DEV(so), m, toep->tp_l2t); // send through L2T
else
cxgb_ofld_send(T3C_DEV(so), m); // send directly
@@ -207,11 +210,12 @@
struct toepcb *toep = tp->t_toe;
struct tx_data_wr *req;
+ INP_LOCK_ASSERT(tp->t_inpcb);
+
req = mtod(m, struct tx_data_wr *);
m->m_len = sizeof(*req);
req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
req->wr_lo = htonl(V_WR_TID(toep->tp_tid));
- req->sndseq = htonl(tp->snd_nxt);
/* len includes the length of any HW ULP additions */
req->len = htonl(len);
req->param = htonl(V_TX_PORT(toep->tp_l2t->smt_idx));
@@ -220,7 +224,7 @@
V_TX_URG(/* skb_urgent(skb) */ 0 ) |
V_TX_SHOVE((!(tp->t_flags & TF_MORETOCOME) &&
(tail ? 0 : 1))));
-
+ req->sndseq = htonl(tp->snd_nxt);
if (__predict_false((toep->tp_flags & TP_DATASENT) == 0)) {
req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
V_TX_CPU_IDX(toep->tp_qset));
@@ -259,16 +263,18 @@
return (0);
}
+ INP_LOCK_ASSERT(tp->t_inpcb);
+
SOCKBUF_LOCK(&so->so_snd);
d = TOM_DATA(TOE_DEV(so));
cdev = d->cdev;
last = tail = so->so_snd.sb_sndptr ? so->so_snd.sb_sndptr : so->so_snd.sb_mb;
total_bytes = 0;
- printf("tail=%p snd.cc=%d tp_last=%p\n", tail, so->so_snd.sb_cc,
- toep->tp_m_last);
+ DPRINTF("wr_avail=%d tail=%p snd.cc=%d tp_last=%p\n",
+ toep->tp_wr_avail, tail, so->so_snd.sb_cc, toep->tp_m_last);
- if (last && toep->tp_m_last == last) {
+ if (last && toep->tp_m_last == last && so->so_snd.sb_sndptroff != 0) {
KASSERT(tail, ("sbdrop error"));
last = tail = tail->m_next;
}
@@ -279,16 +285,15 @@
return (0);
}
+ toep->tp_m_last = NULL;
while (toep->tp_wr_avail && (tail != NULL)) {
-
-
count = bytes = 0;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) {
SOCKBUF_UNLOCK(&so->so_snd);
return (0);
}
-
- while ((mbuf_wrs[count + 1] <= toep->tp_wr_avail) && (tail != NULL) && (count < TX_MAX_SEGS)) {
+ while ((mbuf_wrs[count + 1] <= toep->tp_wr_avail)
+ && (tail != NULL) && (count < TX_MAX_SEGS)) {
bytes += tail->m_len;
count++;
last = tail;
@@ -360,8 +365,6 @@
return (total_bytes);
}
-
-
/*
* Close a connection by sending a CPL_CLOSE_CON_REQ message. Cannot fail
* under any circumstances. We take the easy way out and always queue the
@@ -475,6 +478,8 @@
if (!((tp->t_state == TCPS_ESTABLISHED) || (tp->t_state == TCPS_FIN_WAIT_1) ||
(tp->t_state == TCPS_FIN_WAIT_2)))
return;
+ INP_LOCK_ASSERT(tp->t_inpcb);
+
so = tp->t_inpcb->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
read = toep->tp_enqueued_bytes - so->so_rcv.sb_cc;
@@ -764,7 +769,7 @@
{
struct toepcb *toep = sototoep(so);
toepcb_hold(toep);
-
+
cxgb_insert_tid(d->cdev, d->client, toep, tid);
}
@@ -843,6 +848,7 @@
if (!cdev)
return;
+ INP_LOCK_ASSERT(tp->t_inpcb);
toep->tp_qset = 0;
t3_release_ddp_resources(so);
@@ -945,8 +951,9 @@
{
struct tcpcb *tp = sototcpcb(so);
struct t3c_data *td = T3C_DATA(TOM_DATA(dev)->cdev);
+
+ SOCK_LOCK_ASSERT(so);
-
printf("initializing offload socket\n");
so->so_rcv.sb_flags |= SB_TOE;
so->so_snd.sb_flags |= SB_TOE;
@@ -1070,7 +1077,8 @@
fail_act_open(struct socket *so, int errno)
{
struct tcpcb *tp = sototcpcb(so);
-
+
+ INP_LOCK_ASSERT(tp->t_inpcb);
t3_release_offload_resources(so);
tcp_drop(tp, errno);
@@ -1193,18 +1201,23 @@
e = t3_l2t_get(d->cdev, dst, egress_ifp);
if (!e)
goto free_tid;
-
+
+ INP_LOCK_ASSERT(inp);
m = m_gethdr(MT_DATA, M_WAITOK);
#if 0
m->m_toe.mt_toepcb = tp->t_toe;
set_arp_failure_handler((struct mbuf *)m, act_open_req_arp_failure);
-#endif
+#endif
+ SOCK_LOCK(so);
+
init_offload_socket(so, tdev, atid, e, dst, toep);
install_offload_ops(so);
mk_act_open_req(so, m, atid, e);
+ SOCK_UNLOCK(so);
+
soisconnecting(so);
toep = tp->t_toe;
m_set_toep(m, tp->t_toe);
@@ -1239,9 +1252,9 @@
int mode = CPL_ABORT_SEND_RST;
struct mbuf *m;
+ INP_LOCK_ASSERT(tp->t_inpcb);
if (__predict_false((toep->tp_flags & TP_ABORT_SHUTDOWN) || !TOE_DEV(so)))
return;
-
toep->tp_flags |= (TP_ABORT_RPL_PENDING|TP_ABORT_SHUTDOWN);
/* Purge the send queue so we don't send anything after an abort. */
@@ -1260,6 +1273,7 @@
req->rsvd0 = htonl(tp->snd_nxt);
req->rsvd1 = !(toep->tp_flags & TP_DATASENT);
req->cmd = mode;
+ INP_LOCK_ASSERT(tp->t_inpcb);
if (tp->t_state == TCPS_SYN_SENT)
mbufq_tail(&toep->out_of_order_queue, m); // defer
else
@@ -1440,21 +1454,7 @@
#endif
SOCKBUF_LOCK(&so->so_rcv);
if (sb_notify(&so->so_rcv))
- printf("rx_data so=%p flags=0x%x len=%d\n", so, so->so_rcv.sb_flags, m->m_pkthdr.len);
- if (m->m_pkthdr.len == 80) {
- int i;
- uint64_t *data;
-
- data = mtod(m, uint64_t *);
- printf("80 byte packet:\n");
- for (i = 0; i < 10; i++, data++) {
- uint8_t *dp = (uint8_t *)data;
-
- printf("%02x%02x%02x%02x%02x%02x%02x%02x\n",
- dp[0],dp[1],dp[2],dp[3],dp[4],dp[5],dp[6],dp[7]);
- }
- }
-
+ DPRINTF("rx_data so=%p flags=0x%x len=%d\n", so, so->so_rcv.sb_flags, m->m_pkthdr.len);
sbappendstream_locked(&so->so_rcv, m);
INP_UNLOCK(tp->t_inpcb);
@@ -1695,6 +1695,7 @@
{
struct tcpcb *tp = sototcpcb(so);
+ INP_LOCK_ASSERT(tp->t_inpcb);
/*
* Bump rcv_nxt for the peer FIN. We don't do this at the time we
* process peer_close because we don't want to carry the peer FIN in
@@ -1709,7 +1710,6 @@
tcp_twstart(tp);
}
-
/*
* Handle a peer FIN.
*/
@@ -1741,6 +1741,8 @@
sk->sk_shutdown |= RCV_SHUTDOWN;
sock_set_flag(so, SOCK_DONE);
#endif
+ INP_INFO_WLOCK(&tcbinfo);
+ INP_LOCK(tp->t_inpcb);
if (TCPS_HAVERCVDFIN(tp->t_state) == 0)
socantrcvmore(so);
switch (tp->t_state) {
@@ -1765,11 +1767,7 @@
*/
t3_release_offload_resources(so);
if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
- INP_INFO_WLOCK(&tcbinfo);
- INP_LOCK(tp->t_inpcb);
tcp_close(tp);
- INP_INFO_WUNLOCK(&tcbinfo);
- INP_UNLOCK(tp->t_inpcb);
} else
enter_timewait(so);
break;
@@ -1778,6 +1776,8 @@
"%s: TID %u received PEER_CLOSE in bad state %d\n",
TOE_DEV(so)->name, toep->tp_tid, tp->t_state);
}
+ INP_INFO_WUNLOCK(&tcbinfo);
+ INP_UNLOCK(tp->t_inpcb);
if (!dead) {
printf("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags);
@@ -1831,16 +1831,14 @@
if (!is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_ABORT_RPL_PENDING))
goto out;
+ INP_INFO_WLOCK(&tcbinfo);
+ INP_LOCK(inp);
switch (tp->t_state) {
case TCPS_CLOSING: /* see FIN_WAIT2 case in do_peer_fin */
t3_release_offload_resources(so);
if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
- INP_INFO_WLOCK(&tcbinfo);
- INP_LOCK(inp);
tp = tcp_close(tp);
- INP_INFO_WUNLOCK(&tcbinfo);
- if (tp)
- INP_UNLOCK(inp);
+
} else
enter_timewait(so);
break;
@@ -1851,13 +1849,7 @@
* late, this close_con_rpl is the actual last message.
*/
t3_release_offload_resources(so);
- INP_INFO_WLOCK(&tcbinfo);
- INP_LOCK(inp);
tp = tcp_close(tp);
- INP_INFO_WUNLOCK(&tcbinfo);
- if (tp)
- INP_UNLOCK(inp);
-
break;
case TCPS_FIN_WAIT_1:
#ifdef notyet
@@ -1885,6 +1877,9 @@
TOE_DEV(so)->name, toep->tp_tid,
tp->t_state);
}
+ INP_INFO_WUNLOCK(&tcbinfo);
+ if (tp)
+ INP_UNLOCK(inp);
out:
m_free(m);
}
@@ -1922,7 +1917,8 @@
"process_abort_rpl: GTS rpl pending %d",
sock_flag(sk, ABORT_RPL_PENDING));
#endif
-
+ INP_LOCK_ASSERT(tp->t_inpcb);
+
if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
if (!(toep->tp_flags & TP_ABORT_RPL_RCVD) && !is_t3a(TOE_DEV(so)))
toep->tp_flags |= TP_ABORT_RPL_RCVD;
@@ -1968,7 +1964,6 @@
}
toep = (struct toepcb *)ctx;
- so = toeptoso(toep);
/*
* Sometimes we've already closed the socket, e.g., a post-close
@@ -1977,9 +1972,10 @@
* but FW turns the ABORT_REQ into a regular one and so we get
* ABORT_RPL_RSS with status 0 and no socket. Only on T3A.
*/
- if (!so)
+ if (!toep)
goto discard;
+ so = toeptoso(toep);
toepcb_hold(toep);
process_abort_rpl(so, m);
toepcb_release(toep);
@@ -2161,7 +2157,8 @@
const struct cpl_abort_req_rss *req = cplhdr(m);
struct tcpcb *tp = sototcpcb(so);
struct toepcb *toep = tp->t_toe;
-
+
+ INP_LOCK_ASSERT(tp->t_inpcb);
if ((toep->tp_flags & TP_ABORT_REQ_RCVD) == 0) {
toep->tp_flags |= (TP_ABORT_REQ_RCVD|TP_ABORT_SHUTDOWN);
m_free(m);
@@ -2745,6 +2742,8 @@
const struct t3c_data *td = T3C_DATA(T3C_DEV(so));
struct tcpcb *tp = sototcpcb(so);
struct toepcb *toep = tp->t_toe;
+
+ INP_LOCK_ASSERT(tp->t_inpcb);
toep->tp_mss_clamp = td->mtus[G_TCPOPT_MSS(opt)] - 40;
tp->t_flags |= G_TCPOPT_TSTAMP(opt) ? TF_RCVD_TSTMP : 0;
@@ -2884,6 +2883,7 @@
}
tp = sototcpcb(so);
+ INP_LOCK(tp->t_inpcb);
so->so_snd.sb_flags |= SB_TOE;
so->so_rcv.sb_flags |= SB_TOE;
toep->tp_tp = tp;
@@ -2906,7 +2906,7 @@
make_established(so, ntohl(req->snd_isn), ntohs(req->tcp_opt));
INP_INFO_WUNLOCK(&tcbinfo);
-
+ INP_UNLOCK(tp->t_inpcb);
soisconnected(so);
#ifdef notyet
@@ -2954,6 +2954,7 @@
printf("fixup_and_send_ofo\n");
+ INP_LOCK_ASSERT(tp->t_inpcb);
while ((m = mbufq_dequeue(&toep->out_of_order_queue)) != NULL) {
/*
* A variety of messages can be waiting but the fields we'll
@@ -3192,9 +3193,7 @@
static void
t3_reset_listen_child(struct socket *child)
{
- SOCK_LOCK(child);
t3_send_reset(child);
- SOCK_UNLOCK(child);
}
/*
More information about the p4-projects
mailing list