Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 243062
b: refs/heads/master
c: 279f8f9
h: refs/heads/master
v: v3
  • Loading branch information
Corentin Chary authored and Matthew Garrett committed Mar 28, 2011
1 parent 295f444 commit 5bc39a0
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: afa7c886578ce264d9b66d4bcb1fea51fac47925
refs/heads/master: 279f8f95493c9aaa0a85520c863ccba87c4bf930
78 changes: 72 additions & 6 deletions trunk/drivers/platform/x86/eeepc-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ struct eeepc_wmi {

struct hotplug_slot *hotplug_slot;
struct mutex hotplug_lock;
struct mutex wmi_lock;
struct workqueue_struct *hotplug_workqueue;
struct work_struct hotplug_work;

struct eeepc_wmi_debug debug;
};
Expand Down Expand Up @@ -370,15 +373,19 @@ static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
{
struct pci_dev *dev;
struct pci_bus *bus;
bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
bool blocked;
bool absent;
u32 l;

if (eeepc->wlan_rfkill)
rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
mutex_lock(&eeepc->wmi_lock);
blocked = eeepc_wlan_rfkill_blocked(eeepc);
mutex_unlock(&eeepc->wmi_lock);

mutex_lock(&eeepc->hotplug_lock);

if (eeepc->wlan_rfkill)
rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);

if (eeepc->hotplug_slot) {
bus = pci_find_bus(0, 1);
if (!bus) {
Expand Down Expand Up @@ -435,7 +442,14 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if (event != ACPI_NOTIFY_BUS_CHECK)
return;

eeepc_rfkill_hotplug(eeepc);
/*
* We can't call directly eeepc_rfkill_hotplug because most
* of the time WMBC is still being executed and not reetrant.
* There is currently no way to tell ACPICA that we want this
* method to be serialized, we schedule a eeepc_rfkill_hotplug
* call later, in a safer context.
*/
queue_work(eeepc->hotplug_workqueue, &eeepc->hotplug_work);
}

static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
Expand Down Expand Up @@ -508,6 +522,14 @@ static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
.get_power_status = eeepc_get_adapter_status,
};

static void eeepc_hotplug_work(struct work_struct *work)
{
struct eeepc_wmi *eeepc;

eeepc = container_of(work, struct eeepc_wmi, hotplug_work);
eeepc_rfkill_hotplug(eeepc);
}

static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
{
int ret = -ENOMEM;
Expand All @@ -518,6 +540,13 @@ static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
return -ENODEV;
}

eeepc->hotplug_workqueue =
create_singlethread_workqueue("hotplug_workqueue");
if (!eeepc->hotplug_workqueue)
goto error_workqueue;

INIT_WORK(&eeepc->hotplug_work, eeepc_hotplug_work);

eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
if (!eeepc->hotplug_slot)
goto error_slot;
Expand Down Expand Up @@ -547,6 +576,8 @@ static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
kfree(eeepc->hotplug_slot);
eeepc->hotplug_slot = NULL;
error_slot:
destroy_workqueue(eeepc->hotplug_workqueue);
error_workqueue:
return ret;
}

Expand Down Expand Up @@ -575,6 +606,34 @@ static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
rfkill_set_sw_state(rfkill, !(retval & 0x1));
}

static int eeepc_rfkill_wlan_set(void *data, bool blocked)
{
struct eeepc_wmi *eeepc = data;
int ret;

/*
* This handler is enabled only if hotplug is enabled.
* In this case, the eeepc_wmi_set_devstate() will
* trigger a wmi notification and we need to wait
* this call to finish before being able to call
* any wmi method
*/
mutex_lock(&eeepc->wmi_lock);
ret = eeepc_rfkill_set((void *)(long)EEEPC_WMI_DEVID_WLAN, blocked);
mutex_unlock(&eeepc->wmi_lock);
return ret;
}

static void eeepc_rfkill_wlan_query(struct rfkill *rfkill, void *data)
{
eeepc_rfkill_query(rfkill, (void *)(long)EEEPC_WMI_DEVID_WLAN);
}

static const struct rfkill_ops eeepc_rfkill_wlan_ops = {
.set_block = eeepc_rfkill_wlan_set,
.query = eeepc_rfkill_wlan_query,
};

static const struct rfkill_ops eeepc_rfkill_ops = {
.set_block = eeepc_rfkill_set,
.query = eeepc_rfkill_query,
Expand Down Expand Up @@ -603,8 +662,12 @@ static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
if (!retval || retval == 0x00060000)
return -ENODEV;

*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
&eeepc_rfkill_ops, (void *)(long)dev_id);
if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
&eeepc_rfkill_wlan_ops, eeepc);
else
*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
&eeepc_rfkill_ops, (void *)(long)dev_id);

if (!*rfkill)
return -EINVAL;
Expand Down Expand Up @@ -636,6 +699,8 @@ static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
eeepc_rfkill_hotplug(eeepc);
if (eeepc->hotplug_slot)
pci_hp_deregister(eeepc->hotplug_slot);
if (eeepc->hotplug_workqueue)
destroy_workqueue(eeepc->hotplug_workqueue);

if (eeepc->bluetooth_rfkill) {
rfkill_unregister(eeepc->bluetooth_rfkill);
Expand All @@ -654,6 +719,7 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
int result = 0;

mutex_init(&eeepc->hotplug_lock);
mutex_init(&eeepc->wmi_lock);

result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
"eeepc-wlan", RFKILL_TYPE_WLAN,
Expand Down

0 comments on commit 5bc39a0

Please sign in to comment.