Commit 8720d27d authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Jesse Barnes

PCI: pciehp: remove slot_list field

Since PCIe downstream port has only one slot at most, we don't need
'slot_list' linked list to manage multiple slots under the port.
Acked-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent e2d4304b
......@@ -80,7 +80,6 @@ struct slot {
struct controller *ctrl;
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
struct delayed_work work; /* work for button event */
struct mutex lock;
};
......@@ -98,7 +97,7 @@ struct controller {
int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev;
struct pcie_device *pcie; /* PCI Express port service */
struct list_head slot_list;
struct slot *slot;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
u8 slot_device_offset;
......@@ -181,19 +180,6 @@ static inline const char *slot_name(struct slot *slot)
return hotplug_slot_name(slot->hotplug_slot);
}
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
struct slot *slot;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (slot->device == device)
return slot;
}
ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
return NULL;
}
struct hpc_ops {
int (*power_on_slot)(struct slot *slot);
int (*power_off_slot)(struct slot *slot);
......
......@@ -33,6 +33,11 @@
#define PCIEHP_DETECT_AUTO (2)
#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO
struct dummy_slot {
u32 number;
struct list_head list;
};
static int slot_detection_mode;
static char *pciehp_detect_mode;
module_param(pciehp_detect_mode, charp, 0444);
......@@ -77,7 +82,7 @@ static int __init dummy_probe(struct pcie_device *dev)
int pos;
u32 slot_cap;
acpi_handle handle;
struct slot *slot, *tmp;
struct dummy_slot *slot, *tmp;
struct pci_dev *pdev = dev->port;
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
if (pciehp_get_hp_hw_control_from_firmware(pdev))
......@@ -89,11 +94,11 @@ static int __init dummy_probe(struct pcie_device *dev)
if (!slot)
return -ENOMEM;
slot->number = slot_cap >> 19;
list_for_each_entry(tmp, &dummy_slots, slot_list) {
list_for_each_entry(tmp, &dummy_slots, list) {
if (tmp->number == slot->number)
dup_slot_id++;
}
list_add_tail(&slot->slot_list, &dummy_slots);
list_add_tail(&slot->list, &dummy_slots);
handle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle))
acpi_slot_detected = 1;
......@@ -109,11 +114,11 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
static int __init select_detection_mode(void)
{
struct slot *slot, *tmp;
struct dummy_slot *slot, *tmp;
pcie_port_service_register(&dummy_driver);
pcie_port_service_unregister(&dummy_driver);
list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) {
list_del(&slot->slot_list);
list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
list_del(&slot->list);
kfree(slot);
}
if (acpi_slot_detected && dup_slot_id)
......
......@@ -99,29 +99,28 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(hotplug_slot);
}
static int init_slots(struct controller *ctrl)
static int init_slot(struct controller *ctrl)
{
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
struct slot *slot = ctrl->slot;
struct hotplug_slot *hotplug = NULL;
struct hotplug_slot_info *info = NULL;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
if (!hotplug_slot)
goto error;
hotplug = kzalloc(sizeof(*hotplug), GFP_KERNEL);
if (!hotplug)
goto out;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto error_hpslot;
goto out;
/* register this slot with the hotplug pci core */
hotplug_slot->info = info;
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
slot->hotplug_slot = hotplug_slot;
hotplug->info = info;
hotplug->private = slot;
hotplug->release = &release_slot;
hotplug->ops = &pciehp_hotplug_slot_ops;
slot->hotplug_slot = hotplug;
snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x "
......@@ -129,35 +128,30 @@ static int init_slots(struct controller *ctrl)
pci_domain_nr(ctrl->pci_dev->subordinate),
slot->bus, slot->device, slot->hp_slot, slot->number,
ctrl->slot_device_offset);
retval = pci_hp_register(hotplug_slot,
retval = pci_hp_register(hotplug,
ctrl->pci_dev->subordinate,
slot->device,
name);
if (retval) {
ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
retval);
goto error_info;
}
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);
ctrl_err(ctrl,
"pci_hp_register failed with error %d\n", retval);
goto out;
}
return 0;
error_info:
get_power_status(hotplug, &info->power_status);
get_attention_status(hotplug, &info->attention_status);
get_latch_status(hotplug, &info->latch_status);
get_adapter_status(hotplug, &info->adapter_status);
out:
if (retval) {
kfree(info);
error_hpslot:
kfree(hotplug_slot);
error:
kfree(hotplug);
}
return retval;
}
static void cleanup_slots(struct controller *ctrl)
static void cleanup_slot(struct controller *ctrl)
{
struct slot *slot;
list_for_each_entry(slot, &ctrl->slot_list, slot_list)
pci_hp_deregister(slot->hotplug_slot);
pci_hp_deregister(ctrl->slot->hotplug_slot);
}
/*
......@@ -295,7 +289,7 @@ static int pciehp_probe(struct pcie_device *dev)
{
int rc;
struct controller *ctrl;
struct slot *t_slot;
struct slot *slot;
u8 value;
struct pci_dev *pdev = dev->port;
......@@ -314,7 +308,7 @@ static int pciehp_probe(struct pcie_device *dev)
set_service_data(dev, ctrl);
/* Setup the slot information structures */
rc = init_slots(ctrl);
rc = init_slot(ctrl);
if (rc) {
if (rc == -EBUSY)
ctrl_warn(ctrl, "Slot already registered by another "
......@@ -332,15 +326,15 @@ static int pciehp_probe(struct pcie_device *dev)
}
/* Check if slot is occupied */
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
t_slot->hpc_ops->get_adapter_status(t_slot, &value);
slot = ctrl->slot;
slot->hpc_ops->get_adapter_status(slot, &value);
if (value) {
if (pciehp_force)
pciehp_enable_slot(t_slot);
pciehp_enable_slot(slot);
} else {
/* Power off slot if not occupied */
if (POWER_CTRL(ctrl)) {
rc = t_slot->hpc_ops->power_off_slot(t_slot);
rc = slot->hpc_ops->power_off_slot(slot);
if (rc)
goto err_out_free_ctrl_slot;
}
......@@ -349,7 +343,7 @@ static int pciehp_probe(struct pcie_device *dev)
return 0;
err_out_free_ctrl_slot:
cleanup_slots(ctrl);
cleanup_slot(ctrl);
err_out_release_ctlr:
ctrl->hpc_ops->release_ctlr(ctrl);
err_out_none:
......@@ -360,7 +354,7 @@ static void pciehp_remove (struct pcie_device *dev)
{
struct controller *ctrl = get_service_data(dev);
cleanup_slots(ctrl);
cleanup_slot(ctrl);
ctrl->hpc_ops->release_ctlr(ctrl);
}
......@@ -376,20 +370,20 @@ static int pciehp_resume (struct pcie_device *dev)
dev_info(&dev->device, "%s ENTRY\n", __func__);
if (pciehp_force) {
struct controller *ctrl = get_service_data(dev);
struct slot *t_slot;
struct slot *slot;
u8 status;
/* reinitialize the chipset's event detection logic */
pcie_enable_notification(ctrl);
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
slot = ctrl->slot;
/* Check if slot is occupied */
t_slot->hpc_ops->get_adapter_status(t_slot, &status);
slot->hpc_ops->get_adapter_status(slot, &status);
if (status)
pciehp_enable_slot(t_slot);
pciehp_enable_slot(slot);
else
pciehp_disable_slot(t_slot);
pciehp_disable_slot(slot);
}
return 0;
}
......
......@@ -614,8 +614,8 @@ static int hpc_power_off_slot(struct slot * slot)
static irqreturn_t pcie_isr(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
struct slot *slot = ctrl->slot;
u16 detected, intr_loc;
struct slot *p_slot;
/*
* In order to guarantee that all interrupt events are
......@@ -656,24 +656,22 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
return IRQ_HANDLED;
p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
/* Check MRL Sensor Changed */
if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
pciehp_handle_switch_change(p_slot);
pciehp_handle_switch_change(slot);
/* Check Attention Button Pressed */
if (intr_loc & PCI_EXP_SLTSTA_ABP)
pciehp_handle_attention_button(p_slot);
pciehp_handle_attention_button(slot);
/* Check Presence Detect Changed */
if (intr_loc & PCI_EXP_SLTSTA_PDC)
pciehp_handle_presence_change(p_slot);
pciehp_handle_presence_change(slot);
/* Check Power Fault Detected */
if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
ctrl->power_fault_detected = 1;
pciehp_handle_power_fault(p_slot);
pciehp_handle_power_fault(slot);
}
return IRQ_HANDLED;
}
......@@ -938,15 +936,13 @@ static int pcie_init_slot(struct controller *ctrl)
slot->number = ctrl->first_slot;
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
list_add(&slot->slot_list, &ctrl->slot_list);
ctrl->slot = slot;
return 0;
}
static void pcie_cleanup_slot(struct controller *ctrl)
{
struct slot *slot;
slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
list_del(&slot->slot_list);
struct slot *slot = ctrl->slot;
cancel_delayed_work(&slot->work);
flush_scheduled_work();
flush_workqueue(pciehp_wq);
......@@ -1014,8 +1010,6 @@ struct controller *pcie_init(struct pcie_device *dev)
dev_err(&dev->device, "%s: Out of memory\n", __func__);
goto abort;
}
INIT_LIST_HEAD(&ctrl->slot_list);
ctrl->pcie = dev;
ctrl->pci_dev = pdev;
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment