mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
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 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;
|
||||
ctrl_err(ctrl,
|
||||
"pci_hp_register failed with error %d\n", retval);
|
||||
goto out;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue