Date: Fri, 17 Apr 2015 08:21:04 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r281646 - in projects/ifnet/sys: amd64/conf dev/alc i386/conf Message-ID: <201504170821.t3H8L4km023959@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Fri Apr 17 08:21:04 2015 New Revision: 281646 URL: https://svnweb.freebsd.org/changeset/base/281646 Log: Convert alc(4). Not tested. Sponsored by: Netflix Sponsored by: Nginx, Inc. Modified: projects/ifnet/sys/amd64/conf/IFNET projects/ifnet/sys/dev/alc/if_alc.c projects/ifnet/sys/dev/alc/if_alcvar.h projects/ifnet/sys/i386/conf/IFNET Modified: projects/ifnet/sys/amd64/conf/IFNET ============================================================================== --- projects/ifnet/sys/amd64/conf/IFNET Fri Apr 17 07:11:10 2015 (r281645) +++ projects/ifnet/sys/amd64/conf/IFNET Fri Apr 17 08:21:04 2015 (r281646) @@ -40,7 +40,6 @@ nodevice ale nodevice age nodevice cas nodevice nge -nodevice alc nodevice sis nodevice sf nodevice ae Modified: projects/ifnet/sys/dev/alc/if_alc.c ============================================================================== --- projects/ifnet/sys/dev/alc/if_alc.c Fri Apr 17 07:11:10 2015 (r281645) +++ projects/ifnet/sys/dev/alc/if_alc.c Fri Apr 17 08:21:04 2015 (r281646) @@ -47,16 +47,10 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/taskqueue.h> -#include <net/bpf.h> #include <net/if.h> -#include <net/if_var.h> -#include <net/if_arp.h> -#include <net/ethernet.h> #include <net/if_dl.h> -#include <net/if_llc.h> #include <net/if_media.h> -#include <net/if_types.h> -#include <net/if_vlan_var.h> +#include <net/ethernet.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -141,22 +135,21 @@ static struct alc_ident * alc_find_ident(device_t); #ifndef __NO_STRICT_ALIGNMENT static struct mbuf * - alc_fixup_rx(struct ifnet *, struct mbuf *); + alc_fixup_rx(if_t, struct mbuf *); #endif static void alc_get_macaddr(struct alc_softc *); static void alc_get_macaddr_813x(struct alc_softc *); static void alc_get_macaddr_816x(struct alc_softc *); static void alc_get_macaddr_par(struct alc_softc *); -static void alc_init(void *); static void alc_init_cmb(struct alc_softc *); -static void alc_init_locked(struct alc_softc *); +static void alc_init(struct alc_softc *); static void alc_init_rr_ring(struct alc_softc *); static int alc_init_rx_ring(struct alc_softc *); static void alc_init_smb(struct alc_softc *); static void alc_init_tx_ring(struct alc_softc *); static void alc_int_task(void *, int); static int alc_intr(void *); -static int alc_ioctl(struct ifnet *, u_long, caddr_t); +static int alc_ioctl(if_t, u_long, void *, struct thread *); static void alc_mac_config(struct alc_softc *); static uint32_t alc_mii_readreg_813x(struct alc_softc *, int, int); static uint32_t alc_mii_readreg_816x(struct alc_softc *, int, int); @@ -169,9 +162,9 @@ static uint32_t alc_miidbg_readreg(struc static uint32_t alc_miidbg_writereg(struct alc_softc *, int, int); static uint32_t alc_miiext_readreg(struct alc_softc *, int, int); static uint32_t alc_miiext_writereg(struct alc_softc *, int, int, int); -static int alc_mediachange(struct ifnet *); +static int alc_mediachange(if_t); static int alc_mediachange_locked(struct alc_softc *); -static void alc_mediastatus(struct ifnet *, struct ifmediareq *); +static void alc_mediastatus(if_t, struct ifmediareq *); static int alc_newbuf(struct alc_softc *, struct alc_rxdesc *); static void alc_osc_reset(struct alc_softc *); static void alc_phy_down(struct alc_softc *); @@ -190,8 +183,8 @@ static void alc_setwol(struct alc_softc static void alc_setwol_813x(struct alc_softc *); static void alc_setwol_816x(struct alc_softc *); static int alc_shutdown(device_t); -static void alc_start(struct ifnet *); -static void alc_start_locked(struct ifnet *); +static int alc_transmit(if_t, struct mbuf *); +static int alc_start(struct alc_softc *); static void alc_start_queue(struct alc_softc *); static void alc_stats_clear(struct alc_softc *); static void alc_stats_update(struct alc_softc *); @@ -235,6 +228,17 @@ static devclass_t alc_devclass; DRIVER_MODULE(alc, pci, alc_driver, alc_devclass, 0, 0); DRIVER_MODULE(miibus, alc, miibus_driver, miibus_devclass, 0, 0); +static struct ifdriver alc_ifdrv = { + .ifdrv_ops = { + .ifop_ioctl = alc_ioctl, + .ifop_transmit = alc_transmit, + }, + .ifdrv_name = "alc", + .ifdrv_type = IFT_ETHER, + .ifdrv_hdrlen = sizeof(struct ether_vlan_header), + .ifdrv_maxqlen = ALC_TX_RING_CNT - 1, +}; + static struct resource_spec alc_res_spec_mem[] = { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -398,15 +402,11 @@ alc_miibus_statchg(device_t dev) { struct alc_softc *sc; struct mii_data *mii; - struct ifnet *ifp; uint32_t reg; sc = device_get_softc(dev); - mii = device_get_softc(sc->alc_miibus); - ifp = sc->alc_ifp; - if (mii == NULL || ifp == NULL || - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if (mii == NULL || (sc->alc_flags & ALC_FLAG_RUNNING) == 0) return; sc->alc_flags &= ~ALC_FLAG_LINK; @@ -593,14 +593,14 @@ alc_dsp_fixup(struct alc_softc *sc, int } static void -alc_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) +alc_mediastatus(if_t ifp, struct ifmediareq *ifmr) { struct alc_softc *sc; struct mii_data *mii; - sc = ifp->if_softc; + sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); ALC_LOCK(sc); - if ((ifp->if_flags & IFF_UP) == 0) { + if ((sc->alc_if_flags & IFF_UP) == 0) { ALC_UNLOCK(sc); return; } @@ -613,12 +613,12 @@ alc_mediastatus(struct ifnet *ifp, struc } static int -alc_mediachange(struct ifnet *ifp) +alc_mediachange(if_t ifp) { struct alc_softc *sc; int error; - sc = ifp->if_softc; + sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); ALC_LOCK(sc); error = alc_mediachange_locked(sc); ALC_UNLOCK(sc); @@ -1246,7 +1246,7 @@ alc_aspm_816x(struct alc_softc *sc, int if (init != 0) pmcfg |= PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK; - else if ((sc->alc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + else if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) pmcfg |= PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK; } CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg); @@ -1360,8 +1360,16 @@ alc_config_msi(struct alc_softc *sc) static int alc_attach(device_t dev) { + struct if_attach_args ifat = { + .ifat_version = IF_ATTACH_VERSION, + .ifat_drv = &alc_ifdrv, + .ifat_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST, + .ifat_capabilities = IFCAP_TXCSUM | IFCAP_TSO4 | + IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO, + .ifat_hwassist = ALC_CSUM_FEATURES | CSUM_TSO, + }; struct alc_softc *sc; - struct ifnet *ifp; int base, error, i, msic, msixc; uint16_t burst; @@ -1538,33 +1546,8 @@ alc_attach(device_t dev) /* Load station address. */ alc_get_macaddr(sc); - ifp = sc->alc_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(dev, "cannot allocate ifnet structure.\n"); - error = ENXIO; - goto fail; - } - - ifp->if_softc = sc; - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = alc_ioctl; - ifp->if_start = alc_start; - ifp->if_init = alc_init; - ifp->if_snd.ifq_drv_maxlen = ALC_TX_RING_CNT - 1; - IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); - IFQ_SET_READY(&ifp->if_snd); - ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_TSO4; - ifp->if_hwassist = ALC_CSUM_FEATURES | CSUM_TSO; - if (pci_find_cap(dev, PCIY_PMG, &base) == 0) { - ifp->if_capabilities |= IFCAP_WOL_MAGIC | IFCAP_WOL_MCAST; - sc->alc_flags |= ALC_FLAG_PM; - sc->alc_pmcap = base; - } - ifp->if_capenable = ifp->if_capabilities; - /* Set up MII bus. */ - error = mii_attach(dev, &sc->alc_miibus, ifp, alc_mediachange, + error = mii_attach(dev, &sc->alc_miibus, alc_mediachange, alc_mediastatus, BMSR_DEFCAPMASK, sc->alc_phyaddr, MII_OFFSET_ANY, MIIF_DOPAUSE); if (error != 0) { @@ -1572,38 +1555,11 @@ alc_attach(device_t dev) goto fail; } - ether_ifattach(ifp, sc->alc_eaddr); - - /* VLAN capability setup. */ - ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | - IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO; - ifp->if_capenable = ifp->if_capabilities; - /* - * XXX - * It seems enabling Tx checksum offloading makes more trouble. - * Sometimes the controller does not receive any frames when - * Tx checksum offloading is enabled. I'm not sure whether this - * is a bug in Tx checksum offloading logic or I got broken - * sample boards. To safety, don't enable Tx checksum offloading - * by default but give chance to users to toggle it if they know - * their controllers work without problems. - * Fortunately, Tx checksum offloading for AR816x family - * seems to work. - */ - if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) { - ifp->if_capenable &= ~IFCAP_TXCSUM; - ifp->if_hwassist &= ~ALC_CSUM_FEATURES; - } - - /* Tell the upper layer(s) we support long frames. */ - ifp->if_hdrlen = sizeof(struct ether_vlan_header); - /* Create local taskq. */ sc->alc_tq = taskqueue_create_fast("alc_taskq", M_WAITOK, taskqueue_thread_enqueue, &sc->alc_tq); if (sc->alc_tq == NULL) { device_printf(dev, "could not create taskqueue.\n"); - ether_ifdetach(ifp); error = ENXIO; goto fail; } @@ -1628,14 +1584,39 @@ alc_attach(device_t dev) device_printf(dev, "could not set up interrupt handler.\n"); taskqueue_free(sc->alc_tq); sc->alc_tq = NULL; - ether_ifdetach(ifp); goto fail; } -fail: - if (error != 0) - alc_detach(dev); + ifat.ifat_softc = sc; + ifat.ifat_dunit = device_get_unit(dev); + ifat.ifat_lla = sc->alc_eaddr; + if (pci_find_cap(dev, PCIY_PMG, &base) == 0) { + ifat.ifat_capabilities |= IFCAP_WOL_MAGIC | IFCAP_WOL_MCAST; + sc->alc_flags |= ALC_FLAG_PM; + sc->alc_pmcap = base; + } + ifat.ifat_capenable = ifat.ifat_capabilities; + /* + * XXX + * It seems enabling Tx checksum offloading makes more trouble. + * Sometimes the controller does not receive any frames when + * Tx checksum offloading is enabled. I'm not sure whether this + * is a bug in Tx checksum offloading logic or I got broken + * sample boards. To safety, don't enable Tx checksum offloading + * by default but give chance to users to toggle it if they know + * their controllers work without problems. + * Fortunately, Tx checksum offloading for AR816x family + * seems to work. + */ + if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) { + ifat.ifat_capenable &= ~IFCAP_TXCSUM; + ifat.ifat_hwassist &= ~ALC_CSUM_FEATURES; + } + sc->alc_ifp = if_attach(&ifat); + return (0); +fail: + alc_detach(dev); return (error); } @@ -1643,14 +1624,11 @@ static int alc_detach(device_t dev) { struct alc_softc *sc; - struct ifnet *ifp; int i, msic; sc = device_get_softc(dev); - ifp = sc->alc_ifp; if (device_is_attached(dev)) { - ether_ifdetach(ifp); ALC_LOCK(sc); alc_stop(sc); ALC_UNLOCK(sc); @@ -1671,10 +1649,8 @@ alc_detach(device_t dev) bus_generic_detach(dev); alc_dma_free(sc); - if (ifp != NULL) { - if_free(ifp); - sc->alc_ifp = NULL; - } + if (sc->alc_ifp != NULL) + if_detach(sc->alc_ifp); if ((sc->alc_flags & ALC_FLAG_MSIX) != 0) msic = ALC_MSIX_MESSAGES; @@ -2495,14 +2471,12 @@ alc_setwol(struct alc_softc *sc) static void alc_setwol_813x(struct alc_softc *sc) { - struct ifnet *ifp; uint32_t reg, pmcs; uint16_t pmstat; ALC_LOCK_ASSERT(sc); alc_disable_l0s_l1(sc); - ifp = sc->alc_ifp; if ((sc->alc_flags & ALC_FLAG_PM) == 0) { /* Disable WOL. */ CSR_WRITE_4(sc, ALC_WOL_CFG, 0); @@ -2516,7 +2490,7 @@ alc_setwol_813x(struct alc_softc *sc) return; } - if ((ifp->if_capenable & IFCAP_WOL) != 0) { + if ((sc->alc_capenable & IFCAP_WOL) != 0) { if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0) alc_setlinkspeed(sc); CSR_WRITE_4(sc, ALC_MASTER_CFG, @@ -2524,22 +2498,22 @@ alc_setwol_813x(struct alc_softc *sc) } pmcs = 0; - if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + if ((sc->alc_capenable & IFCAP_WOL_MAGIC) != 0) pmcs |= WOL_CFG_MAGIC | WOL_CFG_MAGIC_ENB; CSR_WRITE_4(sc, ALC_WOL_CFG, pmcs); reg = CSR_READ_4(sc, ALC_MAC_CFG); reg &= ~(MAC_CFG_DBG | MAC_CFG_PROMISC | MAC_CFG_ALLMULTI | MAC_CFG_BCAST); - if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0) + if ((sc->alc_capenable & IFCAP_WOL_MCAST) != 0) reg |= MAC_CFG_ALLMULTI | MAC_CFG_BCAST; - if ((ifp->if_capenable & IFCAP_WOL) != 0) + if ((sc->alc_capenable & IFCAP_WOL) != 0) reg |= MAC_CFG_RX_ENB; CSR_WRITE_4(sc, ALC_MAC_CFG, reg); reg = CSR_READ_4(sc, ALC_PCIE_PHYMISC); reg |= PCIE_PHYMISC_FORCE_RCV_DET; CSR_WRITE_4(sc, ALC_PCIE_PHYMISC, reg); - if ((ifp->if_capenable & IFCAP_WOL) == 0) { + if ((sc->alc_capenable & IFCAP_WOL) == 0) { /* WOL disabled, PHY power down. */ alc_phy_down(sc); CSR_WRITE_4(sc, ALC_MASTER_CFG, @@ -2549,7 +2523,7 @@ alc_setwol_813x(struct alc_softc *sc) pmstat = pci_read_config(sc->alc_dev, sc->alc_pmcap + PCIR_POWER_STATUS, 2); pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); - if ((ifp->if_capenable & IFCAP_WOL) != 0) + if ((sc->alc_capenable & IFCAP_WOL) != 0) pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; pci_write_config(sc->alc_dev, sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2); @@ -2558,13 +2532,11 @@ alc_setwol_813x(struct alc_softc *sc) static void alc_setwol_816x(struct alc_softc *sc) { - struct ifnet *ifp; uint32_t gphy, mac, master, pmcs, reg; uint16_t pmstat; ALC_LOCK_ASSERT(sc); - ifp = sc->alc_ifp; master = CSR_READ_4(sc, ALC_MASTER_CFG); master &= ~MASTER_CLK_SEL_DIS; gphy = CSR_READ_4(sc, ALC_GPHY_CFG); @@ -2576,21 +2548,21 @@ alc_setwol_816x(struct alc_softc *sc) gphy |= GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW; mac = CSR_READ_4(sc, ALC_MAC_CFG); } else { - if ((ifp->if_capenable & IFCAP_WOL) != 0) { + if ((sc->alc_capenable & IFCAP_WOL) != 0) { gphy |= GPHY_CFG_EXT_RESET; if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0) alc_setlinkspeed(sc); } pmcs = 0; - if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + if ((sc->alc_capenable & IFCAP_WOL_MAGIC) != 0) pmcs |= WOL_CFG_MAGIC | WOL_CFG_MAGIC_ENB; CSR_WRITE_4(sc, ALC_WOL_CFG, pmcs); mac = CSR_READ_4(sc, ALC_MAC_CFG); mac &= ~(MAC_CFG_DBG | MAC_CFG_PROMISC | MAC_CFG_ALLMULTI | MAC_CFG_BCAST); - if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0) + if ((sc->alc_capenable & IFCAP_WOL_MCAST) != 0) mac |= MAC_CFG_ALLMULTI | MAC_CFG_BCAST; - if ((ifp->if_capenable & IFCAP_WOL) != 0) + if ((sc->alc_capenable & IFCAP_WOL) != 0) mac |= MAC_CFG_RX_ENB; alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_S3DIG10, ANEG_S3DIG10_SL); @@ -2614,7 +2586,7 @@ alc_setwol_816x(struct alc_softc *sc) pmstat = pci_read_config(sc->alc_dev, sc->alc_pmcap + PCIR_POWER_STATUS, 2); pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); - if ((ifp->if_capenable & IFCAP_WOL) != 0) + if ((sc->alc_capenable & IFCAP_WOL) != 0) pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; pci_write_config(sc->alc_dev, sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2); @@ -2640,7 +2612,6 @@ static int alc_resume(device_t dev) { struct alc_softc *sc; - struct ifnet *ifp; uint16_t pmstat; sc = device_get_softc(dev); @@ -2658,10 +2629,9 @@ alc_resume(device_t dev) } /* Reset PHY. */ alc_phy_reset(sc); - ifp = sc->alc_ifp; - if ((ifp->if_flags & IFF_UP) != 0) { - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - alc_init_locked(sc); + if ((sc->alc_if_flags & IFF_UP) != 0) { + sc->alc_flags &= ~ALC_FLAG_RUNNING; + alc_init(sc); } ALC_UNLOCK(sc); @@ -2900,59 +2870,54 @@ alc_encap(struct alc_softc *sc, struct m return (0); } -static void -alc_start(struct ifnet *ifp) +static int +alc_transmit(if_t ifp, struct mbuf *m) { struct alc_softc *sc; + int error; - sc = ifp->if_softc; + if ((error = if_snd_enqueue(ifp, m)) != 0) + return (error); + + sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); ALC_LOCK(sc); - alc_start_locked(ifp); + error = alc_start(sc); ALC_UNLOCK(sc); + return (error); } -static void -alc_start_locked(struct ifnet *ifp) +static int +alc_start(struct alc_softc *sc) { - struct alc_softc *sc; - struct mbuf *m_head; + struct mbuf *m; int enq; - sc = ifp->if_softc; - ALC_LOCK_ASSERT(sc); /* Reclaim transmitted frames. */ if (sc->alc_cdata.alc_tx_cnt >= ALC_TX_DESC_HIWAT) alc_txeof(sc); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING || (sc->alc_flags & ALC_FLAG_LINK) == 0) - return; + if ((sc->alc_flags & (ALC_FLAG_LINK | ALC_FLAG_RUNNING)) != + (ALC_FLAG_LINK | ALC_FLAG_RUNNING)) + return (ENETDOWN); - for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) - break; + enq = 0; + while ((m = if_snd_dequeue(sc->alc_ifp)) != NULL) { /* * Pack the data into the transmit ring. If we * don't have room, set the OACTIVE flag and wait * for the NIC to drain the ring. */ - if (alc_encap(sc, &m_head)) { - if (m_head == NULL) + if (alc_encap(sc, &m)) { + if (m == NULL) break; - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + if_snd_prepend(sc->alc_ifp, m); break; } enq++; - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - ETHER_BPF_MTAP(ifp, m_head); + if_mtap(sc->alc_ifp, m, NULL, 0); } if (enq > 0) { @@ -2971,12 +2936,14 @@ alc_start_locked(struct ifnet *ifp) /* Set a timeout in case the chip goes out to lunch. */ sc->alc_watchdog_timer = ALC_TX_TIMEOUT; } + + return (0); } static void alc_watchdog(struct alc_softc *sc) { - struct ifnet *ifp; + if_t ifp; ALC_LOCK_ASSERT(sc); @@ -2985,30 +2952,31 @@ alc_watchdog(struct alc_softc *sc) ifp = sc->alc_ifp; if ((sc->alc_flags & ALC_FLAG_LINK) == 0) { - if_printf(sc->alc_ifp, "watchdog timeout (lost link)\n"); + if_printf(ifp, "watchdog timeout (lost link)\n"); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - alc_init_locked(sc); + sc->alc_flags &= ~ALC_FLAG_RUNNING; + alc_init(sc); return; } - if_printf(sc->alc_ifp, "watchdog timeout -- resetting\n"); + if_printf(ifp, "watchdog timeout -- resetting\n"); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - alc_init_locked(sc); - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - alc_start_locked(ifp); + sc->alc_flags &= ~ALC_FLAG_RUNNING; + alc_init(sc); + if (if_snd_len(ifp)) + alc_start(sc); } static int -alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +alc_ioctl(if_t ifp, u_long cmd, void *data, struct thread *td) { struct alc_softc *sc; struct ifreq *ifr; struct mii_data *mii; + uint32_t oflags; int error, mask; - sc = ifp->if_softc; - ifr = (struct ifreq *)data; + sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); + ifr = data; error = 0; switch (cmd) { case SIOCSIFMTU: @@ -3017,38 +2985,37 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, sizeof(struct ether_vlan_header) - ETHER_CRC_LEN) || ((sc->alc_flags & ALC_FLAG_JUMBO) == 0 && ifr->ifr_mtu > ETHERMTU)) - error = EINVAL; - else if (ifp->if_mtu != ifr->ifr_mtu) { - ALC_LOCK(sc); - ifp->if_mtu = ifr->ifr_mtu; - /* AR81[3567]x has 13 bits MSS field. */ - if (ifp->if_mtu > ALC_TSO_MTU && - (ifp->if_capenable & IFCAP_TSO4) != 0) { - ifp->if_capenable &= ~IFCAP_TSO4; - ifp->if_hwassist &= ~CSUM_TSO; - VLAN_CAPABILITIES(ifp); - } - ALC_UNLOCK(sc); + return (EINVAL); + /* AR81[3567]x has 13 bits MSS field. */ + if (ifr->ifr_mtu > ALC_TSO_MTU && + (sc->alc_capenable & IFCAP_TSO4) != 0) { + struct ifreq tmp; + + if_drvioctl(ifp, SIOCGIFCAP, &tmp, td); + tmp.ifr_reqcap &= ~IFCAP_TSO4; + if_drvioctl(ifp, SIOCSIFCAP, &tmp, td); } + sc->alc_mtu = ifr->ifr_mtu; break; case SIOCSIFFLAGS: ALC_LOCK(sc); - if ((ifp->if_flags & IFF_UP) != 0) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && - ((ifp->if_flags ^ sc->alc_if_flags) & + oflags = sc->alc_if_flags; + sc->alc_if_flags = ifr->ifr_flags; + if ((sc->alc_if_flags & IFF_UP) != 0) { + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0 && + ((oflags ^ sc->alc_if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) != 0) alc_rxfilter(sc); else - alc_init_locked(sc); - } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + alc_init(sc); + } else if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) alc_stop(sc); - sc->alc_if_flags = ifp->if_flags; ALC_UNLOCK(sc); break; case SIOCADDMULTI: case SIOCDELMULTI: ALC_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) alc_rxfilter(sc); ALC_UNLOCK(sc); break; @@ -3059,53 +3026,26 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, break; case SIOCSIFCAP: ALC_LOCK(sc); - mask = ifr->ifr_reqcap ^ ifp->if_capenable; - 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 |= ALC_CSUM_FEATURES; - else - ifp->if_hwassist &= ~ALC_CSUM_FEATURES; - } - if ((mask & IFCAP_TSO4) != 0 && - (ifp->if_capabilities & IFCAP_TSO4) != 0) { - ifp->if_capenable ^= IFCAP_TSO4; - if ((ifp->if_capenable & IFCAP_TSO4) != 0) { - /* AR81[3567]x has 13 bits MSS field. */ - if (ifp->if_mtu > ALC_TSO_MTU) { - ifp->if_capenable &= ~IFCAP_TSO4; - ifp->if_hwassist &= ~CSUM_TSO; - } else - ifp->if_hwassist |= CSUM_TSO; - } else - ifp->if_hwassist &= ~CSUM_TSO; + mask = ifr->ifr_reqcap ^ ifr->ifr_curcap; + ifr->ifr_hwassist = 0; + if ((ifr->ifr_reqcap & IFCAP_TXCSUM) != 0) + ifr->ifr_hwassist |= ALC_CSUM_FEATURES; + if ((ifr->ifr_reqcap & IFCAP_TSO4) != 0) { + /* AR81[3567]x has 13 bits MSS field. */ + if (sc->alc_mtu > ALC_TSO_MTU) { + error = EINVAL; + ALC_UNLOCK(sc); + break; + } + ifr->ifr_hwassist |= CSUM_TSO; } - if ((mask & IFCAP_WOL_MCAST) != 0 && - (ifp->if_capabilities & IFCAP_WOL_MCAST) != 0) - ifp->if_capenable ^= IFCAP_WOL_MCAST; - if ((mask & IFCAP_WOL_MAGIC) != 0 && - (ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0) - ifp->if_capenable ^= IFCAP_WOL_MAGIC; - if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && - (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { - ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + sc->alc_capenable = ifr->ifr_reqcap; + if ((mask & IFCAP_VLAN_HWTAGGING) != 0) alc_rxvlan(sc); - } - if ((mask & IFCAP_VLAN_HWCSUM) != 0 && - (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0) - ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; - if ((mask & IFCAP_VLAN_HWTSO) != 0 && - (ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0) - ifp->if_capenable ^= IFCAP_VLAN_HWTSO; - if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) - ifp->if_capenable &= - ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM); ALC_UNLOCK(sc); - VLAN_CAPABILITIES(ifp); break; default: - error = ether_ioctl(ifp, cmd, data); + error = EOPNOTSUPP; break; } @@ -3186,7 +3126,7 @@ alc_stats_update(struct alc_softc *sc) { struct alc_hw_stats *stat; struct smb sb, *smb; - struct ifnet *ifp; + if_t ifp; uint32_t *reg; int i; @@ -3319,7 +3259,7 @@ static void alc_int_task(void *arg, int pending) { struct alc_softc *sc; - struct ifnet *ifp; + if_t ifp; uint32_t status; int more; @@ -3339,14 +3279,14 @@ alc_int_task(void *arg, int pending) CSR_WRITE_4(sc, ALC_INTR_STATUS, status | INTR_DIS_INT); more = 0; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) { if ((status & INTR_RX_PKT) != 0) { more = alc_rxintr(sc, sc->alc_process_limit); if (more == EAGAIN) sc->alc_morework = 1; else if (more == EIO) { - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - alc_init_locked(sc); + sc->alc_flags &= ~ALC_FLAG_RUNNING; + alc_init(sc); ALC_UNLOCK(sc); return; } @@ -3362,14 +3302,13 @@ alc_int_task(void *arg, int pending) if ((status & INTR_TXQ_TO_RST) != 0) device_printf(sc->alc_dev, "TxQ reset! -- resetting\n"); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - alc_init_locked(sc); + sc->alc_flags &= ~ALC_FLAG_RUNNING; + alc_init(sc); ALC_UNLOCK(sc); return; } - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && - !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - alc_start_locked(ifp); + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0 && if_snd_len(ifp)) + alc_start(sc); } if (more == EAGAIN || @@ -3380,7 +3319,7 @@ alc_int_task(void *arg, int pending) } done: - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) { /* Re-enable interrupts if we're running. */ CSR_WRITE_4(sc, ALC_INTR_STATUS, 0x7FFFFFFF); } @@ -3390,15 +3329,12 @@ done: static void alc_txeof(struct alc_softc *sc) { - struct ifnet *ifp; struct alc_txdesc *txd; uint32_t cons, prod; int prog; ALC_LOCK_ASSERT(sc); - ifp = sc->alc_ifp; - if (sc->alc_cdata.alc_tx_cnt == 0) return; bus_dmamap_sync(sc->alc_cdata.alc_tx_ring_tag, @@ -3427,7 +3363,6 @@ alc_txeof(struct alc_softc *sc) if (sc->alc_cdata.alc_tx_cnt <= 0) break; prog++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; sc->alc_cdata.alc_tx_cnt--; txd = &sc->alc_cdata.alc_txdesc[cons]; if (txd->tx_m != NULL) { @@ -3494,7 +3429,6 @@ alc_newbuf(struct alc_softc *sc, struct static int alc_rxintr(struct alc_softc *sc, int count) { - struct ifnet *ifp; struct rx_rdesc *rrd; uint32_t nsegs, status; int rr_cons, prog; @@ -3505,8 +3439,7 @@ alc_rxintr(struct alc_softc *sc, int cou bus_dmamap_sync(sc->alc_cdata.alc_rx_ring_tag, sc->alc_cdata.alc_rx_ring_map, BUS_DMASYNC_POSTWRITE); rr_cons = sc->alc_cdata.alc_rr_cons; - ifp = sc->alc_ifp; - for (prog = 0; (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;) { + for (prog = 0; (sc->alc_flags & ALC_FLAG_RUNNING) != 0;) { if (count-- <= 0) break; rrd = &sc->alc_rdata.alc_rr_ring[rr_cons]; @@ -3565,7 +3498,7 @@ alc_rxintr(struct alc_softc *sc, int cou #ifndef __NO_STRICT_ALIGNMENT static struct mbuf * -alc_fixup_rx(struct ifnet *ifp, struct mbuf *m) +alc_fixup_rx(if_t ifp, struct mbuf *m) { struct mbuf *n; int i; @@ -3606,7 +3539,7 @@ static void alc_rxeof(struct alc_softc *sc, struct rx_rdesc *rrd) { struct alc_rxdesc *rxd; - struct ifnet *ifp; + if_t ifp; struct mbuf *mp, *m; uint32_t rdinfo, status, vtag; int count, nsegs, rx_cons; @@ -3701,7 +3634,7 @@ alc_rxeof(struct alc_softc *sc, struct r * Due to hardware bugs, Rx checksum offloading * was intentionally disabled. */ - if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + if ((sc->alc_capenable & IFCAP_VLAN_HWTAGGING) != 0 && (status & RRD_VLAN_TAG) != 0) { vtag = RRD_VLAN(le32toh(rrd->vtag)); m->m_pkthdr.ether_vtag = ntohs(vtag); @@ -3714,7 +3647,7 @@ alc_rxeof(struct alc_softc *sc, struct r { /* Pass it on. */ ALC_UNLOCK(sc); - (*ifp->if_input)(ifp, m); + if_input(ifp, m); ALC_LOCK(sc); } } @@ -3872,20 +3805,8 @@ alc_reset(struct alc_softc *sc) } static void -alc_init(void *xsc) +alc_init(struct alc_softc *sc) { - struct alc_softc *sc; - - sc = (struct alc_softc *)xsc; - ALC_LOCK(sc); - alc_init_locked(sc); - ALC_UNLOCK(sc); -} - -static void -alc_init_locked(struct alc_softc *sc) -{ - struct ifnet *ifp; struct mii_data *mii; uint8_t eaddr[ETHER_ADDR_LEN]; bus_addr_t paddr; @@ -3893,10 +3814,9 @@ alc_init_locked(struct alc_softc *sc) ALC_LOCK_ASSERT(sc); - ifp = sc->alc_ifp; mii = device_get_softc(sc->alc_miibus); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if ((sc->alc_flags & ALC_FLAG_RUNNING) != 0) return; /* * Cancel any pending I/O. @@ -3931,7 +3851,7 @@ alc_init_locked(struct alc_softc *sc) CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0); /* Reprogram the station address. */ - bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); + bcopy(if_lladdr(sc->alc_ifp), eaddr, ETHER_ADDR_LEN); CSR_WRITE_4(sc, ALC_PAR0, eaddr[2] << 24 | eaddr[3] << 16 | eaddr[4] << 8 | eaddr[5]); CSR_WRITE_4(sc, ALC_PAR1, eaddr[0] << 8 | eaddr[1]); @@ -4261,9 +4181,7 @@ alc_init_locked(struct alc_softc *sc) CSR_WRITE_4(sc, ALC_INTR_STATUS, 0xFFFFFFFF); CSR_WRITE_4(sc, ALC_INTR_STATUS, 0); - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - + sc->alc_flags |= ALC_FLAG_RUNNING; sc->alc_flags &= ~ALC_FLAG_LINK; /* Switch to the current media. */ alc_mediachange_locked(sc); @@ -4274,7 +4192,6 @@ alc_init_locked(struct alc_softc *sc) static void alc_stop(struct alc_softc *sc) { - struct ifnet *ifp; struct alc_txdesc *txd; struct alc_rxdesc *rxd; uint32_t reg; @@ -4284,9 +4201,7 @@ alc_stop(struct alc_softc *sc) /* * Mark the interface down and cancel the watchdog timer. */ - ifp = sc->alc_ifp; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->alc_flags &= ~ALC_FLAG_LINK; + sc->alc_flags &= ~(ALC_FLAG_LINK | ALC_FLAG_RUNNING); callout_stop(&sc->alc_tick_ch); sc->alc_watchdog_timer = 0; alc_stats_update(sc); @@ -4529,14 +4444,12 @@ alc_init_smb(struct alc_softc *sc) static void alc_rxvlan(struct alc_softc *sc) { - struct ifnet *ifp; uint32_t reg; ALC_LOCK_ASSERT(sc); - ifp = sc->alc_ifp; reg = CSR_READ_4(sc, ALC_MAC_CFG); - if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) + if ((sc->alc_capenable & IFCAP_VLAN_HWTAGGING) != 0) reg |= MAC_CFG_VLAN_TAG_STRIP; else reg &= ~MAC_CFG_VLAN_TAG_STRIP; @@ -4544,43 +4457,42 @@ alc_rxvlan(struct alc_softc *sc) } static void +alc_hash_maddr(void *arg, struct sockaddr *maddr) +{ + struct sockaddr_dl *sdl = (struct sockaddr_dl *)maddr; + uint32_t *mchash, crc; + + if (sdl->sdl_family != AF_LINK) + return; + + mchash = arg; + crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN); + mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); +} + +static void alc_rxfilter(struct alc_softc *sc) { - struct ifnet *ifp; - struct ifmultiaddr *ifma; - uint32_t crc; uint32_t mchash[2]; uint32_t rxcfg; ALC_LOCK_ASSERT(sc); - ifp = sc->alc_ifp; - bzero(mchash, sizeof(mchash)); rxcfg = CSR_READ_4(sc, ALC_MAC_CFG); rxcfg &= ~(MAC_CFG_ALLMULTI | MAC_CFG_BCAST | MAC_CFG_PROMISC); - if ((ifp->if_flags & IFF_BROADCAST) != 0) + if ((sc->alc_if_flags & IFF_BROADCAST) != 0) rxcfg |= MAC_CFG_BCAST; - if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { - if ((ifp->if_flags & IFF_PROMISC) != 0) + if ((sc->alc_if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { + if ((sc->alc_if_flags & IFF_PROMISC) != 0) rxcfg |= MAC_CFG_PROMISC; - if ((ifp->if_flags & IFF_ALLMULTI) != 0) + if ((sc->alc_if_flags & IFF_ALLMULTI) != 0) rxcfg |= MAC_CFG_ALLMULTI; mchash[0] = 0xFFFFFFFF; mchash[1] = 0xFFFFFFFF; goto chipit; } - - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &sc->alc_ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504170821.t3H8L4km023959>