From 73721416ee0a328661fd2d5b873fff64bc95695f Mon Sep 17 00:00:00 2001 From: yongari Date: Mon, 23 Aug 2010 00:24:12 +0000 Subject: Clean up SIOCSIFCAP handler and allow RX checksum offloading could be controlled by user. --- sys/dev/xl/if_xl.c | 69 ++++++++++++++++++++++++++++++------------------------ 1 file 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: -- cgit v1.1