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: Alex Chiang <achiang@hp.com> Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
e2d4304b7d
commit
8720d27dab
4 changed files with 73 additions and 94 deletions
|
@ -80,7 +80,6 @@ struct slot {
|
||||||
struct controller *ctrl;
|
struct controller *ctrl;
|
||||||
struct hpc_ops *hpc_ops;
|
struct hpc_ops *hpc_ops;
|
||||||
struct hotplug_slot *hotplug_slot;
|
struct hotplug_slot *hotplug_slot;
|
||||||
struct list_head slot_list;
|
|
||||||
struct delayed_work work; /* work for button event */
|
struct delayed_work work; /* work for button event */
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
};
|
};
|
||||||
|
@ -98,7 +97,7 @@ struct controller {
|
||||||
int slot_num_inc; /* 1 or -1 */
|
int slot_num_inc; /* 1 or -1 */
|
||||||
struct pci_dev *pci_dev;
|
struct pci_dev *pci_dev;
|
||||||
struct pcie_device *pcie; /* PCI Express port service */
|
struct pcie_device *pcie; /* PCI Express port service */
|
||||||
struct list_head slot_list;
|
struct slot *slot;
|
||||||
struct hpc_ops *hpc_ops;
|
struct hpc_ops *hpc_ops;
|
||||||
wait_queue_head_t queue; /* sleep & wake process */
|
wait_queue_head_t queue; /* sleep & wake process */
|
||||||
u8 slot_device_offset;
|
u8 slot_device_offset;
|
||||||
|
@ -181,19 +180,6 @@ static inline const char *slot_name(struct slot *slot)
|
||||||
return hotplug_slot_name(slot->hotplug_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 {
|
struct hpc_ops {
|
||||||
int (*power_on_slot)(struct slot *slot);
|
int (*power_on_slot)(struct slot *slot);
|
||||||
int (*power_off_slot)(struct slot *slot);
|
int (*power_off_slot)(struct slot *slot);
|
||||||
|
|
|
@ -33,6 +33,11 @@
|
||||||
#define PCIEHP_DETECT_AUTO (2)
|
#define PCIEHP_DETECT_AUTO (2)
|
||||||
#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO
|
#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO
|
||||||
|
|
||||||
|
struct dummy_slot {
|
||||||
|
u32 number;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
static int slot_detection_mode;
|
static int slot_detection_mode;
|
||||||
static char *pciehp_detect_mode;
|
static char *pciehp_detect_mode;
|
||||||
module_param(pciehp_detect_mode, charp, 0444);
|
module_param(pciehp_detect_mode, charp, 0444);
|
||||||
|
@ -77,7 +82,7 @@ static int __init dummy_probe(struct pcie_device *dev)
|
||||||
int pos;
|
int pos;
|
||||||
u32 slot_cap;
|
u32 slot_cap;
|
||||||
acpi_handle handle;
|
acpi_handle handle;
|
||||||
struct slot *slot, *tmp;
|
struct dummy_slot *slot, *tmp;
|
||||||
struct pci_dev *pdev = dev->port;
|
struct pci_dev *pdev = dev->port;
|
||||||
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
|
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
|
||||||
if (pciehp_get_hp_hw_control_from_firmware(pdev))
|
if (pciehp_get_hp_hw_control_from_firmware(pdev))
|
||||||
|
@ -89,11 +94,11 @@ static int __init dummy_probe(struct pcie_device *dev)
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
slot->number = slot_cap >> 19;
|
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)
|
if (tmp->number == slot->number)
|
||||||
dup_slot_id++;
|
dup_slot_id++;
|
||||||
}
|
}
|
||||||
list_add_tail(&slot->slot_list, &dummy_slots);
|
list_add_tail(&slot->list, &dummy_slots);
|
||||||
handle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
handle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
||||||
if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle))
|
if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle))
|
||||||
acpi_slot_detected = 1;
|
acpi_slot_detected = 1;
|
||||||
|
@ -109,11 +114,11 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
|
||||||
|
|
||||||
static int __init select_detection_mode(void)
|
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_register(&dummy_driver);
|
||||||
pcie_port_service_unregister(&dummy_driver);
|
pcie_port_service_unregister(&dummy_driver);
|
||||||
list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) {
|
list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
|
||||||
list_del(&slot->slot_list);
|
list_del(&slot->list);
|
||||||
kfree(slot);
|
kfree(slot);
|
||||||
}
|
}
|
||||||
if (acpi_slot_detected && dup_slot_id)
|
if (acpi_slot_detected && dup_slot_id)
|
||||||
|
|
|
@ -99,29 +99,28 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||||
kfree(hotplug_slot);
|
kfree(hotplug_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_slots(struct controller *ctrl)
|
static int init_slot(struct controller *ctrl)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
struct slot *slot = ctrl->slot;
|
||||||
struct hotplug_slot *hotplug_slot;
|
struct hotplug_slot *hotplug = NULL;
|
||||||
struct hotplug_slot_info *info;
|
struct hotplug_slot_info *info = NULL;
|
||||||
char name[SLOT_NAME_SIZE];
|
char name[SLOT_NAME_SIZE];
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
|
|
||||||
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
|
hotplug = kzalloc(sizeof(*hotplug), GFP_KERNEL);
|
||||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
if (!hotplug)
|
||||||
if (!hotplug_slot)
|
goto out;
|
||||||
goto error;
|
|
||||||
|
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||||
if (!info)
|
if (!info)
|
||||||
goto error_hpslot;
|
goto out;
|
||||||
|
|
||||||
/* register this slot with the hotplug pci core */
|
/* register this slot with the hotplug pci core */
|
||||||
hotplug_slot->info = info;
|
hotplug->info = info;
|
||||||
hotplug_slot->private = slot;
|
hotplug->private = slot;
|
||||||
hotplug_slot->release = &release_slot;
|
hotplug->release = &release_slot;
|
||||||
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
|
hotplug->ops = &pciehp_hotplug_slot_ops;
|
||||||
slot->hotplug_slot = hotplug_slot;
|
slot->hotplug_slot = hotplug;
|
||||||
snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
|
snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
|
||||||
|
|
||||||
ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x "
|
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),
|
pci_domain_nr(ctrl->pci_dev->subordinate),
|
||||||
slot->bus, slot->device, slot->hp_slot, slot->number,
|
slot->bus, slot->device, slot->hp_slot, slot->number,
|
||||||
ctrl->slot_device_offset);
|
ctrl->slot_device_offset);
|
||||||
retval = pci_hp_register(hotplug_slot,
|
retval = pci_hp_register(hotplug,
|
||||||
ctrl->pci_dev->subordinate,
|
ctrl->pci_dev->subordinate,
|
||||||
slot->device,
|
slot->device,
|
||||||
name);
|
name);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
|
ctrl_err(ctrl,
|
||||||
retval);
|
"pci_hp_register failed with error %d\n", retval);
|
||||||
goto error_info;
|
goto out;
|
||||||
}
|
}
|
||||||
get_power_status(hotplug_slot, &info->power_status);
|
get_power_status(hotplug, &info->power_status);
|
||||||
get_attention_status(hotplug_slot, &info->attention_status);
|
get_attention_status(hotplug, &info->attention_status);
|
||||||
get_latch_status(hotplug_slot, &info->latch_status);
|
get_latch_status(hotplug, &info->latch_status);
|
||||||
get_adapter_status(hotplug_slot, &info->adapter_status);
|
get_adapter_status(hotplug, &info->adapter_status);
|
||||||
}
|
out:
|
||||||
|
if (retval) {
|
||||||
return 0;
|
|
||||||
error_info:
|
|
||||||
kfree(info);
|
kfree(info);
|
||||||
error_hpslot:
|
kfree(hotplug);
|
||||||
kfree(hotplug_slot);
|
}
|
||||||
error:
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup_slots(struct controller *ctrl)
|
static void cleanup_slot(struct controller *ctrl)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
pci_hp_deregister(ctrl->slot->hotplug_slot);
|
||||||
list_for_each_entry(slot, &ctrl->slot_list, slot_list)
|
|
||||||
pci_hp_deregister(slot->hotplug_slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -295,7 +289,7 @@ static int pciehp_probe(struct pcie_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct controller *ctrl;
|
struct controller *ctrl;
|
||||||
struct slot *t_slot;
|
struct slot *slot;
|
||||||
u8 value;
|
u8 value;
|
||||||
struct pci_dev *pdev = dev->port;
|
struct pci_dev *pdev = dev->port;
|
||||||
|
|
||||||
|
@ -314,7 +308,7 @@ static int pciehp_probe(struct pcie_device *dev)
|
||||||
set_service_data(dev, ctrl);
|
set_service_data(dev, ctrl);
|
||||||
|
|
||||||
/* Setup the slot information structures */
|
/* Setup the slot information structures */
|
||||||
rc = init_slots(ctrl);
|
rc = init_slot(ctrl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc == -EBUSY)
|
if (rc == -EBUSY)
|
||||||
ctrl_warn(ctrl, "Slot already registered by another "
|
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 */
|
/* Check if slot is occupied */
|
||||||
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
|
slot = ctrl->slot;
|
||||||
t_slot->hpc_ops->get_adapter_status(t_slot, &value);
|
slot->hpc_ops->get_adapter_status(slot, &value);
|
||||||
if (value) {
|
if (value) {
|
||||||
if (pciehp_force)
|
if (pciehp_force)
|
||||||
pciehp_enable_slot(t_slot);
|
pciehp_enable_slot(slot);
|
||||||
} else {
|
} else {
|
||||||
/* Power off slot if not occupied */
|
/* Power off slot if not occupied */
|
||||||
if (POWER_CTRL(ctrl)) {
|
if (POWER_CTRL(ctrl)) {
|
||||||
rc = t_slot->hpc_ops->power_off_slot(t_slot);
|
rc = slot->hpc_ops->power_off_slot(slot);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out_free_ctrl_slot;
|
goto err_out_free_ctrl_slot;
|
||||||
}
|
}
|
||||||
|
@ -349,7 +343,7 @@ static int pciehp_probe(struct pcie_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out_free_ctrl_slot:
|
err_out_free_ctrl_slot:
|
||||||
cleanup_slots(ctrl);
|
cleanup_slot(ctrl);
|
||||||
err_out_release_ctlr:
|
err_out_release_ctlr:
|
||||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||||
err_out_none:
|
err_out_none:
|
||||||
|
@ -360,7 +354,7 @@ static void pciehp_remove (struct pcie_device *dev)
|
||||||
{
|
{
|
||||||
struct controller *ctrl = get_service_data(dev);
|
struct controller *ctrl = get_service_data(dev);
|
||||||
|
|
||||||
cleanup_slots(ctrl);
|
cleanup_slot(ctrl);
|
||||||
ctrl->hpc_ops->release_ctlr(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__);
|
dev_info(&dev->device, "%s ENTRY\n", __func__);
|
||||||
if (pciehp_force) {
|
if (pciehp_force) {
|
||||||
struct controller *ctrl = get_service_data(dev);
|
struct controller *ctrl = get_service_data(dev);
|
||||||
struct slot *t_slot;
|
struct slot *slot;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
|
||||||
/* reinitialize the chipset's event detection logic */
|
/* reinitialize the chipset's event detection logic */
|
||||||
pcie_enable_notification(ctrl);
|
pcie_enable_notification(ctrl);
|
||||||
|
|
||||||
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
|
slot = ctrl->slot;
|
||||||
|
|
||||||
/* Check if slot is occupied */
|
/* 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)
|
if (status)
|
||||||
pciehp_enable_slot(t_slot);
|
pciehp_enable_slot(slot);
|
||||||
else
|
else
|
||||||
pciehp_disable_slot(t_slot);
|
pciehp_disable_slot(slot);
|
||||||
}
|
}
|
||||||
return 0;
|
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)
|
static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct controller *ctrl = (struct controller *)dev_id;
|
struct controller *ctrl = (struct controller *)dev_id;
|
||||||
|
struct slot *slot = ctrl->slot;
|
||||||
u16 detected, intr_loc;
|
u16 detected, intr_loc;
|
||||||
struct slot *p_slot;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In order to guarantee that all interrupt events are
|
* 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))
|
if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
|
|
||||||
|
|
||||||
/* Check MRL Sensor Changed */
|
/* Check MRL Sensor Changed */
|
||||||
if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
|
if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
|
||||||
pciehp_handle_switch_change(p_slot);
|
pciehp_handle_switch_change(slot);
|
||||||
|
|
||||||
/* Check Attention Button Pressed */
|
/* Check Attention Button Pressed */
|
||||||
if (intr_loc & PCI_EXP_SLTSTA_ABP)
|
if (intr_loc & PCI_EXP_SLTSTA_ABP)
|
||||||
pciehp_handle_attention_button(p_slot);
|
pciehp_handle_attention_button(slot);
|
||||||
|
|
||||||
/* Check Presence Detect Changed */
|
/* Check Presence Detect Changed */
|
||||||
if (intr_loc & PCI_EXP_SLTSTA_PDC)
|
if (intr_loc & PCI_EXP_SLTSTA_PDC)
|
||||||
pciehp_handle_presence_change(p_slot);
|
pciehp_handle_presence_change(slot);
|
||||||
|
|
||||||
/* Check Power Fault Detected */
|
/* Check Power Fault Detected */
|
||||||
if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
|
if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
|
||||||
ctrl->power_fault_detected = 1;
|
ctrl->power_fault_detected = 1;
|
||||||
pciehp_handle_power_fault(p_slot);
|
pciehp_handle_power_fault(slot);
|
||||||
}
|
}
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -938,15 +936,13 @@ static int pcie_init_slot(struct controller *ctrl)
|
||||||
slot->number = ctrl->first_slot;
|
slot->number = ctrl->first_slot;
|
||||||
mutex_init(&slot->lock);
|
mutex_init(&slot->lock);
|
||||||
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
|
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
|
||||||
list_add(&slot->slot_list, &ctrl->slot_list);
|
ctrl->slot = slot;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcie_cleanup_slot(struct controller *ctrl)
|
static void pcie_cleanup_slot(struct controller *ctrl)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
struct slot *slot = ctrl->slot;
|
||||||
slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
|
|
||||||
list_del(&slot->slot_list);
|
|
||||||
cancel_delayed_work(&slot->work);
|
cancel_delayed_work(&slot->work);
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
flush_workqueue(pciehp_wq);
|
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__);
|
dev_err(&dev->device, "%s: Out of memory\n", __func__);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&ctrl->slot_list);
|
|
||||||
|
|
||||||
ctrl->pcie = dev;
|
ctrl->pcie = dev;
|
||||||
ctrl->pci_dev = pdev;
|
ctrl->pci_dev = pdev;
|
||||||
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||||
|
|
Reference in a new issue