diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 43 |
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, ®32); | ||
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 | |||