summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgb/cxgb_lro.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cxgb/cxgb_lro.c')
-rw-r--r--sys/dev/cxgb/cxgb_lro.c123
1 files changed, 57 insertions, 66 deletions
diff --git a/sys/dev/cxgb/cxgb_lro.c b/sys/dev/cxgb/cxgb_lro.c
index c888291..22b4f73 100644
--- a/sys/dev/cxgb/cxgb_lro.c
+++ b/sys/dev/cxgb/cxgb_lro.c
@@ -65,22 +65,17 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef DEBUG
-#define MBUF_HEADER_CHECK(mh) do { \
- struct mbuf *head = mh->mh_head; \
- struct mbuf *tail = mh->mh_tail; \
- if (head->m_len == 0 || head->m_pkthdr.len == 0 \
- || (head->m_flags & M_PKTHDR) == 0) \
+#define MBUF_HEADER_CHECK(m) do { \
+ if (m->m_len == 0 || m->m_pkthdr.len == 0 \
+ || (m->m_flags & M_PKTHDR) == 0) \
panic("lro_flush_session - mbuf len=%d pktlen=%d flags=0x%x\n", \
- head->m_len, head->m_pkthdr.len, head->m_flags); \
- if ((head->m_flags & M_PKTHDR) == 0) \
+ m->m_len, m->m_pkthdr.len, m->m_flags); \
+ if (m->m_flags & M_PKTHDR) == 0) \
panic("first mbuf is not packet header - flags=0x%x\n", \
- head->m_flags); \
- if ((head == tail && head->m_len != head->m_pkthdr.len)) \
- panic("len=%d pktlen=%d mismatch\n", \
- head->m_len, head->m_pkthdr.len); \
- if (head->m_len < ETHER_HDR_LEN || head->m_pkthdr.len < ETHER_HDR_LEN) \
+ m->m_flags); \
+ if (m->m_len < ETHER_HDR_LEN || m->m_pkthdr.len < ETHER_HDR_LEN) \
panic("packet too small len=%d pktlen=%d\n", \
- head->m_len, head->m_pkthdr.len);\
+ m->m_len, m->m_pkthdr.len);\
} while (0)
#else
#define MBUF_HEADER_CHECK(m)
@@ -100,7 +95,7 @@ static __inline int
lro_match_session(struct sge_lro_session *s,
struct ip *ih, struct tcphdr *th)
{
- struct ip *sih = (struct ip *)(s->mh.mh_head->m_data + IPH_OFFSET);
+ struct ip *sih = (struct ip *)(s->m->m_data + IPH_OFFSET);
struct tcphdr *sth = (struct tcphdr *) (sih + 1);
/*
@@ -121,7 +116,7 @@ lro_find_session(struct sge_lro *l, int idx, struct ip *ih, struct tcphdr *th)
while (active < l->num_active) {
s = lro_session(l, idx);
- if (s->mh.mh_head) {
+ if (s->m) {
if (lro_match_session(s, ih, th)) {
l->last_s = s;
return s;
@@ -179,39 +174,37 @@ can_lro_tcpsegment(struct tcphdr *th)
}
static __inline void
-lro_new_session_init(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
+lro_new_session_init(struct sge_lro_session *s, struct mbuf *m)
{
- struct ip *ih = (struct ip *)(mh->mh_head->m_data + IPH_OFFSET);
+ struct ip *ih = (struct ip *)(m->m_data + IPH_OFFSET);
struct tcphdr *th = (struct tcphdr *) (ih + 1);
int ip_len = ntohs(ih->ip_len);
- DPRINTF("%s(s=%p, mh->mh_head=%p, mh->mh_tail=%p)\n", __FUNCTION__,
- s, mh->mh_head, mh->mh_tail);
+ DPRINTF("%s(s=%p, m=%p)\n", __FUNCTION__, s, m);
- *&(s->mh) = *mh;
-
- MBUF_HEADER_CHECK(mh);
+ s->m = m;
+
+ MBUF_HEADER_CHECK(m);
s->ip_len = ip_len;
s->seq = ntohl(th->th_seq) + ip_len - sizeof(*ih) - (th->th_off << 2);
}
static void
-lro_flush_session(struct sge_qset *qs, struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
+lro_flush_session(struct sge_qset *qs, struct sge_lro_session *s, struct mbuf *m)
{
struct sge_lro *l = &qs->lro;
- struct t3_mbuf_hdr *smh = &s->mh;
- struct ip *ih = (struct ip *)(smh->mh_head->m_data + IPH_OFFSET);
+ struct mbuf *sm = s->m;
+ struct ip *ih = (struct ip *)(sm->m_data + IPH_OFFSET);
DPRINTF("%s(qs=%p, s=%p, ", __FUNCTION__,
qs, s);
- if (mh)
- DPRINTF("mh->mh_head=%p, mh->mh_tail=%p)\n",
- mh->mh_head, mh->mh_tail);
+ if (m)
+ DPRINTF("m=%p)\n", m);
else
- DPRINTF("mh=NULL)\n");
+ DPRINTF("m=NULL)\n");
ih->ip_len = htons(s->ip_len);
ih->ip_sum = 0;
@@ -219,15 +212,14 @@ lro_flush_session(struct sge_qset *qs, struct sge_lro_session *s, struct t3_mbuf
MBUF_HEADER_CHECK(smh);
- smh->mh_head->m_flags |= M_LRO;
- t3_rx_eth(qs->port, &qs->rspq, smh->mh_head, 2);
+ sm->m_flags |= M_LRO;
+ t3_rx_eth(qs->port, &qs->rspq, sm, 2);
- if (mh) {
- *smh = *mh;
- lro_new_session_init(s, mh);
+ if (m) {
+ s->m = m;
+ lro_new_session_init(s, m);
} else {
- smh->mh_head = NULL;
- smh->mh_tail = NULL;
+ s->m = NULL;
l->num_active--;
}
@@ -235,23 +227,23 @@ lro_flush_session(struct sge_qset *qs, struct sge_lro_session *s, struct t3_mbuf
}
static __inline struct sge_lro_session *
-lro_new_session(struct sge_qset *qs, struct t3_mbuf_hdr *mh, uint32_t rss_hash)
+lro_new_session(struct sge_qset *qs, struct mbuf *m, uint32_t rss_hash)
{
struct sge_lro *l = &qs->lro;
int idx = LRO_SESSION_IDX_HINT_HASH(rss_hash);
struct sge_lro_session *s = lro_session(l, idx);
- DPRINTF("%s(qs=%p, mh->mh_head=%p, mh->mh_tail=%p, rss_hash=0x%x)\n", __FUNCTION__,
- qs, mh->mh_head, mh->mh_tail, rss_hash);
+ DPRINTF("%s(qs=%p, m=%p, rss_hash=0x%x)\n", __FUNCTION__,
+ qs, m, rss_hash);
- if (__predict_true(!s->mh.mh_head))
+ if (__predict_true(!s->m))
goto done;
if (l->num_active > MAX_LRO_PER_QSET)
panic("MAX_LRO_PER_QSET exceeded");
if (l->num_active == MAX_LRO_PER_QSET) {
- lro_flush_session(qs, s, mh);
+ lro_flush_session(qs, s, m);
qs->port_stats[SGE_PSTATS_LRO_X_STREAMS]++;
return s;
}
@@ -259,24 +251,21 @@ lro_new_session(struct sge_qset *qs, struct t3_mbuf_hdr *mh, uint32_t rss_hash)
while (1) {
LRO_IDX_INC(idx);
s = lro_session(l, idx);
- if (!s->mh.mh_head)
+ if (!s->m)
break;
}
done:
- lro_new_session_init(s, mh);
-
+ lro_new_session_init(s, m);
l->num_active++;
- return s;
-
+ return s;
}
static __inline int
-lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
+lro_update_session(struct sge_lro_session *s, struct mbuf *m)
{
- struct mbuf *m = mh->mh_head;
- struct t3_mbuf_hdr *smh = &s->mh;
- struct cpl_rx_pkt *cpl = (struct cpl_rx_pkt *)(smh->mh_head->m_data + 2);
+ struct mbuf *sm = s->m;
+ struct cpl_rx_pkt *cpl = (struct cpl_rx_pkt *)(sm->m_data + 2);
struct cpl_rx_pkt *ncpl = (struct cpl_rx_pkt *)(m->m_data + 2);
struct ip *nih = (struct ip *)(m->m_data + IPH_OFFSET);
struct tcphdr *th, *nth = (struct tcphdr *)(nih + 1);
@@ -284,8 +273,7 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
int plen, tcpiphlen, olen = (nth->th_off << 2) - sizeof (*nth);
- DPRINTF("%s(s=%p, mh->mh_head=%p, mh->mh_tail=%p)\n", __FUNCTION__,
- s, mh->mh_head, mh->mh_tail);
+ DPRINTF("%s(s=%p, m=%p)\n", __FUNCTION__, s, m);
if (cpl->vlan_valid && cpl->vlan != ncpl->vlan) {
return -1;
}
@@ -295,7 +283,7 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
}
MBUF_HEADER_CHECK(smh);
- th = (struct tcphdr *)(smh->mh_head->m_data + IPH_OFFSET + sizeof (struct ip));
+ th = (struct tcphdr *)(sm->m_data + IPH_OFFSET + sizeof (struct ip));
if (olen) {
uint32_t *ptr = (uint32_t *)(th + 1);
@@ -315,7 +303,13 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
plen = ntohs(nih->ip_len) - tcpiphlen;
s->seq += plen;
s->ip_len += plen;
- smh->mh_head->m_pkthdr.len += plen;
+ sm->m_pkthdr.len += plen;
+
+ /*
+ * XXX FIX ME
+ *
+ *
+ */
#if 0
/* XXX this I *do not* understand */
@@ -323,8 +317,8 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
skb_shinfo(s->skb)->gso_size = plen;
#endif
#if __FreeBSD_version > 700000
- if (plen > smh->mh_head->m_pkthdr.tso_segsz)
- smh->mh_head->m_pkthdr.tso_segsz = plen;
+ if (plen > sm->m_pkthdr.tso_segsz)
+ sm->m_pkthdr.tso_segsz = plen;
#endif
DPRINTF("m_adj(%d)\n", (int)(IPH_OFFSET + tcpiphlen));
m_adj(m, IPH_OFFSET + tcpiphlen);
@@ -333,9 +327,7 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
skb_shinfo(s->skb)->frag_list = skb;
#endif
- mh->mh_head->m_flags &= ~M_PKTHDR;
- smh->mh_tail->m_next = mh->mh_head;
- smh->mh_tail = mh->mh_tail;
+
#if 0
/*
@@ -354,10 +346,9 @@ lro_update_session(struct sge_lro_session *s, struct t3_mbuf_hdr *mh)
}
void
-t3_rx_eth_lro(adapter_t *adap, struct sge_rspq *rq, struct t3_mbuf_hdr *mh,
+t3_rx_eth_lro(adapter_t *adap, struct sge_rspq *rq, struct mbuf *m,
int ethpad, uint32_t rss_hash, uint32_t rss_csum, int lro)
{
- struct mbuf *m = mh->mh_head;
struct sge_qset *qs = rspq_to_qset(rq);
struct cpl_rx_pkt *cpl = (struct cpl_rx_pkt *)(m->m_data + ethpad);
struct ether_header *eh = (struct ether_header *)(cpl + 1);
@@ -384,12 +375,12 @@ t3_rx_eth_lro(adapter_t *adap, struct sge_rspq *rq, struct t3_mbuf_hdr *mh,
if (__predict_false(!can_lro_tcpsegment(th))) {
goto no_lro;
} else if (__predict_false(!s)) {
- s = lro_new_session(qs, mh, rss_hash);
+ s = lro_new_session(qs, m, rss_hash);
} else {
- if (lro_update_session(s, mh)) {
- lro_flush_session(qs, s, mh);
+ if (lro_update_session(s, m)) {
+ lro_flush_session(qs, s, m);
}
- if (__predict_false(s->mh.mh_head->m_pkthdr.len + pi->ifp->if_mtu > 65535)) {
+ if (__predict_false(s->m->m_pkthdr.len + pi->ifp->if_mtu > 65535)) {
lro_flush_session(qs, s, NULL);
}
}
@@ -417,7 +408,7 @@ t3_sge_lro_flush_all(adapter_t *adap, struct sge_qset *qs)
s = lro_session(l, idx);
while (active < num_active) {
- if (s->mh.mh_head) {
+ if (s->m) {
lro_flush_session(qs, s, NULL);
active++;
}
OpenPOWER on IntegriCloud