aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_core.c')
-rw-r--r--drivers/pci/hotplug/pciehp_core.c133
1 files changed, 38 insertions, 95 deletions
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 43d8ddb2d679..3677495c4f91 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -72,7 +72,6 @@ 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_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
-static int get_address (struct hotplug_slot *slot, u32 *value);
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
@@ -85,7 +84,6 @@ static struct hotplug_slot_ops pciehp_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,
.get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed,
};
@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
*/
static void release_slot(struct hotplug_slot *hotplug_slot)
{
- struct slot *slot = hotplug_slot->private;
-
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
- kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot);
- kfree(slot);
-}
-
-static void make_slot_name(struct slot *slot)
-{
- if (pciehp_slot_with_bus)
- snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
- slot->bus, slot->number);
- else
- snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
- slot->number);
+ kfree(hotplug_slot->info);
+ kfree(hotplug_slot);
}
static int init_slots(struct controller *ctrl)
@@ -210,56 +195,45 @@ static int init_slots(struct controller *ctrl)
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;
+ list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
if (!hotplug_slot)
- goto error_slot;
- slot->hotplug_slot = hotplug_slot;
+ goto error;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto error_hpslot;
- hotplug_slot->info = info;
-
- hotplug_slot->name = slot->name;
-
- 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;
- mutex_init(&slot->lock);
- INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
/* register this slot with the hotplug pci core */
+ hotplug_slot->info = info;
+ hotplug_slot->name = slot->name;
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
- make_slot_name(slot);
hotplug_slot->ops = &pciehp_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);
+ slot->hotplug_slot = hotplug_slot;
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(hotplug_slot);
+ retval = pci_hp_register(hotplug_slot,
+ ctrl->pci_dev->subordinate,
+ slot->device);
if (retval) {
- err ("pci_hp_register failed with error %d\n", retval);
+ err("pci_hp_register failed with error %d\n", retval);
+ if (retval == -EEXIST)
+ err("Failed to register slot because of name "
+ "collision. Try \'pciehp_slot_with_bus\' "
+ "module option.\n");
goto error_info;
}
/* create additional sysfs entries */
if (EMI(ctrl)) {
- retval = sysfs_create_file(&hotplug_slot->kobj,
+ retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
if (retval) {
pci_hp_deregister(hotplug_slot);
@@ -267,8 +241,6 @@ static int init_slots(struct controller *ctrl)
goto error_info;
}
}
-
- list_add(&slot->slot_list, &ctrl->slot_list);
}
return 0;
@@ -276,27 +248,18 @@ error_info:
kfree(info);
error_hpslot:
kfree(hotplug_slot);
-error_slot:
- kfree(slot);
error:
return retval;
}
static void cleanup_slots(struct controller *ctrl)
{
- 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);
+ list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (EMI(ctrl))
- sysfs_remove_file(&slot->hotplug_slot->kobj,
+ sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
- cancel_delayed_work(&slot->work);
- flush_scheduled_work();
- flush_workqueue(pciehp_wq);
pci_hp_deregister(slot->hotplug_slot);
}
}
@@ -394,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
-static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
-{
- struct slot *slot = hotplug_slot->private;
- struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
-
- dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
-
- *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
-
- return 0;
-}
-
-static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
+ enum pci_bus_speed *value)
{
struct slot *slot = hotplug_slot->private;
int retval;
@@ -440,34 +392,30 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
struct controller *ctrl;
struct slot *t_slot;
u8 value;
- struct pci_dev *pdev;
+ struct pci_dev *pdev = dev->port;
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl) {
- err("%s : out of memory\n", __func__);
+ if (pciehp_force)
+ dbg("Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(pdev));
+ else if (pciehp_get_hp_hw_control_from_firmware(pdev))
goto err_out_none;
- }
- INIT_LIST_HEAD(&ctrl->slot_list);
-
- pdev = dev->port;
- ctrl->pci_dev = pdev;
- rc = pcie_init(ctrl, dev);
- if (rc) {
+ ctrl = pcie_init(dev);
+ if (!ctrl) {
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
- goto err_out_free_ctrl;
+ goto err_out_none;
}
-
- pci_set_drvdata(pdev, ctrl);
-
- dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
- __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn), pdev->irq);
+ set_service_data(dev, ctrl);
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
- err("%s: slot initialization failed\n", PCIE_MODULE_NAME);
+ if (rc == -EBUSY)
+ warn("%s: slot already registered by another "
+ "hotplug driver\n", PCIE_MODULE_NAME);
+ else
+ err("%s: slot initialization failed\n",
+ PCIE_MODULE_NAME);
goto err_out_release_ctlr;
}
@@ -491,20 +439,16 @@ err_out_free_ctrl_slot:
cleanup_slots(ctrl);
err_out_release_ctlr:
ctrl->hpc_ops->release_ctlr(ctrl);
-err_out_free_ctrl:
- kfree(ctrl);
err_out_none:
return -ENODEV;
}
static void pciehp_remove (struct pcie_device *dev)
{
- struct pci_dev *pdev = dev->port;
- struct controller *ctrl = pci_get_drvdata(pdev);
+ struct controller *ctrl = get_service_data(dev);
cleanup_slots(ctrl);
ctrl->hpc_ops->release_ctlr(ctrl);
- kfree(ctrl);
}
#ifdef CONFIG_PM
@@ -518,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev)
{
printk("%s ENTRY\n", __func__);
if (pciehp_force) {
- struct pci_dev *pdev = dev->port;
- struct controller *ctrl = pci_get_drvdata(pdev);
+ struct controller *ctrl = get_service_data(dev);
struct slot *t_slot;
u8 status;
/* reinitialize the chipset's event detection logic */
- pcie_init_hardware_part2(ctrl, dev);
+ pcie_enable_notification(ctrl);
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);