[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090224160043.GA12027@srcf.ucam.org>
Date: Tue, 24 Feb 2009 16:00:44 +0000
From: Matthew Garrett <mjg59@...f.ucam.org>
To: Ingo Molnar <mingo@...e.hu>, linux-kernel@...r.kernel.org,
linux-acpi@...r.kernel.org, "Rafael J. Wysocki" <rjw@...k.pl>,
Len Brown <lenb@...nel.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Andrew Morton <akpm@...ux-foundation.org>,
Jesse Barnes <jbarnes@...tuousgeek.org>,
Thomas Gleixner <tglx@...utronix.de>,
"H. Peter Anvin" <hpa@...or.com>,
Corentin Chary <corentincj@...aif.net>,
Darren Salt <linux@...mustbejoking.demon.co.uk>
Subject: Re: Oopses and ACPI problems (Linus 2.6.29-rc4)
On Tue, Feb 24, 2009 at 03:29:36PM +0000, Darren Salt wrote:
> Not HOTPLUG_PCI_PCIE?
No - it just depends on the hotplug PCI core.
> With that selected (I see no point in testing this otherwise) *and*
> pciehp_force=1, I get -EBUSY when the hotplug slot registration is attempted
> and no wireless, bluetooth or hot key reporting; wireless & bluetooth are
> switched off at that point (I made sure that they were enabled via BIOS
> setup). Without that option, all is fine.
Right, so that sounds like everything works as expected. I guess to
avoid breaking existing setups we should probably be a bit nicer there.
Can you test whether this one works?
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b3866ad..75a560b 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -307,6 +307,7 @@ config EEEPC_LAPTOP
select BACKLIGHT_CLASS_DEVICE
select HWMON
select RFKILL
+ select HOTPLUG_PCI
---help---
This driver supports the Fn-Fx keys on Eee PC laptops.
It also adds the ability to switch camera/wlan on/off.
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 786ed86..e2412c9 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -31,6 +31,7 @@
#include <linux/input.h>
#include <linux/rfkill.h>
#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
#define EEEPC_LAPTOP_VERSION "0.1"
@@ -132,6 +133,7 @@ struct eeepc_hotk {
u16 *keycode_map;
struct rfkill *eeepc_wlan_rfkill;
struct rfkill *eeepc_bluetooth_rfkill;
+ struct hotplug_slot *hotplug_slot;
};
/* The actual device the driver binds to */
@@ -194,6 +196,15 @@ static struct acpi_driver eeepc_hotk_driver = {
},
};
+/* PCI hotplug ops */
+static int eeepc_get_adapter_status (struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
+ .owner = THIS_MODULE,
+ .get_adapter_status = eeepc_get_adapter_status,
+ .get_power_status = eeepc_get_adapter_status,
+};
+
/* The backlight device /sys/class/backlight */
static struct backlight_device *eeepc_backlight_device;
@@ -519,6 +530,19 @@ static void notify_brn(void)
bd->props.brightness = read_brightness(bd);
}
+static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
+ u8 *value)
+{
+ int val = get_acpi(CM_ASL_WLAN);
+
+ if (val == 1 || val == 0)
+ *value = val;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
{
struct pci_dev *dev;
@@ -620,6 +644,54 @@ static void eeepc_unregister_rfkill_notifier(char *node)
}
}
+static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+ kfree(hotplug_slot->info);
+ kfree(hotplug_slot);
+}
+
+static int eeepc_setup_pci_hotplug(void)
+{
+ int ret = -ENOMEM;
+ struct pci_bus *bus = pci_find_bus(0, 1);
+
+ if (!bus) {
+ printk(EEEPC_ERR "Unable to find wifi PCI bus\n");
+ return -ENODEV;
+ }
+
+ ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+ if (!ehotk->hotplug_slot)
+ goto error_slot;
+
+ ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+ GFP_KERNEL);
+ if (!ehotk->hotplug_slot->info)
+ goto error_info;
+
+ ehotk->hotplug_slot->private = ehotk;
+ ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
+ ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
+ eeepc_get_adapter_status(ehotk->hotplug_slot,
+ &ehotk->hotplug_slot->info->adapter_status);
+
+ ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
+ if (ret) {
+ printk(EEEPC_ERR "Unable to register hotplug slot - %d\n", ret);
+ goto error_register;
+ }
+
+ return 0;
+
+error_register:
+ kfree(ehotk->hotplug_slot->info);
+error_info:
+ kfree(ehotk->hotplug_slot);
+ ehotk->hotplug_slot = NULL;
+error_slot:
+ return ret;
+}
+
static int eeepc_hotk_add(struct acpi_device *device)
{
acpi_status status = AE_OK;
@@ -700,11 +772,25 @@ static int eeepc_hotk_add(struct acpi_device *device)
goto bluetooth_fail;
}
+ result = eeepc_setup_pci_hotplug();
+
+ /*
+ * If we get -EBUSY then something else is handling the PCI hotplug -
+ * don't fail in this case
+ */
+
+ if (result == -EBUSY)
+ return 0;
+ else if (result)
+ goto pci_fail;
+
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
return 0;
-
+ pci_fail:
+ if (ehotk->eeepc_bluetooth_rfkill)
+ rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
bluetooth_fail:
if (ehotk->eeepc_bluetooth_rfkill)
rfkill_free(ehotk->eeepc_bluetooth_rfkill);
@@ -731,8 +817,11 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
if (ACPI_FAILURE(status))
printk(EEEPC_ERR "Error removing notify handler\n");
- eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
- eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
+ if (ehotk->hotplug_slot) {
+ eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
+ eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
+ pci_hp_deregister(ehotk->hotplug_slot);
+ }
kfree(ehotk);
return 0;
--
Matthew Garrett | mjg59@...f.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists