Deleted Added
full compact
28c28
< * $FreeBSD: head/sys/dev/fxp/if_fxp.c 111119 2003-02-19 05:47:46Z imp $
---
> * $FreeBSD: head/sys/dev/fxp/if_fxp.c 111578 2003-02-26 22:12:04Z wpaul $
69a70,76
> #ifdef FXP_IP_CSUM_WAR
> #include <netinet/in.h>
> #include <netinet/in_systm.h>
> #include <netinet/ip.h>
> #include <machine/in_cksum.h>
> #endif
>
171a179,184
> #ifdef FXP_IP_CSUM_WAR
> #define FXP_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
> #else
> #define FXP_CSUM_FEATURES (CSUM_TCP | CSUM_UDP)
> #endif
>
595a609,624
> * Enable use of extended RFDs and TCBs for 82550
> * and later chips. Note: we need extended TXCB support
> * too, but that's already enabled by the code above.
> * Be careful to do this only on the right devices.
> */
>
> if (sc->revision == FXP_REV_82550 || sc->revision == FXP_REV_82550_C) {
> sc->rfa_size = sizeof (struct fxp_rfa);
> sc->tx_cmd = FXP_CB_COMMAND_IPCBXMIT;
> sc->flags |= FXP_FLAG_EXT_RFA;
> } else {
> sc->rfa_size = sizeof (struct fxp_rfa) - FXP_RFAX_LEN;
> sc->tx_cmd = FXP_CB_COMMAND_XMIT;
> }
>
> /*
646a676,682
> /* Enable checksum offload for 82550 or better chips */
>
> if (sc->flags & FXP_FLAG_EXT_RFA) {
> ifp->if_hwassist = FXP_CSUM_FEATURES;
> ifp->if_capabilities = IFCAP_HWCSUM;
> }
>
1015a1052
> volatile struct fxp_tbd *bdptr;
1048a1086,1163
> * If this is an 82550/82551, then we're using extended
> * TxCBs _and_ we're using checksum offload. This means
> * that the TxCB is really an IPCB. One major difference
> * between the two is that with plain extended TxCBs,
> * the bottom half of the TxCB contains two entries from
> * the TBD array, whereas IPCBs contain just one entry:
> * one entry (8 bytes) has been sacrificed for the TCP/IP
> * checksum offload control bits. So to make things work
> * right, we have to start filling in the TBD array
> * starting from a different place depending on whether
> * the chip is an 82550/82551 or not.
> */
>
> bdptr = &txp->tbd[0];
> if (sc->flags & FXP_FLAG_EXT_RFA)
> bdptr++;
>
> /*
> * Deal with TCP/IP checksum offload. Note that
> * in order for TCP checksum offload to work,
> * the pseudo header checksum must have already
> * been computed and stored in the checksum field
> * in the TCP header. The stack should have
> * already done this for us.
> */
>
> if (mb_head->m_pkthdr.csum_flags) {
> if (mb_head->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
> txp->ipcb_ip_activation_high =
> FXP_IPCB_HARDWAREPARSING_ENABLE;
> txp->ipcb_ip_schedule =
> FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
> if (mb_head->m_pkthdr.csum_flags & CSUM_TCP)
> txp->ipcb_ip_schedule |=
> FXP_IPCB_TCP_PACKET;
> }
> #ifdef FXP_IP_CSUM_WAR
> /*
> * XXX The 82550 chip appears to have trouble
> * dealing with IP header checksums in very small
> * datagrams, namely fragments from 1 to 3 bytes
> * in size. For example, say you want to transmit
> * a UDP packet of 1473 bytes. The packet will be
> * fragmented over two IP datagrams, the latter
> * containing only one byte of data. The 82550 will
> * botch the header checksum on the 1-byte fragment.
> * As long as the datagram contains 4 or more bytes
> * of data, you're ok.
> *
> * The following code attempts to work around this
> * problem: if the datagram is less than 38 bytes
> * in size (14 bytes ether header, 20 bytes IP header,
> * plus 4 bytes of data), we punt and compute the IP
> * header checksum by hand. This workaround doesn't
> * work very well, however, since it can be fooled
> * by things like VLAN tags and IP options that make
> * the header sizes/offsets vary.
> */
>
> if (mb_head->m_pkthdr.csum_flags & CSUM_IP) {
> if (mb_head->m_pkthdr.len < 38) {
> struct ip *ip;
> mb_head->m_data += ETHER_HDR_LEN;
> ip = mtod(mb_head, struct ip *);
> ip->ip_sum = in_cksum(mb_head,
> ip->ip_hl << 2);
> mb_head->m_data -= ETHER_HDR_LEN;
> } else {
> txp->ipcb_ip_activation_high =
> FXP_IPCB_HARDWAREPARSING_ENABLE;
> txp->ipcb_ip_schedule |=
> FXP_IPCB_IP_CHECKSUM_ENABLE;
> }
> }
> #endif
> }
>
> /*
1056c1171
< if (segment == FXP_NTXSEG)
---
> if (segment == (FXP_NTXSEG - 1))
1058c1173
< txp->tbd[segment].tb_addr =
---
> bdptr[segment].tb_addr =
1060c1175
< txp->tbd[segment].tb_size = m->m_len;
---
> bdptr[segment].tb_size = m->m_len;
1092a1208
> txp->byte_count = 0;
1098c1214
< FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF |
---
> sc->tx_cmd | FXP_CB_COMMAND_SF |
1102c1218
< FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF |
---
> sc->tx_cmd | FXP_CB_COMMAND_SF |
1272a1389,1390
> /* clear this to reset csum offload bits */
> txp->tbd[0].tb_addr = 0;
1354a1473,1492
> /* Do IP checksum checking. */
> if (rfa->rfa_status & FXP_RFA_STATUS_PARSE) {
> if (rfa->rfax_csum_sts &
> FXP_RFDX_CS_IP_CSUM_BIT_VALID)
> m->m_pkthdr.csum_flags |=
> CSUM_IP_CHECKED;
> if (rfa->rfax_csum_sts &
> FXP_RFDX_CS_IP_CSUM_VALID)
> m->m_pkthdr.csum_flags |=
> CSUM_IP_VALID;
> if ((rfa->rfax_csum_sts &
> FXP_RFDX_CS_TCPUDP_CSUM_BIT_VALID) &&
> (rfa->rfax_csum_sts &
> FXP_RFDX_CS_TCPUDP_CSUM_VALID)) {
> m->m_pkthdr.csum_flags |=
> CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
> m->m_pkthdr.csum_data = 0xffff;
> }
> }
>
1428a1567,1568
> /* clear this to reset csum offload bits */
> txp->tbd[0].tb_addr = 0;
1518a1659,1660
> /* clear this to reset csum offload bits */
> txp[i].tbd[0].tb_addr = 0;
1639c1781
< cbp->byte_count = 22; /* (22) bytes to config */
---
> cbp->byte_count = sc->flags & FXP_FLAG_EXT_RFA ? 32 : 22;
1661a1804
> cbp->ext_rfa = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0;
1692a1836
> cbp->gamla_rx = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0;
1895,1896c2039,2041
< m->m_data += sizeof(struct fxp_rfa);
< rfa->size = (u_int16_t)(MCLBYTES - sizeof(struct fxp_rfa) - RFA_ALIGNMENT_FUDGE);
---
> m->m_data += sc->rfa_size;
> rfa->size = (u_int16_t)(MCLBYTES - sizeof(struct fxp_rfa) -
> RFA_ALIGNMENT_FUDGE);