From 51fac8388a0325a43f0ae67453ece2c373e2ec28 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 24 Jan 2013 00:24:48 +0100 Subject: ACPI: Remove useless type argument of driver .remove() operation The second argument of ACPI driver .remove() operation is only used by the ACPI processor driver and the value passed to that driver through it is always available from the given struct acpi_device object's removal_type field. For this reason, the second ACPI driver .remove() argument is in fact useless, so drop it. Signed-off-by: Rafael J. Wysocki Reviewed-by: Jiang Liu Acked-by: Toshi Kani Acked-by: Yinghai Lu diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c index 6192f71..916ffe7 100644 --- a/arch/ia64/hp/common/aml_nfw.c +++ b/arch/ia64/hp/common/aml_nfw.c @@ -191,7 +191,7 @@ static int aml_nfw_add(struct acpi_device *device) return aml_nfw_add_global_handler(); } -static int aml_nfw_remove(struct acpi_device *device, int type) +static int aml_nfw_remove(struct acpi_device *device) { return aml_nfw_remove_global_handler(); } diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 2fdca25..fef7d0b 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -195,7 +195,7 @@ err_sysfs: return r; } -static int xo15_sci_remove(struct acpi_device *device, int type) +static int xo15_sci_remove(struct acpi_device *device) { acpi_disable_gpe(NULL, xo15_sci_gpe); acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler); diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d5fdd36..6d5bf64 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -60,7 +60,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file); #endif static int acpi_ac_add(struct acpi_device *device); -static int acpi_ac_remove(struct acpi_device *device, int type); +static int acpi_ac_remove(struct acpi_device *device); static void acpi_ac_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id ac_device_ids[] = { @@ -337,7 +337,7 @@ static int acpi_ac_resume(struct device *dev) } #endif -static int acpi_ac_remove(struct acpi_device *device, int type) +static int acpi_ac_remove(struct acpi_device *device) { struct acpi_ac *ac = NULL; diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 03d18f2..94c823b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); #define MEMORY_POWER_OFF_STATE 2 static int acpi_memory_device_add(struct acpi_device *device); -static int acpi_memory_device_remove(struct acpi_device *device, int type); +static int acpi_memory_device_remove(struct acpi_device *device); static const struct acpi_device_id memory_device_ids[] = { {ACPI_MEMORY_DEVICE_HID, 0}, @@ -415,7 +415,7 @@ static int acpi_memory_device_add(struct acpi_device *device) return result; } -static int acpi_memory_device_remove(struct acpi_device *device, int type) +static int acpi_memory_device_remove(struct acpi_device *device) { struct acpi_memory_device *mem_device = NULL; int result; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 16fa979..31de104 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -482,8 +482,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device, - int type) +static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(0); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7efaeaa..c5cd5b5 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1111,7 +1111,7 @@ fail: return result; } -static int acpi_battery_remove(struct acpi_device *device, int type) +static int acpi_battery_remove(struct acpi_device *device) { struct acpi_battery *battery = NULL; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index f0d936b..86c7d54 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -75,7 +75,7 @@ static const struct acpi_device_id button_device_ids[] = { MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device, int type); +static int acpi_button_remove(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP @@ -433,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device) return error; } -static int acpi_button_remove(struct acpi_device *device, int type) +static int acpi_button_remove(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index cc79d3e..cc0bf46 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION("ACPI container driver"); MODULE_LICENSE("GPL"); static int acpi_container_add(struct acpi_device *device); -static int acpi_container_remove(struct acpi_device *device, int type); +static int acpi_container_remove(struct acpi_device *device); static const struct acpi_device_id container_device_ids[] = { {"ACPI0004", 0}, @@ -125,7 +125,7 @@ static int acpi_container_add(struct acpi_device *device) return 0; } -static int acpi_container_remove(struct acpi_device *device, int type) +static int acpi_container_remove(struct acpi_device *device) { acpi_status status = AE_OK; struct acpi_container *pc = NULL; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 354007d..d45b287 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -852,7 +852,7 @@ static int acpi_ec_add(struct acpi_device *device) return ret; } -static int acpi_ec_remove(struct acpi_device *device, int type) +static int acpi_ec_remove(struct acpi_device *device) { struct acpi_ec *ec; struct acpi_ec_query_handler *handler, *tmp; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 3bd6a54..f815da8 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -45,7 +45,7 @@ MODULE_DESCRIPTION("ACPI Fan Driver"); MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); -static int acpi_fan_remove(struct acpi_device *device, int type); +static int acpi_fan_remove(struct acpi_device *device); static const struct acpi_device_id fan_device_ids[] = { {"PNP0C0B", 0}, @@ -172,7 +172,7 @@ static int acpi_fan_add(struct acpi_device *device) return result; } -static int acpi_fan_remove(struct acpi_device *device, int type) +static int acpi_fan_remove(struct acpi_device *device) { struct thermal_cooling_device *cdev = acpi_driver_data(device); diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index a0cc796..13b1d39 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -70,7 +70,7 @@ static int acpi_hed_add(struct acpi_device *device) return 0; } -static int acpi_hed_remove(struct acpi_device *device, int type) +static int acpi_hed_remove(struct acpi_device *device) { hed_handle = NULL; return 0; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index a128082..b659279 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -54,7 +54,7 @@ ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_MAX_POSSIBLE 16 static int acpi_pci_link_add(struct acpi_device *device); -static int acpi_pci_link_remove(struct acpi_device *device, int type); +static int acpi_pci_link_remove(struct acpi_device *device); static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, @@ -766,7 +766,7 @@ static void irqrouter_resume(void) } } -static int acpi_pci_link_remove(struct acpi_device *device, int type) +static int acpi_pci_link_remove(struct acpi_device *device) { struct acpi_pci_link *link; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 22a8458..8890775 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); -static int acpi_pci_root_remove(struct acpi_device *device, int type); +static int acpi_pci_root_remove(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -627,7 +627,7 @@ end: return result; } -static int acpi_pci_root_remove(struct acpi_device *device, int type) +static int acpi_pci_root_remove(struct acpi_device *device) { acpi_status status; acpi_handle handle; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 9c5929a..c5d2fd8 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -81,7 +81,7 @@ MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); static int acpi_processor_add(struct acpi_device *device); -static int acpi_processor_remove(struct acpi_device *device, int type); +static int acpi_processor_remove(struct acpi_device *device); static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr); static int acpi_processor_handle_eject(struct acpi_processor *pr); @@ -610,7 +610,7 @@ err_free_pr: return result; } -static int acpi_processor_remove(struct acpi_device *device, int type) +static int acpi_processor_remove(struct acpi_device *device) { struct acpi_processor *pr = NULL; @@ -623,7 +623,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) if (pr->id >= nr_cpu_ids) goto free; - if (type == ACPI_BUS_REMOVAL_EJECT) { + if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index ff0740e..e523245 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -130,7 +130,7 @@ struct acpi_sbs { #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) -static int acpi_sbs_remove(struct acpi_device *device, int type); +static int acpi_sbs_remove(struct acpi_device *device); static int acpi_battery_get_state(struct acpi_battery *battery); static inline int battery_scale(int log) @@ -949,11 +949,11 @@ static int acpi_sbs_add(struct acpi_device *device) acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: if (result) - acpi_sbs_remove(device, 0); + acpi_sbs_remove(device); return result; } -static int acpi_sbs_remove(struct acpi_device *device, int type) +static int acpi_sbs_remove(struct acpi_device *device) { struct acpi_sbs *sbs; int id; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index cf6129a..b78bc60 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -33,7 +33,7 @@ struct acpi_smb_hc { }; static int acpi_smbus_hc_add(struct acpi_device *device); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type); +static int acpi_smbus_hc_remove(struct acpi_device *device); static const struct acpi_device_id sbs_device_ids[] = { {"ACPI0001", 0}, @@ -296,7 +296,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type) +static int acpi_smbus_hc_remove(struct acpi_device *device) { struct acpi_smb_hc *hc; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bc8077f..0989b32 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -577,8 +577,7 @@ static int acpi_device_probe(struct device * dev) ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, - acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); return ret; } } @@ -600,7 +599,7 @@ static int acpi_device_remove(struct device * dev) if (acpi_drv->ops.notify) acpi_device_remove_notify_handler(acpi_dev); if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); } acpi_dev->driver = NULL; acpi_dev->driver_data = NULL; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 506fbd4..da079d4 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -97,7 +97,7 @@ module_param(psv, int, 0644); MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static int acpi_thermal_add(struct acpi_device *device); -static int acpi_thermal_remove(struct acpi_device *device, int type); +static int acpi_thermal_remove(struct acpi_device *device); static void acpi_thermal_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id thermal_device_ids[] = { @@ -1111,7 +1111,7 @@ end: return result; } -static int acpi_thermal_remove(struct acpi_device *device, int type) +static int acpi_thermal_remove(struct acpi_device *device) { struct acpi_thermal *tz = NULL; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ac9a69c..5be60ad 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -88,7 +88,7 @@ module_param(use_bios_initial_backlight, bool, 0644); static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); -static int acpi_video_bus_remove(struct acpi_device *device, int type); +static int acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id video_device_ids[] = { @@ -1740,7 +1740,7 @@ static int acpi_video_bus_add(struct acpi_device *device) return error; } -static int acpi_video_bus_remove(struct acpi_device *device, int type) +static int acpi_video_bus_remove(struct acpi_device *device) { struct acpi_video_bus *video = NULL; diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fe6d4be..e3f9a99 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -1041,7 +1041,7 @@ static int hpet_acpi_add(struct acpi_device *device) return hpet_alloc(&data); } -static int hpet_acpi_remove(struct acpi_device *device, int type) +static int hpet_acpi_remove(struct acpi_device *device) { /* XXX need to unregister clocksource, dealloc mem, etc */ return -EINVAL; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index d780295..6386a98 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1142,7 +1142,7 @@ static int sonypi_acpi_add(struct acpi_device *device) return 0; } -static int sonypi_acpi_remove(struct acpi_device *device, int type) +static int sonypi_acpi_remove(struct acpi_device *device) { sonypi_acpi_device = NULL; return 0; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 1672e2a..6351aba 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -911,7 +911,7 @@ exit: return res; } -static int acpi_power_meter_remove(struct acpi_device *device, int type) +static int acpi_power_meter_remove(struct acpi_device *device) { struct acpi_power_meter_resource *resource; diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 56dbcfb..b25c643 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -190,7 +190,7 @@ struct atk_acpi_input_buf { }; static int atk_add(struct acpi_device *device); -static int atk_remove(struct acpi_device *device, int type); +static int atk_remove(struct acpi_device *device); static void atk_print_sensor(struct atk_data *data, union acpi_object *obj); static int atk_read_value(struct atk_sensor_data *sensor, u64 *value); static void atk_free_sensors(struct atk_data *data); @@ -1416,7 +1416,7 @@ out: return err; } -static int atk_remove(struct acpi_device *device, int type) +static int atk_remove(struct acpi_device *device) { struct atk_data *data = device->driver_data; dev_dbg(&device->dev, "removing...\n"); diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 6aafa3d..c447e8d 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -406,7 +406,7 @@ err: return -EIO; } -static int acpi_smbus_cmi_remove(struct acpi_device *device, int type) +static int acpi_smbus_cmi_remove(struct acpi_device *device) { struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device); diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 26f1313..5d44023 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device) return err; } -static int atlas_acpi_button_remove(struct acpi_device *device, int type) +static int atlas_acpi_button_remove(struct acpi_device *device) { acpi_status status; diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index fcde4e5..d9f9a0d 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1910,7 +1910,7 @@ fail_platform: return result; } -static int asus_acpi_remove(struct acpi_device *device, int type) +static int asus_acpi_remove(struct acpi_device *device) { struct asus_laptop *asus = acpi_driver_data(device); diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index c87ff16..36e5e6c 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -432,7 +432,7 @@ failed_sensitivity: return error; } -static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) +static int cmpc_accel_remove_v4(struct acpi_device *acpi) { struct input_dev *inputdev; struct cmpc_accel *accel; @@ -668,7 +668,7 @@ failed_file: return error; } -static int cmpc_accel_remove(struct acpi_device *acpi, int type) +static int cmpc_accel_remove(struct acpi_device *acpi) { struct input_dev *inputdev; struct cmpc_accel *accel; @@ -753,7 +753,7 @@ static int cmpc_tablet_add(struct acpi_device *acpi) cmpc_tablet_idev_init); } -static int cmpc_tablet_remove(struct acpi_device *acpi, int type) +static int cmpc_tablet_remove(struct acpi_device *acpi) { return cmpc_remove_acpi_notify_device(acpi); } @@ -1000,7 +1000,7 @@ out_bd: return retval; } -static int cmpc_ipml_remove(struct acpi_device *acpi, int type) +static int cmpc_ipml_remove(struct acpi_device *acpi) { struct ipml200_dev *ipml; @@ -1079,7 +1079,7 @@ static int cmpc_keys_add(struct acpi_device *acpi) cmpc_keys_idev_init); } -static int cmpc_keys_remove(struct acpi_device *acpi, int type) +static int cmpc_keys_remove(struct acpi_device *acpi) { return cmpc_remove_acpi_notify_device(acpi); } diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 528e949..98935f9 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1501,7 +1501,7 @@ fail_platform: return result; } -static int eeepc_acpi_remove(struct acpi_device *device, int type) +static int eeepc_acpi_remove(struct acpi_device *device) { struct eeepc_laptop *eeepc = acpi_driver_data(device); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index c4c1a54..1c9386e 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -733,7 +733,7 @@ err_stop: return result; } -static int acpi_fujitsu_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_remove(struct acpi_device *device) { struct fujitsu_t *fujitsu = acpi_driver_data(device); struct input_dev *input = fujitsu->input; @@ -938,7 +938,7 @@ err_stop: return result; } -static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) +static int acpi_fujitsu_hotkey_remove(struct acpi_device *device) { struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device); struct input_dev *input = fujitsu_hotkey->input; diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index 174ca01..570926c 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -431,7 +431,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev) return 0; } -static int acpi_fujitsu_remove(struct acpi_device *adev, int type) +static int acpi_fujitsu_remove(struct acpi_device *adev) { free_irq(fujitsu.irq, fujitsu_interrupt); release_region(fujitsu.io_base, fujitsu.io_length); diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 18d74f2..e64a7a8 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -337,7 +337,7 @@ static int lis3lv02d_add(struct acpi_device *device) return ret; } -static int lis3lv02d_remove(struct acpi_device *device, int type) +static int lis3lv02d_remove(struct acpi_device *device) { if (!device) return -EINVAL; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 64bfb30..17f00b8 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -834,7 +834,7 @@ platform_failed: return ret; } -static int ideapad_acpi_remove(struct acpi_device *adevice, int type) +static int ideapad_acpi_remove(struct acpi_device *adevice) { struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); int i; diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c index 3271ac8..d6cfc15 100644 --- a/drivers/platform/x86/intel_menlow.c +++ b/drivers/platform/x86/intel_menlow.c @@ -200,7 +200,7 @@ static int intel_menlow_memory_add(struct acpi_device *device) } -static int intel_menlow_memory_remove(struct acpi_device *device, int type) +static int intel_menlow_memory_remove(struct acpi_device *device) { struct thermal_cooling_device *cdev = acpi_driver_data(device); diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 8e8caa7..4add9a3 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -176,7 +176,7 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0, /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */ static int acpi_pcc_hotkey_add(struct acpi_device *device); -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); +static int acpi_pcc_hotkey_remove(struct acpi_device *device); static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id pcc_device_ids[] = { @@ -663,7 +663,7 @@ static int __init acpi_pcc_init(void) return 0; } -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) +static int acpi_pcc_hotkey_remove(struct acpi_device *device) { struct pcc_acpi *pcc = acpi_driver_data(device); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index b8ad71f..ceb41ef 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2740,7 +2740,7 @@ outwalk: return result; } -static int sony_nc_remove(struct acpi_device *device, int type) +static int sony_nc_remove(struct acpi_device *device) { struct sony_nc_value *item; @@ -4111,7 +4111,7 @@ found: * ACPI driver * *****************/ -static int sony_pic_remove(struct acpi_device *device, int type) +static int sony_pic_remove(struct acpi_device *device) { struct sony_pic_ioport *io, *tmp_io; struct sony_pic_irq *irq, *tmp_irq; diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index d727bfe..4ab618c 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -157,7 +157,7 @@ add_err: return -ENODEV; } -static int acpi_topstar_remove(struct acpi_device *device, int type) +static int acpi_topstar_remove(struct acpi_device *device) { struct topstar_hkey *tps_hkey = acpi_driver_data(device); diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c272789..904476b 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1118,7 +1118,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) return 0; } -static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) +static int toshiba_acpi_remove(struct acpi_device *acpi_dev) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); @@ -1250,7 +1250,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) return 0; error: - toshiba_acpi_remove(acpi_dev, 0); + toshiba_acpi_remove(acpi_dev); return ret; } diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index e95be0b..74dd01a 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); static int toshiba_bt_rfkill_add(struct acpi_device *device); -static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type); +static int toshiba_bt_rfkill_remove(struct acpi_device *device); static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id bt_device_ids[] = { @@ -122,7 +122,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device) return result; } -static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type) +static int toshiba_bt_rfkill_remove(struct acpi_device *device) { /* clean up */ return 0; diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 42a4dcc..e4ac38a 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -92,7 +92,7 @@ module_param(debug_dump_wdg, bool, 0444); MODULE_PARM_DESC(debug_dump_wdg, "Dump available WMI interfaces [0/1]"); -static int acpi_wmi_remove(struct acpi_device *device, int type); +static int acpi_wmi_remove(struct acpi_device *device); static int acpi_wmi_add(struct acpi_device *device); static void acpi_wmi_notify(struct acpi_device *device, u32 event); @@ -917,7 +917,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event) } } -static int acpi_wmi_remove(struct acpi_device *device, int type) +static int acpi_wmi_remove(struct acpi_device *device) { acpi_remove_address_space_handler(device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 16d340c..4b1377b 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -150,7 +150,7 @@ static int ebook_switch_add(struct acpi_device *device) return error; } -static int ebook_switch_remove(struct acpi_device *device, int type) +static int ebook_switch_remove(struct acpi_device *device) { struct ebook_switch *button = acpi_driver_data(device); diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index cac3207..adb8da5 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -296,7 +296,7 @@ fail_config: return ret; } -static int quickstart_acpi_remove(struct acpi_device *device, int type) +static int quickstart_acpi_remove(struct acpi_device *device) { acpi_status status; struct quickstart_acpi *quickstart; diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c index f088d4c..d843296 100644 --- a/drivers/video/backlight/apple_bl.c +++ b/drivers/video/backlight/apple_bl.c @@ -196,7 +196,7 @@ static int apple_bl_add(struct acpi_device *dev) return 0; } -static int apple_bl_remove(struct acpi_device *dev, int type) +static int apple_bl_remove(struct acpi_device *dev) { backlight_device_unregister(apple_backlight_device); diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c index da39191..c763479 100644 --- a/drivers/xen/xen-acpi-pad.c +++ b/drivers/xen/xen-acpi-pad.c @@ -140,8 +140,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device, - int type) +static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&xen_cpu_lock); xen_acpi_pad_idle_cpus(0); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 2c722de..7714a1c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -89,7 +89,7 @@ struct acpi_device; */ typedef int (*acpi_op_add) (struct acpi_device * device); -typedef int (*acpi_op_remove) (struct acpi_device * device, int type); +typedef int (*acpi_op_remove) (struct acpi_device * device); typedef int (*acpi_op_start) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -- cgit v0.10.2 From 09212fddc8661e67a964d91a6584209784f52500 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 24 Jan 2013 00:24:51 +0100 Subject: ACPI: Drop device start operation that is not used The ACPI device start operation, acpi_op_start, is never used, so drop it. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7714a1c..31b33d9 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -90,13 +90,11 @@ struct acpi_device; typedef int (*acpi_op_add) (struct acpi_device * device); typedef int (*acpi_op_remove) (struct acpi_device * device); -typedef int (*acpi_op_start) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; - acpi_op_start start; acpi_op_notify notify; }; -- cgit v0.10.2 From 2c0d4fe0189ae5e29fd9602d5b83f3b2b169bd1b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 29 Jan 2013 13:57:20 +0100 Subject: ACPI / scan: Make scanning of fixed devices follow the general scheme Make acpi_bus_scan_fixed() use device_attach() directly to attach drivers, if any, to the fixed devices in analogy with how acpi_bus_scan() works, which allows the last argument of acpi_add_single_object() to be dropped and the manipulation of the flags.match_driver bit to be moved to acpi_init_device_object() and acpi_device_add_finalize(). After these changes all of the functions for the initialization and registration of struct acpi_device objects work in the same way for all of them. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a4a2595..b206ce5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1441,19 +1441,21 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, acpi_device_get_busid(device); acpi_device_set_id(device); acpi_bus_get_flags(device); + device->flags.match_driver = false; device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); } void acpi_device_add_finalize(struct acpi_device *device) { + device->flags.match_driver = true; dev_set_uevent_suppress(&device->dev, false); kobject_uevent(&device->dev.kobj, KOBJ_ADD); } static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, - unsigned long long sta, bool match_driver) + unsigned long long sta) { int result; struct acpi_device *device; @@ -1469,7 +1471,6 @@ static int acpi_add_single_object(struct acpi_device **child, acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); - device->flags.match_driver = match_driver; result = acpi_device_add(device, acpi_device_release); if (result) { acpi_device_release(&device->dev); @@ -1562,12 +1563,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; } - acpi_add_single_object(&device, handle, type, sta, false); + acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; - device->flags.match_driver = true; - out: if (!*return_value) *return_value = device; @@ -1679,25 +1678,39 @@ EXPORT_SYMBOL_GPL(acpi_bus_trim); static int acpi_bus_scan_fixed(void) { int result = 0; - struct acpi_device *device = NULL; /* * Enumerate all fixed-feature devices. */ - if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, true); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); + if (result < 0) + return result; + device_init_wakeup(&device->dev, true); } - if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, true); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); } - return result; + return result < 0 ? result : 0; } int __init acpi_scan_init(void) -- cgit v0.10.2 From ca589f9469641916f4f9bd6a820012a27102ef63 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Jan 2013 14:27:29 +0100 Subject: ACPI / scan: Introduce struct acpi_scan_handler Introduce struct acpi_scan_handler for representing objects that will do configuration tasks depending on ACPI device nodes' hardware IDs (HIDs). Currently, those tasks are done either directly by the ACPI namespace scanning code or by ACPI device drivers designed specifically for this purpose. None of the above is desirable, however, because doing that directly in the namespace scanning code makes that code overly complicated and difficult to follow and doing that in "special" device drivers leads to a great deal of confusion about their role and to confusing interactions with the driver core (for example, sysfs directories are created for those drivers, but they are completely unnecessary and only increase the kernel's memory footprint in vain). Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Yasuaki Ishimatsu Acked-by: Toshi Kani diff --git a/Documentation/acpi/scan_handlers.txt b/Documentation/acpi/scan_handlers.txt new file mode 100644 index 0000000..3246ccf --- /dev/null +++ b/Documentation/acpi/scan_handlers.txt @@ -0,0 +1,77 @@ +ACPI Scan Handlers + +Copyright (C) 2012, Intel Corporation +Author: Rafael J. Wysocki + +During system initialization and ACPI-based device hot-add, the ACPI namespace +is scanned in search of device objects that generally represent various pieces +of hardware. This causes a struct acpi_device object to be created and +registered with the driver core for every device object in the ACPI namespace +and the hierarchy of those struct acpi_device objects reflects the namespace +layout (i.e. parent device objects in the namespace are represented by parent +struct acpi_device objects and analogously for their children). Those struct +acpi_device objects are referred to as "device nodes" in what follows, but they +should not be confused with struct device_node objects used by the Device Trees +parsing code (although their role is analogous to the role of those objects). + +During ACPI-based device hot-remove device nodes representing pieces of hardware +being removed are unregistered and deleted. + +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic +initialization of device nodes, such as retrieving common configuration +information from the device objects represented by them and populating them with +appropriate data, but some of them require additional handling after they have +been registered. For example, if the given device node represents a PCI host +bridge, its registration should cause the PCI bus under that bridge to be +enumerated and PCI devices on that bus to be registered with the driver core. +Similarly, if the device node represents a PCI interrupt link, it is necessary +to configure that link so that the kernel can use it. + +Those additional configuration tasks usually depend on the type of the hardware +component represented by the given device node which can be determined on the +basis of the device node's hardware ID (HID). They are performed by objects +called ACPI scan handlers represented by the following structure: + +struct acpi_scan_handler { + const struct acpi_device_id *ids; + struct list_head list_node; + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); + void (*detach)(struct acpi_device *dev); +}; + +where ids is the list of IDs of device nodes the given handler is supposed to +take care of, list_node is the hook to the global list of ACPI scan handlers +maintained by the ACPI core and the .attach() and .detach() callbacks are +executed, respectively, after registration of new device nodes and before +unregistration of device nodes the handler attached to previously. + +The namespace scanning function, acpi_bus_scan(), first registers all of the +device nodes in the given namespace scope with the driver core. Then, it tries +to match a scan handler against each of them using the ids arrays of the +available scan handlers. If a matching scan handler is found, its .attach() +callback is executed for the given device node. If that callback returns 1, +that means that the handler has claimed the device node and is now responsible +for carrying out any additional configuration tasks related to it. It also will +be responsible for preparing the device node for unregistration in that case. +The device node's handler field is then populated with the address of the scan +handler that has claimed it. + +If the .attach() callback returns 0, it means that the device node is not +interesting to the given scan handler and may be matched against the next scan +handler in the list. If it returns a (negative) error code, that means that +the namespace scan should be terminated due to a serious error. The error code +returned should then reflect the type of the error. + +The namespace trimming function, acpi_bus_trim(), first executes .detach() +callbacks from the scan handlers of all device nodes in the given namespace +scope (if they have scan handlers). Next, it unregisters all of the device +nodes in that scope. + +ACPI scan handlers can be added to the list maintained by the ACPI core with the +help of the acpi_scan_add_handler() function taking a pointer to the new scan +handler as an argument. The order in which scan handlers are added to the list +is the order in which they are matched against device nodes during namespace +scans. + +All scan handles must be added to the list before acpi_bus_scan() is run for the +first time and they cannot be removed from it. diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fe9f2c9..1453cd0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); +static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); @@ -62,6 +63,15 @@ struct acpi_device_bus_id{ struct list_head node; }; +int acpi_scan_add_handler(struct acpi_scan_handler *handler) +{ + if (!handler || !handler->attach) + return -EINVAL; + + list_add_tail(&handler->list_node, &acpi_scan_handlers_list); + return 0; +} + /* * Creates hid/cid(s) string needed for modalias and uevent * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_OK; } +static int acpi_scan_attach_handler(struct acpi_device *device) +{ + struct acpi_scan_handler *handler; + int ret = 0; + + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { + const struct acpi_device_id *id; + + id = __acpi_match_device(device, handler->ids); + if (!id) + continue; + + ret = handler->attach(device, id); + if (ret > 0) { + device->handler = handler; + break; + } else if (ret < 0) { + break; + } + } + return ret; +} + static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, void *not_used, void **ret_not_used) { const struct acpi_device_id *id; - acpi_status status = AE_OK; struct acpi_device *device; unsigned long long sta_not_used; - int type_not_used; + int ret; /* * Ignore errors ignored by acpi_bus_check_add() to avoid terminating * namespace walks prematurely. */ - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) return AE_OK; if (acpi_bus_get_device(handle, &device)) @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, if (id) { /* This is a known good platform device. */ acpi_create_platform_device(device, id->driver_data); - } else if (device_attach(&device->dev) < 0) { - status = AE_CTRL_DEPTH; + return AE_OK; } - return status; + + ret = acpi_scan_attach_handler(device); + if (ret) + return ret > 0 ? AE_OK : AE_CTRL_DEPTH; + + ret = device_attach(&device->dev); + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; } /** @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, struct acpi_device *device = NULL; if (!acpi_bus_get_device(handle, &device)) { + struct acpi_scan_handler *dev_handler = device->handler; + device->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&device->dev); + if (dev_handler) { + if (dev_handler->detach) + dev_handler->detach(device); + + device->handler = NULL; + } else { + device_release_driver(&device->dev); + } } return AE_OK; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ad0a86a..41850cb 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -84,6 +84,18 @@ struct acpi_driver; struct acpi_device; /* + * ACPI Scan Handler + * ----------------- + */ + +struct acpi_scan_handler { + const struct acpi_device_id *ids; + struct list_head list_node; + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); + void (*detach)(struct acpi_device *dev); +}; + +/* * ACPI Driver * ----------- */ @@ -269,6 +281,7 @@ struct acpi_device { struct acpi_device_wakeup wakeup; struct acpi_device_perf performance; struct acpi_device_dir dir; + struct acpi_scan_handler *handler; struct acpi_driver *driver; void *driver_data; struct device dev; @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_bus_event *event); static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) { return 0; } #endif +int acpi_scan_add_handler(struct acpi_scan_handler *handler); int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_scan(acpi_handle handle); -- cgit v0.10.2 From 00c43b9682507dc622c03172fde1032e2a216e9d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Jan 2013 14:27:33 +0100 Subject: ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Make the ACPI PCI root bridge driver use struct acpi_scan_handler for representing the object used to enumerate the PCI busses under PCI host bridges found in the ACPI namespace (and to tear down data structures representing the bus and devices on it before unregistering the host bridges' ACPI device nodes). This simplifies the code slightly and reduces the kernel's memory footprint by avoiding the registration of a struct device_driver object with the driver core and creation of its sysfs directory which is unnecessary. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index da23347..8310ba0 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -25,6 +25,7 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); +void acpi_pci_root_init(void); int acpi_sysfs_init(void); void acpi_csrt_init(void); @@ -86,7 +87,6 @@ struct acpi_ec { extern struct acpi_ec *first_ec; -int acpi_pci_root_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 8890775..b3cc69c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -45,8 +45,9 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" -static int acpi_pci_root_add(struct acpi_device *device); -static int acpi_pci_root_remove(struct acpi_device *device); +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_root_remove(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -57,16 +58,11 @@ static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, root_device_ids); -static struct acpi_driver acpi_pci_root_driver = { - .name = "pci_root", - .class = ACPI_PCI_ROOT_CLASS, +static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, - .ops = { - .add = acpi_pci_root_add, - .remove = acpi_pci_root_remove, - }, + .attach = acpi_pci_root_add, + .detach = acpi_pci_root_remove, }; /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ @@ -428,7 +424,8 @@ out: } EXPORT_SYMBOL(acpi_pci_osc_control_set); -static int acpi_pci_root_add(struct acpi_device *device) +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { unsigned long long segment, bus; acpi_status status; @@ -614,7 +611,7 @@ static int acpi_pci_root_add(struct acpi_device *device) pci_enable_bridges(root->bus); pci_bus_add_devices(root->bus); - return 0; + return 1; out_del_root: mutex_lock(&acpi_pci_root_lock); @@ -627,7 +624,7 @@ end: return result; } -static int acpi_pci_root_remove(struct acpi_device *device) +static void acpi_pci_root_remove(struct acpi_device *device) { acpi_status status; acpi_handle handle; @@ -655,19 +652,14 @@ static int acpi_pci_root_remove(struct acpi_device *device) list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); - return 0; } -int __init acpi_pci_root_init(void) +void __init acpi_pci_root_init(void) { acpi_hest_init(); - if (acpi_pci_disabled) - return 0; - - pci_acpi_crs_quirks(); - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) - return -ENODEV; - - return 0; + if (!acpi_pci_disabled) { + pci_acpi_crs_quirks(); + acpi_scan_add_handler(&pci_root_handler); + } } -- cgit v0.10.2 From 4daeaf68379f75dedd120582add5206c7c5ad72e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Jan 2013 14:27:37 +0100 Subject: ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler Make the ACPI PCI IRQ link driver use struct acpi_scan_handler for representing the object used to set up ACPI interrupt links and to remove data structures used for this purpose before unregistering the corresponding ACPI device nodes. This simplifies the code slightly and reduces the kernel's memory footprint by avoiding the registration of a struct device_driver object with the driver core and creation of its sysfs directory which is unnecessary. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Toshi Kani diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8310ba0..e5a6521 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -26,6 +26,7 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); void acpi_pci_root_init(void); +void acpi_pci_link_init(void); int acpi_sysfs_init(void); void acpi_csrt_init(void); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index b659279..ab764ed 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_FILE_STATUS "state" #define ACPI_PCI_LINK_MAX_POSSIBLE 16 -static int acpi_pci_link_add(struct acpi_device *device); -static int acpi_pci_link_remove(struct acpi_device *device); +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_link_remove(struct acpi_device *device); static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, link_device_ids); -static struct acpi_driver acpi_pci_link_driver = { - .name = "pci_link", - .class = ACPI_PCI_LINK_CLASS, +static struct acpi_scan_handler pci_link_handler = { .ids = link_device_ids, - .ops = { - .add = acpi_pci_link_add, - .remove = acpi_pci_link_remove, - }, + .attach = acpi_pci_link_add, + .detach = acpi_pci_link_remove, }; /* @@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle handle) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_pci_link_add(struct acpi_device *device) +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { int result; struct acpi_pci_link *link; @@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi_device *device) if (result) kfree(link); - return result; + return result < 0 ? result : 1; } static int acpi_pci_link_resume(struct acpi_pci_link *link) @@ -766,7 +763,7 @@ static void irqrouter_resume(void) } } -static int acpi_pci_link_remove(struct acpi_device *device) +static void acpi_pci_link_remove(struct acpi_device *device) { struct acpi_pci_link *link; @@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct acpi_device *device) mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } /* @@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_syscore_ops = { .resume = irqrouter_resume, }; -static int __init irqrouter_init_ops(void) -{ - if (!acpi_disabled && !acpi_noirq) - register_syscore_ops(&irqrouter_syscore_ops); - - return 0; -} - -device_initcall(irqrouter_init_ops); - -static int __init acpi_pci_link_init(void) +void __init acpi_pci_link_init(void) { if (acpi_noirq) - return 0; + return; if (acpi_irq_balance == -1) { /* no command line switch: enable balancing in IOAPIC mode */ @@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(void) else acpi_irq_balance = 0; } - - if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) - return -ENODEV; - - return 0; + register_syscore_ops(&irqrouter_syscore_ops); + acpi_scan_add_handler(&pci_link_handler); } - -subsys_initcall(acpi_pci_link_init); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1453cd0..c282169 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1774,6 +1774,7 @@ int __init acpi_scan_init(void) } acpi_pci_root_init(); + acpi_pci_link_init(); acpi_csrt_init(); /* -- cgit v0.10.2 From 141a297bd02e8ddc5ab625cc3a1a5926b1ff929a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Jan 2013 14:27:40 +0100 Subject: ACPI / platform: Use struct acpi_scan_handler for creating devices Currently, the ACPI namespace scanning code creates platform device objects for ACPI device nodes whose IDs match the contents of the acpi_platform_device_ids[] table. However, this adds a superfluous special case into acpi_bus_device_attach() and makes it more difficult to follow than it has to be. It also will make it more difficult to implement removal code for those platform device objects in the future. For the above reasons, introduce a struct acpi_scan_handler object for creating platform devices and move the code related to that from acpi_bus_device_attach() to the .attach() callback of that object. Also move the acpi_platform_device_ids[] table to acpi_platform.c. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Yasuaki Ishimatsu Acked-by: Toshi Kani Reviewed-by: Mika Westerberg Tested-by: Mika Westerberg diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 2d1fb4c..26fce4b 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -22,6 +22,30 @@ ACPI_MODULE_NAME("platform"); +/* Flags for acpi_create_platform_device */ +#define ACPI_PLATFORM_CLK BIT(0) + +/* + * The following ACPI IDs are known to be suitable for representing as + * platform devices. + */ +static const struct acpi_device_id acpi_platform_device_ids[] = { + + { "PNP0D40" }, + + /* Haswell LPSS devices */ + { "INT33C0", ACPI_PLATFORM_CLK }, + { "INT33C1", ACPI_PLATFORM_CLK }, + { "INT33C2", ACPI_PLATFORM_CLK }, + { "INT33C3", ACPI_PLATFORM_CLK }, + { "INT33C4", ACPI_PLATFORM_CLK }, + { "INT33C5", ACPI_PLATFORM_CLK }, + { "INT33C6", ACPI_PLATFORM_CLK }, + { "INT33C7", ACPI_PLATFORM_CLK }, + + { } +}; + static int acpi_create_platform_clks(struct acpi_device *adev) { static struct platform_device *pdev; @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(struct acpi_device *adev) /** * acpi_create_platform_device - Create platform device for ACPI device node * @adev: ACPI device node to create a platform device for. - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform - * devices. + * @id: ACPI device ID used to match @adev. * * Check if the given @adev can be represented as a platform device and, if * that's the case, create and register a platform device, populate its common @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(struct acpi_device *adev) * * Name of the platform device will be the same as @adev's. */ -struct platform_device *acpi_create_platform_device(struct acpi_device *adev, - unsigned long flags) +static int acpi_create_platform_device(struct acpi_device *adev, + const struct acpi_device_id *id) { + unsigned long flags = id->driver_data; struct platform_device *pdev = NULL; struct acpi_device *acpi_parent; struct platform_device_info pdevinfo; @@ -59,25 +83,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, struct resource *resources; int count; - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) { - dev_err(&adev->dev, "failed to create clocks\n"); - return NULL; + if (flags & ACPI_PLATFORM_CLK) { + int ret = acpi_create_platform_clks(adev); + if (ret) { + dev_err(&adev->dev, "failed to create clocks\n"); + return ret; + } } /* If the ACPI node already has a physical device attached, skip it. */ if (adev->physical_node_count) - return NULL; + return 0; INIT_LIST_HEAD(&resource_list); count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); if (count <= 0) - return NULL; + return 0; resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL); if (!resources) { dev_err(&adev->dev, "No memory for resources\n"); acpi_dev_free_resource_list(&resource_list); - return NULL; + return -ENOMEM; } count = 0; list_for_each_entry(rentry, &resource_list, node) @@ -123,5 +150,15 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, } kfree(resources); - return pdev; + return 1; +} + +static struct acpi_scan_handler platform_handler = { + .ids = acpi_platform_device_ids, + .attach = acpi_create_platform_device, +}; + +void __init acpi_platform_init(void) +{ + acpi_scan_add_handler(&platform_handler); } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index e5a6521..0d1397d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -27,6 +27,7 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); void acpi_pci_root_init(void); void acpi_pci_link_init(void); +void acpi_platform_init(void); int acpi_sysfs_init(void); void acpi_csrt_init(void); @@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(void) {} -------------------------------------------------------------------------- */ struct platform_device; -/* Flags for acpi_create_platform_device */ -#define ACPI_PLATFORM_CLK BIT(0) - -struct platform_device *acpi_create_platform_device(struct acpi_device *adev, - unsigned long flags); - #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c282169..a849d24 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root; static const char *dummy_hid = "device"; -/* - * The following ACPI IDs are known to be suitable for representing as - * platform devices. - */ -static const struct acpi_device_id acpi_platform_device_ids[] = { - - { "PNP0D40" }, - - /* Haswell LPSS devices */ - { "INT33C0", ACPI_PLATFORM_CLK }, - { "INT33C1", ACPI_PLATFORM_CLK }, - { "INT33C2", ACPI_PLATFORM_CLK }, - { "INT33C3", ACPI_PLATFORM_CLK }, - { "INT33C4", ACPI_PLATFORM_CLK }, - { "INT33C5", ACPI_PLATFORM_CLK }, - { "INT33C6", ACPI_PLATFORM_CLK }, - { "INT33C7", ACPI_PLATFORM_CLK }, - - { } -}; - static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); @@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(struct acpi_device *device) static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, void *not_used, void **ret_not_used) { - const struct acpi_device_id *id; struct acpi_device *device; unsigned long long sta_not_used; int ret; @@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - id = __acpi_match_device(device, acpi_platform_device_ids); - if (id) { - /* This is a known good platform device. */ - acpi_create_platform_device(device, id->driver_data); - return AE_OK; - } - ret = acpi_scan_attach_handler(device); if (ret) return ret > 0 ? AE_OK : AE_CTRL_DEPTH; @@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void) acpi_pci_root_init(); acpi_pci_link_init(); + acpi_platform_init(); acpi_csrt_init(); /* -- cgit v0.10.2 From 456de893ea1a693dc266c5464a6d857bfed0875f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 31 Jan 2013 20:57:40 +0100 Subject: ACPI / scan: Clean up acpi_bus_get_parent() Make acpi_bus_get_parent() more straightforward and remove an unnecessary local variable ret from it. Signed-off-by: Rafael J. Wysocki Acked-by: Yasuaki Ishimatsu Acked-by: Yinghai Lu Reviewed-by: Mika Westerberg diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a849d24..360f133 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -871,29 +871,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver); -------------------------------------------------------------------------- */ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) { + struct acpi_device *device = NULL; acpi_status status; - int ret; - struct acpi_device *device; /* * Fixed hardware devices do not appear in the namespace and do not * have handles, but we fabricate acpi_devices for them, so we have * to deal with them specially. */ - if (handle == NULL) + if (!handle) return acpi_root; do { status = acpi_get_parent(handle, &handle); - if (status == AE_NULL_ENTRY) - return NULL; if (ACPI_FAILURE(status)) - return acpi_root; - - ret = acpi_bus_get_device(handle, &device); - if (ret == 0) - return device; - } while (1); + return status == AE_NULL_ENTRY ? NULL : acpi_root; + } while (acpi_bus_get_device(handle, &device)); + return device; } acpi_status -- cgit v0.10.2 From 02df7349d29f99ede4c97504ab67e3082c95c15e Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Thu, 31 Jan 2013 03:23:53 +0000 Subject: ACPI / dock: Fix acpi_bus_get_device() check in drivers/acpi/dock.c acpi_bus_get_device() returns int not acpi_status. The patch change not to apply ACPI_SUCCESS() to the return value of acpi_bus_get_device(). Signed-off-by: Yasuaki Ishimatsu Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 78648f8..68d720a 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -825,7 +825,7 @@ static ssize_t show_docked(struct device *dev, struct dock_station *dock_station = dev->platform_data; - if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) + if (!acpi_bus_get_device(dock_station->handle, &tmp)) return snprintf(buf, PAGE_SIZE, "1\n"); return snprintf(buf, PAGE_SIZE, "0\n"); } -- cgit v0.10.2 From 73ce873a898ff385cd18e9068d38a35ff48e7585 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sun, 3 Feb 2013 14:55:45 +0100 Subject: ACPI / PCI: pci_slot: replace printk(KERN_xxx) with pr_xxx() Trivial changes to replace printk(KERN_xxx) with pr_xxx(). Signed-off-by: Jiang Liu Acked-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d22585f..2c630c0 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -50,13 +50,12 @@ module_param(debug, bool, 0644); ACPI_MODULE_NAME("pci_slot"); #define MY_NAME "pci_slot" -#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) +#define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg) +#define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg) #define dbg(format, arg...) \ do { \ if (debug) \ - printk(KERN_DEBUG "%s: " format, \ - MY_NAME , ## arg); \ + pr_debug("%s: " format, MY_NAME , ## arg); \ } while (0) #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ -- cgit v0.10.2 From 87b85b3c8a4ac286d41a1c6419014b7562e4663b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 6 Feb 2013 13:05:22 +0100 Subject: ACPI / scan: Follow priorities of IDs when matching scan handlers The IDs of ACPI device nodes stored in their pnp.ids member arrays are sorted by decreasing priority (i.e. the highest-priority ID is the first entry). This means that when matching scan handlers to device nodes, the namespace scanning code should walk the list of scan handlers for each device node ID instead of walking the list of device node IDs for each handler (the latter causes the first handler matching any of the device node IDs to be chosen, although there may be another handler matching an ID of a higher priority which should be preferred). Make the code follow this observation. This change has been suggested and justified by Toshi Kani. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 360f133..688b7f7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1553,26 +1553,42 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_OK; } -static int acpi_scan_attach_handler(struct acpi_device *device) +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) { struct acpi_scan_handler *handler; - int ret = 0; list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { - const struct acpi_device_id *id; + const struct acpi_device_id *devid; - id = __acpi_match_device(device, handler->ids); - if (!id) - continue; + for (devid = handler->ids; devid->id[0]; devid++) { + int ret; - ret = handler->attach(device, id); - if (ret > 0) { - device->handler = handler; - break; - } else if (ret < 0) { - break; + if (strcmp((char *)devid->id, id)) + continue; + + ret = handler->attach(device, devid); + if (ret > 0) { + device->handler = handler; + return ret; + } else if (ret < 0) { + return ret; + } } } + return 0; +} + +static int acpi_scan_attach_handler(struct acpi_device *device) +{ + struct acpi_hardware_id *hwid; + int ret = 0; + + list_for_each_entry(hwid, &device->pnp.ids, list) { + ret = acpi_scan_do_attach_handler(device, hwid->id); + if (ret) + break; + + } return ret; } -- cgit v0.10.2 From ce7685ad764f070a9234df6a12a17eb92471d126 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 7 Feb 2013 12:50:53 +0100 Subject: ACPI: sysfs eject support for ACPI scan handlers Changed sysfs eject, acpi_eject_store(), so that it doesn't return error codes for devices nodes with ACPI scan handlers attached and no ACPI drivers. [rjw: Changelog] Signed-off-by: Toshi Kani Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 688b7f7..95547ef 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -203,7 +203,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, return -EINVAL; } #ifndef FORCE_EJECT - if (acpi_device->driver == NULL) { + if (!acpi_device->driver && !acpi_device->handler) { ret = -ENODEV; goto err; } -- cgit v0.10.2 From 5f27ee8e1261e47ec2e9dbebf17e87e55f568d75 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 7 Feb 2013 21:19:13 +0000 Subject: ACPI: Unbind ACPI drv when probe failed When acpi_device_install_notify_handler() failed in acpi_device_probe(), it calls acpi_drv->ops.remove() and fails the probe. However, the ACPI driver is left bound to the acpi_device. Fix it by clearing the driver and driver_data fields. Signed-off-by: Toshi Kani Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 95547ef..bf6e2c2 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -627,6 +627,8 @@ static int acpi_device_probe(struct device * dev) if (ret) { if (acpi_drv->ops.remove) acpi_drv->ops.remove(acpi_dev); + acpi_dev->driver = NULL; + acpi_dev->driver_data = NULL; return ret; } } -- cgit v0.10.2 From 38475b3be1517a16d263b0b04dae862bf7027d48 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 8 Feb 2013 23:52:23 +0100 Subject: ACPI / scan: Remove useless #ifndef from acpi_eject_store() Since the FORCE_EJECT symbol is never defined, the #ifndef FORCE_EJECT in acpi_eject_store() is always true, so drop it. Signed-off-by: Rafael J. Wysocki Acked-by: Yasuaki Ishimatsu Tested-by: Yasuaki Ishimatsu Reviewed-by: Toshi Kani Tested-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bf6e2c2..5bc2641 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -202,12 +202,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if ((!count) || (buf[0] != '1')) { return -EINVAL; } -#ifndef FORCE_EJECT if (!acpi_device->driver && !acpi_device->handler) { ret = -ENODEV; goto err; } -#endif status = acpi_get_type(acpi_device->handle, &type); if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { ret = -ENODEV; -- cgit v0.10.2 From 737f1a9f808280c481681b1f46254fd67023ec2f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 8 Feb 2013 23:52:39 +0100 Subject: ACPI / scan: Make container driver use struct acpi_scan_handler Make the ACPI container driver use struct acpi_scan_handler for representing the object used to initialize ACPI containers and remove the ACPI driver structure used previously and the data structures created by it, since in fact they were not used for any purpose. This simplifies the code and reduces the kernel's memory footprint by avoiding the registration of a struct device_driver object with the driver core and creation of its sysfs directory which is unnecessary. In addition to that, make the namespace walk callback used for installing the notify handlers for ACPI containers more straightforward. This change includes fixes from Toshi Kani. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu Acked-by: Yasuaki Ishimatsu Tested-by: Yasuaki Ishimatsu Reviewed-by: Toshi Kani Tested-by: Toshi Kani diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 38c5078..78105b3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -337,7 +337,7 @@ config X86_PM_TIMER systems require this timer. config ACPI_CONTAINER - tristate "Container and Module Devices (EXPERIMENTAL)" + bool "Container and Module Devices (EXPERIMENTAL)" depends on EXPERIMENTAL default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) help diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index cc0bf46..9053e86 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -38,42 +38,31 @@ #define PREFIX "ACPI: " -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" -#define ACPI_CONTAINER_CLASS "container" - -#define INSTALL_NOTIFY_HANDLER 1 -#define UNINSTALL_NOTIFY_HANDLER 2 - #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); -MODULE_AUTHOR("Anil S Keshavamurthy"); -MODULE_DESCRIPTION("ACPI container driver"); -MODULE_LICENSE("GPL"); - -static int acpi_container_add(struct acpi_device *device); -static int acpi_container_remove(struct acpi_device *device); - static const struct acpi_device_id container_device_ids[] = { {"ACPI0004", 0}, {"PNP0A05", 0}, {"PNP0A06", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, container_device_ids); -static struct acpi_driver acpi_container_driver = { - .name = "container", - .class = ACPI_CONTAINER_CLASS, +static int container_device_attach(struct acpi_device *device, + const struct acpi_device_id *not_used) +{ + /* + * FIXME: This is necessary, so that acpi_eject_store() doesn't return + * -ENODEV for containers. + */ + return 1; +} + +static struct acpi_scan_handler container_device_handler = { .ids = container_device_ids, - .ops = { - .add = acpi_container_add, - .remove = acpi_container_remove, - }, + .attach = container_device_attach, }; -/*******************************************************************/ - static int is_device_present(acpi_handle handle) { acpi_handle temp; @@ -92,49 +81,6 @@ static int is_device_present(acpi_handle handle) return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); } -static bool is_container_device(const char *hid) -{ - const struct acpi_device_id *container_id; - - for (container_id = container_device_ids; - container_id->id[0]; container_id++) { - if (!strcmp((char *)container_id->id, hid)) - return true; - } - - return false; -} - -/*******************************************************************/ -static int acpi_container_add(struct acpi_device *device) -{ - struct acpi_container *container; - - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); - if (!container) - return -ENOMEM; - - container->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); - device->driver_data = container; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", - acpi_device_name(device), acpi_device_bid(device))); - - return 0; -} - -static int acpi_container_remove(struct acpi_device *device) -{ - acpi_status status = AE_OK; - struct acpi_container *pc = NULL; - - pc = acpi_driver_data(device); - kfree(pc); - return status; -} - static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -199,84 +145,43 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) return; } -static acpi_status -container_walk_namespace_cb(acpi_handle handle, - u32 lvl, void *context, void **rv) +static bool is_container(acpi_handle handle) { - char *hid = NULL; struct acpi_device_info *info; - acpi_status status; - int *action = context; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - return AE_OK; - } + bool ret = false; - if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.string; + if (ACPI_FAILURE(acpi_get_object_info(handle, &info))) + return false; - if (hid == NULL) { - goto end; - } - - if (!is_container_device(hid)) - goto end; + if (info->valid & ACPI_VALID_HID) { + const struct acpi_device_id *id; - switch (*action) { - case INSTALL_NOTIFY_HANDLER: - acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb, NULL); - break; - case UNINSTALL_NOTIFY_HANDLER: - acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb); - break; - default: - break; + for (id = container_device_ids; id->id[0]; id++) { + ret = !strcmp((char *)id->id, info->hardware_id.string); + if (ret) + break; + } } - - end: kfree(info); - - return AE_OK; + return ret; } -static int __init acpi_container_init(void) +static acpi_status acpi_container_register_notify_handler(acpi_handle handle, + u32 lvl, void *ctxt, + void **retv) { - int result = 0; - int action = INSTALL_NOTIFY_HANDLER; - - result = acpi_bus_register_driver(&acpi_container_driver); - if (result < 0) { - return (result); - } - - /* register notify handler to every container device */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); + if (is_container(handle)) + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + container_notify_cb, NULL); - return (0); + return AE_OK; } -static void __exit acpi_container_exit(void) +void __init acpi_container_init(void) { - int action = UNINSTALL_NOTIFY_HANDLER; - - - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_container_register_notify_handler, NULL, + NULL, NULL); - acpi_bus_unregister_driver(&acpi_container_driver); - - return; + acpi_scan_add_handler(&container_device_handler); } - -module_init(acpi_container_init); -module_exit(acpi_container_exit); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 0d1397d..7909232 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -30,6 +30,11 @@ void acpi_pci_link_init(void); void acpi_platform_init(void); int acpi_sysfs_init(void); void acpi_csrt_init(void); +#ifdef CONFIG_ACPI_CONTAINER +void acpi_container_init(void); +#else +static inline void acpi_container_init(void) {} +#endif #ifdef CONFIG_DEBUG_FS extern struct dentry *acpi_debugfs_dir; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5bc2641..a48b6e9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1758,6 +1758,7 @@ int __init acpi_scan_init(void) acpi_pci_link_init(); acpi_platform_init(); acpi_csrt_init(); + acpi_container_init(); /* * Enumerate devices in the ACPI namespace. -- cgit v0.10.2 From e253673ec5e3e0b82e6261d5c14505fed77d8b18 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 9 Feb 2013 00:00:13 +0100 Subject: ACPI / Documentation: refer to correct file for acpi_platform_device_ids[] table When the ACPI platform device code was converted to the new ACPI scan handler facility, the the acpi_platform_device_ids[] was moved to drivers/acpi/acpi_platform.c. Update the documentation accordingly. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index 54469bc..94a6561 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -63,8 +63,8 @@ from ACPI tables. Currently the kernel is not able to automatically determine from which ACPI device it should make the corresponding platform device so we need to add the ACPI device explicitly to acpi_platform_device_ids list defined in -drivers/acpi/scan.c. This limitation is only for the platform devices, SPI -and I2C devices are created automatically as described below. +drivers/acpi/acpi_platform.c. This limitation is only for the platform +devices, SPI and I2C devices are created automatically as described below. SPI serial bus support ~~~~~~~~~~~~~~~~~~~~~~ -- cgit v0.10.2 From 87d4a4da7353c8582049dab50b880798d88ff9d7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Feb 2013 01:08:20 +0100 Subject: ACPI: Drop the container.h header file The include/acpi/container.h only contains a definition of a structure that is not used any more, so drop it entirely. Similar change was proposed earlier by Toshi Kani. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 9053e86..4cc2937 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -34,7 +34,6 @@ #include #include #include -#include #define PREFIX "ACPI: " diff --git a/include/acpi/container.h b/include/acpi/container.h deleted file mode 100644 index a703f14..0000000 --- a/include/acpi/container.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ACPI_CONTAINER_H -#define __ACPI_CONTAINER_H - -#include - -struct acpi_container { - acpi_handle handle; - unsigned long sun; - int state; -}; - -#endif /* __ACPI_CONTAINER_H */ -- cgit v0.10.2 From f058cdf4cf3e5181172455f90fc73f2127b6ddf8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Feb 2013 15:29:11 +0100 Subject: ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock The ACPI scan lock has been introduced to prevent acpi_bus_scan() and acpi_bus_trim() from running in parallel with each other for overlapping ACPI namespace scopes. However, it is not sufficient to do that, because if acpi_bus_scan() is run (for an overlapping namespace scope) right after the acpi_bus_trim() in acpi_bus_hot_remove_device(), the subsequent eject will remove devices without removing the corresponding struct acpi_device objects (and possibly companion "physical" device objects). Therefore acpi_bus_hot_remove_device() has to acquire the scan lock before carrying out the bus trimming and hold it through the evaluation of _EJ0, so make that happen. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a48b6e9..75fb14f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -95,6 +95,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); +static void __acpi_bus_trim(struct acpi_device *start); + /** * acpi_bus_hot_remove_device: hot-remove a device and its children * @context: struct acpi_eject_event pointer (freed in this func) @@ -114,10 +116,12 @@ void acpi_bus_hot_remove_device(void *context) acpi_status status = AE_OK; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + mutex_lock(&acpi_scan_lock); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - acpi_bus_trim(device); + __acpi_bus_trim(device); /* Device node has been released. */ device = NULL; @@ -146,18 +150,14 @@ void acpi_bus_hot_remove_device(void *context) status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Eject device failed\n"); - goto err_out; - } + acpi_handle_warn(handle, "Eject failed\n"); - kfree(context); - return; + /* Tell the firmware the hot-remove operation has failed. */ + acpi_evaluate_hotplug_ost(handle, ej_event->event, + ost_code, NULL); + } -err_out: - /* Inform firmware the hot-remove operation has completed w/ error */ - (void) acpi_evaluate_hotplug_ost(handle, - ej_event->event, ost_code, NULL); + mutex_unlock(&acpi_scan_lock); kfree(context); return; } @@ -1683,10 +1683,8 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, return AE_OK; } -void acpi_bus_trim(struct acpi_device *start) +static void __acpi_bus_trim(struct acpi_device *start) { - mutex_lock(&acpi_scan_lock); - /* * Execute acpi_bus_device_detach() as a post-order callback to detach * all ACPI drivers from the device nodes being removed. @@ -1701,7 +1699,12 @@ void acpi_bus_trim(struct acpi_device *start) acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, acpi_bus_remove, NULL, NULL); acpi_bus_remove(start->handle, 0, NULL, NULL); +} +void acpi_bus_trim(struct acpi_device *start) +{ + mutex_lock(&acpi_scan_lock); + __acpi_bus_trim(start); mutex_unlock(&acpi_scan_lock); } EXPORT_SYMBOL_GPL(acpi_bus_trim); -- cgit v0.10.2 From 0aa120a0138398d6597350f4c1dcb46d14be1a0b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Feb 2013 15:29:20 +0100 Subject: ACPI / scan: Full transition to D3cold in acpi_device_unregister() In order to drop reference counts of all power resources used by an ACPI device node being removed, acpi_device_unregister() calls acpi_power_transition(device, ACPI_STATE_D3_COLD), which effectively transitions the device node into D3cold if it uses any power resources. However, for some device nodes it may not be appropriate to remove power from them entirely before putting them into D3hot before. On the other hand, executing _PS3 for devices that don't use power resources before removing them shouldn't really hurt. In fact, that is done by acpi_bus_hot_remove_device(), but this is not the right place to do it, because the bus trimming may have caused power to be removed from the device node in question already before. For these reasons, make acpi_device_unregister() carry out full power-off transition for all device nodes supporting that and remove the direct evaluation of _PS3 from acpi_bus_hot_remove_device(). Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 75fb14f..c7676ee 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -125,12 +125,6 @@ void acpi_bus_hot_remove_device(void *context) /* Device node has been released. */ device = NULL; - /* power off device */ - status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Power-off device failed\n"); - if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { arg_list.count = 1; arg_list.pointer = &arg; @@ -780,10 +774,11 @@ static void acpi_device_unregister(struct acpi_device *device) device_del(&device->dev); /* - * Drop the reference counts of all power resources the device depends - * on and turn off the ones that have no more references. + * Transition the device to D3cold to drop the reference counts of all + * power resources the device depends on and turn off the ones that have + * no more references. */ - acpi_power_transition(device, ACPI_STATE_D3_COLD); + acpi_device_set_power(device, ACPI_STATE_D3_COLD); put_device(&device->dev); } -- cgit v0.10.2 From 64fd7401c5e4cf7c64452ecd9b700a55a5ebea50 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Mon, 11 Feb 2013 22:33:20 +0000 Subject: ACPI: Remove the use of CONFIG_ACPI_CONTAINER_MODULE config ACPI_CONTAINER has been changed to bool (y/n), and its module option is no longer valid. So, remove the use of CONFIG_ACPI_CONTAINER_MODULE. Signed-off-by: Toshi Kani Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/acpi.h b/include/linux/acpi.h index c6ccd9f..bcbdd74 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -363,8 +363,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, #if defined(CONFIG_ACPI_HOTPLUG_CPU) && \ (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \ defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) && \ - (defined(CONFIG_ACPI_CONTAINER) || \ - defined(CONFIG_ACPI_CONTAINER_MODULE)) + defined(CONFIG_ACPI_CONTAINER) #define ACPI_HOTPLUG_OST #endif -- cgit v0.10.2 From 3757b94802fb65d8f696597a74053cf21738da0b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Feb 2013 14:36:47 +0100 Subject: ACPI / hotplug: Fix concurrency issues and memory leaks This changeset is aimed at fixing a few different but related problems in the ACPI hotplug infrastructure. First of all, since notify handlers may be run in parallel with acpi_bus_scan(), acpi_bus_trim() and acpi_bus_hot_remove_device() and some of them are installed for ACPI handles that have no struct acpi_device objects attached (i.e. before those objects are created), those notify handlers have to take acpi_scan_lock to prevent races from taking place (e.g. a struct acpi_device is found to be present for the given ACPI handle, but right after that it is removed by acpi_bus_trim() running in parallel to the given notify handler). Moreover, since some of them call acpi_bus_scan() and acpi_bus_trim(), this leads to the conclusion that acpi_scan_lock should be acquired by the callers of these two funtions rather by these functions themselves. For these reasons, make all notify handlers that can handle device addition and eject events take acpi_scan_lock and remove the acpi_scan_lock locking from acpi_bus_scan() and acpi_bus_trim(). Accordingly, update all of their users to make sure that they are always called under acpi_scan_lock. Furthermore, since eject operations are carried out asynchronously with respect to the notify events that trigger them, with the help of acpi_bus_hot_remove_device(), even if notify handlers take the ACPI scan lock, it still is possible that, for example, acpi_bus_trim() will run between acpi_bus_hot_remove_device() and the notify handler that scheduled its execution and that acpi_bus_trim() will remove the device node passed to acpi_bus_hot_remove_device() for ejection. In that case, the struct acpi_device object obtained by acpi_bus_hot_remove_device() will be invalid and not-so-funny things will ensue. To protect agaist that, make the users of acpi_bus_hot_remove_device() run get_device() on ACPI device node objects that are about to be passed to it and make acpi_bus_hot_remove_device() run put_device() on them and check if their ACPI handles are not NULL (make acpi_device_unregister() clear the device nodes' ACPI handles for that check to work). Finally, observe that acpi_os_hotplug_execute() actually can fail, in which case its caller ought to free memory allocated for the context object to prevent leaks from happening. It also needs to run put_device() on the device node that it ran get_device() on previously in that case. Modify the code accordingly. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 94c823b..034d3e7 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -153,14 +153,16 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) return 0; } -static int -acpi_memory_get_device(acpi_handle handle, - struct acpi_memory_device **mem_device) +static int acpi_memory_get_device(acpi_handle handle, + struct acpi_memory_device **mem_device) { struct acpi_device *device = NULL; - int result; + int result = 0; - if (!acpi_bus_get_device(handle, &device) && device) + acpi_scan_lock_acquire(); + + acpi_bus_get_device(handle, &device); + if (device) goto end; /* @@ -169,23 +171,28 @@ acpi_memory_get_device(acpi_handle handle, */ result = acpi_bus_scan(handle); if (result) { - acpi_handle_warn(handle, "Cannot add acpi bus\n"); - return -EINVAL; + acpi_handle_warn(handle, "ACPI namespace scan failed\n"); + result = -EINVAL; + goto out; } result = acpi_bus_get_device(handle, &device); if (result) { acpi_handle_warn(handle, "Missing device object\n"); - return -EINVAL; + result = -EINVAL; + goto out; } - end: + end: *mem_device = acpi_driver_data(device); if (!(*mem_device)) { dev_err(&device->dev, "driver data not found\n"); - return -ENODEV; + result = -ENODEV; + goto out; } - return 0; + out: + acpi_scan_lock_release(); + return result; } static int acpi_memory_check_device(struct acpi_memory_device *mem_device) @@ -305,6 +312,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) struct acpi_device *device; struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; switch (event) { case ACPI_NOTIFY_BUS_CHECK: @@ -327,29 +335,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived EJECT REQUEST notification for device\n")); + status = AE_ERROR; + acpi_scan_lock_acquire(); + if (acpi_bus_get_device(handle, &device)) { acpi_handle_err(handle, "Device doesn't exist\n"); - break; + goto unlock; } mem_device = acpi_driver_data(device); if (!mem_device) { acpi_handle_err(handle, "Driver Data is NULL\n"); - break; + goto unlock; } ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); if (!ej_event) { pr_err(PREFIX "No memory, dropping EJECT\n"); - break; + goto unlock; } + get_device(&device->dev); ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, - (void *)ej_event); + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + } - /* eject is performed asynchronously */ - return; + unlock: + acpi_scan_lock_release(); + if (ACPI_SUCCESS(status)) + return; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); @@ -360,7 +379,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; } static void acpi_memory_device_free(struct acpi_memory_device *mem_device) diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 4cc2937..5523ba7 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -88,6 +88,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) acpi_status status; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* Fall through */ @@ -103,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) /* device exist and this is a remove request */ device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; } @@ -130,18 +132,20 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!acpi_bus_get_device(handle, &device) && device) { device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; default: /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } static bool is_container(acpi_handle handle) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 68d720a..4fdea38 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -744,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context) { struct dock_data *data = context; + acpi_scan_lock_acquire(); dock_notify(data->handle, data->event, data->ds); + acpi_scan_lock_release(); kfree(data); } @@ -757,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this, if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return 0; + + acpi_scan_lock_acquire(); + list_for_each_entry(dock_station, &dock_stations, sibling) { if (dock_station->handle == handle) { struct dock_data *dd; + acpi_status status; dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) - return 0; + break; + dd->handle = handle; dd->event = event; dd->ds = dock_station; - acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); - return 0 ; + status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dd); + if (ACPI_FAILURE(status)) + kfree(dd); + + break; } } + + acpi_scan_lock_release(); return 0; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index c5d2fd8..cbf1f12 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -683,8 +683,11 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, struct acpi_device *device = NULL; struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; int result; + acpi_scan_lock_acquire(); + switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: @@ -733,25 +736,32 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, break; } + get_device(&device->dev); ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, - (void *)ej_event); - - /* eject is performed asynchronously */ - return; + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + break; + } + goto out; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } static acpi_status is_processor_device(acpi_handle handle) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c7676ee..d16a94e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -42,6 +42,18 @@ struct acpi_device_bus_id{ struct list_head node; }; +void acpi_scan_lock_acquire(void) +{ + mutex_lock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire); + +void acpi_scan_lock_release(void) +{ + mutex_unlock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_release); + int acpi_scan_add_handler(struct acpi_scan_handler *handler) { if (!handler || !handler->attach) @@ -95,8 +107,6 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static void __acpi_bus_trim(struct acpi_device *start); - /** * acpi_bus_hot_remove_device: hot-remove a device and its children * @context: struct acpi_eject_event pointer (freed in this func) @@ -107,7 +117,7 @@ static void __acpi_bus_trim(struct acpi_device *start); */ void acpi_bus_hot_remove_device(void *context) { - struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; + struct acpi_eject_event *ej_event = context; struct acpi_device *device = ej_event->device; acpi_handle handle = device->handle; acpi_handle temp; @@ -118,11 +128,19 @@ void acpi_bus_hot_remove_device(void *context) mutex_lock(&acpi_scan_lock); + /* If there is no handle, the device node has been unregistered. */ + if (!device->handle) { + dev_dbg(&device->dev, "ACPI handle missing\n"); + put_device(&device->dev); + goto out; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - __acpi_bus_trim(device); - /* Device node has been released. */ + acpi_bus_trim(device); + /* Device node has been unregistered. */ + put_device(&device->dev); device = NULL; if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { @@ -151,6 +169,7 @@ void acpi_bus_hot_remove_device(void *context) ost_code, NULL); } + out: mutex_unlock(&acpi_scan_lock); kfree(context); return; @@ -212,6 +231,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } + get_device(&acpi_device->dev); ej_event->device = acpi_device; if (acpi_device->flags.eject_pending) { /* event originated from ACPI eject notification */ @@ -224,7 +244,11 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); } - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); + if (ACPI_FAILURE(status)) { + put_device(&acpi_device->dev); + kfree(ej_event); + } err: return ret; } @@ -779,6 +803,7 @@ static void acpi_device_unregister(struct acpi_device *device) * no more references. */ acpi_device_set_power(device, ACPI_STATE_D3_COLD); + device->handle = NULL; put_device(&device->dev); } @@ -1623,14 +1648,14 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, * there has been a real error. There just have been no suitable ACPI objects * in the table trunk from which the kernel could create a device and add an * appropriate driver. + * + * Must be called under acpi_scan_lock. */ int acpi_bus_scan(acpi_handle handle) { void *device = NULL; int error = 0; - mutex_lock(&acpi_scan_lock); - if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, NULL, &device); @@ -1641,7 +1666,6 @@ int acpi_bus_scan(acpi_handle handle) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_device_attach, NULL, NULL, NULL); - mutex_unlock(&acpi_scan_lock); return error; } EXPORT_SYMBOL(acpi_bus_scan); @@ -1678,7 +1702,13 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, return AE_OK; } -static void __acpi_bus_trim(struct acpi_device *start) +/** + * acpi_bus_trim - Remove ACPI device node and all of its descendants + * @start: Root of the ACPI device nodes subtree to remove. + * + * Must be called under acpi_scan_lock. + */ +void acpi_bus_trim(struct acpi_device *start) { /* * Execute acpi_bus_device_detach() as a post-order callback to detach @@ -1695,13 +1725,6 @@ static void __acpi_bus_trim(struct acpi_device *start) acpi_bus_remove, NULL, NULL); acpi_bus_remove(start->handle, 0, NULL, NULL); } - -void acpi_bus_trim(struct acpi_device *start) -{ - mutex_lock(&acpi_scan_lock); - __acpi_bus_trim(start); - mutex_unlock(&acpi_scan_lock); -} EXPORT_SYMBOL_GPL(acpi_bus_trim); static int acpi_bus_scan_fixed(void) @@ -1758,23 +1781,27 @@ int __init acpi_scan_init(void) acpi_csrt_init(); acpi_container_init(); + mutex_lock(&acpi_scan_lock); /* * Enumerate devices in the ACPI namespace. */ result = acpi_bus_scan(ACPI_ROOT_OBJECT); if (result) - return result; + goto out; result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); if (result) - return result; + goto out; result = acpi_bus_scan_fixed(); if (result) { acpi_device_unregister(acpi_root); - return result; + goto out; } acpi_update_all_gpes(); - return 0; + + out: + mutex_unlock(&acpi_scan_lock); + return result; } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index d1a6f4a..a951c22 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1218,6 +1218,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) handle = hp_work->handle; type = hp_work->type; + acpi_scan_lock_acquire(); + if (acpi_bus_get_device(handle, &device)) { /* This bridge must have just been physically inserted */ handle_bridge_insertion(handle, type); @@ -1295,6 +1297,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) } out: + acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } @@ -1341,6 +1344,8 @@ static void _handle_hotplug_event_func(struct work_struct *work) func = (struct acpiphp_func *)context; + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ @@ -1371,6 +1376,7 @@ static void _handle_hotplug_event_func(struct work_struct *work) break; } + acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ } diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index ae606b3..574421b 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -425,6 +425,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) pdevice = NULL; } + acpi_scan_lock_acquire(); /* * Walk the rootbus node's immediate children looking for * the slot's device node(s). There can be more than @@ -458,6 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) } } } + acpi_scan_lock_release(); } /* Call the driver for the new device */ @@ -508,6 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) /* Get the rootbus node pointer */ phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; + acpi_scan_lock_acquire(); /* * Walk the rootbus node's immediate children looking for * the slot's device node(s). There can be more than @@ -538,7 +541,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) acpi_bus_trim(device); } } - + acpi_scan_lock_release(); } /* Free the SN resources assigned to the Linux device.*/ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 41850cb..227ba7d 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -395,6 +395,9 @@ int acpi_bus_receive_event(struct acpi_bus_event *event); static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) { return 0; } #endif + +void acpi_scan_lock_acquire(void); +void acpi_scan_lock_release(void); int acpi_scan_add_handler(struct acpi_scan_handler *handler); int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); -- cgit v0.10.2