aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/pciehp.h16
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c17
-rw-r--r--drivers/pci/hotplug/pciehp_core.c120
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c20
4 files changed, 76 insertions, 97 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 36faa9a8e18f..af397b1291ea 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -80,7 +80,6 @@ struct slot {
80 struct controller *ctrl; 80 struct controller *ctrl;
81 struct hpc_ops *hpc_ops; 81 struct hpc_ops *hpc_ops;
82 struct hotplug_slot *hotplug_slot; 82 struct hotplug_slot *hotplug_slot;
83 struct list_head slot_list;
84 struct delayed_work work; /* work for button event */ 83 struct delayed_work work; /* work for button event */
85 struct mutex lock; 84 struct mutex lock;
86}; 85};
@@ -98,7 +97,7 @@ struct controller {
98 int slot_num_inc; /* 1 or -1 */ 97 int slot_num_inc; /* 1 or -1 */
99 struct pci_dev *pci_dev; 98 struct pci_dev *pci_dev;
100 struct pcie_device *pcie; /* PCI Express port service */ 99 struct pcie_device *pcie; /* PCI Express port service */
101 struct list_head slot_list; 100 struct slot *slot;
102 struct hpc_ops *hpc_ops; 101 struct hpc_ops *hpc_ops;
103 wait_queue_head_t queue; /* sleep & wake process */ 102 wait_queue_head_t queue; /* sleep & wake process */
104 u8 slot_device_offset; 103 u8 slot_device_offset;
@@ -181,19 +180,6 @@ static inline const char *slot_name(struct slot *slot)
181 return hotplug_slot_name(slot->hotplug_slot); 180 return hotplug_slot_name(slot->hotplug_slot);
182} 181}
183 182
184static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
185{
186 struct slot *slot;
187
188 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
189 if (slot->device == device)
190 return slot;
191 }
192
193 ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
194 return NULL;
195}
196
197struct hpc_ops { 183struct hpc_ops {
198 int (*power_on_slot)(struct slot *slot); 184 int (*power_on_slot)(struct slot *slot);
199 int (*power_off_slot)(struct slot *slot); 185 int (*power_off_slot)(struct slot *slot);
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 7163e6a6cfae..37c8d3d0323e 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -33,6 +33,11 @@
33#define PCIEHP_DETECT_AUTO (2) 33#define PCIEHP_DETECT_AUTO (2)
34#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO 34#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO
35 35
36struct dummy_slot {
37 u32 number;
38 struct list_head list;
39};
40
36static int slot_detection_mode; 41static int slot_detection_mode;
37static char *pciehp_detect_mode; 42static char *pciehp_detect_mode;
38module_param(pciehp_detect_mode, charp, 0444); 43module_param(pciehp_detect_mode, charp, 0444);
@@ -77,7 +82,7 @@ static int __init dummy_probe(struct pcie_device *dev)
77 int pos; 82 int pos;
78 u32 slot_cap; 83 u32 slot_cap;
79 acpi_handle handle; 84 acpi_handle handle;
80 struct slot *slot, *tmp; 85 struct dummy_slot *slot, *tmp;
81 struct pci_dev *pdev = dev->port; 86 struct pci_dev *pdev = dev->port;
82 /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ 87 /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
83 if (pciehp_get_hp_hw_control_from_firmware(pdev)) 88 if (pciehp_get_hp_hw_control_from_firmware(pdev))
@@ -89,11 +94,11 @@ static int __init dummy_probe(struct pcie_device *dev)
89 if (!slot) 94 if (!slot)
90 return -ENOMEM; 95 return -ENOMEM;
91 slot->number = slot_cap >> 19; 96 slot->number = slot_cap >> 19;
92 list_for_each_entry(tmp, &dummy_slots, slot_list) { 97 list_for_each_entry(tmp, &dummy_slots, list) {
93 if (tmp->number == slot->number) 98 if (tmp->number == slot->number)
94 dup_slot_id++; 99 dup_slot_id++;
95 } 100 }
96 list_add_tail(&slot->slot_list, &dummy_slots); 101 list_add_tail(&slot->list, &dummy_slots);
97 handle = DEVICE_ACPI_HANDLE(&pdev->dev); 102 handle = DEVICE_ACPI_HANDLE(&pdev->dev);
98 if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle)) 103 if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle))
99 acpi_slot_detected = 1; 104 acpi_slot_detected = 1;
@@ -109,11 +114,11 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
109 114
110static int __init select_detection_mode(void) 115static int __init select_detection_mode(void)
111{ 116{
112 struct slot *slot, *tmp; 117 struct dummy_slot *slot, *tmp;
113 pcie_port_service_register(&dummy_driver); 118 pcie_port_service_register(&dummy_driver);
114 pcie_port_service_unregister(&dummy_driver); 119 pcie_port_service_unregister(&dummy_driver);
115 list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) { 120 list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
116 list_del(&slot->slot_list); 121 list_del(&slot->list);
117 kfree(slot); 122 kfree(slot);
118 } 123 }
119 if (acpi_slot_detected && dup_slot_id) 124 if (acpi_slot_detected && dup_slot_id)
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 2317557fdee6..d2cec882a2f5 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -99,65 +99,59 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
99 kfree(hotplug_slot); 99 kfree(hotplug_slot);
100} 100}
101 101
102static int init_slots(struct controller *ctrl) 102static int init_slot(struct controller *ctrl)
103{ 103{
104 struct slot *slot; 104 struct slot *slot = ctrl->slot;
105 struct hotplug_slot *hotplug_slot; 105 struct hotplug_slot *hotplug = NULL;
106 struct hotplug_slot_info *info; 106 struct hotplug_slot_info *info = NULL;
107 char name[SLOT_NAME_SIZE]; 107 char name[SLOT_NAME_SIZE];
108 int retval = -ENOMEM; 108 int retval = -ENOMEM;
109 109
110 list_for_each_entry(slot, &ctrl->slot_list, slot_list) { 110 hotplug = kzalloc(sizeof(*hotplug), GFP_KERNEL);
111 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 111 if (!hotplug)
112 if (!hotplug_slot) 112 goto out;
113 goto error; 113
114 114 info = kzalloc(sizeof(*info), GFP_KERNEL);
115 info = kzalloc(sizeof(*info), GFP_KERNEL); 115 if (!info)
116 if (!info) 116 goto out;
117 goto error_hpslot; 117
118 118 /* register this slot with the hotplug pci core */
119 /* register this slot with the hotplug pci core */ 119 hotplug->info = info;
120 hotplug_slot->info = info; 120 hotplug->private = slot;
121 hotplug_slot->private = slot; 121 hotplug->release = &release_slot;
122 hotplug_slot->release = &release_slot; 122 hotplug->ops = &pciehp_hotplug_slot_ops;
123 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 123 slot->hotplug_slot = hotplug;
124 slot->hotplug_slot = hotplug_slot; 124 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
125 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); 125
126 126 ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x "
127 ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " 127 "hp_slot=%x sun=%x slot_device_offset=%x\n",
128 "hp_slot=%x sun=%x slot_device_offset=%x\n", 128 pci_domain_nr(ctrl->pci_dev->subordinate),
129 pci_domain_nr(ctrl->pci_dev->subordinate), 129 slot->bus, slot->device, slot->hp_slot, slot->number,
130 slot->bus, slot->device, slot->hp_slot, slot->number, 130 ctrl->slot_device_offset);
131 ctrl->slot_device_offset); 131 retval = pci_hp_register(hotplug,
132 retval = pci_hp_register(hotplug_slot, 132 ctrl->pci_dev->subordinate,
133 ctrl->pci_dev->subordinate, 133 slot->device,
134 slot->device, 134 name);
135 name); 135 if (retval) {
136 if (retval) { 136 ctrl_err(ctrl,
137 ctrl_err(ctrl, "pci_hp_register failed with error %d\n", 137 "pci_hp_register failed with error %d\n", retval);
138 retval); 138 goto out;
139 goto error_info; 139 }
140 } 140 get_power_status(hotplug, &info->power_status);
141 get_power_status(hotplug_slot, &info->power_status); 141 get_attention_status(hotplug, &info->attention_status);
142 get_attention_status(hotplug_slot, &info->attention_status); 142 get_latch_status(hotplug, &info->latch_status);
143 get_latch_status(hotplug_slot, &info->latch_status); 143 get_adapter_status(hotplug, &info->adapter_status);
144 get_adapter_status(hotplug_slot, &info->adapter_status); 144out:
145 if (retval) {
146 kfree(info);
147 kfree(hotplug);
145 } 148 }
146
147 return 0;
148error_info:
149 kfree(info);
150error_hpslot:
151 kfree(hotplug_slot);
152error:
153 return retval; 149 return retval;
154} 150}
155 151
156static void cleanup_slots(struct controller *ctrl) 152static void cleanup_slot(struct controller *ctrl)
157{ 153{
158 struct slot *slot; 154 pci_hp_deregister(ctrl->slot->hotplug_slot);
159 list_for_each_entry(slot, &ctrl->slot_list, slot_list)
160 pci_hp_deregister(slot->hotplug_slot);
161} 155}
162 156
163/* 157/*
@@ -295,7 +289,7 @@ static int pciehp_probe(struct pcie_device *dev)
295{ 289{
296 int rc; 290 int rc;
297 struct controller *ctrl; 291 struct controller *ctrl;
298 struct slot *t_slot; 292 struct slot *slot;
299 u8 value; 293 u8 value;
300 struct pci_dev *pdev = dev->port; 294 struct pci_dev *pdev = dev->port;
301 295
@@ -314,7 +308,7 @@ static int pciehp_probe(struct pcie_device *dev)
314 set_service_data(dev, ctrl); 308 set_service_data(dev, ctrl);
315 309
316 /* Setup the slot information structures */ 310 /* Setup the slot information structures */
317 rc = init_slots(ctrl); 311 rc = init_slot(ctrl);
318 if (rc) { 312 if (rc) {
319 if (rc == -EBUSY) 313 if (rc == -EBUSY)
320 ctrl_warn(ctrl, "Slot already registered by another " 314 ctrl_warn(ctrl, "Slot already registered by another "
@@ -332,15 +326,15 @@ static int pciehp_probe(struct pcie_device *dev)
332 } 326 }
333 327
334 /* Check if slot is occupied */ 328 /* Check if slot is occupied */
335 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 329 slot = ctrl->slot;
336 t_slot->hpc_ops->get_adapter_status(t_slot, &value); 330 slot->hpc_ops->get_adapter_status(slot, &value);
337 if (value) { 331 if (value) {
338 if (pciehp_force) 332 if (pciehp_force)
339 pciehp_enable_slot(t_slot); 333 pciehp_enable_slot(slot);
340 } else { 334 } else {
341 /* Power off slot if not occupied */ 335 /* Power off slot if not occupied */
342 if (POWER_CTRL(ctrl)) { 336 if (POWER_CTRL(ctrl)) {
343 rc = t_slot->hpc_ops->power_off_slot(t_slot); 337 rc = slot->hpc_ops->power_off_slot(slot);
344 if (rc) 338 if (rc)
345 goto err_out_free_ctrl_slot; 339 goto err_out_free_ctrl_slot;
346 } 340 }
@@ -349,7 +343,7 @@ static int pciehp_probe(struct pcie_device *dev)
349 return 0; 343 return 0;
350 344
351err_out_free_ctrl_slot: 345err_out_free_ctrl_slot:
352 cleanup_slots(ctrl); 346 cleanup_slot(ctrl);
353err_out_release_ctlr: 347err_out_release_ctlr:
354 ctrl->hpc_ops->release_ctlr(ctrl); 348 ctrl->hpc_ops->release_ctlr(ctrl);
355err_out_none: 349err_out_none:
@@ -360,7 +354,7 @@ static void pciehp_remove (struct pcie_device *dev)
360{ 354{
361 struct controller *ctrl = get_service_data(dev); 355 struct controller *ctrl = get_service_data(dev);
362 356
363 cleanup_slots(ctrl); 357 cleanup_slot(ctrl);
364 ctrl->hpc_ops->release_ctlr(ctrl); 358 ctrl->hpc_ops->release_ctlr(ctrl);
365} 359}
366 360
@@ -376,20 +370,20 @@ static int pciehp_resume (struct pcie_device *dev)
376 dev_info(&dev->device, "%s ENTRY\n", __func__); 370 dev_info(&dev->device, "%s ENTRY\n", __func__);
377 if (pciehp_force) { 371 if (pciehp_force) {
378 struct controller *ctrl = get_service_data(dev); 372 struct controller *ctrl = get_service_data(dev);
379 struct slot *t_slot; 373 struct slot *slot;
380 u8 status; 374 u8 status;
381 375
382 /* reinitialize the chipset's event detection logic */ 376 /* reinitialize the chipset's event detection logic */
383 pcie_enable_notification(ctrl); 377 pcie_enable_notification(ctrl);
384 378
385 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 379 slot = ctrl->slot;
386 380
387 /* Check if slot is occupied */ 381 /* Check if slot is occupied */
388 t_slot->hpc_ops->get_adapter_status(t_slot, &status); 382 slot->hpc_ops->get_adapter_status(slot, &status);
389 if (status) 383 if (status)
390 pciehp_enable_slot(t_slot); 384 pciehp_enable_slot(slot);
391 else 385 else
392 pciehp_disable_slot(t_slot); 386 pciehp_disable_slot(slot);
393 } 387 }
394 return 0; 388 return 0;
395} 389}
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 271f917b6f2c..cb0cf2cae7b7 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -614,8 +614,8 @@ static int hpc_power_off_slot(struct slot * slot)
614static irqreturn_t pcie_isr(int irq, void *dev_id) 614static irqreturn_t pcie_isr(int irq, void *dev_id)
615{ 615{
616 struct controller *ctrl = (struct controller *)dev_id; 616 struct controller *ctrl = (struct controller *)dev_id;
617 struct slot *slot = ctrl->slot;
617 u16 detected, intr_loc; 618 u16 detected, intr_loc;
618 struct slot *p_slot;
619 619
620 /* 620 /*
621 * In order to guarantee that all interrupt events are 621 * In order to guarantee that all interrupt events are
@@ -656,24 +656,22 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
656 if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) 656 if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
657 return IRQ_HANDLED; 657 return IRQ_HANDLED;
658 658
659 p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
660
661 /* Check MRL Sensor Changed */ 659 /* Check MRL Sensor Changed */
662 if (intr_loc & PCI_EXP_SLTSTA_MRLSC) 660 if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
663 pciehp_handle_switch_change(p_slot); 661 pciehp_handle_switch_change(slot);
664 662
665 /* Check Attention Button Pressed */ 663 /* Check Attention Button Pressed */
666 if (intr_loc & PCI_EXP_SLTSTA_ABP) 664 if (intr_loc & PCI_EXP_SLTSTA_ABP)
667 pciehp_handle_attention_button(p_slot); 665 pciehp_handle_attention_button(slot);
668 666
669 /* Check Presence Detect Changed */ 667 /* Check Presence Detect Changed */
670 if (intr_loc & PCI_EXP_SLTSTA_PDC) 668 if (intr_loc & PCI_EXP_SLTSTA_PDC)
671 pciehp_handle_presence_change(p_slot); 669 pciehp_handle_presence_change(slot);
672 670
673 /* Check Power Fault Detected */ 671 /* Check Power Fault Detected */
674 if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { 672 if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
675 ctrl->power_fault_detected = 1; 673 ctrl->power_fault_detected = 1;
676 pciehp_handle_power_fault(p_slot); 674 pciehp_handle_power_fault(slot);
677 } 675 }
678 return IRQ_HANDLED; 676 return IRQ_HANDLED;
679} 677}
@@ -938,15 +936,13 @@ static int pcie_init_slot(struct controller *ctrl)
938 slot->number = ctrl->first_slot; 936 slot->number = ctrl->first_slot;
939 mutex_init(&slot->lock); 937 mutex_init(&slot->lock);
940 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); 938 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
941 list_add(&slot->slot_list, &ctrl->slot_list); 939 ctrl->slot = slot;
942 return 0; 940 return 0;
943} 941}
944 942
945static void pcie_cleanup_slot(struct controller *ctrl) 943static void pcie_cleanup_slot(struct controller *ctrl)
946{ 944{
947 struct slot *slot; 945 struct slot *slot = ctrl->slot;
948 slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
949 list_del(&slot->slot_list);
950 cancel_delayed_work(&slot->work); 946 cancel_delayed_work(&slot->work);
951 flush_scheduled_work(); 947 flush_scheduled_work();
952 flush_workqueue(pciehp_wq); 948 flush_workqueue(pciehp_wq);
@@ -1014,8 +1010,6 @@ struct controller *pcie_init(struct pcie_device *dev)
1014 dev_err(&dev->device, "%s: Out of memory\n", __func__); 1010 dev_err(&dev->device, "%s: Out of memory\n", __func__);
1015 goto abort; 1011 goto abort;
1016 } 1012 }
1017 INIT_LIST_HEAD(&ctrl->slot_list);
1018
1019 ctrl->pcie = dev; 1013 ctrl->pcie = dev;
1020 ctrl->pci_dev = pdev; 1014 ctrl->pci_dev = pdev;
1021 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); 1015 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);