summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2008-11-25 01:33:16 +0000
committeryongari <yongari@FreeBSD.org>2008-11-25 01:33:16 +0000
commit16105734c1cb06b26d7c241fd3dfb4b1c9f3d4c3 (patch)
tree764a63163d9079b2219f57e3c5a5b12e2901bf25 /sys/dev
parent31a900b6ef449b5fafa15bd52464567f82b13284 (diff)
downloadFreeBSD-src-16105734c1cb06b26d7c241fd3dfb4b1c9f3d4c3.zip
FreeBSD-src-16105734c1cb06b26d7c241fd3dfb4b1c9f3d4c3.tar.gz
Fix Tx/Rx checksum offload ioctl handling and make Rx handler honor
checksum offload configuration. Now checksum offload can be controlled by ifconfig(8). While I'm here add an additional check for interface capabilities before applying user's request.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fxp/if_fxp.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index b4ee5aa..6f13e68 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1558,6 +1558,7 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack,
struct fxp_rfa *rfa;
int rnr = (statack & FXP_SCB_STATACK_RNR) ? 1 : 0;
int fxp_rc = 0;
+ uint16_t status;
FXP_LOCK_ASSERT(sc, MA_OWNED);
if (rnr)
@@ -1635,7 +1636,8 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack,
}
#endif /* DEVICE_POLLING */
- if ((le16toh(rfa->rfa_status) & FXP_RFA_STATUS_C) == 0)
+ status = le16toh(rfa->rfa_status);
+ if ((status & FXP_RFA_STATUS_C) == 0)
break;
/*
@@ -1661,14 +1663,14 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack,
total_len = le16toh(rfa->actual_size) & 0x3fff;
if (total_len < sizeof(struct ether_header) ||
total_len > MCLBYTES - RFA_ALIGNMENT_FUDGE -
- sc->rfa_size ||
- le16toh(rfa->rfa_status) & FXP_RFA_STATUS_CRC) {
+ sc->rfa_size || status & FXP_RFA_STATUS_CRC) {
m_freem(m);
continue;
}
/* Do IP checksum checking. */
- if (le16toh(rfa->rfa_status) & FXP_RFA_STATUS_PARSE) {
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 &&
+ (status & FXP_RFA_STATUS_PARSE)) {
if (rfa->rfax_csum_sts &
FXP_RFDX_CS_IP_CSUM_BIT_VALID)
m->m_pkthdr.csum_flags |=
@@ -2372,7 +2374,7 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct fxp_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct mii_data *mii;
- int flag, mask, error = 0;
+ int flag, mask, error = 0, reinit;
switch (command) {
case SIOCSIFFLAGS:
@@ -2432,6 +2434,7 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFCAP:
+ reinit = 0;
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
@@ -2454,8 +2457,20 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
}
#endif
- if (mask & IFCAP_VLAN_MTU) {
- FXP_LOCK(sc);
+ FXP_LOCK(sc);
+ if ((mask & IFCAP_TXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+ ifp->if_hwassist |= FXP_CSUM_FEATURES;
+ else
+ ifp->if_hwassist &= ~FXP_CSUM_FEATURES;
+ }
+ if ((mask & IFCAP_RXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_RXCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ if ((mask & IFCAP_VLAN_MTU) != 0 &&
+ (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) {
ifp->if_capenable ^= IFCAP_VLAN_MTU;
if (sc->revision != FXP_REV_82557)
flag = FXP_FLAG_LONG_PKT_EN;
@@ -2463,9 +2478,11 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
flag = FXP_FLAG_SAVE_BAD;
sc->flags ^= flag;
if (ifp->if_flags & IFF_UP)
- fxp_init_body(sc);
- FXP_UNLOCK(sc);
+ reinit++;
}
+ if (reinit > 0)
+ fxp_init_body(sc);
+ FXP_UNLOCK(sc);
break;
default:
OpenPOWER on IntegriCloud