FreeBSD/sys/dev/ixl/if_ixlv.c
/*********************************************************************
 *  Ioctl entry point
 *
 *  ixlv_ioctl is called when the user wants to configure the
 *  interface.
 *
 *  return 0 on success, positive on failure
 **********************************************************************/
Ioctl entry point
ixlv_ioctl is called when the user wants to configure the
interface.

return 0 on success, positive on failure
Ioctl entry point ixlv_ioctl is called when the user wants to configure the interface . return 0 on success positive on failure
static int
ixlv_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
	struct ixl_vsi		*vsi = ifp->if_softc;
	struct ixlv_sc	*sc = vsi->back;
	struct ifreq		*ifr = (struct ifreq *)data;
#if defined(INET) || defined(INET6)
	struct ifaddr 		*ifa = (struct ifaddr *)data;
	bool			avoid_reset = FALSE;
#endif
	int             	error = 0;
	switch (command) {
        case SIOCSIFADDR:
#ifdef INET
		if (ifa->ifa_addr->sa_family == AF_INET)
			avoid_reset = TRUE;
#endif
#ifdef INET6
		if (ifa->ifa_addr->sa_family == AF_INET6)
			avoid_reset = TRUE;
#endif
#if defined(INET) || defined(INET6)
		if (avoid_reset) {
			ifp->if_flags |= IFF_UP;
			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
				ixlv_init(vsi);
#ifdef INET
			if (!(ifp->if_flags & IFF_NOARP))
				arp_ifinit(ifp, ifa);
#endif
		} else
			error = ether_ioctl(ifp, command, data);
		break;
#endif
	case SIOCSIFMTU:
		IOCTL_DBG_IF2(ifp, "SIOCSIFMTU (Set Interface MTU)");
		mtx_lock(&sc->mtx);
		if (ifr->ifr_mtu > IXL_MAX_FRAME -
		    ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN) {
			error = EINVAL;
			IOCTL_DBG_IF(ifp, "mtu too large");
		} else {
			IOCTL_DBG_IF2(ifp, "mtu: %lu -> %d", (u_long)ifp->if_mtu, ifr->ifr_mtu);
			ifp->if_mtu = (u_long)ifr->ifr_mtu;
			vsi->max_frame_size =
			    ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
			    + ETHER_VLAN_ENCAP_LEN;
			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
				ixlv_init_locked(sc);
		}
		mtx_unlock(&sc->mtx);
		break;
	case SIOCSIFFLAGS:
		IOCTL_DBG_IF2(ifp, "SIOCSIFFLAGS (Set Interface Flags)");
		mtx_lock(&sc->mtx);
		if (ifp->if_flags & IFF_UP) {
			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
				ixlv_init_locked(sc);
		} else
			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
				ixlv_stop(sc);
		sc->if_flags = ifp->if_flags;
		mtx_unlock(&sc->mtx);
		break;
	case SIOCADDMULTI:
		IOCTL_DBG_IF2(ifp, "SIOCADDMULTI");
		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
			mtx_lock(&sc->mtx);
			ixlv_disable_intr(vsi);
			ixlv_add_multi(vsi);
			ixlv_enable_intr(vsi);
			mtx_unlock(&sc->mtx);
		}
		break;
	case SIOCDELMULTI:
		IOCTL_DBG_IF2(ifp, "SIOCDELMULTI");
		if (sc->init_state == IXLV_RUNNING) {
			mtx_lock(&sc->mtx);
			ixlv_disable_intr(vsi);
			ixlv_del_multi(vsi);
			ixlv_enable_intr(vsi);
			mtx_unlock(&sc->mtx);
		}
		break;
	case SIOCSIFMEDIA:
	case SIOCGIFMEDIA:
		IOCTL_DBG_IF2(ifp, "SIOCxIFMEDIA (Get/Set Interface Media)");
		error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
		break;
	case SIOCSIFCAP:
	{
		int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
		IOCTL_DBG_IF2(ifp, "SIOCSIFCAP (Set Capabilities)");
		ixlv_cap_txcsum_tso(vsi, ifp, mask);
		if (mask & IFCAP_RXCSUM)
			ifp->if_capenable ^= IFCAP_RXCSUM;
		if (mask & IFCAP_RXCSUM_IPV6)
			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
		if (mask & IFCAP_LRO)
			ifp->if_capenable ^= IFCAP_LRO;
		if (mask & IFCAP_VLAN_HWTAGGING)
			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
		if (mask & IFCAP_VLAN_HWFILTER)
			ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
		if (mask & IFCAP_VLAN_HWTSO)
			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
			ixlv_init(vsi);
		}
		VLAN_CAPABILITIES(ifp);
		break;
	}
	default:
		IOCTL_DBG_IF2(ifp, "UNKNOWN (0x%X)", (int)command);
		error = ether_ioctl(ifp, command, data);
		break;
	}
	return (error);
}
static int ixlv_ioctl ( struct ifnet * ifp , u_long command , caddr_t data ) { struct ixl_vsi * vsi = ifp -> if_softc ; struct ixlv_sc * sc = vsi -> back ; struct ifreq * ifr = ( struct ifreq * ) data ; #if defined ( INET ) || defined ( INET6 ) struct ifaddr * ifa = ( struct ifaddr * ) data ; bool avoid_reset = FALSE ; #endif int error = 0 ; switch ( command ) { case SIOCSIFADDR : #ifdef INET if ( ifa -> ifa_addr -> sa_family == AF_INET ) avoid_reset = TRUE ; #endif #ifdef INET6 if ( ifa -> ifa_addr -> sa_family == AF_INET6 ) avoid_reset = TRUE ; #endif #if defined ( INET ) || defined ( INET6 ) if ( avoid_reset ) { ifp -> if_flags |= IFF_UP ; if ( ! ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) ) ixlv_init ( vsi ) ; #ifdef INET if ( ! ( ifp -> if_flags & IFF_NOARP ) ) arp_ifinit ( ifp , ifa ) ; #endif } else error = ether_ioctl ( ifp , command , data ) ; break ; #endif case SIOCSIFMTU : IOCTL_DBG_IF2 ( ifp , " " ) ; mtx_lock ( & sc -> mtx ) ; if ( ifr -> ifr_mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN ) { error = EINVAL ; IOCTL_DBG_IF ( ifp , " " ) ; } else { IOCTL_DBG_IF2 ( ifp , " " , ( u_long ) ifp -> if_mtu , ifr -> ifr_mtu ) ; ifp -> if_mtu = ( u_long ) ifr -> ifr_mtu ; vsi -> max_frame_size = ifp -> if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN ; if ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) ixlv_init_locked ( sc ) ; } mtx_unlock ( & sc -> mtx ) ; break ; case SIOCSIFFLAGS : IOCTL_DBG_IF2 ( ifp , " " ) ; mtx_lock ( & sc -> mtx ) ; if ( ifp -> if_flags & IFF_UP ) { if ( ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) == 0 ) ixlv_init_locked ( sc ) ; } else if ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) ixlv_stop ( sc ) ; sc -> if_flags = ifp -> if_flags ; mtx_unlock ( & sc -> mtx ) ; break ; case SIOCADDMULTI : IOCTL_DBG_IF2 ( ifp , " " ) ; if ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) { mtx_lock ( & sc -> mtx ) ; ixlv_disable_intr ( vsi ) ; ixlv_add_multi ( vsi ) ; ixlv_enable_intr ( vsi ) ; mtx_unlock ( & sc -> mtx ) ; } break ; case SIOCDELMULTI : IOCTL_DBG_IF2 ( ifp , " " ) ; if ( sc -> init_state == IXLV_RUNNING ) { mtx_lock ( & sc -> mtx ) ; ixlv_disable_intr ( vsi ) ; ixlv_del_multi ( vsi ) ; ixlv_enable_intr ( vsi ) ; mtx_unlock ( & sc -> mtx ) ; } break ; case SIOCSIFMEDIA : case SIOCGIFMEDIA : IOCTL_DBG_IF2 ( ifp , " " ) ; error = ifmedia_ioctl ( ifp , ifr , & sc -> media , command ) ; break ; case SIOCSIFCAP : { int mask = ifr -> ifr_reqcap ^ ifp -> if_capenable ; IOCTL_DBG_IF2 ( ifp , " " ) ; ixlv_cap_txcsum_tso ( vsi , ifp , mask ) ; if ( mask & IFCAP_RXCSUM ) ifp -> if_capenable ^= IFCAP_RXCSUM ; if ( mask & IFCAP_RXCSUM_IPV6 ) ifp -> if_capenable ^= IFCAP_RXCSUM_IPV6 ; if ( mask & IFCAP_LRO ) ifp -> if_capenable ^= IFCAP_LRO ; if ( mask & IFCAP_VLAN_HWTAGGING ) ifp -> if_capenable ^= IFCAP_VLAN_HWTAGGING ; if ( mask & IFCAP_VLAN_HWFILTER ) ifp -> if_capenable ^= IFCAP_VLAN_HWFILTER ; if ( mask & IFCAP_VLAN_HWTSO ) ifp -> if_capenable ^= IFCAP_VLAN_HWTSO ; if ( ifp -> if_drv_flags & IFF_DRV_RUNNING ) { ixlv_init ( vsi ) ; } VLAN_CAPABILITIES ( ifp ) ; break ; } default : IOCTL_DBG_IF2 ( ifp , " " , ( int ) command ) ; error = ether_ioctl ( ifp , command , data ) ; break ; } return ( error ) ; }
Ioctl entry point
  ixlv_ioctl is called when the user wants to configure the
  interface.
Ioctl entry point ixlv_ioctl is called when the user wants to configure the interface .
/*
		** Calling init results in link renegotiation,
		** so we avoid doing it when possible.
		*/ // ERJ: Interestingly enough, these types don't match