summaryrefslogtreecommitdiffstats
path: root/sys/dev/alc/if_alc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/alc/if_alc.c')
-rw-r--r--sys/dev/alc/if_alc.c59
1 files changed, 30 insertions, 29 deletions
diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c
index 7b23fae..25625c4 100644
--- a/sys/dev/alc/if_alc.c
+++ b/sys/dev/alc/if_alc.c
@@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <machine/atomic.h>
#include <machine/bus.h>
#include <machine/in_cksum.h>
@@ -160,6 +159,7 @@ static void alc_setlinkspeed(struct alc_softc *);
static void alc_setwol(struct alc_softc *);
static int alc_shutdown(device_t);
static void alc_start(struct ifnet *);
+static void alc_start_locked(struct ifnet *);
static void alc_start_queue(struct alc_softc *);
static void alc_stats_clear(struct alc_softc *);
static void alc_stats_update(struct alc_softc *);
@@ -169,7 +169,6 @@ static void alc_stop_queue(struct alc_softc *);
static int alc_suspend(device_t);
static void alc_sysctl_node(struct alc_softc *);
static void alc_tick(void *);
-static void alc_tx_task(void *, int);
static void alc_txeof(struct alc_softc *);
static void alc_watchdog(struct alc_softc *);
static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
@@ -678,7 +677,7 @@ alc_aspm(struct alc_softc *sc, int media)
pmcfg &= ~PM_CFG_SERDES_PD_EX_L1;
pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_LCKDET_TIMER_MASK);
pmcfg |= PM_CFG_MAC_ASPM_CHK;
- pmcfg |= PM_CFG_SERDES_ENB | PM_CFG_RBER_ENB;
+ pmcfg |= (PM_CFG_LCKDET_TIMER_DEFAULT << PM_CFG_LCKDET_TIMER_SHIFT);
pmcfg &= ~(PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
@@ -811,7 +810,7 @@ alc_attach(device_t dev)
CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
PCIE_PHYMISC_FORCE_RCV_DET);
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B &&
- sc->alc_rev == ATHEROS_AR8152_B_V10) {
+ pci_get_revid(dev) == ATHEROS_AR8152_B_V10) {
val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
PCIE_PHYMISC2_SERDES_TH_MASK);
@@ -1003,7 +1002,6 @@ alc_attach(device_t dev)
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
/* Create local taskq. */
- TASK_INIT(&sc->alc_tx_task, 1, alc_tx_task, ifp);
sc->alc_tq = taskqueue_create_fast("alc_taskq", M_WAITOK,
taskqueue_thread_enqueue, &sc->alc_tq);
if (sc->alc_tq == NULL) {
@@ -1054,14 +1052,12 @@ alc_detach(device_t dev)
ifp = sc->alc_ifp;
if (device_is_attached(dev)) {
+ ether_ifdetach(ifp);
ALC_LOCK(sc);
- sc->alc_flags |= ALC_FLAG_DETACH;
alc_stop(sc);
ALC_UNLOCK(sc);
callout_drain(&sc->alc_tick_ch);
taskqueue_drain(sc->alc_tq, &sc->alc_int_task);
- taskqueue_drain(sc->alc_tq, &sc->alc_tx_task);
- ether_ifdetach(ifp);
}
if (sc->alc_tq != NULL) {
@@ -1109,7 +1105,7 @@ alc_detach(device_t dev)
#define ALC_SYSCTL_STAT_ADD32(c, h, n, p, d) \
SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
#define ALC_SYSCTL_STAT_ADD64(c, h, n, p, d) \
- SYSCTL_ADD_QUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d)
+ SYSCTL_ADD_UQUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d)
static void
alc_sysctl_node(struct alc_softc *sc)
@@ -2238,16 +2234,18 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
}
static void
-alc_tx_task(void *arg, int pending)
+alc_start(struct ifnet *ifp)
{
- struct ifnet *ifp;
+ struct alc_softc *sc;
- ifp = (struct ifnet *)arg;
- alc_start(ifp);
+ sc = ifp->if_softc;
+ ALC_LOCK(sc);
+ alc_start_locked(ifp);
+ ALC_UNLOCK(sc);
}
static void
-alc_start(struct ifnet *ifp)
+alc_start_locked(struct ifnet *ifp)
{
struct alc_softc *sc;
struct mbuf *m_head;
@@ -2255,17 +2253,15 @@ alc_start(struct ifnet *ifp)
sc = ifp->if_softc;
- ALC_LOCK(sc);
+ 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) {
- ALC_UNLOCK(sc);
+ IFF_DRV_RUNNING || (sc->alc_flags & ALC_FLAG_LINK) == 0)
return;
- }
for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@@ -2304,8 +2300,6 @@ alc_start(struct ifnet *ifp)
/* Set a timeout in case the chip goes out to lunch. */
sc->alc_watchdog_timer = ALC_TX_TIMEOUT;
}
-
- ALC_UNLOCK(sc);
}
static void
@@ -2331,7 +2325,7 @@ alc_watchdog(struct alc_softc *sc)
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
alc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue(sc->alc_tq, &sc->alc_tx_task);
+ alc_start_locked(ifp);
}
static int
@@ -2373,7 +2367,7 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
((ifp->if_flags ^ sc->alc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI)) != 0)
alc_rxfilter(sc);
- else if ((sc->alc_flags & ALC_FLAG_DETACH) == 0)
+ else
alc_init_locked(sc);
} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
alc_stop(sc);
@@ -2668,9 +2662,11 @@ alc_int_task(void *arg, int pending)
ifp = sc->alc_ifp;
status = CSR_READ_4(sc, ALC_INTR_STATUS);
- more = atomic_readandclear_int(&sc->alc_morework);
- if (more != 0)
+ ALC_LOCK(sc);
+ if (sc->alc_morework != 0) {
+ sc->alc_morework = 0;
status |= INTR_RX_PKT;
+ }
if ((status & ALC_INTRS) == 0)
goto done;
@@ -2682,9 +2678,8 @@ alc_int_task(void *arg, int pending)
if ((status & INTR_RX_PKT) != 0) {
more = alc_rxintr(sc, sc->alc_process_limit);
if (more == EAGAIN)
- atomic_set_int(&sc->alc_morework, 1);
+ sc->alc_morework = 1;
else if (more == EIO) {
- ALC_LOCK(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
alc_init_locked(sc);
ALC_UNLOCK(sc);
@@ -2702,7 +2697,6 @@ alc_int_task(void *arg, int pending)
if ((status & INTR_TXQ_TO_RST) != 0)
device_printf(sc->alc_dev,
"TxQ reset! -- resetting\n");
- ALC_LOCK(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
alc_init_locked(sc);
ALC_UNLOCK(sc);
@@ -2710,11 +2704,12 @@ alc_int_task(void *arg, int pending)
}
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue(sc->alc_tq, &sc->alc_tx_task);
+ alc_start_locked(ifp);
}
if (more == EAGAIN ||
(CSR_READ_4(sc, ALC_INTR_STATUS) & ALC_INTRS) != 0) {
+ ALC_UNLOCK(sc);
taskqueue_enqueue(sc->alc_tq, &sc->alc_int_task);
return;
}
@@ -2724,6 +2719,7 @@ done:
/* Re-enable interrupts if we're running. */
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0x7FFFFFFF);
}
+ ALC_UNLOCK(sc);
}
static void
@@ -3043,7 +3039,9 @@ alc_rxeof(struct alc_softc *sc, struct rx_rdesc *rrd)
#endif
{
/* Pass it on. */
+ ALC_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
+ ALC_LOCK(sc);
}
}
}
@@ -3150,6 +3148,9 @@ alc_init_locked(struct alc_softc *sc)
alc_init_cmb(sc);
alc_init_smb(sc);
+ /* Enable all clocks. */
+ CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
+
/* Reprogram the station address. */
bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
CSR_WRITE_4(sc, ALC_PAR0,
@@ -3555,7 +3556,7 @@ alc_stop_queue(struct alc_softc *sc)
}
/* Disable TxQ. */
reg = CSR_READ_4(sc, ALC_TXQ_CFG);
- if ((reg & TXQ_CFG_ENB) == 0) {
+ if ((reg & TXQ_CFG_ENB) != 0) {
reg &= ~TXQ_CFG_ENB;
CSR_WRITE_4(sc, ALC_TXQ_CFG, reg);
}
OpenPOWER on IntegriCloud