changeset 6062:f12fdb80179b

6613955 pcwl show wrong channel value with command "dladm show-linkprop" 6632753 wpi need to support SUSPEND/RESUME 6637814 WiFi wpi driver tries to set power when it knows transmitter is off
author hx147065
date Thu, 21 Feb 2008 22:32:06 -0800
parents fb86e2a70b6a
children 82d075ed8729
files usr/src/uts/common/io/pcwl/pcwl.c usr/src/uts/common/io/wpi/wpi.c usr/src/uts/common/io/wpi/wpireg.h usr/src/uts/common/io/wpi/wpivar.h
diffstat 4 files changed, 126 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/pcwl/pcwl.c	Thu Feb 21 22:26:00 2008 -0800
+++ b/usr/src/uts/common/io/pcwl/pcwl.c	Thu Feb 21 22:32:06 2008 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -711,7 +711,7 @@
 			break;
 		}
 		if (tbl_p->flags & CISTPL_CFTABLE_TPCE_FS_PWR &&
-			tbl_p->pd.flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
+		    tbl_p->pd.flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
 			if (tbl_p->pd.pd_vcc.avgI > hi) {
 				hi = tbl_p->pd.pd_vcc.avgI;
 				pcwl_p->pcwl_config_hi = tbl_p->index;
@@ -2456,7 +2456,7 @@
 			bzero(buf + WIFI_BUF_OFFSET,
 			    sizeof (wl_bssid_t));
 		} else if (ret == WL_PORT_TO_IBSS ||
-			ret == WL_PORT_TO_BSS || ret == WL_PORT_OOR) {
+		    ret == WL_PORT_TO_BSS || ret == WL_PORT_OOR) {
 			(void) pcwl_get_ltv(pcwl_p, 6,
 			    WL_RID_BSSID, (uint16_t *)bssid);
 			PCWL_SWAP16((uint16_t *)bssid, 6);
@@ -2769,7 +2769,7 @@
 static int
 pcwl_cfg_phy(mblk_t *mp, pcwl_maci_t *pcwl_p, uint32_t cmd)
 {
-	uint16_t ret, i;
+	uint16_t ret, retval, i;
 	pcwl_rf_t *rf_p;
 	wldp_t	*infp;
 	wldp_t *outfp;
@@ -2790,13 +2790,13 @@
 	outfp->wldp_length = WIFI_BUF_OFFSET + sizeof (wl_dsss_t);
 	if (cmd == WLAN_GET_PARAM) {
 		if (ret = pcwl_get_ltv(pcwl_p, 2,
-		    WL_RID_CURRENT_CHNL, &ret)) {
+		    WL_RID_CURRENT_CHNL, &retval)) {
 			outfp->wldp_length = WIFI_BUF_OFFSET;
 			outfp->wldp_result = WL_HW_ERROR;
 			goto done;
 		}
-		((wl_dsss_t *)(outfp->wldp_buf))->wl_dsss_channel = ret;
-		PCWLDBG((CE_CONT, "pcwl_getset: channel=%d\n", ret));
+		((wl_dsss_t *)(outfp->wldp_buf))->wl_dsss_channel = retval;
+		PCWLDBG((CE_CONT, "pcwl_getset: channel=%d\n", retval));
 		((wl_dsss_t *)(outfp->wldp_buf))->wl_dsss_subtype = WL_DSSS;
 		outfp->wldp_result = WL_SUCCESS;
 	} else if (cmd == WLAN_SET_PARAM) {
@@ -2966,7 +2966,7 @@
 			}
 		}
 		PCWLDBG((CE_CONT, "pcwl: get rate=%d\n", rate));
-		    outfp->wldp_result = WL_SUCCESS;
+		outfp->wldp_result = WL_SUCCESS;
 	} else if (cmd == WLAN_SET_PARAM) {
 		bzero(rates, sizeof (rates));
 		for (i = 0; i < 4; i++) {
@@ -3468,7 +3468,7 @@
 				    rf_p->rf_ckeys[i].ckey_dat, i));
 			}
 			PCWLDBG((CE_CONT, "pcwl: rf_ckeys[%d]=%s\n", i,
-				(char *)(rf_p->rf_ckeys[i].ckey_dat)));
+			    (char *)(rf_p->rf_ckeys[i].ckey_dat)));
 		}
 		outfp->wldp_result = WL_SUCCESS;
 	} else {
--- a/usr/src/uts/common/io/wpi/wpi.c	Thu Feb 21 22:26:00 2008 -0800
+++ b/usr/src/uts/common/io/wpi/wpi.c	Thu Feb 21 22:32:06 2008 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -71,6 +71,7 @@
 #define	WPI_DEBUG_TX		(1 << 11)
 #define	WPI_DEBUG_RATECTL	(1 << 12)
 #define	WPI_DEBUG_RADIO		(1 << 13)
+#define	WPI_DEBUG_RESUME	(1 << 14)
 uint32_t wpi_dbg_flags = 0;
 #define	WPI_DBG(x) \
 	wpi_dbg x
@@ -399,7 +400,23 @@
 	wifi_data_t		wd = { 0 };
 	mac_register_t		*macp;
 
-	if (cmd != DDI_ATTACH) {
+	switch (cmd) {
+	case DDI_ATTACH:
+		break;
+	case DDI_RESUME:
+		sc = ddi_get_soft_state(wpi_soft_state_p,
+		    ddi_get_instance(dip));
+		ASSERT(sc != NULL);
+		mutex_enter(&sc->sc_glock);
+		sc->sc_flags &= ~WPI_F_SUSPEND;
+		mutex_exit(&sc->sc_glock);
+		if (sc->sc_flags & WPI_F_RUNNING) {
+			(void) wpi_init(sc);
+			ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
+		}
+		WPI_DBG((WPI_DEBUG_RESUME, "wpi: resume \n"));
+		return (DDI_SUCCESS);
+	default:
 		err = DDI_FAILURE;
 		goto attach_fail1;
 	}
@@ -669,8 +686,21 @@
 	sc = ddi_get_soft_state(wpi_soft_state_p, ddi_get_instance(dip));
 	ASSERT(sc != NULL);
 
-	if (cmd != DDI_DETACH)
+	switch (cmd) {
+	case DDI_DETACH:
+		break;
+	case DDI_SUSPEND:
+		if (sc->sc_flags & WPI_F_RUNNING) {
+			wpi_stop(sc);
+		}
+		mutex_enter(&sc->sc_glock);
+		sc->sc_flags |= WPI_F_SUSPEND;
+		mutex_exit(&sc->sc_glock);
+		WPI_DBG((WPI_DEBUG_RESUME, "wpi: suspend \n"));
+		return (DDI_SUCCESS);
+	default:
 		return (DDI_FAILURE);
+	}
 	if (!(sc->sc_flags & WPI_F_ATTACHED))
 		return (DDI_FAILURE);
 
@@ -1777,9 +1807,19 @@
 			    LE_32(*status)));
 
 			if (LE_32(*status) & 1) {
-				/* the radio button has to be pushed */
+				/*
+				 * the radio button has to be pushed(OFF). It
+				 * is considered as a hw error, the
+				 * wpi_thread() tries to recover it after the
+				 * button is pushed again(ON)
+				 */
 				cmn_err(CE_NOTE,
 				    "wpi: Radio transmitter is off\n");
+				sc->sc_ostate = sc->sc_ic.ic_state;
+				ieee80211_new_state(&sc->sc_ic,
+				    IEEE80211_S_INIT, -1);
+				sc->sc_flags |=
+				    (WPI_F_HW_ERR_RECOVER | WPI_F_RADIO_OFF);
 			}
 			break;
 		}
@@ -1822,6 +1862,11 @@
 	uint32_t r, rfh;
 
 	mutex_enter(&sc->sc_glock);
+	if (sc->sc_flags & WPI_F_SUSPEND) {
+		mutex_exit(&sc->sc_glock);
+		return (DDI_INTR_UNCLAIMED);
+	}
+
 	r = WPI_READ(sc, WPI_INTR);
 	if (r == 0 || r == 0xffffffff) {
 		mutex_exit(&sc->sc_glock);
@@ -1903,6 +1948,11 @@
 	ieee80211com_t	*ic = &sc->sc_ic;
 	mblk_t			*next;
 
+	if (sc->sc_flags & WPI_F_SUSPEND) {
+		freemsgchain(mp);
+		return (NULL);
+	}
+
 	if (ic->ic_state != IEEE80211_S_RUN) {
 		freemsgchain(mp);
 		return (NULL);
@@ -1945,6 +1995,16 @@
 	bzero(cmd, sizeof (*cmd));
 
 	mutex_enter(&sc->sc_tx_lock);
+	if (sc->sc_flags & WPI_F_SUSPEND) {
+		mutex_exit(&sc->sc_tx_lock);
+		if ((type & IEEE80211_FC0_TYPE_MASK) !=
+		    IEEE80211_FC0_TYPE_DATA) {
+			freemsg(mp);
+		}
+		err = WPI_FAIL;
+		goto exit;
+	}
+
 	if (ring->queued > ring->count - 64) {
 		WPI_DBG((WPI_DEBUG_TX, "wpi_send(): no txbuf\n"));
 		sc->sc_need_reschedule = 1;
@@ -2230,9 +2290,24 @@
 		DELAY(1000000);
 		err = wpi_init(sc);
 	}
+
+	if (err) {
+		/*
+		 * The hw init err(eg. RF is OFF). Return Success to make
+		 * the 'plumb' succeed. The wpi_thread() tries to re-init
+		 * background.
+		 */
+		mutex_enter(&sc->sc_glock);
+		sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
+		mutex_exit(&sc->sc_glock);
+		return (WPI_SUCCESS);
+	}
 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
-
-	return (err);
+	mutex_enter(&sc->sc_glock);
+	sc->sc_flags |= WPI_F_RUNNING;
+	mutex_exit(&sc->sc_glock);
+
+	return (WPI_SUCCESS);
 }
 
 static void
@@ -2247,6 +2322,9 @@
 	sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
 	sc->sc_flags &= ~WPI_F_RATE_AUTO_CTL;
 	mutex_exit(&sc->sc_mt_lock);
+	mutex_enter(&sc->sc_glock);
+	sc->sc_flags &= ~WPI_F_RUNNING;
+	mutex_exit(&sc->sc_glock);
 }
 
 /*ARGSUSED*/
@@ -2294,9 +2372,27 @@
 	ieee80211com_t	*ic = &sc->sc_ic;
 	clock_t clk;
 	int times = 0, err, n = 0, timeout = 0;
+	uint32_t tmp;
 
 	mutex_enter(&sc->sc_mt_lock);
 	while (sc->sc_mf_thread_switch) {
+		tmp = WPI_READ(sc, WPI_GPIO_CTL);
+		if (tmp & WPI_GPIO_HW_RF_KILL) {
+			sc->sc_flags &= ~WPI_F_RADIO_OFF;
+		} else {
+			sc->sc_flags |= WPI_F_RADIO_OFF;
+		}
+		/*
+		 * If in SUSPEND or the RF is OFF, do nothing
+		 */
+		if ((sc->sc_flags & WPI_F_SUSPEND) ||
+		    (sc->sc_flags & WPI_F_RADIO_OFF)) {
+			mutex_exit(&sc->sc_mt_lock);
+			delay(drv_usectohz(100000));
+			mutex_enter(&sc->sc_mt_lock);
+			continue;
+		}
+
 		/*
 		 * recovery fatal error
 		 */
@@ -2320,6 +2416,8 @@
 					continue;
 			}
 			n = 0;
+			if (!err)
+				sc->sc_flags |= WPI_F_RUNNING;
 			sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
 			mutex_exit(&sc->sc_mt_lock);
 			delay(drv_usectohz(2000000));
@@ -2927,6 +3025,12 @@
 	(void) wpi_power_up(sc);
 	wpi_hw_config(sc);
 
+	tmp = WPI_READ(sc, WPI_GPIO_CTL);
+	if (!(tmp & WPI_GPIO_HW_RF_KILL)) {
+		cmn_err(CE_WARN, "wpi_init(): Radio transmitter is off\n");
+		goto fail1;
+	}
+
 	/* init Rx ring */
 	wpi_mem_lock(sc);
 	WPI_WRITE(sc, WPI_RX_BASE, sc->sc_rxq.dma_desc.cookie.dmac_address);
--- a/usr/src/uts/common/io/wpi/wpireg.h	Thu Feb 21 22:26:00 2008 -0800
+++ b/usr/src/uts/common/io/wpi/wpireg.h	Thu Feb 21 22:32:06 2008 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -147,6 +147,7 @@
 #define	WPI_GPIO_SLEEP		(1 << 4)
 #define	WPI_GPIO_PWR_STATUS	0x07000000
 #define	WPI_GPIO_PWR_SLEEP	(4 << 24)
+#define	WPI_GPIO_HW_RF_KILL	(1 << 27)
 
 /*
  * possible flags for register WPI_CHICKEN
@@ -180,6 +181,7 @@
 #define	WPI_ALIVE_INTR	(1 << 0)
 #define	WPI_WAKEUP_INTR	(1 << 1)
 #define	WPI_RX_SWINT	(1 << 3)
+#define	WPI_RF_KILL	(1 << 7)
 #define	WPI_SW_ERROR	(1 << 25)
 #define	WPI_TX_INTR	(1 << 27)
 #define	WPI_HW_ERROR	(1 << 29)
--- a/usr/src/uts/common/io/wpi/wpivar.h	Thu Feb 21 22:26:00 2008 -0800
+++ b/usr/src/uts/common/io/wpi/wpivar.h	Thu Feb 21 22:32:06 2008 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -184,6 +184,7 @@
 	uint32_t		sc_tx_err;
 	uint32_t		sc_rx_err;
 	uint32_t		sc_tx_retries;
+
 #ifdef WPI_BPF
 	struct bpf_if		*sc_drvbpf;
 
@@ -209,6 +210,8 @@
 #define	WPI_F_HW_ERR_RECOVER	(1 << 3)
 #define	WPI_F_RATE_AUTO_CTL	(1 << 4)
 #define	WPI_F_RUNNING		(1 << 5)
+#define	WPI_F_SUSPEND		(1 << 6)
+#define	WPI_F_RADIO_OFF		(1 << 7)
 
 #define	WPI_SUCCESS		0
 #define	WPI_FAIL		1