Deleted Added
full compact
31c31
< __FBSDID("$FreeBSD: head/sys/dev/fxp/if_fxp.c 185329 2008-11-26 06:36:53Z yongari $");
---
> __FBSDID("$FreeBSD: head/sys/dev/fxp/if_fxp.c 185330 2008-11-26 07:36:17Z yongari $");
622c622,623
< if (sc->flags & FXP_FLAG_EXT_RFA)
---
> sc->maxsegsize = MCLBYTES;
> if (sc->flags & FXP_FLAG_EXT_RFA) {
623a625,626
> sc->maxsegsize = FXP_TSO_SEGSIZE;
> }
626c629,630
< MCLBYTES * sc->maxtxseg, sc->maxtxseg, MCLBYTES, 0,
---
> sc->maxsegsize * sc->maxtxseg + sizeof(struct ether_vlan_header),
> sc->maxtxseg, sc->maxsegsize, 0,
783c787
< /* Enable checksum offload for 82550 or better chips */
---
> /* Enable checksum offload/TSO for 82550 or better chips */
785,787c789,791
< ifp->if_hwassist = FXP_CSUM_FEATURES;
< ifp->if_capabilities |= IFCAP_HWCSUM;
< ifp->if_capenable |= IFCAP_HWCSUM;
---
> ifp->if_hwassist = FXP_CSUM_FEATURES | CSUM_TSO;
> ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4;
> ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_TSO4;
1277a1282
> struct tcphdr *tcp;
1279c1284
< int error, i, nseg;
---
> int error, i, nseg, tcp_payload;
1283a1289,1290
> tcp_payload = 0;
> tcp = NULL;
1360a1368,1436
> if (m->m_pkthdr.csum_flags & CSUM_TSO) {
> /*
> * 82550/82551 requires ethernet/IP/TCP headers must be
> * contained in the first active transmit buffer.
> */
> struct ether_header *eh;
> struct ip *ip;
> uint32_t ip_off, poff;
>
> if (M_WRITABLE(*m_head) == 0) {
> /* Get a writable copy. */
> m = m_dup(*m_head, M_DONTWAIT);
> m_freem(*m_head);
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
> *m_head = m;
> }
> ip_off = sizeof(struct ether_header);
> m = m_pullup(*m_head, ip_off);
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
> eh = mtod(m, struct ether_header *);
> /* Check the existence of VLAN tag. */
> if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
> ip_off = sizeof(struct ether_vlan_header);
> m = m_pullup(m, ip_off);
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
> }
> m = m_pullup(m, ip_off + sizeof(struct ip));
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
> ip = (struct ip *)(mtod(m, char *) + ip_off);
> poff = ip_off + (ip->ip_hl << 2);
> m = m_pullup(m, poff + sizeof(struct tcphdr));
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
> tcp = (struct tcphdr *)(mtod(m, char *) + poff);
> m = m_pullup(m, poff + sizeof(struct tcphdr) + tcp->th_off);
> if (m == NULL) {
> *m_head = NULL;
> return (ENOBUFS);
> }
>
> /*
> * Since 82550/82551 doesn't modify IP length and pseudo
> * checksum in the first frame driver should compute it.
> */
> ip->ip_sum = 0;
> ip->ip_len = htons(ifp->if_mtu);
> tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
> htons(IPPROTO_TCP + (tcp->th_off << 2) +
> m->m_pkthdr.tso_segsz));
> /* Compute total TCP payload. */
> tcp_payload = m->m_pkthdr.len - ip_off - (ip->ip_hl << 2);
> tcp_payload -= tcp->th_off << 2;
> *m_head = m;
> }
>
1391d1466
< KASSERT(segs[i].ds_len <= MCLBYTES, ("segment size too large"));
1406,1407c1481,1482
< cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr);
< cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len);
---
> cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr);
> cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len);
1413c1488,1502
< cbp->tbd_number = nseg;
---
> if (sc->flags & FXP_FLAG_EXT_RFA) {
> /* Configure dynamic TBD for 82550/82551. */
> cbp->tbd_number = 0xFF;
> cbp->tbd[nseg + 1].tb_size |= htole32(0x8000);
> } else
> cbp->tbd_number = nseg;
> /* Configure TSO. */
> if (m->m_pkthdr.csum_flags & CSUM_TSO) {
> cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
> cbp->tbd[1].tb_size = htole32(tcp_payload << 16);
> cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
> FXP_IPCB_IP_CHECKSUM_ENABLE |
> FXP_IPCB_TCP_PACKET |
> FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
> }
1426c1515,1516
< txp->tx_cb->tx_threshold = tx_threshold;
---
> if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0)
> txp->tx_cb->tx_threshold = tx_threshold;
2100c2190
< cbp->dyn_tbd = 0; /* (no) dynamic TBD mode */
---
> cbp->dyn_tbd = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0;
2591a2682,2689
> if ((mask & IFCAP_TSO4) != 0 &&
> (ifp->if_capabilities & IFCAP_TSO4) != 0) {
> ifp->if_capenable ^= IFCAP_TSO4;
> if ((ifp->if_capenable & IFCAP_TSO4) != 0)
> ifp->if_hwassist |= CSUM_TSO;
> else
> ifp->if_hwassist &= ~CSUM_TSO;
> }