summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2012-08-21 18:09:33 +0000
committernp <np@FreeBSD.org>2012-08-21 18:09:33 +0000
commit7a7bbaad5a88b5ee15bae1e36c3ff798c6c4b3f2 (patch)
tree9f814090f3bce843d8595af3bdf1348e87592883
parenta41fb634e4ef4b2df2c1bbec2f5f30d75a14084f (diff)
downloadFreeBSD-src-7a7bbaad5a88b5ee15bae1e36c3ff798c6c4b3f2.zip
FreeBSD-src-7a7bbaad5a88b5ee15bae1e36c3ff798c6c4b3f2.tar.gz
Correctly handle the case where an inp has already been dropped by the time
the TOE driver reports that an active open failed. toe_connect_failed is supposed to handle this but it should be provided the inpcb instead of the tcpcb which may no longer be around.
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c22
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c21
-rw-r--r--sys/netinet/toecore.c10
-rw-r--r--sys/netinet/toecore.h2
4 files changed, 25 insertions, 30 deletions
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
index 16b5394..49ad074 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
@@ -880,10 +880,10 @@ act_open_rpl_status_to_errno(int status)
case CPL_ERR_CONN_TIMEDOUT:
return (ETIMEDOUT);
case CPL_ERR_TCAM_FULL:
- return (ENOMEM);
+ return (EAGAIN);
case CPL_ERR_CONN_EXIST:
log(LOG_ERR, "ACTIVE_OPEN_RPL: 4-tuple in use\n");
- return (EADDRINUSE);
+ return (EAGAIN);
default:
return (EIO);
}
@@ -912,8 +912,7 @@ do_act_open_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
unsigned int atid = G_TID(ntohl(rpl->atid));
struct toepcb *toep = lookup_atid(&td->tid_maps, atid);
struct inpcb *inp = toep->tp_inp;
- struct tcpcb *tp = intotcpcb(inp);
- int s = rpl->status;
+ int s = rpl->status, rc;
CTR3(KTR_CXGB, "%s: atid %u, status %u ", __func__, atid, s);
@@ -923,17 +922,14 @@ do_act_open_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
if (act_open_has_tid(s))
queue_tid_release(tod, GET_TID(rpl));
- if (s == CPL_ERR_TCAM_FULL || s == CPL_ERR_CONN_EXIST) {
- INP_WLOCK(inp);
- toe_connect_failed(tod, tp, EAGAIN);
- toepcb_release(toep); /* unlocks inp */
- } else {
+ rc = act_open_rpl_status_to_errno(s);
+ if (rc != EAGAIN)
INP_INFO_WLOCK(&V_tcbinfo);
- INP_WLOCK(inp);
- toe_connect_failed(tod, tp, act_open_rpl_status_to_errno(s));
- toepcb_release(toep); /* unlocks inp */
+ INP_WLOCK(inp);
+ toe_connect_failed(tod, inp, rc);
+ toepcb_release(toep); /* unlocks inp */
+ if (rc != EAGAIN)
INP_INFO_WUNLOCK(&V_tcbinfo);
- }
m_freem(m);
return (0);
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index b48a971..1f46b44 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -167,10 +167,10 @@ act_open_rpl_status_to_errno(int status)
case CPL_ERR_CONN_TIMEDOUT:
return (ETIMEDOUT);
case CPL_ERR_TCAM_FULL:
- return (ENOMEM);
+ return (EAGAIN);
case CPL_ERR_CONN_EXIST:
log(LOG_ERR, "ACTIVE_OPEN_RPL: 4-tuple in use\n");
- return (EADDRINUSE);
+ return (EAGAIN);
default:
return (EIO);
}
@@ -186,8 +186,8 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
unsigned int status = G_AOPEN_STATUS(be32toh(cpl->atid_status));
struct toepcb *toep = lookup_atid(sc, atid);
struct inpcb *inp = toep->inp;
- struct tcpcb *tp = intotcpcb(inp);
struct toedev *tod = &toep->td->tod;
+ int rc;
KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
KASSERT(toep->tid == atid, ("%s: toep tid/atid mismatch", __func__));
@@ -204,17 +204,14 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
if (status && act_open_has_tid(status))
release_tid(sc, GET_TID(cpl), toep->ctrlq);
- if (status == CPL_ERR_TCAM_FULL) {
- INP_WLOCK(inp);
- toe_connect_failed(tod, tp, EAGAIN);
- final_cpl_received(toep); /* unlocks inp */
- } else {
+ rc = act_open_rpl_status_to_errno(status);
+ if (rc != EAGAIN)
INP_INFO_WLOCK(&V_tcbinfo);
- INP_WLOCK(inp);
- toe_connect_failed(tod, tp, act_open_rpl_status_to_errno(status));
- final_cpl_received(toep); /* unlocks inp */
+ INP_WLOCK(inp);
+ toe_connect_failed(tod, inp, rc);
+ final_cpl_received(toep); /* unlocks inp */
+ if (rc != EAGAIN)
INP_INFO_WUNLOCK(&V_tcbinfo);
- }
return (0);
}
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 4b4efb7..7e498dd 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -478,15 +478,17 @@ toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
}
void
-toe_connect_failed(struct toedev *tod, struct tcpcb *tp, int err)
+toe_connect_failed(struct toedev *tod, struct inpcb *inp, int err)
{
- struct inpcb *inp = tp->t_inpcb;
INP_WLOCK_ASSERT(inp);
- KASSERT(tp->t_flags & TF_TOE,
- ("%s: tp %p not offloaded.", __func__, tp));
if (!(inp->inp_flags & INP_DROPPED)) {
+ struct tcpcb *tp = intotcpcb(inp);
+
+ KASSERT(tp->t_flags & TF_TOE,
+ ("%s: tp %p not offloaded.", __func__, tp));
+
if (err == EAGAIN) {
/*
diff --git a/sys/netinet/toecore.h b/sys/netinet/toecore.h
index a381825..6ea9851 100644
--- a/sys/netinet/toecore.h
+++ b/sys/netinet/toecore.h
@@ -119,7 +119,7 @@ int unregister_toedev(struct toedev *);
int toe_l2_resolve(struct toedev *, struct ifnet *, struct sockaddr *,
uint8_t *, uint16_t *);
-void toe_connect_failed(struct toedev *, struct tcpcb *, int);
+void toe_connect_failed(struct toedev *, struct inpcb *, int);
void toe_syncache_add(struct in_conninfo *, struct tcpopt *, struct tcphdr *,
struct inpcb *, void *, void *);
OpenPOWER on IntegriCloud