X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpci%2Fhotplug%2Fshpchp_core.c;h=590cd3cbe0104fd8a3e1eba2a70f28aa8d3e9260;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=a2b3f0010ceceaf049b59eeee97095dce4d9cb14;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a2b3f0010..590cd3cbe 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -32,13 +32,14 @@ #include #include #include +#include #include "shpchp.h" /* Global variables */ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -struct controller *shpchp_ctrl_list; /* = NULL */ +struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -57,7 +58,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); #define SHPC_MODULE_NAME "shpchp" -static int shpc_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); @@ -94,143 +94,106 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } +static void make_slot_name(struct slot *slot) +{ + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); +} + static int init_slots(struct controller *ctrl) { - struct slot *new_slot; - u8 number_of_slots; - u8 slot_device; - u32 slot_number, sun; - int result = -ENOMEM; - - number_of_slots = ctrl->num_slots; - slot_device = ctrl->slot_device_offset; - slot_number = ctrl->first_slot; - - while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!new_slot) + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *info; + int retval = -ENOMEM; + int i; + + for (i = 0; i < ctrl->num_slots; i++) { + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) goto error; - memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + if (!hotplug_slot) goto error_slot; - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + slot->hotplug_slot = hotplug_slot; - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) goto error_hpslot; - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) - goto error_info; - - new_slot->magic = SLOT_MAGIC; - new_slot->ctrl = ctrl; - new_slot->bus = ctrl->slot_bus; - new_slot->device = slot_device; - new_slot->hpc_ops = ctrl->hpc_ops; + hotplug_slot->info = info; - if (shpchprm_get_physical_slot_number(ctrl, &sun, - new_slot->bus, new_slot->device)) - goto error_name; + hotplug_slot->name = slot->name; - new_slot->number = sun; - new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + slot->hp_slot = i; + slot->ctrl = ctrl; + slot->bus = ctrl->pci_dev->subordinate->number; + slot->device = ctrl->slot_device_offset + i; + slot->hpc_ops = ctrl->hpc_ops; + slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); + mutex_init(&slot->lock); + INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ - new_slot->hotplug_slot->private = new_slot; - new_slot->hotplug_slot->release = &release_slot; - make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); - new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; - - new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); - new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); - new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); - new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); - - dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, - new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); - result = pci_hp_register (new_slot->hotplug_slot); - if (result) { - err ("pci_hp_register failed with error %d\n", result); - goto error_name; + hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; + make_slot_name(slot); + hotplug_slot->ops = &shpchp_hotplug_slot_ops; + + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); + + dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " + "slot_device_offset=%x\n", slot->bus, slot->device, + slot->hp_slot, slot->number, ctrl->slot_device_offset); + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_info; } - new_slot->next = ctrl->slot; - ctrl->slot = new_slot; - - number_of_slots--; - slot_device++; - slot_number += ctrl->slot_num_inc; + list_add(&slot->slot_list, &ctrl->slot_list); } return 0; - -error_name: - kfree(new_slot->hotplug_slot->name); error_info: - kfree(new_slot->hotplug_slot->info); + kfree(info); error_hpslot: - kfree(new_slot->hotplug_slot); + kfree(hotplug_slot); error_slot: - kfree(new_slot); + kfree(slot); error: - return result; -} - -static void cleanup_slots(struct controller *ctrl) -{ - struct slot *old_slot, *next_slot; - - old_slot = ctrl->slot; - ctrl->slot = NULL; - - while (old_slot) { - next_slot = old_slot->next; - pci_hp_deregister(old_slot->hotplug_slot); - old_slot = next_slot; - } + return retval; } -static int get_ctlr_slot_config(struct controller *ctrl) +void cleanup_slots(struct controller *ctrl) { - int num_ctlr_slots; - int first_device_num; - int physical_slot_num; - int updown; - int rc; - int flags; - - rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); - if (rc) { - err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); - return -1; + struct list_head *tmp; + struct list_head *next; + struct slot *slot; + + list_for_each_safe(tmp, next, &ctrl->slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + cancel_delayed_work(&slot->work); + flush_scheduled_work(); + flush_workqueue(shpchp_wq); + pci_hp_deregister(slot->hotplug_slot); } - - ctrl->num_slots = num_ctlr_slots; - ctrl->slot_device_offset = first_device_num; - ctrl->first_slot = physical_slot_num; - ctrl->slot_num_inc = updown; /* either -1 or 1 */ - - dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); - - return 0; } - /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -240,29 +203,27 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) return 0; } - static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_enable_slot(slot); + return shpchp_sysfs_enable_slot(slot); } - static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_disable_slot(slot); + return shpchp_sysfs_disable_slot(slot); } static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -276,7 +237,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -290,7 +251,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -304,7 +265,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -318,7 +279,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -330,11 +291,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -344,11 +305,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -371,96 +332,42 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; struct controller *ctrl; - struct slot *t_slot; - int first_device_num; /* first PCI device number supported by this SHPC */ - int num_ctlr_slots; /* number of slots supported by this SHPC */ if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); + INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); if (rc) { - dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); + dbg("%s: controller initialization failed\n", + SHPC_MODULE_NAME); goto err_out_free_ctrl; } pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); - if (!ctrl->pci_bus) { - err("out of memory\n"); - rc = -ENOMEM; - goto err_out_unmap_mmio_region; - } - - memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); - ctrl->bus = pdev->bus->number; - ctrl->slot_bus = pdev->subordinate->number; - - ctrl->device = PCI_SLOT(pdev->devfn); - ctrl->function = PCI_FUNC(pdev->devfn); - dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); - - /* - * Save configuration headers for this and subordinate PCI buses - */ - - rc = get_ctlr_slot_config(ctrl); - if (rc) { - err(msg_initialization_err, rc); - goto err_out_free_ctrl_bus; - } - first_device_num = ctrl->slot_device_offset; - num_ctlr_slots = ctrl->num_slots; - - ctrl->add_support = 1; - /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { - err(msg_initialization_err, 6); - goto err_out_free_ctrl_slot; - } - - /* Now hpc_functions (slot->hpc_ops->functions) are ready */ - t_slot = shpchp_find_slot(ctrl, first_device_num); - - /* Check for operation bus speed */ - rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed); - dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); - - if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { - err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); - ctrl->speed = PCI_SPEED_33MHz; + err("%s: slot initialization failed\n", SHPC_MODULE_NAME); + goto err_out_release_ctlr; } - /* Finish setting up the hot plug ctrl device */ - ctrl->next_event = 0; - - if (!shpchp_ctrl_list) { - shpchp_ctrl_list = ctrl; - ctrl->next = NULL; - } else { - ctrl->next = shpchp_ctrl_list; - shpchp_ctrl_list = ctrl; - } - - shpchp_create_ctrl_files(ctrl); + rc = shpchp_create_ctrl_files(ctrl); + if (rc) + goto err_cleanup_slots; return 0; -err_out_free_ctrl_slot: +err_cleanup_slots: cleanup_slots(ctrl); -err_out_free_ctrl_bus: - kfree(ctrl->pci_bus); -err_out_unmap_mmio_region: +err_out_release_ctlr: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: kfree(ctrl); @@ -468,74 +375,28 @@ err_out_none: return -ENODEV; } - -static int shpc_start_thread(void) -{ - int retval = 0; - - dbg("Initialize + Start the notification/polling mechanism \n"); - - retval = shpchp_event_start_thread(); - if (retval) { - dbg("shpchp_event_start_thread() failed\n"); - return retval; - } - - return retval; -} - -static void __exit unload_shpchpd(void) +static void shpc_remove(struct pci_dev *dev) { - struct controller *ctrl; - struct controller *tctrl; - - ctrl = shpchp_ctrl_list; - - while (ctrl) { - shpchp_remove_ctrl_files(ctrl); - cleanup_slots(ctrl); - - kfree (ctrl->pci_bus); - ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); - } - - /* Stop the notification mechanism */ - shpchp_event_stop_thread(); + struct controller *ctrl = pci_get_drvdata(dev); + shpchp_remove_ctrl_files(ctrl); + ctrl->hpc_ops->release_ctlr(ctrl); + kfree(ctrl); } - static struct pci_device_id shpcd_pci_tbl[] = { - { - .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), - .class_mask = ~0, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - + {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, { /* end: all zeroes */ } }; - MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); - - static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, .probe = shpc_probe, - /* remove: shpc_remove_one, */ + .remove = shpc_remove, }; - - static int __init shpcd_init(void) { int retval = 0; @@ -544,28 +405,16 @@ static int __init shpcd_init(void) shpchp_poll_mode = 1; #endif - retval = shpc_start_thread(); - if (retval) - goto error_hpc_init; - retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - -error_hpc_init: - if (retval) { - shpchp_event_stop_thread(); - } return retval; } static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); - unload_shpchpd(); - pci_unregister_driver(&shpc_driver); - info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); }