summaryrefslogtreecommitdiffstats
path: root/sys/dev/xl
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-08-23 00:24:12 +0000
committeryongari <yongari@FreeBSD.org>2010-08-23 00:24:12 +0000
commit73721416ee0a328661fd2d5b873fff64bc95695f (patch)
tree5371df2457f73225228329ad02784d5e7aba0f9c /sys/dev/xl
parent1b3ec208346e23bc8cec30152779da9d58ac17b8 (diff)
downloadFreeBSD-src-73721416ee0a328661fd2d5b873fff64bc95695f.zip
FreeBSD-src-73721416ee0a328661fd2d5b873fff64bc95695f.tar.gz
Clean up SIOCSIFCAP handler and allow RX checksum offloading could
be controlled by user.
Diffstat (limited to 'sys/dev/xl')
-rw-r--r--sys/dev/xl/if_xl.c69
1 files changed, 38 insertions, 31 deletions
diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c
index 05150af..2145ec8 100644
--- a/sys/dev/xl/if_xl.c
+++ b/sys/dev/xl/if_xl.c
@@ -3083,7 +3083,7 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct xl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0;
+ int error = 0, mask;
struct mii_data *mii = NULL;
u_int8_t rxfilt;
@@ -3143,40 +3143,47 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
&mii->mii_media, command);
break;
case SIOCSIFCAP:
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
- if (ifr->ifr_reqcap & IFCAP_POLLING &&
- !(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(xl_poll, ifp);
- if (error)
- return(error);
- XL_LOCK(sc);
- /* Disable interrupts */
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
- ifp->if_capenable |= IFCAP_POLLING;
- XL_UNLOCK(sc);
- return (error);
- }
- if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
- ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
- /* Enable interrupts. */
- XL_LOCK(sc);
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
- if (sc->xl_flags & XL_FLAG_FUNCREG)
- bus_space_write_4(sc->xl_ftag, sc->xl_fhandle,
- 4, 0x8000);
- ifp->if_capenable &= ~IFCAP_POLLING;
- XL_UNLOCK(sc);
- return (error);
+ if ((mask & IFCAP_POLLING) != 0 &&
+ (ifp->if_capabilities & IFCAP_POLLING) != 0) {
+ ifp->if_capenable ^= IFCAP_POLLING;
+ if ((ifp->if_capenable & IFCAP_POLLING) != 0) {
+ error = ether_poll_register(xl_poll, ifp);
+ if (error)
+ break;
+ XL_LOCK(sc);
+ /* Disable interrupts */
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
+ ifp->if_capenable |= IFCAP_POLLING;
+ XL_UNLOCK(sc);
+ } else {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ XL_LOCK(sc);
+ CSR_WRITE_2(sc, XL_COMMAND,
+ XL_CMD_INTR_ACK | 0xFF);
+ CSR_WRITE_2(sc, XL_COMMAND,
+ XL_CMD_INTR_ENB | XL_INTRS);
+ if (sc->xl_flags & XL_FLAG_FUNCREG)
+ bus_space_write_4(sc->xl_ftag,
+ sc->xl_fhandle, 4, 0x8000);
+ XL_UNLOCK(sc);
+ }
}
#endif /* DEVICE_POLLING */
XL_LOCK(sc);
- ifp->if_capenable = ifr->ifr_reqcap;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist = XL905B_CSUM_FEATURES;
- else
- ifp->if_hwassist = 0;
+ 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 |= XL905B_CSUM_FEATURES;
+ else
+ ifp->if_hwassist &= ~XL905B_CSUM_FEATURES;
+ }
+ if ((mask & IFCAP_RXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_RXCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_RXCSUM;
XL_UNLOCK(sc);
break;
default:
OpenPOWER on IntegriCloud