diff options
author | Andres Salomon <dilinger@debian.org> | 2008-09-12 18:33:57 -0400 |
---|---|---|
committer | Andres Salomon <dilinger@debian.org> | 2008-09-12 18:33:57 -0400 |
commit | fff47581179f48a2bc5bcc83b691d23de4185bc0 (patch) | |
tree | f9456132c3200326b640c265942ab47ea90a31bc | |
parent | 93970329291a9ff73301a96a27c4af274f096835 (diff) | |
parent | 850b087f7daf1b0251d299cfd04a4aa7b043ba4e (diff) | |
download | lwn-fff47581179f48a2bc5bcc83b691d23de4185bc0.tar.gz lwn-fff47581179f48a2bc5bcc83b691d23de4185bc0.zip |
Merge branch 'testing' of git+ssh://dev.laptop.org/git/olpc-2.6 into testing
-rw-r--r-- | arch/x86/kernel/olpc-pm.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 19 |
2 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/kernel/olpc-pm.c b/arch/x86/kernel/olpc-pm.c index acedefbba498..4c758f7e6e02 100644 --- a/arch/x86/kernel/olpc-pm.c +++ b/arch/x86/kernel/olpc-pm.c @@ -373,6 +373,15 @@ void olpc_fixup_wakeup(void) /* tell the wireless module to restart USB communication */ olpc_ec_cmd(0x24, NULL, 0, NULL, 0); } + + /* + * Re-enable all LID events + */ + if (olpc_board_at_least(olpc_board(0xb2))) { + geode_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN); + geode_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN); + geode_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); + } } int olpc_fixup_sleep(void) @@ -711,6 +720,9 @@ static struct attribute_group olpc_attrs = { static ssize_t wackup_event_show(struct kobject *s, struct kobj_attribute *attr, char *buf); static ssize_t wackup_event_store(struct kobject *s, struct kobj_attribute *attr, const char *buf, size_t n); +static ssize_t wackup_all_show(struct kobject *s, struct kobj_attribute *attr, char *buf); +static ssize_t wackup_all_store(struct kobject *s, struct kobj_attribute *attr, const char *buf, size_t n); + static struct kobj_attribute wackup_event_attr[] = { __ATTR(ps2event, 0600, wackup_event_show, wackup_event_store), __ATTR(battery_state, 0600, wackup_event_show, wackup_event_store), @@ -719,6 +731,7 @@ static struct kobj_attribute wackup_event_attr[] = { __ATTR(ebook_mode_change, 0600, wackup_event_show, wackup_event_store), __ATTR(wlan, 0600, wackup_event_show, wackup_event_store), __ATTR(ac_power, 0600, wackup_event_show, wackup_event_store), + __ATTR(all, 0600, wackup_all_show, wackup_all_store) }; static DEFINE_RWLOCK(wackup_event_lock); @@ -758,6 +771,43 @@ static ssize_t wackup_event_store(struct kobject *s, struct kobj_attribute *attr return n; } +static ssize_t wackup_all_show(struct kobject *s, struct kobj_attribute *attr, char *buf) +{ + u8 data; + + read_lock(&wackup_event_lock); + olpc_ec_cmd(EC_READ_SCI_MASK, NULL, 0, &data, 1); + read_unlock(&wackup_event_lock); + + if (data == 0xff) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t wackup_all_store(struct kobject *s, struct kobj_attribute *attr, const char *buf, size_t n) +{ + unsigned enabled; + u8 data; + unsigned char shift = attr - wackup_event_attr; + + if (sscanf(buf, "%d\n", &enabled) != 1) + return -EINVAL; + + if (enabled == 1) + data = 0xff; + else if (!enabled) + data = 0; + else + return -EINVAL; + + write_lock(&wackup_event_lock); + olpc_ec_cmd(EC_WRITE_SCI_MASK, &data, 1, NULL, 0); + write_unlock(&wackup_event_lock); + + return n; +} + static struct attribute * olpc_wackup_event_attributes[] = { &wackup_event_attr[0].attr, &wackup_event_attr[1].attr, @@ -766,6 +816,7 @@ static struct attribute * olpc_wackup_event_attributes[] = { &wackup_event_attr[4].attr, &wackup_event_attr[5].attr, &wackup_event_attr[6].attr, + &wackup_event_attr[7].attr, NULL }; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 87972fb17569..6ccd395d0972 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1212,7 +1212,13 @@ int lbs_remove_card(struct lbs_private *priv) cancel_delayed_work(&priv->scan_work); cancel_delayed_work(&priv->assoc_work); cancel_work_sync(&priv->mcast_work); + + /* worker thread destruction blocks on the in-flight command which + * should have been cleared already in lbs_stop_card(). + */ + lbs_deb_main("destroying worker thread\n"); destroy_workqueue(priv->work_thread); + lbs_deb_main("done destroying worker thread\n"); if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; @@ -1324,13 +1330,26 @@ int lbs_stop_card(struct lbs_private *priv) device_remove_file(&dev->dev, &dev_attr_lbs_mesh); } + /* Delete the timeout of the currently processing command */ + del_timer_sync(&priv->command_timer); + /* Flush pending command nodes */ spin_lock_irqsave(&priv->driver_lock, flags); + lbs_deb_main("clearing pending commands\n"); list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { cmdnode->result = -ENOENT; cmdnode->cmdwaitqwoken = 1; wake_up_interruptible(&cmdnode->cmdwait_q); } + + /* Flush the command the card is currently processing */ + if (priv->cur_cmd) { + lbs_deb_main("clearing current command\n"); + priv->cur_cmd->result = -ENOENT; + priv->cur_cmd->cmdwaitqwoken = 1; + wake_up_interruptible(&priv->cur_cmd->cmdwait_q); + } + lbs_deb_main("done clearing commands\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); unregister_netdev(dev); |