diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_core.c')
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 198 |
1 files changed, 60 insertions, 138 deletions
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index e2fef60c2d0..e291efcd02a 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -31,25 +31,26 @@ * */ +#define pr_fmt(fmt) "acpiphp: " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/pci-acpi.h> +#include <linux/pci_hotplug.h> #include <linux/slab.h> #include <linux/smp.h> -#include <linux/smp_lock.h> -#include "pci_hotplug.h" #include "acpiphp.h" -#define MY_NAME "acpiphp" +/* name size which is used for entries in pcihpfs */ +#define SLOT_NAME_SIZE 21 /* {_SUN} */ -static int debug; -int acpiphp_debug; +bool acpiphp_disabled; /* local variables */ -static int num_slots; static struct acpiphp_attention_info *attention_info; #define DRIVER_VERSION "0.5" @@ -59,24 +60,18 @@ static struct acpiphp_attention_info *attention_info; MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(debug, bool, 0644); - -/* export the attention callback registration methods */ -EXPORT_SYMBOL_GPL(acpiphp_register_attention); -EXPORT_SYMBOL_GPL(acpiphp_unregister_attention); +MODULE_PARM_DESC(disable, "disable acpiphp driver"); +module_param_named(disable, acpiphp_disabled, bool, 0444); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); -static int get_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static struct hotplug_slot_ops acpi_hotplug_slot_ops = { - .owner = THIS_MODULE, .enable_slot = enable_slot, .disable_slot = disable_slot, .set_attention_status = set_attention_status, @@ -84,18 +79,16 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, - .get_address = get_address, }; - /** * acpiphp_register_attention - set attention LED callback * @info: must be completely filled with LED callbacks * - * Description: this is used to register a hardware specific ACPI + * Description: This is used to register a hardware specific ACPI * driver that manipulates the attention LED. All the fields in * info must be set. - **/ + */ int acpiphp_register_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -107,16 +100,17 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info) } return retval; } +EXPORT_SYMBOL_GPL(acpiphp_register_attention); /** * acpiphp_unregister_attention - unset attention LED callback * @info: must match the pointer used to register * - * Description: this is used to un-register a hardware specific acpi - * driver that manipulates the attention LED. The pointer to the + * Description: This is used to un-register a hardware specific acpi + * driver that manipulates the attention LED. The pointer to the * info struct must be the same as the one used to set it. - **/ + */ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -127,6 +121,7 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) } return retval; } +EXPORT_SYMBOL_GPL(acpiphp_unregister_attention); /** @@ -134,13 +129,12 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) * @hotplug_slot: slot to enable * * Actual tasks are done in acpiphp_enable_slot() - * */ static int enable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); /* enable the specified slot */ return acpiphp_enable_slot(slot->acpi_slot); @@ -152,42 +146,42 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) * @hotplug_slot: slot to disable * * Actual tasks are done in acpiphp_disable_slot() - * */ static int disable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); /* disable the specified slot */ return acpiphp_disable_slot(slot->acpi_slot); } - /** - * set_attention_status - set attention LED +/** + * set_attention_status - set attention LED * @hotplug_slot: slot to set attention LED on * @status: value to set attention LED to (0 or 1) * * attention status LED, so we use a callback that * was registered with us. This allows hardware specific * ACPI implementations to blink the light for us. - **/ - static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) - { + */ +static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) +{ int retval = -ENODEV; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + pr_debug("%s - physical_slot = %s\n", __func__, + hotplug_slot_name(hotplug_slot)); + if (attention_info && try_module_get(attention_info->owner)) { retval = attention_info->set_attn(hotplug_slot, status); module_put(attention_info->owner); } else attention_info = NULL; return retval; - } - +} + /** * get_power_status - get power status of a slot @@ -196,13 +190,12 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) * * Some platforms may not implement _STA method properly. * In that case, the value returned may not be reliable. - * */ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_power_status(slot->acpi_slot); @@ -210,7 +203,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) } - /** +/** * get_attention_status - get attention LED status * @hotplug_slot: slot to get status from * @value: returns with value of attention LED @@ -218,13 +211,14 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) * ACPI doesn't have known method to determine the state * of the attention status LED, so we use a callback that * was registered with us. This allows hardware specific - * ACPI implementations to determine its state - **/ + * ACPI implementations to determine its state. + */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { int retval = -EINVAL; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, + hotplug_slot_name(hotplug_slot)); if (attention_info && try_module_get(attention_info->owner)) { retval = attention_info->get_attn(hotplug_slot, value); @@ -241,14 +235,13 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access latch status. - * Instead, we fake latch status from _STA - * + * Instead, we fake latch status from _STA. */ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_latch_status(slot->acpi_slot); @@ -262,66 +255,19 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access adapter status. - * Instead, we fake adapter status from _STA - * + * Instead, we fake adapter status from _STA. */ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = acpiphp_get_adapter_status(slot->acpi_slot); return 0; } - -/** - * get_address - get pci address of a slot - * @hotplug_slot: slot to get status - * @value: pointer to struct pci_busdev (seg, bus, dev) - */ -static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) -{ - struct slot *slot = hotplug_slot->private; - - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - - *value = acpiphp_get_address(slot->acpi_slot); - - return 0; -} - -static int __init init_acpi(void) -{ - int retval; - - /* initialize internal data structure etc. */ - retval = acpiphp_glue_init(); - - /* read initial number of slots */ - if (!retval) { - num_slots = acpiphp_get_num_slots(); - if (num_slots == 0) - retval = -ENODEV; - } - - return retval; -} - - -/** - * make_slot_name - make a slot name that appears in pcihpfs - * @slot: slot to name - * - */ -static void make_slot_name(struct slot *slot) -{ - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%u", - slot->acpi_slot->sun); -} - /** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free @@ -330,38 +276,29 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } /* callback routine to initialize 'struct slot' for each slot */ -int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) +int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, + unsigned int sun) { struct slot *slot; - struct hotplug_slot *hotplug_slot; - struct hotplug_slot_info *hotplug_slot_info; int retval = -ENOMEM; + char name[SLOT_NAME_SIZE]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kzalloc(sizeof(*slot->hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; - slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), - GFP_KERNEL); - if (!slot->hotplug_slot->info) - goto error_hpslot; - - slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) - goto error_info; + slot->hotplug_slot->info = &slot->info; slot->hotplug_slot->private = slot; slot->hotplug_slot->release = &release_slot; @@ -372,25 +309,23 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) slot->hotplug_slot->info->attention_status = 0; slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); - slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; acpiphp_slot->slot = slot; - make_slot_name(slot); + slot->sun = sun; + snprintf(name, SLOT_NAME_SIZE, "%u", sun); - retval = pci_hp_register(slot->hotplug_slot); + retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus, + acpiphp_slot->device, name); + if (retval == -EBUSY) + goto error_hpslot; if (retval) { - err("pci_hp_register failed with error %d\n", retval); - goto error_name; - } + pr_err("pci_hp_register failed with error %d\n", retval); + goto error_hpslot; + } - info("Slot [%s] registered\n", slot->hotplug_slot->name); + pr_info("Slot [%s] registered\n", slot_name(slot)); return 0; -error_name: - kfree(slot->hotplug_slot->name); -error_info: - kfree(slot->hotplug_slot->info); error_hpslot: kfree(slot->hotplug_slot); error_slot: @@ -405,30 +340,17 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) struct slot *slot = acpiphp_slot->slot; int retval = 0; - info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); + pr_info("Slot [%s] unregistered\n", slot_name(slot)); retval = pci_hp_deregister(slot->hotplug_slot); if (retval) - err("pci_hp_deregister failed with error %d\n", retval); + pr_err("pci_hp_deregister failed with error %d\n", retval); } -static int __init acpiphp_init(void) +void __init acpiphp_init(void) { - info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - - acpiphp_debug = debug; - - /* read all the ACPI info from the system */ - return init_acpi(); + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", + acpiphp_disabled ? ", disabled by user; please report a bug" + : ""); } - - -static void __exit acpiphp_exit(void) -{ - /* deallocate internal data structures etc. */ - acpiphp_glue_exit(); -} - -module_init(acpiphp_init); -module_exit(acpiphp_exit); |
