Support IFCAP_VLANHWTSO in cxgb(4). It works with or without vlanhwtag.

While here, remove old DPRINTFs and tidy up the capability code a bit.
This commit is contained in:
Navdeep Parhar 2010-02-26 07:08:44 +00:00
parent dcfeda6122
commit f9c6e16451
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=204348
2 changed files with 48 additions and 48 deletions

View File

@ -972,7 +972,8 @@ cxgb_makedev(struct port_info *pi)
}
#define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \
IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO)
IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \
IFCAP_VLAN_HWTSO)
#define CXGB_CAP_ENABLE (CXGB_CAP & ~IFCAP_TSO6)
static int
@ -1015,8 +1016,8 @@ cxgb_port_attach(device_t dev)
* Disable TSO on 4-port - it isn't supported by the firmware.
*/
if (sc->params.nports > 2) {
ifp->if_capabilities &= ~IFCAP_TSO;
ifp->if_capenable &= ~IFCAP_TSO;
ifp->if_capabilities &= ~(IFCAP_TSO | IFCAP_VLAN_HWTSO);
ifp->if_capenable &= ~(IFCAP_TSO | IFCAP_VLAN_HWTSO);
ifp->if_hwassist &= ~CSUM_TSO;
}
@ -2045,28 +2046,34 @@ fail:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
if (IFCAP_TXCSUM & ifp->if_capenable) {
ifp->if_capenable &= ~(IFCAP_TXCSUM|IFCAP_TSO4);
ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP
| CSUM_IP | CSUM_TSO);
} else {
ifp->if_capenable |= IFCAP_TXCSUM;
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP
| CSUM_IP);
ifp->if_capenable ^= IFCAP_TXCSUM;
ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
if (IFCAP_TSO & ifp->if_capenable &&
!(IFCAP_TXCSUM & ifp->if_capenable)) {
ifp->if_capenable &= ~IFCAP_TSO;
ifp->if_hwassist &= ~CSUM_TSO;
if_printf(ifp,
"tso disabled due to -txcsum.\n");
}
}
if (mask & IFCAP_RXCSUM) {
if (mask & IFCAP_RXCSUM)
ifp->if_capenable ^= IFCAP_RXCSUM;
}
if (mask & IFCAP_TSO4) {
if (IFCAP_TSO4 & ifp->if_capenable) {
ifp->if_capenable &= ~IFCAP_TSO4;
ifp->if_hwassist &= ~CSUM_TSO;
} else if (IFCAP_TXCSUM & ifp->if_capenable) {
ifp->if_capenable |= IFCAP_TSO4;
ifp->if_hwassist |= CSUM_TSO;
ifp->if_capenable ^= IFCAP_TSO4;
if (IFCAP_TSO & ifp->if_capenable) {
if (IFCAP_TXCSUM & ifp->if_capenable)
ifp->if_hwassist |= CSUM_TSO;
else {
ifp->if_capenable &= ~IFCAP_TSO;
ifp->if_hwassist &= ~CSUM_TSO;
if_printf(ifp,
"enable txcsum first.\n");
error = EAGAIN;
}
} else
error = EINVAL;
ifp->if_hwassist &= ~CSUM_TSO;
}
if (mask & IFCAP_LRO) {
ifp->if_capenable ^= IFCAP_LRO;
@ -2090,6 +2097,8 @@ fail:
PORT_UNLOCK(p);
}
}
if (mask & IFCAP_VLAN_HWTSO)
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
if (mask & IFCAP_VLAN_HWCSUM)
ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;

View File

@ -50,8 +50,12 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/socket.h>
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_vlan_var.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@ -1362,8 +1366,8 @@ write_wr_hdr_sgl(unsigned int ndesc, struct tx_desc *txd, struct txq_state *txqs
}
}
/* sizeof(*eh) + sizeof(*vhdr) + sizeof(*ip) + sizeof(*tcp) */
#define TCPPKTHDRSIZE (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + 20 + 20)
/* sizeof(*eh) + sizeof(*ip) + sizeof(*tcp) */
#define TCPPKTHDRSIZE (ETHER_HDR_LEN + 20 + 20)
#define GET_VTAG(cntrl, m) \
do { \
@ -1399,10 +1403,7 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
prefetch(txd);
m0 = *m;
DPRINTF("t3_encap port_id=%d qsidx=%d ", pi->port_id, pi->first_qset);
DPRINTF("mlen=%d txpkt_intf=%d tx_chan=%d\n", m[0]->m_pkthdr.len, pi->txpkt_intf, pi->tx_chan);
mtx_assert(&qs->lock, MA_OWNED);
cntrl = V_TXPKT_INTF(pi->txpkt_intf);
KASSERT(m0->m_flags & M_PKTHDR, ("not packet header\n"));
@ -1475,11 +1476,11 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
check_ring_tx_db(sc, txq);
return (0);
} else if (tso_info) {
int min_size = TCPPKTHDRSIZE, eth_type, tagged;
int eth_type;
struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)txd;
struct ether_header *eh;
struct ip *ip;
struct tcphdr *tcp;
char *pkthdr;
txd->flit[2] = 0;
GET_VTAG(cntrl, m0);
@ -1487,13 +1488,7 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
hdr->cntrl = htonl(cntrl);
hdr->len = htonl(mlen | 0x80000000);
DPRINTF("tso buf len=%d\n", mlen);
tagged = m0->m_flags & M_VLANTAG;
if (!tagged)
min_size -= ETHER_VLAN_ENCAP_LEN;
if (__predict_false(mlen < min_size)) {
if (__predict_false(mlen < TCPPKTHDRSIZE)) {
printf("mbuf=%p,len=%d,tso_segsz=%d,csum_flags=%#x,flags=%#x",
m0, mlen, m0->m_pkthdr.tso_segsz,
m0->m_pkthdr.csum_flags, m0->m_flags);
@ -1501,25 +1496,23 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
}
/* Make sure that ether, ip, tcp headers are all in m0 */
if (__predict_false(m0->m_len < min_size)) {
m0 = m_pullup(m0, min_size);
if (__predict_false(m0->m_len < TCPPKTHDRSIZE)) {
m0 = m_pullup(m0, TCPPKTHDRSIZE);
if (__predict_false(m0 == NULL)) {
/* XXX panic probably an overreaction */
panic("couldn't fit header into mbuf");
}
}
pkthdr = m0->m_data;
if (tagged) {
eh = mtod(m0, struct ether_header *);
if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
eth_type = CPL_ETH_II_VLAN;
ip = (struct ip *)(pkthdr + ETHER_HDR_LEN +
ETHER_VLAN_ENCAP_LEN);
ip = (struct ip *)((struct ether_vlan_header *)eh + 1);
} else {
eth_type = CPL_ETH_II;
ip = (struct ip *)(pkthdr + ETHER_HDR_LEN);
ip = (struct ip *)(eh + 1);
}
tcp = (struct tcphdr *)((uint8_t *)ip +
sizeof(*ip));
tcp = (struct tcphdr *)(ip + 1);
tso_info |= V_LSO_ETH_TYPE(eth_type) |
V_LSO_IPHDR_WORDS(ip->ip_hl) |
@ -1527,12 +1520,10 @@ t3_encap(struct sge_qset *qs, struct mbuf **m)
hdr->lso_info = htonl(tso_info);
if (__predict_false(mlen <= PIO_LEN)) {
/* pkt not undersized but fits in PIO_LEN
/*
* pkt not undersized but fits in PIO_LEN
* Indicates a TSO bug at the higher levels.
*
*/
DPRINTF("**5592 Fix** mbuf=%p,len=%d,tso_segsz=%d,csum_flags=%#x,flags=%#x",
m0, mlen, m0->m_pkthdr.tso_segsz, m0->m_pkthdr.csum_flags, m0->m_flags);
txsd->m = NULL;
m_copydata(m0, 0, mlen, (caddr_t)&txd->flit[3]);
flits = (mlen + 7) / 8 + 3;