svn commit: r282400 - head/sys/dev/wpi

Adrian Chadd adrian at FreeBSD.org
Sun May 3 23:39:03 UTC 2015


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 <s3erios at gmail.com>

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;


More information about the svn-src-head mailing list