o wl3501: first cut at power management support

parent e04fa26a
...@@ -46,7 +46,7 @@ enum wl3501_signals { ...@@ -46,7 +46,7 @@ enum wl3501_signals {
WL3501_SIG_DISASSOC_REQ, WL3501_SIG_DISASSOC_REQ,
WL3501_SIG_GET_REQ, WL3501_SIG_GET_REQ,
WL3501_SIG_JOIN_REQ, WL3501_SIG_JOIN_REQ,
WL3501_SIG_POWERMGT_REQ, WL3501_SIG_PWR_MGMT_REQ,
WL3501_SIG_REASSOC_REQ, WL3501_SIG_REASSOC_REQ,
WL3501_SIG_SCAN_REQ, WL3501_SIG_SCAN_REQ,
WL3501_SIG_SET_REQ, WL3501_SIG_SET_REQ,
...@@ -345,6 +345,21 @@ struct wl3501_join_confirm { ...@@ -345,6 +345,21 @@ struct wl3501_join_confirm {
u16 status; u16 status;
}; };
struct wl3501_pwr_mgmt_req {
u16 next_blk;
unsigned char sig_id;
u8 pwr_save;
u8 wake_up;
u8 receive_dtims;
};
struct wl3501_pwr_mgmt_confirm {
u16 next_blk;
unsigned char sig_id;
unsigned char reserved;
u16 status;
};
struct wl3501_scan_req { struct wl3501_scan_req {
u16 next_blk; u16 next_blk;
unsigned char sig_id; unsigned char sig_id;
...@@ -503,6 +518,7 @@ struct wl3501_card { ...@@ -503,6 +518,7 @@ struct wl3501_card {
spinlock_t lock; spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
struct wl3501_get_confirm sig_get_confirm; struct wl3501_get_confirm sig_get_confirm;
struct wl3501_pwr_mgmt_confirm sig_pwr_mgmt_confirm;
u16 tx_buffer_size; u16 tx_buffer_size;
u16 tx_buffer_head; u16 tx_buffer_head;
u16 tx_buffer_tail; u16 tx_buffer_tail;
......
...@@ -88,6 +88,9 @@ MODULE_PARM(pc_debug, "i"); ...@@ -88,6 +88,9 @@ MODULE_PARM(pc_debug, "i");
#define WL3501_RELEASE_TIMEOUT (25 * HZ) #define WL3501_RELEASE_TIMEOUT (25 * HZ)
#define WL3501_MAX_ADHOC_TRIES 16 #define WL3501_MAX_ADHOC_TRIES 16
#define WL3501_RESUME 0
#define WL3501_SUSPEND 1
/* Parameters that can be set with 'insmod' */ /* Parameters that can be set with 'insmod' */
/* Bit map of interrupts to choose from */ /* Bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
...@@ -445,6 +448,38 @@ static int wl3501_get_mib_value(struct wl3501_card *this, u8 index, ...@@ -445,6 +448,38 @@ static int wl3501_get_mib_value(struct wl3501_card *this, u8 index,
return rc; return rc;
} }
static int wl3501_pwr_mgmt(struct wl3501_card *this, int suspend)
{
struct wl3501_pwr_mgmt_req sig = {
.sig_id = WL3501_SIG_PWR_MGMT_REQ,
.pwr_save = suspend,
.wake_up = !suspend,
.receive_dtims = 10,
};
unsigned long flags;
int rc = -EIO;
spin_lock_irqsave(&this->lock, flags);
if (wl3501_esbq_req_test(this)) {
u16 ptr = wl3501_get_tx_buffer(this, sizeof(sig));
if (ptr) {
wl3501_set_to_wla(this, ptr, &sig, sizeof(sig));
wl3501_esbq_req(this, &ptr);
this->sig_pwr_mgmt_confirm.status = 255;
spin_unlock_irqrestore(&this->lock, flags);
rc = wait_event_interruptible(this->wait,
this->sig_pwr_mgmt_confirm.status != 255);
printk(KERN_INFO "%s: %s status=%d\n", __FUNCTION__,
suspend ? "suspend" : "resume",
this->sig_pwr_mgmt_confirm.status);
goto out;
}
}
spin_unlock_irqrestore(&this->lock, flags);
out:
return rc;
}
/** /**
* wl3501_send_pkt - Send a packet. * wl3501_send_pkt - Send a packet.
* @this - card * @this - card
...@@ -956,7 +991,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, ...@@ -956,7 +991,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
} }
static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this, static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this,
u16 addr) u16 addr, void *sig, int size)
{ {
dprintk(3, "entry"); dprintk(3, "entry");
wl3501_get_from_wla(this, addr, &this->sig_get_confirm, wl3501_get_from_wla(this, addr, &this->sig_get_confirm,
...@@ -1031,7 +1066,14 @@ static inline void wl3501_rx_interrupt(struct net_device *dev) ...@@ -1031,7 +1066,14 @@ static inline void wl3501_rx_interrupt(struct net_device *dev)
wl3501_md_ind_interrupt(dev, this, addr); wl3501_md_ind_interrupt(dev, this, addr);
break; break;
case WL3501_SIG_GET_CONFIRM: case WL3501_SIG_GET_CONFIRM:
wl3501_get_confirm_interrupt(this, addr); wl3501_get_confirm_interrupt(this, addr,
&this->sig_get_confirm,
sizeof(this->sig_get_confirm));
break;
case WL3501_SIG_PWR_MGMT_CONFIRM:
wl3501_get_confirm_interrupt(this, addr,
&this->sig_pwr_mgmt_confirm,
sizeof(this->sig_pwr_mgmt_confirm));
break; break;
case WL3501_SIG_START_CONFIRM: case WL3501_SIG_START_CONFIRM:
wl3501_start_confirm_interrupt(dev, this, addr); wl3501_start_confirm_interrupt(dev, this, addr);
...@@ -2167,6 +2209,7 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) ...@@ -2167,6 +2209,7 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
break; break;
case CS_EVENT_PM_SUSPEND: case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
/* Fall through... */ /* Fall through... */
case CS_EVENT_RESET_PHYSICAL: case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
...@@ -2177,6 +2220,7 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) ...@@ -2177,6 +2220,7 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
break; break;
case CS_EVENT_PM_RESUME: case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
/* Fall through... */ /* Fall through... */
case CS_EVENT_CARD_RESET: case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment