summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorhx147065 <none@none>2008-02-21 22:32:06 -0800
committerhx147065 <none@none>2008-02-21 22:32:06 -0800
commit19b23afcc35b3926d062efc1930e65c5fed1084d (patch)
tree28b61627b2307c9db8b8e5d53a7029130f91ece8 /usr/src
parentbdb0fa453175b220dad117359624622021aad5b2 (diff)
downloadillumos-gate-19b23afcc35b3926d062efc1930e65c5fed1084d.tar.gz
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
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/pcwl/pcwl.c18
-rw-r--r--usr/src/uts/common/io/wpi/wpi.c114
-rw-r--r--usr/src/uts/common/io/wpi/wpireg.h4
-rw-r--r--usr/src/uts/common/io/wpi/wpivar.h5
4 files changed, 125 insertions, 16 deletions
diff --git a/usr/src/uts/common/io/pcwl/pcwl.c b/usr/src/uts/common/io/pcwl/pcwl.c
index a72862c379..6a5eed3a4e 100644
--- a/usr/src/uts/common/io/pcwl/pcwl.c
+++ b/usr/src/uts/common/io/pcwl/pcwl.c
@@ -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 @@ pcwl_card_insert(pcwl_maci_t *pcwl_p)
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 @@ pcwl_cfg_bssid(mblk_t *mp, pcwl_maci_t *pcwl_p, uint32_t cmd)
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 @@ done:
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 @@ pcwl_cfg_phy(mblk_t *mp, pcwl_maci_t *pcwl_p, uint32_t cmd)
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 @@ pcwl_cfg_desiredrates(mblk_t *mp, pcwl_maci_t *pcwl_p, uint32_t cmd)
}
}
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 @@ pcwl_cfg_wepkey(mblk_t *mp, pcwl_maci_t *pcwl_p, uint32_t cmd)
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 {
diff --git a/usr/src/uts/common/io/wpi/wpi.c b/usr/src/uts/common/io/wpi/wpi.c
index c32dfcd67c..3ab12c28af 100644
--- a/usr/src/uts/common/io/wpi/wpi.c
+++ b/usr/src/uts/common/io/wpi/wpi.c
@@ -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 @@ wpi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
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 @@ wpi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
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 @@ wpi_notif_softintr(caddr_t arg)
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 @@ wpi_intr(caddr_t arg)
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 @@ wpi_m_tx(void *arg, mblk_t *mp)
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 @@ wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
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 @@ wpi_m_start(void *arg)
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);
+ mutex_enter(&sc->sc_glock);
+ sc->sc_flags |= WPI_F_RUNNING;
+ mutex_exit(&sc->sc_glock);
- return (err);
+ return (WPI_SUCCESS);
}
static void
@@ -2247,6 +2322,9 @@ wpi_m_stop(void *arg)
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 @@ wpi_thread(wpi_sc_t *sc)
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 @@ wpi_thread(wpi_sc_t *sc)
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 @@ wpi_init(wpi_sc_t *sc)
(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);
diff --git a/usr/src/uts/common/io/wpi/wpireg.h b/usr/src/uts/common/io/wpi/wpireg.h
index a873d11e5c..0670ed2b16 100644
--- a/usr/src/uts/common/io/wpi/wpireg.h
+++ b/usr/src/uts/common/io/wpi/wpireg.h
@@ -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 @@ extern "C" {
#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 @@ extern "C" {
#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)
diff --git a/usr/src/uts/common/io/wpi/wpivar.h b/usr/src/uts/common/io/wpi/wpivar.h
index 967acfb386..55f8b68a1c 100644
--- a/usr/src/uts/common/io/wpi/wpivar.h
+++ b/usr/src/uts/common/io/wpi/wpivar.h
@@ -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 @@ typedef struct wpi_softc {
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 @@ typedef struct wpi_softc {
#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