summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQin Michael Li <Mikore.Li@Sun.COM>2009-11-19 11:57:44 +0800
committerQin Michael Li <Mikore.Li@Sun.COM>2009-11-19 11:57:44 +0800
commit6dea387a9f9ddc2932a4c49a09384dfdcd5a703b (patch)
tree244955fccd29f2b578f40d826480172e79fb7748
parent34b927e90f4d68874d010c79326093e71e90b2b6 (diff)
downloadillumos-joyent-6dea387a9f9ddc2932a4c49a09384dfdcd5a703b.tar.gz
6900514 Need to support suspend/resume for CISCO Aironet AIR-PCM352 pcmcia wifi driver(pcan)
6901512 Need to support suspend/resume for Orinoco pcmcia wifi driver(pcwl)
-rw-r--r--usr/src/uts/common/io/pcan/pcan.c108
-rw-r--r--usr/src/uts/common/io/pcan/pcan.h7
-rw-r--r--usr/src/uts/common/io/pcwl/pcwl.c104
-rw-r--r--usr/src/uts/common/io/pcwl/pcwl.h6
-rw-r--r--usr/src/uts/common/pcmcia/nexus/pcmcia.c3
5 files changed, 207 insertions, 21 deletions
diff --git a/usr/src/uts/common/io/pcan/pcan.c b/usr/src/uts/common/io/pcan/pcan.c
index 3199ebb014..71b79baffa 100644
--- a/usr/src/uts/common/io/pcan/pcan.c
+++ b/usr/src/uts/common/io/pcan/pcan.c
@@ -40,6 +40,7 @@
#include <sys/sunddi.h>
#include <sys/dlpi.h>
#include <sys/ethernet.h>
+#include <sys/strsubr.h>
#include <sys/strsun.h>
#include <sys/stat.h>
#include <sys/byteorder.h>
@@ -526,8 +527,8 @@ pcan_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
(void) mac_unregister(pcan_p->pcan_mh);
- mutex_enter(&pcan_p->pcan_glock);
if (pcan_p->pcan_device_type == PCAN_DEVICE_PCI) {
+ mutex_enter(&pcan_p->pcan_glock);
ddi_remove_intr(dip, 0, pcan_p->pcan_ib_cookie);
pcan_free_dma(pcan_p);
if (pcan_p->pcan_handle0)
@@ -536,12 +537,12 @@ pcan_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
ddi_regs_map_free(&pcan_p->pcan_handle1);
if (pcan_p->pcan_handle2)
ddi_regs_map_free(&pcan_p->pcan_handle2);
+ mutex_exit(&pcan_p->pcan_glock);
} else if (pcan_p->pcan_device_type == PCAN_DEVICE_PCCARD) {
pcan_unregister_cs(pcan_p);
} else {
cmn_err(CE_WARN, "pcan detach: unsupported device type\n");
}
- mutex_exit(&pcan_p->pcan_glock);
pcan_destroy_locks(pcan_p);
if (pcan_p->pcan_info_softint_id)
ddi_remove_softintr(pcan_p->pcan_info_softint_id);
@@ -652,7 +653,6 @@ pcan_unregister_cs(pcan_maci_t *pcan_p)
if (pcan_p->pcan_flag & PCAN_CARD_READY) {
pcan_card_remove(pcan_p);
- pcan_p->pcan_flag &= ~PCAN_CARD_READY;
}
mutex_destroy(&pcan_p->pcan_cslock);
cv_destroy(&pcan_p->pcan_cscv);
@@ -701,6 +701,9 @@ pcan_ev_hdlr(event_t event, int priority, event_callback_args_t *arg)
(void) strcpy(ci_p->VendorName, CS_SUN_VENDOR_DESCRIPTION);
ci_p->Attributes |= CS_CLIENT_INFO_VALID;
break;
+ case CS_EVENT_PM_SUSPEND:
+ pcan_do_suspend(pcan_p);
+ break;
default:
ret = CS_UNSUPPORTED_EVENT;
break;
@@ -721,6 +724,7 @@ pcan_card_insert(pcan_maci_t *pcan_p)
cistpl_config_t config;
cistpl_cftable_entry_t *tbl_p;
register client_handle_t chdl = pcan_p->pcan_chdl;
+ modify_config_t cfgmod;
bzero(&tuple, sizeof (tuple));
tuple.DesiredTuple = CISTPL_MANFID;
@@ -845,6 +849,33 @@ pcan_card_insert(pcan_maci_t *pcan_p)
cmn_err(CE_WARN, "pcan: RequestConfiguration failed %x\n", ret);
goto un_irq;
}
+
+ if (pcan_p->pcan_flag & PCAN_SUSPENDED) {
+ mutex_enter(&pcan_p->pcan_glock);
+ pcan_reset_backend(pcan_p, pcan_p->pcan_reset_delay);
+ /* turn on CS interrupt */
+ cfgmod.Attributes = CONF_ENABLE_IRQ_STEERING |
+ CONF_IRQ_CHANGE_VALID;
+ cfgmod.Vpp1 = 50;
+ cfgmod.Vpp2 = 50;
+ (void) csx_ModifyConfiguration(pcan_p->pcan_chdl, &cfgmod);
+
+ if (ret = pcan_init_nicmem(pcan_p)) {
+ cmn_err(CE_WARN, "pcan insert: init_nicmem failed %x\n",
+ ret);
+ }
+ PCAN_DISABLE_INTR_CLEAR(pcan_p);
+ ret = pcan_set_cmd(pcan_p, AN_CMD_DISABLE, 0);
+ PCANDBG((CE_NOTE, "pcan insert set cmd ret =%x\n", ret));
+ pcan_p->pcan_flag &= ~PCAN_SUSPENDED;
+ mutex_exit(&pcan_p->pcan_glock);
+ }
+
+ if (pcan_p->pcan_flag & PCAN_PLUMBED) {
+ pcan_start(pcan_p);
+ pcan_p->pcan_flag &= ~PCAN_PLUMBED;
+ PCANDBG((CE_NOTE, "pcan insert: active interrupt\n"));
+ }
return (CS_SUCCESS);
un_irq:
(void) csx_ReleaseIRQ(chdl, &irq);
@@ -862,6 +893,33 @@ insert_ret:
* assume card is already removed, don't touch the hardware
*/
static void
+pcan_do_suspend(pcan_maci_t *pcan_p)
+{
+ int ret;
+ if (pcan_p->pcan_flag & PCAN_CARD_LINKUP) {
+ if (pcan_p->pcan_connect_timeout_id != 0) {
+ (void) untimeout(pcan_p->pcan_connect_timeout_id);
+ pcan_p->pcan_connect_timeout_id = 0;
+ }
+ mutex_enter(&pcan_p->pcan_glock);
+ pcan_p->pcan_flag &= ~PCAN_CARD_LINKUP;
+ if (ret = pcan_set_cmd(pcan_p, AN_CMD_DISABLE, 0))
+ PCANDBG((CE_NOTE, "pcan: disable failed, ret %d\n",
+ ret));
+ if (ret = pcan_loaddef(pcan_p))
+ PCANDBG((CE_NOTE, "pcan: loaddef failed, ret %d\n",
+ ret));
+ mac_link_update(GLD3(pcan_p), LINK_STATE_DOWN);
+ mutex_exit(&pcan_p->pcan_glock);
+ }
+ pcan_p->pcan_flag |= PCAN_SUSPENDED;
+}
+
+
+/*
+ * assume card is already removed, don't touch the hardware
+ */
+static void
pcan_card_remove(pcan_maci_t *pcan_p)
{
int ret;
@@ -870,6 +928,23 @@ pcan_card_remove(pcan_maci_t *pcan_p)
if (!(pcan_p->pcan_flag & PCAN_CARD_READY))
return;
+ if (pcan_p->pcan_connect_timeout_id != 0) {
+ (void) untimeout(pcan_p->pcan_connect_timeout_id);
+ pcan_p->pcan_connect_timeout_id = 0;
+ }
+
+ if (pcan_p->pcan_flag & PCAN_CARD_LINKUP) {
+ pcan_p->pcan_flag &= ~PCAN_CARD_LINKUP;
+ mac_link_update(GLD3(pcan_p), LINK_STATE_DOWN);
+ }
+ mutex_enter(&pcan_p->pcan_glock);
+ if (pcan_p->pcan_flag & PCAN_CARD_INTREN) {
+ pcan_stop_locked(pcan_p);
+ pcan_p->pcan_flag |= PCAN_PLUMBED;
+ }
+ pcan_p->pcan_flag &= ~PCAN_CARD_READY;
+ mutex_exit(&pcan_p->pcan_glock);
+
if (ret = csx_ReleaseConfiguration(pcan_p->pcan_chdl, NULL))
cmn_err(CE_WARN, "pcan: ReleaseConfiguration failed %x\n", ret);
@@ -878,6 +953,7 @@ pcan_card_remove(pcan_maci_t *pcan_p)
cmn_err(CE_WARN, "pcan: ReleaseIRQ failed %x\n", ret);
ddi_remove_softintr(pcan_p->pcan_softint_id);
+ pcan_p->pcan_softint_id = 0;
bzero(&io, sizeof (io));
io.BasePort1.handle = pcan_p->pcan_port;
@@ -886,7 +962,7 @@ pcan_card_remove(pcan_maci_t *pcan_p)
cmn_err(CE_WARN, "pcan: Release IO failed %x\n", ret);
pcan_p->pcan_port = 0;
- pcan_p->pcan_flag &= ~PCAN_CARD_READY;
+ PCANDBG((CE_NOTE, "pcan: removed\n"));
}
/*
@@ -973,7 +1049,7 @@ pcan_send(pcan_maci_t *pcan_p, mblk_t *mblk_p)
#ifdef PCAN_SEND_DEBUG
struct an_ltv_status radio_status;
#endif /* PCAN_SEND_DEBUG */
- uint16_t pkt_len, xmt_id, ring_idx;
+ uint16_t pkt_len, xmt_id, ring_idx, r = 0;
struct ieee80211_frame *wh;
int i = 0;
@@ -1084,7 +1160,7 @@ pcan_send(pcan_maci_t *pcan_p, mblk_t *mblk_p)
(void) WRCH1(pcan_p, xmt_id, 0, (uint16_t *)buf_p, 0x38); /* frm */
(void) WRPKT(pcan_p, xmt_id, 0x38, (uint16_t *)(buf_p + 0x38),
pkt_len + 12);
- ring_idx = pcan_set_cmd(pcan_p, AN_CMD_TX, xmt_id);
+ r = pcan_set_cmd(pcan_p, AN_CMD_TX, xmt_id);
mutex_exit(&pcan_p->pcan_glock);
PCANDBG((CE_NOTE, "pcan: pkt_len=0x44+%x=%x xmt=%x ret=%x\n",
@@ -1097,7 +1173,7 @@ pcan_send(pcan_maci_t *pcan_p, mblk_t *mblk_p)
PCANDBG((CE_NOTE, "pcan: radio status:\n"));
}
#endif /* PCAN_SEND_DEBUG */
- if (ring_idx)
+ if (r)
return (PCAN_FAIL);
else {
freemsg(mblk_p);
@@ -1214,7 +1290,8 @@ pcan_tx(void *arg, mblk_t *mp)
if ((pcan_p->pcan_flag & (PCAN_CARD_LINKUP | PCAN_CARD_READY)) !=
(PCAN_CARD_LINKUP | PCAN_CARD_READY)) {
mutex_exit(&pcan_p->pcan_glock);
- return (mp);
+ freemsgchain(mp);
+ return (NULL);
}
mutex_exit(&pcan_p->pcan_glock);
while (mp != NULL) {
@@ -2336,7 +2413,6 @@ pcan_scanresult_ltv(int rw, pcan_maci_t *pcan_p, uint16_t type,
struct an_ltv_scanresult *scanresult_p)
{
uint16_t ret, len;
-
if (rw != PCAN_READ_LTV) {
cmn_err(CE_WARN, "pcan scan_ltv: readonly rid %x\n", type);
return (PCAN_FAIL);
@@ -4206,6 +4282,10 @@ pcan_getset(mblk_t *mp, pcan_maci_t *pcan_p, uint32_t cmd)
pcan_p->pcan_connect_timeout_id = 0;
}
mutex_enter(&pcan_p->pcan_glock);
+ if (!(pcan_p->pcan_flag & PCAN_CARD_READY)) {
+ mutex_exit(&pcan_p->pcan_glock);
+ return (PCAN_FAIL);
+ }
ret = pcan_cmd_scan(pcan_p);
/*
* a trick here.
@@ -4239,6 +4319,10 @@ pcan_getset(mblk_t *mp, pcan_maci_t *pcan_p, uint32_t cmd)
pcan_p->pcan_connect_timeout_id = 0;
}
mutex_enter(&pcan_p->pcan_glock);
+ if (!(pcan_p->pcan_flag & PCAN_CARD_READY)) {
+ mutex_exit(&pcan_p->pcan_glock);
+ return (PCAN_FAIL);
+ }
pcan_p->pcan_flag &= ~PCAN_CARD_LINKUP;
if (ret = pcan_set_cmd(pcan_p, AN_CMD_DISABLE, 0)) {
ret = (int)WL_HW_ERROR;
@@ -4258,6 +4342,10 @@ pcan_getset(mblk_t *mp, pcan_maci_t *pcan_p, uint32_t cmd)
pcan_p->pcan_connect_timeout_id = 0;
}
mutex_enter(&pcan_p->pcan_glock);
+ if (!(pcan_p->pcan_flag & PCAN_CARD_READY)) {
+ mutex_exit(&pcan_p->pcan_glock);
+ return (PCAN_FAIL);
+ }
if (ret = pcan_set_cmd(pcan_p, AN_CMD_DISABLE, 0)) {
ret = (int)WL_HW_ERROR;
break;
@@ -4507,7 +4595,7 @@ pcan_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
case MAC_PROP_WL_SETOPTIE:
case MAC_PROP_WL_MLME:
cmn_err(CE_WARN, "pcan_getprop:"
- "opmode not support\n");
+ "opmode not support %x\n", wldp_pr_num);
err = ENOTSUP;
break;
default:
diff --git a/usr/src/uts/common/io/pcan/pcan.h b/usr/src/uts/common/io/pcan/pcan.h
index 9795e371f5..e6338521b9 100644
--- a/usr/src/uts/common/io/pcan/pcan.h
+++ b/usr/src/uts/common/io/pcan/pcan.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -39,8 +39,6 @@
#ifndef _SYS_PCAN_H
#define _SYS_PCAN_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -1212,6 +1210,8 @@ typedef struct pcan_macinfo {
#define PCAN_CARD_SEND 0x20
#define PCAN_CARD_READY 0x40
#define PCAN_CARD_FAILED 0x80
+#define PCAN_PLUMBED 0x100
+#define PCAN_SUSPENDED 0x200
#define PCAN_STATE_IDLE 0x1
@@ -1230,6 +1230,7 @@ static int pcan_card_insert(pcan_maci_t *pcan_p);
static int pcan_ev_hdlr(event_t ev, int pri, event_callback_args_t *arg);
static void pcan_card_remove(pcan_maci_t *pcan_p);
static int pcan_init_nicmem(pcan_maci_t *pcan_p);
+static void pcan_do_suspend(pcan_maci_t *pcan_p);
/*
* high level device access primitives, glock must held before calling
diff --git a/usr/src/uts/common/io/pcwl/pcwl.c b/usr/src/uts/common/io/pcwl/pcwl.c
index f2b0012d1d..a099a60b8b 100644
--- a/usr/src/uts/common/io/pcwl/pcwl.c
+++ b/usr/src/uts/common/io/pcwl/pcwl.c
@@ -40,6 +40,7 @@
#include <sys/sunddi.h>
#include <sys/dlpi.h>
#include <sys/ethernet.h>
+#include <sys/strsubr.h>
#include <sys/strsun.h>
#include <sys/stat.h>
#include <sys/byteorder.h>
@@ -86,6 +87,8 @@ static int pcwl_m_setprop(void *arg, const char *pr_name,
static int pcwl_m_getprop(void *arg, const char *pr_name,
mac_prop_id_t wldp_pr_num, uint_t pr_flags,
uint_t wldp_length, void *wldp_buf, uint_t *perm);
+static void
+pcwl_delay(pcwl_maci_t *, clock_t);
mac_callbacks_t pcwl_m_callbacks = {
MC_IOCTL | MC_SETPROP | MC_GETPROP,
@@ -479,15 +482,15 @@ pcwl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
mutex_exit(&pcwl_p->pcwl_scanlist_lock);
(void) mac_unregister(pcwl_p->pcwl_mh);
- mutex_enter(&pcwl_p->pcwl_glock);
if (pcwl_p->pcwl_device_type == PCWL_DEVICE_PCI) {
+ mutex_enter(&pcwl_p->pcwl_glock);
ddi_remove_intr(dip, 0, pcwl_p->pcwl_ib_cookie);
ddi_regs_map_free(&pcwl_p->pcwl_handle);
ddi_regs_map_free(&pcwl_p->pcwl_cfg_handle);
+ mutex_exit(&pcwl_p->pcwl_glock);
} else if (pcwl_p->pcwl_device_type == PCWL_DEVICE_PCCARD) {
pcwl_unregister_cs(pcwl_p);
}
- mutex_exit(&pcwl_p->pcwl_glock);
pcwl_destroy_locks(pcwl_p);
ddi_remove_minor_node(dip, NULL);
ddi_soft_state_free(pcwl_soft_state_p, ddi_get_instance(dip));
@@ -607,6 +610,9 @@ pcwl_destroy_locks(pcwl_maci_t *pcwl_p)
mutex_destroy(&pcwl_p->pcwl_glock);
}
+static void
+pcwl_do_suspend(pcwl_maci_t *pcwl_p);
+
static int
pcwl_ev_hdlr(event_t event, int priority, event_callback_args_t *arg)
{
@@ -641,6 +647,9 @@ pcwl_ev_hdlr(event_t event, int priority, event_callback_args_t *arg)
(void) strcpy(ci_p->VendorName, CS_SUN_VENDOR_DESCRIPTION);
ci_p->Attributes |= CS_CLIENT_INFO_VALID;
break;
+ case CS_EVENT_PM_SUSPEND:
+ pcwl_do_suspend(pcwl_p);
+ break;
default:
ret = CS_UNSUPPORTED_EVENT;
break;
@@ -649,6 +658,52 @@ pcwl_ev_hdlr(event_t event, int priority, event_callback_args_t *arg)
return (ret);
}
+/*
+ * assume card is already removed, don't touch the hardware
+ */
+static void
+pcwl_do_suspend(pcwl_maci_t *pcwl_p)
+{
+ int ret;
+
+ if (pcwl_p->pcwl_flag & PCWL_CARD_LINKUP) {
+ if (pcwl_p->pcwl_connect_timeout_id != 0) {
+ (void) untimeout(pcwl_p->pcwl_connect_timeout_id);
+ pcwl_p->pcwl_connect_timeout_id = 0;
+ }
+ mutex_enter(&pcwl_p->pcwl_glock);
+ pcwl_p->pcwl_flag &= ~PCWL_CARD_LINKUP;
+ (void) pcwl_set_cmd(pcwl_p, WL_CMD_DISABLE, 0);
+ /*
+ * A workaround here: If the card is in ad-hoc mode, the
+ * following scan will not work correctly, so any
+ * 'dladm connect-wifi' which need a scan first will not
+ * succeed. software reset the card here as a workround.
+ */
+ if ((pcwl_p->pcwl_rf.rf_porttype == WL_BSS_IBSS) &&
+ (pcwl_p->pcwl_chip_type == PCWL_CHIP_LUCENT)) {
+ (void) pcwl_reset_backend(pcwl_p);
+ (void) pcwl_init_nicmem(pcwl_p);
+ pcwl_start_locked(pcwl_p);
+ }
+ if (ret = pcwl_loaddef_rf(pcwl_p)) {
+ PCWLDBG((CE_WARN, "cfg_loaddef_err %d\n", ret));
+ }
+ if (ret = pcwl_set_cmd(pcwl_p, WL_CMD_ENABLE, 0)) {
+ PCWLDBG((CE_WARN, "set enable cmd err\n"));
+ }
+ pcwl_delay(pcwl_p, 1000000);
+ if (ret = pcwl_set_cmd(pcwl_p, WL_CMD_DISABLE, 0)) {
+ PCWLDBG((CE_WARN, "set disable cmd err\n"));
+ }
+ mac_link_update(GLD3(pcwl_p), LINK_STATE_DOWN);
+ mutex_exit(&pcwl_p->pcwl_glock);
+ }
+ pcwl_p->pcwl_flag |= PCWL_CARD_SUSPEND;
+ PCWLDBG((CE_WARN, "pcwl: do suspend\n"));
+}
+
+
static int
pcwl_card_insert(pcwl_maci_t *pcwl_p)
{
@@ -661,6 +716,7 @@ pcwl_card_insert(pcwl_maci_t *pcwl_p)
cistpl_config_t config;
cistpl_cftable_entry_t *tbl_p;
register client_handle_t chdl = pcwl_p->pcwl_chdl;
+ modify_config_t cfgmod;
bzero(&tuple, sizeof (tuple));
tuple.DesiredTuple = CISTPL_MANFID;
@@ -785,6 +841,29 @@ pcwl_card_insert(pcwl_maci_t *pcwl_p)
cmn_err(CE_WARN, "pcwl: RequestConfiguration failed %x\n", ret);
goto un_irq;
}
+
+ if (pcwl_p->pcwl_flag & PCWL_CARD_SUSPEND) {
+ mutex_enter(&pcwl_p->pcwl_glock);
+ pcwl_reset_backend(pcwl_p);
+ /* turn on CS interrupt */
+ cfgmod.Attributes = CONF_ENABLE_IRQ_STEERING |
+ CONF_IRQ_CHANGE_VALID;
+ cfgmod.Vpp1 = 50;
+ cfgmod.Vpp2 = 50;
+ (void) csx_ModifyConfiguration(pcwl_p->pcwl_chdl, &cfgmod);
+
+ (void) pcwl_init_nicmem(pcwl_p);
+ pcwl_chip_type(pcwl_p);
+ (void) pcwl_loaddef_rf(pcwl_p);
+ (void) pcwl_set_cmd(pcwl_p, WL_CMD_DISABLE, 0);
+ pcwl_stop_locked(pcwl_p); /* leaves interface down */
+ pcwl_p->pcwl_flag &= ~PCWL_CARD_SUSPEND;
+ mutex_exit(&pcwl_p->pcwl_glock);
+ }
+ if (pcwl_p->pcwl_flag & PCWL_CARD_PLUMBED) {
+ pcwl_start(pcwl_p);
+ pcwl_p->pcwl_flag &= ~PCWL_CARD_PLUMBED;
+ }
return (CS_SUCCESS);
un_irq:
(void) csx_ReleaseIRQ(chdl, &irq);
@@ -814,6 +893,23 @@ pcwl_card_remove(pcwl_maci_t *pcwl_p)
*/
if (!(pcwl_p->pcwl_flag & PCWL_CARD_READY))
return;
+
+ if (pcwl_p->pcwl_connect_timeout_id != 0) {
+ (void) untimeout(pcwl_p->pcwl_connect_timeout_id);
+ pcwl_p->pcwl_connect_timeout_id = 0;
+ }
+
+ if (pcwl_p->pcwl_flag & PCWL_CARD_LINKUP) {
+ pcwl_p->pcwl_flag &= ~PCWL_CARD_LINKUP;
+ mac_link_update(GLD3(pcwl_p), LINK_STATE_DOWN);
+ }
+ mutex_enter(&pcwl_p->pcwl_glock);
+ if (pcwl_p->pcwl_flag & PCWL_CARD_INTREN) {
+ pcwl_stop_locked(pcwl_p);
+ pcwl_p->pcwl_flag |= PCWL_CARD_PLUMBED;
+ }
+ pcwl_p->pcwl_flag &= ~PCWL_CARD_READY;
+ mutex_exit(&pcwl_p->pcwl_glock);
if (ret = csx_ReleaseConfiguration(pcwl_p->pcwl_chdl, NULL))
cmn_err(CE_WARN, "pcwl: ReleaseConfiguration failed %x\n", ret);
@@ -830,7 +926,6 @@ pcwl_card_remove(pcwl_maci_t *pcwl_p)
cmn_err(CE_WARN, "pcwl: ReleaseIO failed %x\n", ret);
pcwl_p->pcwl_port = 0;
- pcwl_p->pcwl_flag &= ~PCWL_CARD_READY;
}
/*
@@ -1030,7 +1125,8 @@ pcwl_tx(void *arg, mblk_t *mp)
if ((pcwl_p->pcwl_flag & (PCWL_CARD_LINKUP | PCWL_CARD_READY)) !=
(PCWL_CARD_LINKUP | PCWL_CARD_READY)) {
mutex_exit(&pcwl_p->pcwl_glock);
- return (mp);
+ freemsgchain(mp);
+ return (NULL);
}
mutex_exit(&pcwl_p->pcwl_glock);
while (mp != NULL) {
diff --git a/usr/src/uts/common/io/pcwl/pcwl.h b/usr/src/uts/common/io/pcwl/pcwl.h
index e80d11125e..4d52a65da2 100644
--- a/usr/src/uts/common/io/pcwl/pcwl.h
+++ b/usr/src/uts/common/io/pcwl/pcwl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -43,8 +43,6 @@
#ifndef _SYS_PCWL_H
#define _SYS_PCWL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -762,6 +760,8 @@ typedef struct pcwl_macinfo {
#define PCWL_CARD_READY 0x80
#define PCWL_CARD_FAILED 0x100
#define PCWL_CARD_INTR 0x200
+#define PCWL_CARD_PLUMBED 0x400
+#define PCWL_CARD_SUSPEND 0x800
#define PCWL_STATE_IDLE 0x1
diff --git a/usr/src/uts/common/pcmcia/nexus/pcmcia.c b/usr/src/uts/common/pcmcia/nexus/pcmcia.c
index d60fc96ba8..069c1897d4 100644
--- a/usr/src/uts/common/pcmcia/nexus/pcmcia.c
+++ b/usr/src/uts/common/pcmcia/nexus/pcmcia.c
@@ -3738,7 +3738,8 @@ SSSetSocket(set_socket_t *socket)
newsock = *socket;
/* note: we force CS to always get insert/removal events */
sockp->ls_cs_events = pcm_mapevents(newsock.SCIntMask) |
- PCE_E2M(PCE_CARD_INSERT) | PCE_E2M(PCE_CARD_REMOVAL);
+ PCE_E2M(PCE_CARD_INSERT) | PCE_E2M(PCE_CARD_REMOVAL) |
+ PCE_E2M(PCE_PM_SUSPEND);
#if defined(PCMCIA_DEBUG)
if (pcmcia_debug > 1)
cmn_err(CE_CONT,