Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] pciehp: allow bridged card hotplug

This patch fixes bugs in the pciehp driver that prevent hot-add
of a card with PCI bridges on it.

Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Rajesh Shah and committed by
Greg Kroah-Hartman
0eb3bcfd c7ab337f

+28 -24
+28 -24
drivers/pci/hotplug/pciehp_pci.c
··· 34 34 #include "../pci.h" 35 35 #include "pciehp.h" 36 36 37 + static int pciehp_add_bridge(struct pci_dev *dev) 38 + { 39 + struct pci_bus *parent = dev->bus; 40 + int pass, busnr, start = parent->secondary; 41 + int end = parent->subordinate; 42 + 43 + for (busnr = start; busnr <= end; busnr++) { 44 + if (!pci_find_bus(pci_domain_nr(parent), busnr)) 45 + break; 46 + } 47 + if (busnr-- > end) { 48 + err("No bus number available for hot-added bridge %s\n", 49 + pci_name(dev)); 50 + return -1; 51 + } 52 + for (pass = 0; pass < 2; pass++) 53 + busnr = pci_scan_bridge(parent, dev, busnr, pass); 54 + if (!dev->subordinate) 55 + return -1; 56 + pci_bus_size_bridges(dev->subordinate); 57 + pci_bus_assign_resources(parent); 58 + pci_enable_bridges(parent); 59 + pci_bus_add_devices(parent); 60 + return 0; 61 + } 37 62 38 63 int pciehp_configure_device(struct slot *p_slot) 39 64 { ··· 80 55 } 81 56 82 57 for (fn = 0; fn < 8; fn++) { 83 - if (!(dev = pci_find_slot(p_slot->bus, 84 - PCI_DEVFN(p_slot->device, fn)))) 58 + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); 59 + if (!dev) 85 60 continue; 86 61 if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 87 62 err("Cannot hot-add display device %s\n", ··· 90 65 } 91 66 if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || 92 67 (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { 93 - /* Find an unused bus number for the new bridge */ 94 - struct pci_bus *child; 95 - unsigned char busnr, start = parent->secondary; 96 - unsigned char end = parent->subordinate; 97 - for (busnr = start; busnr <= end; busnr++) { 98 - if (!pci_find_bus(pci_domain_nr(parent), 99 - busnr)) 100 - break; 101 - } 102 - if (busnr >= end) { 103 - err("No free bus for hot-added bridge\n"); 104 - continue; 105 - } 106 - child = pci_add_new_bus(parent, dev, busnr); 107 - if (!child) { 108 - err("Cannot add new bus for %s\n", 109 - pci_name(dev)); 110 - continue; 111 - } 112 - child->subordinate = pci_do_scan_bus(child); 113 - pci_bus_size_bridges(child); 68 + pciehp_add_bridge(dev); 114 69 } 115 70 /* TBD: program firmware provided _HPP values */ 116 71 /* program_fw_provided_values(dev); */ ··· 98 93 99 94 pci_bus_assign_resources(parent); 100 95 pci_bus_add_devices(parent); 101 - pci_enable_bridges(parent); 102 96 return 0; 103 97 } 104 98