xen-netfront: improve the logic when handling nic features from ioctl

Simplify the logic involved in changing the nic features on the fly, and
only reset the frontend when really needed (when changing RX features). Also
don't return from the ioctl until the interface has been properly
reconfigured.

While there, make sure XN_CSUM_FEATURES is used consistently.

Reported by:	julian
MFC after:	5 days
X-MFC-with:	r303488
Sponsored by:	Citrix Systems R&D
This commit is contained in:
Roger Pau Monné 2016-08-05 15:48:56 +00:00
parent 37e56c6efe
commit 3c9d594089

@ -1760,7 +1760,7 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
#ifdef INET
struct ifaddr *ifa = (struct ifaddr *)data;
#endif
int mask, error = 0;
int mask, error = 0, reinit;
dev = sc->xbdev;
@ -1809,41 +1809,36 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
reinit = 0;
if (mask & IFCAP_TXCSUM) {
if (IFCAP_TXCSUM & ifp->if_capenable) {
ifp->if_capenable &= ~(IFCAP_TXCSUM|IFCAP_TSO4);
ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP
| CSUM_IP | CSUM_TSO);
} else {
ifp->if_capenable |= IFCAP_TXCSUM;
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP
| CSUM_IP);
}
}
if (mask & IFCAP_RXCSUM) {
ifp->if_capenable ^= IFCAP_RXCSUM;
ifp->if_capenable ^= IFCAP_TXCSUM;
ifp->if_hwassist ^= XN_CSUM_FEATURES;
}
if (mask & IFCAP_TSO4) {
if (IFCAP_TSO4 & ifp->if_capenable) {
ifp->if_capenable &= ~IFCAP_TSO4;
ifp->if_hwassist &= ~CSUM_TSO;
} else if (IFCAP_TXCSUM & ifp->if_capenable) {
ifp->if_capenable |= IFCAP_TSO4;
ifp->if_hwassist |= CSUM_TSO;
} else {
IPRINTK("Xen requires tx checksum offload"
" be enabled to use TSO\n");
error = EINVAL;
}
ifp->if_capenable ^= IFCAP_TSO4;
ifp->if_hwassist ^= CSUM_TSO;
}
if (mask & IFCAP_LRO) {
ifp->if_capenable ^= IFCAP_LRO;
if (mask & (IFCAP_RXCSUM | IFCAP_LRO)) {
/* These Rx features require us to renegotiate. */
reinit = 1;
if (mask & IFCAP_RXCSUM)
ifp->if_capenable ^= IFCAP_RXCSUM;
if (mask & IFCAP_LRO)
ifp->if_capenable ^= IFCAP_LRO;
}
if (reinit == 0)
break;
/*
* We must reset the interface so the backend picks up the
* new features.
*/
device_printf(sc->xbdev,
"performing interface reset due to feature change\n");
XN_LOCK(sc);
netfront_carrier_off(sc);
sc->xn_reset = true;
@ -1865,6 +1860,13 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
xs_rm(XST_NIL, xenbus_get_node(dev), "feature-gso-tcpv4");
xs_rm(XST_NIL, xenbus_get_node(dev), "feature-no-csum-offload");
xenbus_set_state(dev, XenbusStateClosing);
/*
* Wait for the frontend to reconnect before returning
* from the ioctl. 30s should be more than enough for any
* sane backend to reconnect.
*/
error = tsleep(sc, 0, "xn_rst", 30*hz);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
@ -1971,6 +1973,7 @@ xn_connect(struct netfront_info *np)
* packets.
*/
netfront_carrier_on(np);
wakeup(np);
return (0);
}
@ -2085,7 +2088,7 @@ xn_configure_features(struct netfront_info *np)
#endif
if ((ifp->if_capabilities & cap_enabled & IFCAP_TXCSUM) != 0) {
ifp->if_capenable |= IFCAP_TXCSUM;
ifp->if_hwassist |= CSUM_TCP|CSUM_UDP;
ifp->if_hwassist |= XN_CSUM_FEATURES;
}
if ((ifp->if_capabilities & cap_enabled & IFCAP_RXCSUM) != 0)
ifp->if_capenable |= IFCAP_RXCSUM;