pciehp: block new requests from the device before power off

Disable Bus Master, SERR# and INTx to ensure that no new Requests will
be generated from the device before turning power off, in accordance
with the specification.

Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by Kenji Kaneshige and committed by Greg Kroah-Hartman 2326e2b9 f1050a35

+21 -12
+21 -12
drivers/pci/hotplug/pciehp_pci.c
··· 243 243 u8 bctl = 0; 244 244 u8 presence = 0; 245 245 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; 246 + u16 command; 246 247 247 248 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, 248 249 p_slot->device); 250 + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence); 251 + if (ret) 252 + presence = 0; 249 253 250 254 for (j = 0; j < 8; j++) { 251 255 struct pci_dev* temp = pci_get_slot(parent, ··· 262 258 pci_dev_put(temp); 263 259 continue; 264 260 } 265 - if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 266 - ret = p_slot->hpc_ops->get_adapter_status(p_slot, 267 - &presence); 268 - if (!ret && presence) { 269 - pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, 270 - &bctl); 271 - if (bctl & PCI_BRIDGE_CTL_VGA) { 272 - err("Cannot remove display device %s\n", 273 - pci_name(temp)); 274 - pci_dev_put(temp); 275 - continue; 276 - } 261 + if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { 262 + pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); 263 + if (bctl & PCI_BRIDGE_CTL_VGA) { 264 + err("Cannot remove display device %s\n", 265 + pci_name(temp)); 266 + pci_dev_put(temp); 267 + continue; 277 268 } 278 269 } 279 270 pci_remove_bus_device(temp); 271 + /* 272 + * Ensure that no new Requests will be generated from 273 + * the device. 274 + */ 275 + if (presence) { 276 + pci_read_config_word(temp, PCI_COMMAND, &command); 277 + command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); 278 + command |= PCI_COMMAND_INTX_DISABLE; 279 + pci_write_config_word(temp, PCI_COMMAND, command); 280 + } 280 281 pci_dev_put(temp); 281 282 } 282 283 /*