Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/sfxge/sfxge.c
Show First 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | sfxge_start(struct sfxge_softc *sc) | ||||
/* Start the transmitter side. */ | /* Start the transmitter side. */ | ||||
if ((rc = sfxge_tx_start(sc)) != 0) | if ((rc = sfxge_tx_start(sc)) != 0) | ||||
goto fail6; | goto fail6; | ||||
sc->init_state = SFXGE_STARTED; | sc->init_state = SFXGE_STARTED; | ||||
/* Tell the stack we're running. */ | /* Tell the stack we're running. */ | ||||
sc->ifnet->if_drv_flags |= IFF_DRV_RUNNING; | if_setdrvflagbits(sc->ifnet, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); | ||||
sc->ifnet->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
return (0); | return (0); | ||||
fail6: | fail6: | ||||
sfxge_rx_stop(sc); | sfxge_rx_stop(sc); | ||||
fail5: | fail5: | ||||
sfxge_port_stop(sc); | sfxge_port_stop(sc); | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | sfxge_stop(struct sfxge_softc *sc) | ||||
/* Stop processing events. */ | /* Stop processing events. */ | ||||
sfxge_ev_stop(sc); | sfxge_ev_stop(sc); | ||||
/* Stop processing interrupts. */ | /* Stop processing interrupts. */ | ||||
sfxge_intr_stop(sc); | sfxge_intr_stop(sc); | ||||
efx_nic_fini(sc->enp); | efx_nic_fini(sc->enp); | ||||
sc->ifnet->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(sc->ifnet, 0, IFF_DRV_RUNNING); | ||||
} | } | ||||
static int | static int | ||||
sfxge_vpd_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ioc) | sfxge_vpd_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ioc) | ||||
{ | { | ||||
efx_vpd_value_t value; | efx_vpd_value_t value; | ||||
int rc = 0; | int rc = 0; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | sfxge_private_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ioc) | ||||
case SFXGE_VPD_IOC: | case SFXGE_VPD_IOC: | ||||
return (sfxge_vpd_ioctl(sc, ioc)); | return (sfxge_vpd_ioctl(sc, ioc)); | ||||
default: | default: | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) | sfxge_if_ioctl(if_t ifp, unsigned long command, caddr_t data) | ||||
{ | { | ||||
struct sfxge_softc *sc; | struct sfxge_softc *sc; | ||||
struct ifreq *ifr; | struct ifreq *ifr; | ||||
sfxge_ioc_t ioc; | sfxge_ioc_t ioc; | ||||
int error; | int error; | ||||
ifr = (struct ifreq *)data; | ifr = (struct ifreq *)data; | ||||
sc = ifp->if_softc; | sc = if_getsoftc(ifp); | ||||
error = 0; | error = 0; | ||||
switch (command) { | switch (command) { | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
SFXGE_ADAPTER_LOCK(sc); | SFXGE_ADAPTER_LOCK(sc); | ||||
if (ifp->if_flags & IFF_UP) { | if (if_getflags(ifp) & IFF_UP) { | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { | ||||
if ((ifp->if_flags ^ sc->if_flags) & | if ((if_getflags(ifp) ^ sc->if_flags) & | ||||
(IFF_PROMISC | IFF_ALLMULTI)) { | (IFF_PROMISC | IFF_ALLMULTI)) { | ||||
sfxge_mac_filter_set(sc); | sfxge_mac_filter_set(sc); | ||||
} | } | ||||
} else | } else | ||||
sfxge_start(sc); | sfxge_start(sc); | ||||
} else | } else | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
sfxge_stop(sc); | sfxge_stop(sc); | ||||
sc->if_flags = ifp->if_flags; | sc->if_flags = if_getflags(ifp); | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCSIFMTU: | case SIOCSIFMTU: | ||||
if (ifr->ifr_mtu == ifp->if_mtu) { | if (ifr->ifr_mtu == if_getmtu(ifp)) { | ||||
/* Nothing to do */ | /* Nothing to do */ | ||||
error = 0; | error = 0; | ||||
} else if (ifr->ifr_mtu > SFXGE_MAX_MTU) { | } else if (ifr->ifr_mtu > SFXGE_MAX_MTU) { | ||||
error = EINVAL; | error = EINVAL; | ||||
} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | } else if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) { | ||||
ifp->if_mtu = ifr->ifr_mtu; | if_setmtu(ifp, ifr->ifr_mtu); | ||||
error = 0; | error = 0; | ||||
} else { | } else { | ||||
/* Restart required */ | /* Restart required */ | ||||
SFXGE_ADAPTER_LOCK(sc); | SFXGE_ADAPTER_LOCK(sc); | ||||
sfxge_stop(sc); | sfxge_stop(sc); | ||||
ifp->if_mtu = ifr->ifr_mtu; | if_setmtu(ifp, ifr->ifr_mtu); | ||||
error = sfxge_start(sc); | error = sfxge_start(sc); | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
if (error != 0) { | if (error != 0) { | ||||
ifp->if_flags &= ~IFF_UP; | if_setflagbits(ifp, 0, IFF_UP); | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
if_down(ifp); | if_down(ifp); | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case SIOCADDMULTI: | case SIOCADDMULTI: | ||||
case SIOCDELMULTI: | case SIOCDELMULTI: | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
sfxge_mac_filter_set(sc); | sfxge_mac_filter_set(sc); | ||||
break; | break; | ||||
case SIOCSIFCAP: | case SIOCSIFCAP: | ||||
{ | { | ||||
int reqcap = ifr->ifr_reqcap; | int reqcap = ifr->ifr_reqcap; | ||||
int capchg_mask; | int capchg_mask; | ||||
SFXGE_ADAPTER_LOCK(sc); | SFXGE_ADAPTER_LOCK(sc); | ||||
/* Capabilities to be changed in accordance with request */ | /* Capabilities to be changed in accordance with request */ | ||||
capchg_mask = ifp->if_capenable ^ reqcap; | capchg_mask = if_getcapenable(ifp) ^ reqcap; | ||||
/* | /* | ||||
* The networking core already rejects attempts to | * The networking core already rejects attempts to | ||||
* enable capabilities we don't have. We still have | * enable capabilities we don't have. We still have | ||||
* to reject attempts to disable capabilities that we | * to reject attempts to disable capabilities that we | ||||
* can't (yet) disable. | * can't (yet) disable. | ||||
*/ | */ | ||||
KASSERT((reqcap & ~ifp->if_capabilities) == 0, | KASSERT((reqcap & ~if_getcapabilities(ifp)) == 0, | ||||
("Unsupported capabilities 0x%x requested 0x%x vs " | ("Unsupported capabilities 0x%x requested 0x%x vs " | ||||
"supported 0x%x", | "supported 0x%x", | ||||
reqcap & ~ifp->if_capabilities, | reqcap & ~if_getcapabilities(ifp), | ||||
reqcap , ifp->if_capabilities)); | reqcap , if_getcapabilities(ifp))); | ||||
if (capchg_mask & SFXGE_CAP_FIXED) { | if (capchg_mask & SFXGE_CAP_FIXED) { | ||||
error = EINVAL; | error = EINVAL; | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
/* Check request before any changes */ | /* Check request before any changes */ | ||||
if ((capchg_mask & IFCAP_TSO4) && | if ((capchg_mask & IFCAP_TSO4) && | ||||
(reqcap & (IFCAP_TSO4 | IFCAP_TXCSUM)) == IFCAP_TSO4) { | (reqcap & (IFCAP_TSO4 | IFCAP_TXCSUM)) == IFCAP_TSO4) { | ||||
error = EAGAIN; | error = EAGAIN; | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
if_printf(ifp, "enable txcsum before tso4\n"); | if_printf(ifp, "enable txcsum before tso4\n"); | ||||
break; | break; | ||||
} | } | ||||
if ((capchg_mask & IFCAP_TSO6) && | if ((capchg_mask & IFCAP_TSO6) && | ||||
(reqcap & (IFCAP_TSO6 | IFCAP_TXCSUM_IPV6)) == IFCAP_TSO6) { | (reqcap & (IFCAP_TSO6 | IFCAP_TXCSUM_IPV6)) == IFCAP_TSO6) { | ||||
error = EAGAIN; | error = EAGAIN; | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
if_printf(ifp, "enable txcsum6 before tso6\n"); | if_printf(ifp, "enable txcsum6 before tso6\n"); | ||||
break; | break; | ||||
} | } | ||||
if (reqcap & IFCAP_TXCSUM) { | if (reqcap & IFCAP_TXCSUM) { | ||||
ifp->if_hwassist |= (CSUM_IP | CSUM_TCP | CSUM_UDP); | if_sethwassistbits(ifp, (CSUM_IP | CSUM_TCP | CSUM_UDP), 0); | ||||
} else { | } else { | ||||
ifp->if_hwassist &= ~(CSUM_IP | CSUM_TCP | CSUM_UDP); | if_sethwassistbits(ifp, 0, (CSUM_IP | CSUM_TCP | CSUM_UDP)); | ||||
if (reqcap & IFCAP_TSO4) { | if (reqcap & IFCAP_TSO4) { | ||||
reqcap &= ~IFCAP_TSO4; | reqcap &= ~IFCAP_TSO4; | ||||
if_printf(ifp, | if_printf(ifp, | ||||
"tso4 disabled due to -txcsum\n"); | "tso4 disabled due to -txcsum\n"); | ||||
} | } | ||||
} | } | ||||
if (reqcap & IFCAP_TXCSUM_IPV6) { | if (reqcap & IFCAP_TXCSUM_IPV6) { | ||||
ifp->if_hwassist |= (CSUM_TCP_IPV6 | CSUM_UDP_IPV6); | if_sethwassistbits(ifp, (CSUM_TCP_IPV6 | CSUM_UDP_IPV6), 0); | ||||
} else { | } else { | ||||
ifp->if_hwassist &= ~(CSUM_TCP_IPV6 | CSUM_UDP_IPV6); | if_sethwassistbits(ifp, 0, (CSUM_TCP_IPV6 | CSUM_UDP_IPV6)); | ||||
if (reqcap & IFCAP_TSO6) { | if (reqcap & IFCAP_TSO6) { | ||||
reqcap &= ~IFCAP_TSO6; | reqcap &= ~IFCAP_TSO6; | ||||
if_printf(ifp, | if_printf(ifp, | ||||
"tso6 disabled due to -txcsum6\n"); | "tso6 disabled due to -txcsum6\n"); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* The kernel takes both IFCAP_TSOx and CSUM_TSO into | * The kernel takes both IFCAP_TSOx and CSUM_TSO into | ||||
* account before using TSO. So, we do not touch | * account before using TSO. So, we do not touch | ||||
* checksum flags when IFCAP_TSOx is modified. | * checksum flags when IFCAP_TSOx is modified. | ||||
* Note that CSUM_TSO is (CSUM_IP_TSO|CSUM_IP6_TSO), | * Note that CSUM_TSO is (CSUM_IP_TSO|CSUM_IP6_TSO), | ||||
* but both bits are set in IPv4 and IPv6 mbufs. | * but both bits are set in IPv4 and IPv6 mbufs. | ||||
*/ | */ | ||||
ifp->if_capenable = reqcap; | if_setcapenable(ifp, reqcap); | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
case SIOCSIFMEDIA: | case SIOCSIFMEDIA: | ||||
case SIOCGIFMEDIA: | case SIOCGIFMEDIA: | ||||
error = ifmedia_ioctl(ifp, ifr, &sc->media, command); | error = ifmedia_ioctl(ifp, ifr, &sc->media, command); | ||||
break; | break; | ||||
Show All 38 Lines | #endif | ||||
default: | default: | ||||
error = ether_ioctl(ifp, command, data); | error = ether_ioctl(ifp, command, data); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
sfxge_ifnet_fini(struct ifnet *ifp) | sfxge_ifnet_fini(if_t ifp) | ||||
{ | { | ||||
struct sfxge_softc *sc = ifp->if_softc; | struct sfxge_softc *sc = if_getsoftc(ifp); | ||||
SFXGE_ADAPTER_LOCK(sc); | SFXGE_ADAPTER_LOCK(sc); | ||||
sfxge_stop(sc); | sfxge_stop(sc); | ||||
SFXGE_ADAPTER_UNLOCK(sc); | SFXGE_ADAPTER_UNLOCK(sc); | ||||
ifmedia_removeall(&sc->media); | ifmedia_removeall(&sc->media); | ||||
ether_ifdetach(ifp); | ether_ifdetach(ifp); | ||||
if_free(ifp); | if_free(ifp); | ||||
} | } | ||||
static int | static int | ||||
sfxge_ifnet_init(struct ifnet *ifp, struct sfxge_softc *sc) | sfxge_ifnet_init(if_t ifp, struct sfxge_softc *sc) | ||||
{ | { | ||||
const efx_nic_cfg_t *encp = efx_nic_cfg_get(sc->enp); | const efx_nic_cfg_t *encp = efx_nic_cfg_get(sc->enp); | ||||
device_t dev; | device_t dev; | ||||
int rc; | int rc; | ||||
dev = sc->dev; | dev = sc->dev; | ||||
sc->ifnet = ifp; | sc->ifnet = ifp; | ||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | ||||
ifp->if_init = sfxge_if_init; | if_setinitfn(ifp, sfxge_if_init); | ||||
ifp->if_softc = sc; | if_setsoftc(ifp, sc); | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); | ||||
ifp->if_ioctl = sfxge_if_ioctl; | if_setioctlfn(ifp, sfxge_if_ioctl); | ||||
ifp->if_capabilities = SFXGE_CAP; | if_setcapabilities(ifp, SFXGE_CAP); | ||||
ifp->if_capenable = SFXGE_CAP_ENABLE; | if_setcapenable(ifp, SFXGE_CAP_ENABLE); | ||||
ifp->if_hw_tsomax = SFXGE_TSO_MAX_SIZE; | if_sethwtsomax(ifp, SFXGE_TSO_MAX_SIZE); | ||||
ifp->if_hw_tsomaxsegcount = SFXGE_TX_MAPPING_MAX_SEG; | if_sethwtsomaxsegcount(ifp, SFXGE_TX_MAPPING_MAX_SEG); | ||||
ifp->if_hw_tsomaxsegsize = PAGE_SIZE; | if_sethwtsomaxsegsize(ifp, PAGE_SIZE); | ||||
#ifdef SFXGE_LRO | #ifdef SFXGE_LRO | ||||
ifp->if_capabilities |= IFCAP_LRO; | if_setcapabilitiesbit(ifp, IFCAP_LRO, 0); | ||||
ifp->if_capenable |= IFCAP_LRO; | if_setcapenablebit(ifp, IFCAP_LRO, 0); | ||||
#endif | #endif | ||||
if (encp->enc_hw_tx_insert_vlan_enabled) { | if (encp->enc_hw_tx_insert_vlan_enabled) { | ||||
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; | if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWTAGGING, 0); | ||||
ifp->if_capenable |= IFCAP_VLAN_HWTAGGING; | if_setcapenablebit(ifp, IFCAP_VLAN_HWTAGGING, 0); | ||||
} | } | ||||
ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO | | if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO | | ||||
CSUM_TCP_IPV6 | CSUM_UDP_IPV6; | CSUM_TCP_IPV6 | CSUM_UDP_IPV6, 0); | ||||
ether_ifattach(ifp, encp->enc_mac_addr); | ether_ifattach(ifp, encp->enc_mac_addr); | ||||
ifp->if_transmit = sfxge_if_transmit; | if_settransmitfn(ifp, sfxge_if_transmit); | ||||
ifp->if_qflush = sfxge_if_qflush; | if_setqflushfn(ifp, sfxge_if_qflush); | ||||
ifp->if_get_counter = sfxge_get_counter; | if_setgetcounterfn(ifp, sfxge_get_counter); | ||||
DBGPRINT(sc->dev, "ifmedia_init"); | DBGPRINT(sc->dev, "ifmedia_init"); | ||||
if ((rc = sfxge_port_ifmedia_init(sc)) != 0) | if ((rc = sfxge_port_ifmedia_init(sc)) != 0) | ||||
goto fail; | goto fail; | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
▲ Show 20 Lines • Show All 440 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
taskqueue_enqueue(taskqueue_thread, &sc->task_reset); | taskqueue_enqueue(taskqueue_thread, &sc->task_reset); | ||||
} | } | ||||
static int | static int | ||||
sfxge_attach(device_t dev) | sfxge_attach(device_t dev) | ||||
{ | { | ||||
struct sfxge_softc *sc; | struct sfxge_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
int error; | int error; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
/* Allocate ifnet. */ | /* Allocate ifnet. */ | ||||
ifp = if_alloc(IFT_ETHER); | ifp = if_alloc(IFT_ETHER); | ||||
if (ifp == NULL) { | if (ifp == NULL) { | ||||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |