aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Makefile2
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c251
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c11
-rw-r--r--drivers/pci/hotplug/pciehp.h2
-rw-r--r--drivers/pci/hotplug/pciehp_core.c7
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c17
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c9
-rw-r--r--drivers/pci/hotplug/pcihp_slot.c180
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c8
9 files changed, 23 insertions, 464 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 3e6532b945c1..4a9aa08b08f1 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -24,7 +24,7 @@ obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o
24 24
25obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o 25obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
26 26
27pci_hotplug-objs := pci_hotplug_core.o pcihp_slot.o 27pci_hotplug-objs := pci_hotplug_core.o
28 28
29ifdef CONFIG_HOTPLUG_PCI_CPCI 29ifdef CONFIG_HOTPLUG_PCI_CPCI
30pci_hotplug-objs += cpci_hotplug_core.o \ 30pci_hotplug-objs += cpci_hotplug_core.o \
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 2cac54802567..876ccc620440 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -46,215 +46,6 @@
46 46
47static bool debug_acpi; 47static bool debug_acpi;
48 48
49static acpi_status
50decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
51{
52 int i;
53 union acpi_object *fields = record->package.elements;
54 u32 revision = fields[1].integer.value;
55
56 switch (revision) {
57 case 1:
58 if (record->package.count != 6)
59 return AE_ERROR;
60 for (i = 2; i < 6; i++)
61 if (fields[i].type != ACPI_TYPE_INTEGER)
62 return AE_ERROR;
63 hpx->t0 = &hpx->type0_data;
64 hpx->t0->revision = revision;
65 hpx->t0->cache_line_size = fields[2].integer.value;
66 hpx->t0->latency_timer = fields[3].integer.value;
67 hpx->t0->enable_serr = fields[4].integer.value;
68 hpx->t0->enable_perr = fields[5].integer.value;
69 break;
70 default:
71 printk(KERN_WARNING
72 "%s: Type 0 Revision %d record not supported\n",
73 __func__, revision);
74 return AE_ERROR;
75 }
76 return AE_OK;
77}
78
79static acpi_status
80decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
81{
82 int i;
83 union acpi_object *fields = record->package.elements;
84 u32 revision = fields[1].integer.value;
85
86 switch (revision) {
87 case 1:
88 if (record->package.count != 5)
89 return AE_ERROR;
90 for (i = 2; i < 5; i++)
91 if (fields[i].type != ACPI_TYPE_INTEGER)
92 return AE_ERROR;
93 hpx->t1 = &hpx->type1_data;
94 hpx->t1->revision = revision;
95 hpx->t1->max_mem_read = fields[2].integer.value;
96 hpx->t1->avg_max_split = fields[3].integer.value;
97 hpx->t1->tot_max_split = fields[4].integer.value;
98 break;
99 default:
100 printk(KERN_WARNING
101 "%s: Type 1 Revision %d record not supported\n",
102 __func__, revision);
103 return AE_ERROR;
104 }
105 return AE_OK;
106}
107
108static acpi_status
109decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
110{
111 int i;
112 union acpi_object *fields = record->package.elements;
113 u32 revision = fields[1].integer.value;
114
115 switch (revision) {
116 case 1:
117 if (record->package.count != 18)
118 return AE_ERROR;
119 for (i = 2; i < 18; i++)
120 if (fields[i].type != ACPI_TYPE_INTEGER)
121 return AE_ERROR;
122 hpx->t2 = &hpx->type2_data;
123 hpx->t2->revision = revision;
124 hpx->t2->unc_err_mask_and = fields[2].integer.value;
125 hpx->t2->unc_err_mask_or = fields[3].integer.value;
126 hpx->t2->unc_err_sever_and = fields[4].integer.value;
127 hpx->t2->unc_err_sever_or = fields[5].integer.value;
128 hpx->t2->cor_err_mask_and = fields[6].integer.value;
129 hpx->t2->cor_err_mask_or = fields[7].integer.value;
130 hpx->t2->adv_err_cap_and = fields[8].integer.value;
131 hpx->t2->adv_err_cap_or = fields[9].integer.value;
132 hpx->t2->pci_exp_devctl_and = fields[10].integer.value;
133 hpx->t2->pci_exp_devctl_or = fields[11].integer.value;
134 hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value;
135 hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value;
136 hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
137 hpx->t2->sec_unc_err_sever_or = fields[15].integer.value;
138 hpx->t2->sec_unc_err_mask_and = fields[16].integer.value;
139 hpx->t2->sec_unc_err_mask_or = fields[17].integer.value;
140 break;
141 default:
142 printk(KERN_WARNING
143 "%s: Type 2 Revision %d record not supported\n",
144 __func__, revision);
145 return AE_ERROR;
146 }
147 return AE_OK;
148}
149
150static acpi_status
151acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
152{
153 acpi_status status;
154 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
155 union acpi_object *package, *record, *fields;
156 u32 type;
157 int i;
158
159 /* Clear the return buffer with zeros */
160 memset(hpx, 0, sizeof(struct hotplug_params));
161
162 status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
163 if (ACPI_FAILURE(status))
164 return status;
165
166 package = (union acpi_object *)buffer.pointer;
167 if (package->type != ACPI_TYPE_PACKAGE) {
168 status = AE_ERROR;
169 goto exit;
170 }
171
172 for (i = 0; i < package->package.count; i++) {
173 record = &package->package.elements[i];
174 if (record->type != ACPI_TYPE_PACKAGE) {
175 status = AE_ERROR;
176 goto exit;
177 }
178
179 fields = record->package.elements;
180 if (fields[0].type != ACPI_TYPE_INTEGER ||
181 fields[1].type != ACPI_TYPE_INTEGER) {
182 status = AE_ERROR;
183 goto exit;
184 }
185
186 type = fields[0].integer.value;
187 switch (type) {
188 case 0:
189 status = decode_type0_hpx_record(record, hpx);
190 if (ACPI_FAILURE(status))
191 goto exit;
192 break;
193 case 1:
194 status = decode_type1_hpx_record(record, hpx);
195 if (ACPI_FAILURE(status))
196 goto exit;
197 break;
198 case 2:
199 status = decode_type2_hpx_record(record, hpx);
200 if (ACPI_FAILURE(status))
201 goto exit;
202 break;
203 default:
204 printk(KERN_ERR "%s: Type %d record not supported\n",
205 __func__, type);
206 status = AE_ERROR;
207 goto exit;
208 }
209 }
210 exit:
211 kfree(buffer.pointer);
212 return status;
213}
214
215static acpi_status
216acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
217{
218 acpi_status status;
219 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
220 union acpi_object *package, *fields;
221 int i;
222
223 memset(hpp, 0, sizeof(struct hotplug_params));
224
225 status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer);
226 if (ACPI_FAILURE(status))
227 return status;
228
229 package = (union acpi_object *) buffer.pointer;
230 if (package->type != ACPI_TYPE_PACKAGE ||
231 package->package.count != 4) {
232 status = AE_ERROR;
233 goto exit;
234 }
235
236 fields = package->package.elements;
237 for (i = 0; i < 4; i++) {
238 if (fields[i].type != ACPI_TYPE_INTEGER) {
239 status = AE_ERROR;
240 goto exit;
241 }
242 }
243
244 hpp->t0 = &hpp->type0_data;
245 hpp->t0->revision = 1;
246 hpp->t0->cache_line_size = fields[0].integer.value;
247 hpp->t0->latency_timer = fields[1].integer.value;
248 hpp->t0->enable_serr = fields[2].integer.value;
249 hpp->t0->enable_perr = fields[3].integer.value;
250
251exit:
252 kfree(buffer.pointer);
253 return status;
254}
255
256
257
258/* acpi_run_oshp - get control of hotplug from the firmware 49/* acpi_run_oshp - get control of hotplug from the firmware
259 * 50 *
260 * @handle - the handle of the hotplug controller. 51 * @handle - the handle of the hotplug controller.
@@ -283,48 +74,6 @@ static acpi_status acpi_run_oshp(acpi_handle handle)
283 return status; 74 return status;
284} 75}
285 76
286/* pci_get_hp_params
287 *
288 * @dev - the pci_dev for which we want parameters
289 * @hpp - allocated by the caller
290 */
291int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
292{
293 acpi_status status;
294 acpi_handle handle, phandle;
295 struct pci_bus *pbus;
296
297 handle = NULL;
298 for (pbus = dev->bus; pbus; pbus = pbus->parent) {
299 handle = acpi_pci_get_bridge_handle(pbus);
300 if (handle)
301 break;
302 }
303
304 /*
305 * _HPP settings apply to all child buses, until another _HPP is
306 * encountered. If we don't find an _HPP for the input pci dev,
307 * look for it in the parent device scope since that would apply to
308 * this pci dev.
309 */
310 while (handle) {
311 status = acpi_run_hpx(handle, hpp);
312 if (ACPI_SUCCESS(status))
313 return 0;
314 status = acpi_run_hpp(handle, hpp);
315 if (ACPI_SUCCESS(status))
316 return 0;
317 if (acpi_is_root_bridge(handle))
318 break;
319 status = acpi_get_parent(handle, &phandle);
320 if (ACPI_FAILURE(status))
321 break;
322 handle = phandle;
323 }
324 return -ENODEV;
325}
326EXPORT_SYMBOL_GPL(pci_get_hp_params);
327
328/** 77/**
329 * acpi_get_hp_hw_control_from_firmware 78 * acpi_get_hp_hw_control_from_firmware
330 * @dev: the pci_dev of the bridge that has a hotplug controller 79 * @dev: the pci_dev of the bridge that has a hotplug controller
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 70741c8c46a0..a6f8e0ba0bfe 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -61,7 +61,6 @@ static DEFINE_MUTEX(bridge_mutex);
61static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type); 61static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type);
62static void acpiphp_post_dock_fixup(struct acpi_device *adev); 62static void acpiphp_post_dock_fixup(struct acpi_device *adev);
63static void acpiphp_sanitize_bus(struct pci_bus *bus); 63static void acpiphp_sanitize_bus(struct pci_bus *bus);
64static void acpiphp_set_hpp_values(struct pci_bus *bus);
65static void hotplug_event(u32 type, struct acpiphp_context *context); 64static void hotplug_event(u32 type, struct acpiphp_context *context);
66static void free_bridge(struct kref *kref); 65static void free_bridge(struct kref *kref);
67 66
@@ -510,7 +509,7 @@ static void enable_slot(struct acpiphp_slot *slot)
510 __pci_bus_assign_resources(bus, &add_list, NULL); 509 __pci_bus_assign_resources(bus, &add_list, NULL);
511 510
512 acpiphp_sanitize_bus(bus); 511 acpiphp_sanitize_bus(bus);
513 acpiphp_set_hpp_values(bus); 512 pcie_bus_configure_settings(bus);
514 acpiphp_set_acpi_region(slot); 513 acpiphp_set_acpi_region(slot);
515 514
516 list_for_each_entry(dev, &bus->devices, bus_list) { 515 list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -702,14 +701,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
702 } 701 }
703} 702}
704 703
705static void acpiphp_set_hpp_values(struct pci_bus *bus)
706{
707 struct pci_dev *dev;
708
709 list_for_each_entry(dev, &bus->devices, bus_list)
710 pci_configure_slot(dev);
711}
712
713/* 704/*
714 * Remove devices for which we could not assign resources, call 705 * Remove devices for which we could not assign resources, call
715 * arch specific code to fix-up the bus 706 * arch specific code to fix-up the bus
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 9e5a9fbb93d7..b11521953485 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -92,7 +92,7 @@ struct controller {
92 struct slot *slot; 92 struct slot *slot;
93 wait_queue_head_t queue; /* sleep & wake process */ 93 wait_queue_head_t queue; /* sleep & wake process */
94 u32 slot_cap; 94 u32 slot_cap;
95 u32 slot_ctrl; 95 u16 slot_ctrl;
96 struct timer_list poll_timer; 96 struct timer_list poll_timer;
97 unsigned long cmd_started; /* jiffies */ 97 unsigned long cmd_started; /* jiffies */
98 unsigned int cmd_busy:1; 98 unsigned int cmd_busy:1;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 07aa722bb12c..3a5e7e28b874 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -262,6 +262,13 @@ static int pciehp_probe(struct pcie_device *dev)
262 goto err_out_none; 262 goto err_out_none;
263 } 263 }
264 264
265 if (!dev->port->subordinate) {
266 /* Can happen if we run out of bus numbers during probe */
267 dev_err(&dev->device,
268 "Hotplug bridge without secondary bus, ignoring\n");
269 goto err_out_none;
270 }
271
265 ctrl = pcie_init(dev); 272 ctrl = pcie_init(dev);
266 if (!ctrl) { 273 if (!ctrl) {
267 dev_err(&dev->device, "Controller initialization failed\n"); 274 dev_err(&dev->device, "Controller initialization failed\n");
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9da84b8b27d8..f0dc6cb9c5be 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -171,9 +171,9 @@ static void pcie_wait_cmd(struct controller *ctrl)
171 * interrupts. 171 * interrupts.
172 */ 172 */
173 if (!rc) 173 if (!rc)
174 ctrl_info(ctrl, "Timeout on hotplug command %#010x (issued %u msec ago)\n", 174 ctrl_info(ctrl, "Timeout on hotplug command %#06x (issued %u msec ago)\n",
175 ctrl->slot_ctrl, 175 ctrl->slot_ctrl,
176 jiffies_to_msecs(now - ctrl->cmd_started)); 176 jiffies_to_msecs(jiffies - ctrl->cmd_started));
177} 177}
178 178
179/** 179/**
@@ -422,9 +422,9 @@ void pciehp_set_attention_status(struct slot *slot, u8 value)
422 default: 422 default:
423 return; 423 return;
424 } 424 }
425 pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC);
425 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, 426 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
426 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); 427 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
427 pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC);
428} 428}
429 429
430void pciehp_green_led_on(struct slot *slot) 430void pciehp_green_led_on(struct slot *slot)
@@ -602,6 +602,8 @@ void pcie_enable_notification(struct controller *ctrl)
602 PCI_EXP_SLTCTL_DLLSCE); 602 PCI_EXP_SLTCTL_DLLSCE);
603 603
604 pcie_write_cmd(ctrl, cmd, mask); 604 pcie_write_cmd(ctrl, cmd, mask);
605 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
606 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd);
605} 607}
606 608
607static void pcie_disable_notification(struct controller *ctrl) 609static void pcie_disable_notification(struct controller *ctrl)
@@ -613,6 +615,8 @@ static void pcie_disable_notification(struct controller *ctrl)
613 PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | 615 PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
614 PCI_EXP_SLTCTL_DLLSCE); 616 PCI_EXP_SLTCTL_DLLSCE);
615 pcie_write_cmd(ctrl, 0, mask); 617 pcie_write_cmd(ctrl, 0, mask);
618 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
619 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, 0);
616} 620}
617 621
618/* 622/*
@@ -640,6 +644,8 @@ int pciehp_reset_slot(struct slot *slot, int probe)
640 stat_mask |= PCI_EXP_SLTSTA_DLLSC; 644 stat_mask |= PCI_EXP_SLTSTA_DLLSC;
641 645
642 pcie_write_cmd(ctrl, 0, ctrl_mask); 646 pcie_write_cmd(ctrl, 0, ctrl_mask);
647 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
648 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, 0);
643 if (pciehp_poll_mode) 649 if (pciehp_poll_mode)
644 del_timer_sync(&ctrl->poll_timer); 650 del_timer_sync(&ctrl->poll_timer);
645 651
@@ -647,6 +653,8 @@ int pciehp_reset_slot(struct slot *slot, int probe)
647 653
648 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask); 654 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
649 pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask); 655 pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
656 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
657 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, ctrl_mask);
650 if (pciehp_poll_mode) 658 if (pciehp_poll_mode)
651 int_poll_timeout(ctrl->poll_timer.data); 659 int_poll_timeout(ctrl->poll_timer.data);
652 660
@@ -785,9 +793,6 @@ struct controller *pcie_init(struct pcie_device *dev)
785 PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | 793 PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
786 PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); 794 PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
787 795
788 /* Disable software notification */
789 pcie_disable_notification(ctrl);
790
791 ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n", 796 ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n",
792 (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, 797 (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19,
793 FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), 798 FLAG(slot_cap, PCI_EXP_SLTCAP_ABP),
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 5f871f4c4af1..9e69403be632 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -65,14 +65,7 @@ int pciehp_configure_device(struct slot *p_slot)
65 pci_hp_add_bridge(dev); 65 pci_hp_add_bridge(dev);
66 66
67 pci_assign_unassigned_bridge_resources(bridge); 67 pci_assign_unassigned_bridge_resources(bridge);
68 68 pcie_bus_configure_settings(parent);
69 list_for_each_entry(dev, &parent->devices, bus_list) {
70 if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
71 continue;
72
73 pci_configure_slot(dev);
74 }
75
76 pci_bus_add_devices(parent); 69 pci_bus_add_devices(parent);
77 70
78 out: 71 out:
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
deleted file mode 100644
index e246a10a0d2c..000000000000
--- a/drivers/pci/hotplug/pcihp_slot.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 * Copyright (C) 1995,2001 Compaq Computer Corporation
3 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
4 * Copyright (C) 2001 IBM Corp.
5 * Copyright (C) 2003-2004 Intel Corporation
6 * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
7 *
8 * All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18 * NON INFRINGEMENT. See the GNU General Public License for more
19 * details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/pci.h>
27#include <linux/export.h>
28#include <linux/pci_hotplug.h>
29
30static struct hpp_type0 pci_default_type0 = {
31 .revision = 1,
32 .cache_line_size = 8,
33 .latency_timer = 0x40,
34 .enable_serr = 0,
35 .enable_perr = 0,
36};
37
38static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
39{
40 u16 pci_cmd, pci_bctl;
41
42 if (!hpp) {
43 /*
44 * Perhaps we *should* use default settings for PCIe, but
45 * pciehp didn't, so we won't either.
46 */
47 if (pci_is_pcie(dev))
48 return;
49 dev_info(&dev->dev, "using default PCI settings\n");
50 hpp = &pci_default_type0;
51 }
52
53 if (hpp->revision > 1) {
54 dev_warn(&dev->dev,
55 "PCI settings rev %d not supported; using defaults\n",
56 hpp->revision);
57 hpp = &pci_default_type0;
58 }
59
60 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
61 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
62 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
63 if (hpp->enable_serr)
64 pci_cmd |= PCI_COMMAND_SERR;
65 else
66 pci_cmd &= ~PCI_COMMAND_SERR;
67 if (hpp->enable_perr)
68 pci_cmd |= PCI_COMMAND_PARITY;
69 else
70 pci_cmd &= ~PCI_COMMAND_PARITY;
71 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
72
73 /* Program bridge control value */
74 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
75 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
76 hpp->latency_timer);
77 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
78 if (hpp->enable_serr)
79 pci_bctl |= PCI_BRIDGE_CTL_SERR;
80 else
81 pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
82 if (hpp->enable_perr)
83 pci_bctl |= PCI_BRIDGE_CTL_PARITY;
84 else
85 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
86 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
87 }
88}
89
90static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
91{
92 if (hpp)
93 dev_warn(&dev->dev, "PCI-X settings not supported\n");
94}
95
96static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
97{
98 int pos;
99 u32 reg32;
100
101 if (!hpp)
102 return;
103
104 if (hpp->revision > 1) {
105 dev_warn(&dev->dev, "PCIe settings rev %d not supported\n",
106 hpp->revision);
107 return;
108 }
109
110 /* Initialize Device Control Register */
111 pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
112 ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
113
114 /* Initialize Link Control Register */
115 if (dev->subordinate)
116 pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
117 ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
118
119 /* Find Advanced Error Reporting Enhanced Capability */
120 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
121 if (!pos)
122 return;
123
124 /* Initialize Uncorrectable Error Mask Register */
125 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
126 reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
127 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
128
129 /* Initialize Uncorrectable Error Severity Register */
130 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
131 reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
132 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
133
134 /* Initialize Correctable Error Mask Register */
135 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
136 reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
137 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
138
139 /* Initialize Advanced Error Capabilities and Control Register */
140 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
141 reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
142 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
143
144 /*
145 * FIXME: The following two registers are not supported yet.
146 *
147 * o Secondary Uncorrectable Error Severity Register
148 * o Secondary Uncorrectable Error Mask Register
149 */
150}
151
152void pci_configure_slot(struct pci_dev *dev)
153{
154 struct pci_dev *cdev;
155 struct hotplug_params hpp;
156 int ret;
157
158 if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
159 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
160 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
161 return;
162
163 pcie_bus_configure_settings(dev->bus);
164
165 memset(&hpp, 0, sizeof(hpp));
166 ret = pci_get_hp_params(dev, &hpp);
167 if (ret)
168 dev_warn(&dev->dev, "no hotplug settings from platform\n");
169
170 program_hpp_type2(dev, hpp.t2);
171 program_hpp_type1(dev, hpp.t1);
172 program_hpp_type0(dev, hpp.t0);
173
174 if (dev->subordinate) {
175 list_for_each_entry(cdev, &dev->subordinate->devices,
176 bus_list)
177 pci_configure_slot(cdev);
178 }
179}
180EXPORT_SYMBOL_GPL(pci_configure_slot);
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 469454e0cc48..f8cd3a27e351 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -69,13 +69,7 @@ int shpchp_configure_device(struct slot *p_slot)
69 } 69 }
70 70
71 pci_assign_unassigned_bridge_resources(bridge); 71 pci_assign_unassigned_bridge_resources(bridge);
72 72 pcie_bus_configure_settings(parent);
73 list_for_each_entry(dev, &parent->devices, bus_list) {
74 if (PCI_SLOT(dev->devfn) != p_slot->device)
75 continue;
76 pci_configure_slot(dev);
77 }
78
79 pci_bus_add_devices(parent); 73 pci_bus_add_devices(parent);
80 74
81 out: 75 out: