From owner-svn-src-all@FreeBSD.ORG Sun May 3 23:39:03 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 3F9E7598; Sun, 3 May 2015 23:39:03 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2D8AA1A75; Sun, 3 May 2015 23:39:03 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t43Nd3pV095865; Sun, 3 May 2015 23:39:03 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t43Nd2G6095862; Sun, 3 May 2015 23:39:02 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201505032339.t43Nd2G6095862@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sun, 3 May 2015 23:39:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r282400 - head/sys/dev/wpi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 May 2015 23:39:03 -0000 Author: adrian Date: Sun May 3 23:39:02 2015 New Revision: 282400 URL: https://svnweb.freebsd.org/changeset/base/282400 Log: Fix various powersave races + optimize tx/rx pointer update when powersave is off. PR: kern/197143 Submitted by: Andriy Voskoboinyk Modified: head/sys/dev/wpi/if_wpi.c head/sys/dev/wpi/if_wpivar.h Modified: head/sys/dev/wpi/if_wpi.c ============================================================================== --- head/sys/dev/wpi/if_wpi.c Sun May 3 23:38:32 2015 (r282399) +++ head/sys/dev/wpi/if_wpi.c Sun May 3 23:39:02 2015 (r282400) @@ -152,11 +152,14 @@ static int wpi_alloc_fwmem(struct wpi_so static void wpi_free_fwmem(struct wpi_softc *); static int wpi_alloc_rx_ring(struct wpi_softc *); static void wpi_update_rx_ring(struct wpi_softc *); +static void wpi_update_rx_ring_ps(struct wpi_softc *); static void wpi_reset_rx_ring(struct wpi_softc *); static void wpi_free_rx_ring(struct wpi_softc *); static int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *, int); static void wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); +static void wpi_update_tx_ring_ps(struct wpi_softc *, + struct wpi_tx_ring *); static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static int wpi_read_eeprom(struct wpi_softc *, @@ -521,6 +524,9 @@ wpi_attach(device_t dev) ic->ic_scan_mindwell = wpi_scan_mindwell; ic->ic_setregdomain = wpi_setregdomain; + sc->sc_update_rx_ring = wpi_update_rx_ring; + sc->sc_update_tx_ring = wpi_update_tx_ring; + wpi_radiotap_attach(sc); callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); @@ -1089,6 +1095,12 @@ fail: wpi_free_rx_ring(sc); static void wpi_update_rx_ring(struct wpi_softc *sc) { + WPI_WRITE(sc, WPI_FH_RX_WPTR, sc->rxq.cur & ~7); +} + +static void +wpi_update_rx_ring_ps(struct wpi_softc *sc) +{ struct wpi_rx_ring *ring = &sc->rxq; if (ring->update != 0) { @@ -1096,14 +1108,15 @@ wpi_update_rx_ring(struct wpi_softc *sc) return; } - if (WPI_READ(sc, WPI_UCODE_GP1) & WPI_UCODE_GP1_MAC_SLEEP) { + WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s: wakeup request\n", __func__); - - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); ring->update = 1; - } else - WPI_WRITE(sc, WPI_FH_RX_WPTR, ring->cur & ~7); + } else { + wpi_update_rx_ring(sc); + WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + } } static void @@ -1247,19 +1260,27 @@ fail: wpi_free_tx_ring(sc, ring); static void wpi_update_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) { + WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); +} + +static void +wpi_update_tx_ring_ps(struct wpi_softc *sc, struct wpi_tx_ring *ring) +{ + if (ring->update != 0) { /* Wait for INT_WAKEUP event. */ return; } - if (WPI_READ(sc, WPI_UCODE_GP1) & WPI_UCODE_GP1_MAC_SLEEP) { + WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s (%d): requesting wakeup\n", __func__, ring->qid); - - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); ring->update = 1; - } else - WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); + } else { + wpi_update_tx_ring(sc, ring); + WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + } } static void @@ -2067,6 +2088,18 @@ wpi_cmd_done(struct wpi_softc *sc, struc } wakeup(&ring->cmd[desc->idx]); + + if (desc->type == WPI_CMD_SET_POWER_MODE) { + WPI_TXQ_LOCK(sc); + if (sc->sc_flags & WPI_PS_PATH) { + sc->sc_update_rx_ring = wpi_update_rx_ring_ps; + sc->sc_update_tx_ring = wpi_update_tx_ring_ps; + } else { + sc->sc_update_rx_ring = wpi_update_rx_ring; + sc->sc_update_tx_ring = wpi_update_tx_ring; + } + WPI_TXQ_UNLOCK(sc); + } } static void @@ -2262,7 +2295,7 @@ wpi_notif_intr(struct wpi_softc *sc) if (sc->rxq.cur % 8 == 0) { /* Tell the firmware what we have processed. */ - wpi_update_rx_ring(sc); + sc->sc_update_rx_ring(sc); } } } @@ -2293,9 +2326,8 @@ wpi_wakeup_intr(struct wpi_softc *sc) wpi_update_tx_ring(sc, ring); } } - WPI_TXQ_UNLOCK(sc); - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + WPI_TXQ_UNLOCK(sc); } /* @@ -2595,7 +2627,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wp /* Kick TX ring. */ ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - wpi_update_tx_ring(sc, ring); + sc->sc_update_tx_ring(sc, ring); if (ring->qid < WPI_CMD_QUEUE_NUM) { /* Mark TX ring as full if we reach a certain threshold. */ @@ -3147,7 +3179,7 @@ wpi_cmd(struct wpi_softc *sc, int code, /* Kick command ring. */ ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - wpi_update_tx_ring(sc, ring); + sc->sc_update_tx_ring(sc, ring); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); @@ -3648,8 +3680,13 @@ wpi_set_pslevel(struct wpi_softc *sc, ui pmgt = &wpi_pmgt[1][level]; memset(&cmd, 0, sizeof cmd); - if (level != 0) /* not CAM */ + WPI_TXQ_LOCK(sc); + if (level != 0) { /* not CAM */ cmd.flags |= htole16(WPI_PS_ALLOW_SLEEP); + sc->sc_flags |= WPI_PS_PATH; + } else + sc->sc_flags &= ~WPI_PS_PATH; + WPI_TXQ_UNLOCK(sc); /* Retrieve PCIe Active State Power Management (ASPM). */ reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1); if (!(reg & 0x1)) /* L0s Entry disabled. */ Modified: head/sys/dev/wpi/if_wpivar.h ============================================================================== --- head/sys/dev/wpi/if_wpivar.h Sun May 3 23:38:32 2015 (r282399) +++ head/sys/dev/wpi/if_wpivar.h Sun May 3 23:39:02 2015 (r282400) @@ -164,6 +164,9 @@ struct wpi_softc { struct ifnet *sc_ifp; int sc_debug; + int sc_flags; +#define WPI_PS_PATH (1 << 0) + struct mtx sc_mtx; struct mtx tx_mtx; @@ -210,6 +213,9 @@ struct wpi_softc { struct mtx nt_mtx; void (*sc_node_free)(struct ieee80211_node *); + void (*sc_update_rx_ring)(struct wpi_softc *); + void (*sc_update_tx_ring)(struct wpi_softc *, + struct wpi_tx_ring *); struct wpi_rx_radiotap_header sc_rxtap; struct wpi_tx_radiotap_header sc_txtap;