aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_pci.c')
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index c424aded13fb..dd50713966d1 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
105 } 105 }
106 106
107 /* Find Advanced Error Reporting Enhanced Capability */ 107 /* Find Advanced Error Reporting Enhanced Capability */
108 pos = 256; 108 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
109 do {
110 pci_read_config_dword(dev, pos, &reg32);
111 if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
112 break;
113 } while ((pos = PCI_EXT_CAP_NEXT(reg32)));
114 if (!pos) 109 if (!pos)
115 return; 110 return;
116 111
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
248 u8 bctl = 0; 243 u8 bctl = 0;
249 u8 presence = 0; 244 u8 presence = 0;
250 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; 245 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
246 u16 command;
251 247
252 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, 248 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
253 p_slot->device); 249 p_slot->device);
250 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
251 if (ret)
252 presence = 0;
254 253
255 for (j=0; j<8 ; j++) { 254 for (j = 0; j < 8; j++) {
256 struct pci_dev* temp = pci_get_slot(parent, 255 struct pci_dev* temp = pci_get_slot(parent,
257 (p_slot->device << 3) | j); 256 (p_slot->device << 3) | j);
258 if (!temp) 257 if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
263 pci_dev_put(temp); 262 pci_dev_put(temp);
264 continue; 263 continue;
265 } 264 }
266 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 265 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
267 ret = p_slot->hpc_ops->get_adapter_status(p_slot, 266 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
268 &presence); 267 if (bctl & PCI_BRIDGE_CTL_VGA) {
269 if (!ret && presence) { 268 err("Cannot remove display device %s\n",
270 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, 269 pci_name(temp));
271 &bctl); 270 pci_dev_put(temp);
272 if (bctl & PCI_BRIDGE_CTL_VGA) { 271 continue;
273 err("Cannot remove display device %s\n",
274 pci_name(temp));
275 pci_dev_put(temp);
276 continue;
277 }
278 } 272 }
279 } 273 }
280 pci_remove_bus_device(temp); 274 pci_remove_bus_device(temp);
275 /*
276 * Ensure that no new Requests will be generated from
277 * the device.
278 */
279 if (presence) {
280 pci_read_config_word(temp, PCI_COMMAND, &command);
281 command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
282 command |= PCI_COMMAND_INTX_DISABLE;
283 pci_write_config_word(temp, PCI_COMMAND, command);
284 }
281 pci_dev_put(temp); 285 pci_dev_put(temp);
282 } 286 }
283 /* 287 /*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
288 292
289 return rc; 293 return rc;
290} 294}
291