diff options
Diffstat (limited to 'drivers/pci/hotplug/rpaphp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/rpaphp_pci.c | 167 |
1 files changed, 51 insertions, 116 deletions
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 6f6cbede5135..54ca8650d511 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -64,75 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state) | |||
64 | return rc; | 64 | return rc; |
65 | } | 65 | } |
66 | 66 | ||
67 | /** | ||
68 | * get_pci_adapter_status - get the status of a slot | ||
69 | * | ||
70 | * 0-- slot is empty | ||
71 | * 1-- adapter is configured | ||
72 | * 2-- adapter is not configured | ||
73 | * 3-- not valid | ||
74 | */ | ||
75 | int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) | ||
76 | { | ||
77 | struct pci_bus *bus; | ||
78 | int state, rc; | ||
79 | |||
80 | *value = NOT_VALID; | ||
81 | rc = rpaphp_get_sensor_state(slot, &state); | ||
82 | if (rc) | ||
83 | goto exit; | ||
84 | |||
85 | if (state == EMPTY) | ||
86 | *value = EMPTY; | ||
87 | else if (state == PRESENT) { | ||
88 | if (!is_init) { | ||
89 | /* at run-time slot->state can be changed by */ | ||
90 | /* config/unconfig adapter */ | ||
91 | *value = slot->state; | ||
92 | } else { | ||
93 | bus = pcibios_find_pci_bus(slot->dn); | ||
94 | if (bus && !list_empty(&bus->devices)) | ||
95 | *value = CONFIGURED; | ||
96 | else | ||
97 | *value = NOT_CONFIGURED; | ||
98 | } | ||
99 | } | ||
100 | exit: | ||
101 | return rc; | ||
102 | } | ||
103 | |||
104 | static void print_slot_pci_funcs(struct pci_bus *bus) | ||
105 | { | ||
106 | struct device_node *dn; | ||
107 | struct pci_dev *dev; | ||
108 | |||
109 | dn = pci_bus_to_OF_node(bus); | ||
110 | if (!dn) | ||
111 | return; | ||
112 | |||
113 | dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name); | ||
114 | list_for_each_entry (dev, &bus->devices, bus_list) | ||
115 | dbg("\t%s\n", pci_name(dev)); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | static int setup_pci_hotplug_slot_info(struct slot *slot) | ||
120 | { | ||
121 | struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; | ||
122 | |||
123 | dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", | ||
124 | __FUNCTION__); | ||
125 | rpaphp_get_power_status(slot, &hotplug_slot_info->power_status); | ||
126 | rpaphp_get_pci_adapter_status(slot, 1, | ||
127 | &hotplug_slot_info->adapter_status); | ||
128 | if (hotplug_slot_info->adapter_status == NOT_VALID) { | ||
129 | err("%s: NOT_VALID: skip dn->full_name=%s\n", | ||
130 | __FUNCTION__, slot->dn->full_name); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void set_slot_name(struct slot *slot) | 67 | static void set_slot_name(struct slot *slot) |
137 | { | 68 | { |
138 | struct pci_bus *bus = slot->bus; | 69 | struct pci_bus *bus = slot->bus; |
@@ -146,69 +77,73 @@ static void set_slot_name(struct slot *slot) | |||
146 | bus->number); | 77 | bus->number); |
147 | } | 78 | } |
148 | 79 | ||
149 | static int setup_pci_slot(struct slot *slot) | 80 | /** |
81 | * rpaphp_enable_slot - record slot state, config pci device | ||
82 | * | ||
83 | * Initialize values in the slot, and the hotplug_slot info | ||
84 | * structures to indicate if there is a pci card plugged into | ||
85 | * the slot. If the slot is not empty, run the pcibios routine | ||
86 | * to get pcibios stuff correctly set up. | ||
87 | */ | ||
88 | int rpaphp_enable_slot(struct slot *slot) | ||
150 | { | 89 | { |
151 | struct device_node *dn = slot->dn; | 90 | int rc, level, state; |
152 | struct pci_bus *bus; | 91 | struct pci_bus *bus; |
92 | struct hotplug_slot_info *info = slot->hotplug_slot->info; | ||
93 | |||
94 | info->adapter_status = NOT_VALID; | ||
95 | slot->state = EMPTY; | ||
96 | |||
97 | /* Find out if the power is turned on for the slot */ | ||
98 | rc = rtas_get_power_level(slot->power_domain, &level); | ||
99 | if (rc) | ||
100 | return rc; | ||
101 | info->power_status = level; | ||
102 | |||
103 | /* Figure out if there is an adapter in the slot */ | ||
104 | rc = rpaphp_get_sensor_state(slot, &state); | ||
105 | if (rc) | ||
106 | return rc; | ||
153 | 107 | ||
154 | BUG_ON(!dn); | 108 | bus = pcibios_find_pci_bus(slot->dn); |
155 | bus = pcibios_find_pci_bus(dn); | ||
156 | if (!bus) { | 109 | if (!bus) { |
157 | err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); | 110 | err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name); |
158 | goto exit_rc; | 111 | return -EINVAL; |
159 | } | 112 | } |
160 | 113 | ||
114 | info->adapter_status = EMPTY; | ||
161 | slot->bus = bus; | 115 | slot->bus = bus; |
162 | slot->pci_devs = &bus->devices; | 116 | slot->pci_devs = &bus->devices; |
163 | set_slot_name(slot); | 117 | set_slot_name(slot); |
164 | 118 | ||
165 | /* find slot's pci_dev if it's not empty */ | 119 | /* if there's an adapter in the slot, go add the pci devices */ |
166 | if (slot->hotplug_slot->info->adapter_status == EMPTY) { | 120 | if (state == PRESENT) { |
167 | slot->state = EMPTY; /* slot is empty */ | 121 | info->adapter_status = NOT_CONFIGURED; |
168 | } else { | 122 | slot->state = NOT_CONFIGURED; |
169 | /* slot is occupied */ | 123 | |
170 | if (!dn->child) { | 124 | /* non-empty slot has to have child */ |
171 | /* non-empty slot has to have child */ | 125 | if (!slot->dn->child) { |
172 | err("%s: slot[%s]'s device_node doesn't have child for adapter\n", | 126 | err("%s: slot[%s]'s device_node doesn't have child for adapter\n", |
173 | __FUNCTION__, slot->name); | 127 | __FUNCTION__, slot->name); |
174 | goto exit_rc; | 128 | return -EINVAL; |
175 | } | 129 | } |
176 | 130 | ||
177 | if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { | 131 | if (list_empty(&bus->devices)) |
178 | dbg("%s CONFIGURING pci adapter in slot[%s]\n", | 132 | pcibios_add_pci_devices(bus); |
179 | __FUNCTION__, slot->name); | ||
180 | pcibios_add_pci_devices(slot->bus); | ||
181 | 133 | ||
182 | } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { | 134 | if (!list_empty(&bus->devices)) { |
183 | err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", | 135 | info->adapter_status = CONFIGURED; |
184 | __FUNCTION__, slot->name); | ||
185 | goto exit_rc; | ||
186 | } | ||
187 | print_slot_pci_funcs(slot->bus); | ||
188 | if (!list_empty(slot->pci_devs)) { | ||
189 | slot->state = CONFIGURED; | 136 | slot->state = CONFIGURED; |
190 | } else { | 137 | } |
191 | /* DLPAR add as opposed to | 138 | |
192 | * boot time */ | 139 | if (debug) { |
193 | slot->state = NOT_CONFIGURED; | 140 | struct pci_dev *dev; |
141 | dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name); | ||
142 | list_for_each_entry (dev, &bus->devices, bus_list) | ||
143 | dbg("\t%s\n", pci_name(dev)); | ||
194 | } | 144 | } |
195 | } | 145 | } |
196 | return 0; | ||
197 | exit_rc: | ||
198 | dealloc_slot_struct(slot); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | 146 | ||
202 | int rpaphp_register_pci_slot(struct slot *slot) | 147 | return 0; |
203 | { | ||
204 | int rc = -EINVAL; | ||
205 | |||
206 | if (setup_pci_hotplug_slot_info(slot)) | ||
207 | goto exit_rc; | ||
208 | if (setup_pci_slot(slot)) | ||
209 | goto exit_rc; | ||
210 | rc = rpaphp_register_slot(slot); | ||
211 | exit_rc: | ||
212 | return rc; | ||
213 | } | 148 | } |
214 | 149 | ||