diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 89e404805777..6209972313f3 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -38,6 +38,55 @@ | |||
38 | #include "../pci.h" | 38 | #include "../pci.h" |
39 | #include "shpchp.h" | 39 | #include "shpchp.h" |
40 | 40 | ||
41 | void program_fw_provided_values(struct pci_dev *dev) | ||
42 | { | ||
43 | u16 pci_cmd, pci_bctl; | ||
44 | struct pci_dev *cdev; | ||
45 | struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */ | ||
46 | |||
47 | /* Program hpp values for this device */ | ||
48 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
49 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
50 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
51 | return; | ||
52 | |||
53 | get_hp_params_from_firmware(dev, &hpp); | ||
54 | |||
55 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); | ||
56 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); | ||
57 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
58 | if (hpp.enable_serr) | ||
59 | pci_cmd |= PCI_COMMAND_SERR; | ||
60 | else | ||
61 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
62 | if (hpp.enable_perr) | ||
63 | pci_cmd |= PCI_COMMAND_PARITY; | ||
64 | else | ||
65 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
66 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
67 | |||
68 | /* Program bridge control value and child devices */ | ||
69 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
70 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
71 | hpp.latency_timer); | ||
72 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
73 | if (hpp.enable_serr) | ||
74 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
75 | else | ||
76 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
77 | if (hpp.enable_perr) | ||
78 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
79 | else | ||
80 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
81 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
82 | if (dev->subordinate) { | ||
83 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
84 | bus_list) | ||
85 | program_fw_provided_values(cdev); | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
41 | int shpchp_configure_device(struct slot *p_slot) | 90 | int shpchp_configure_device(struct slot *p_slot) |
42 | { | 91 | { |
43 | struct pci_dev *dev; | 92 | struct pci_dev *dev; |
@@ -90,8 +139,7 @@ int shpchp_configure_device(struct slot *p_slot) | |||
90 | child->subordinate = pci_do_scan_bus(child); | 139 | child->subordinate = pci_do_scan_bus(child); |
91 | pci_bus_size_bridges(child); | 140 | pci_bus_size_bridges(child); |
92 | } | 141 | } |
93 | /* TBD: program firmware provided _HPP values */ | 142 | program_fw_provided_values(dev); |
94 | /* program_fw_provided_values(dev); */ | ||
95 | } | 143 | } |
96 | 144 | ||
97 | pci_bus_assign_resources(parent); | 145 | pci_bus_assign_resources(parent); |