diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_ctrl.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_ctrl.c | 152 |
1 files changed, 36 insertions, 116 deletions
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 10f3257b18a7..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -198,7 +198,8 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
198 | 198 | ||
199 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); | 199 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); |
200 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { | 200 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { |
201 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); | 201 | err("%s: Issue of set bus speed mode command failed\n", |
202 | __FUNCTION__); | ||
202 | return WRONG_BUS_FREQUENCY; | 203 | return WRONG_BUS_FREQUENCY; |
203 | } | 204 | } |
204 | return rc; | 205 | return rc; |
@@ -209,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, | |||
209 | enum pci_bus_speed msp) | 210 | enum pci_bus_speed msp) |
210 | { | 211 | { |
211 | int rc = 0; | 212 | int rc = 0; |
212 | 213 | ||
213 | if (flag != 0) { /* Other slots on the same bus are occupied */ | 214 | /* |
214 | if ( asp < bsp ) { | 215 | * If other slots on the same bus are occupied, we cannot |
215 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); | 216 | * change the bus speed. |
216 | return WRONG_BUS_FREQUENCY; | 217 | */ |
218 | if (flag) { | ||
219 | if (asp < bsp) { | ||
220 | err("%s: speed of bus %x and adapter %x mismatch\n", | ||
221 | __FUNCTION__, bsp, asp); | ||
222 | rc = WRONG_BUS_FREQUENCY; | ||
217 | } | 223 | } |
224 | return rc; | ||
225 | } | ||
226 | |||
227 | if (asp < msp) { | ||
228 | if (bsp != asp) | ||
229 | rc = change_bus_speed(ctrl, pslot, asp); | ||
218 | } else { | 230 | } else { |
219 | /* Other slots on the same bus are empty */ | 231 | if (bsp != msp) |
220 | if (msp == bsp) { | 232 | rc = change_bus_speed(ctrl, pslot, msp); |
221 | /* if adapter_speed >= bus_speed, do nothing */ | ||
222 | if (asp < bsp) { | ||
223 | /* | ||
224 | * Try to lower bus speed to accommodate the adapter if other slots | ||
225 | * on the same controller are empty | ||
226 | */ | ||
227 | if ((rc = change_bus_speed(ctrl, pslot, asp))) | ||
228 | return rc; | ||
229 | } | ||
230 | } else { | ||
231 | if (asp < msp) { | ||
232 | if ((rc = change_bus_speed(ctrl, pslot, asp))) | ||
233 | return rc; | ||
234 | } else { | ||
235 | if ((rc = change_bus_speed(ctrl, pslot, msp))) | ||
236 | return rc; | ||
237 | } | ||
238 | } | ||
239 | } | 233 | } |
240 | return rc; | 234 | return rc; |
241 | } | 235 | } |
@@ -252,8 +246,7 @@ static int board_added(struct slot *p_slot) | |||
252 | u8 hp_slot; | 246 | u8 hp_slot; |
253 | u8 slots_not_empty = 0; | 247 | u8 slots_not_empty = 0; |
254 | int rc = 0; | 248 | int rc = 0; |
255 | enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; | 249 | enum pci_bus_speed asp, bsp, msp; |
256 | u8 pi, mode; | ||
257 | struct controller *ctrl = p_slot->ctrl; | 250 | struct controller *ctrl = p_slot->ctrl; |
258 | 251 | ||
259 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 252 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
@@ -285,109 +278,36 @@ static int board_added(struct slot *p_slot) | |||
285 | } | 278 | } |
286 | } | 279 | } |
287 | 280 | ||
288 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); | 281 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); |
289 | /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ | 282 | if (rc) { |
290 | /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ | 283 | err("%s: Can't get adapter speed or bus mode mismatch\n", |
291 | /* 0xd = PCI-X 133 Mhz 533 */ | 284 | __FUNCTION__); |
292 | /* This encoding is different from the one used in cur_bus_speed & */ | ||
293 | /* max_bus_speed */ | ||
294 | |||
295 | if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { | ||
296 | err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); | ||
297 | return WRONG_BUS_FREQUENCY; | 285 | return WRONG_BUS_FREQUENCY; |
298 | } | 286 | } |
299 | 287 | ||
300 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); | 288 | rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); |
301 | if (rc || bus_speed == PCI_SPEED_UNKNOWN) { | 289 | if (rc) { |
302 | err("%s: Can't get bus operation speed\n", __FUNCTION__); | 290 | err("%s: Can't get bus operation speed\n", __FUNCTION__); |
303 | return WRONG_BUS_FREQUENCY; | 291 | return WRONG_BUS_FREQUENCY; |
304 | } | 292 | } |
305 | 293 | ||
306 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); | 294 | rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); |
307 | if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { | 295 | if (rc) { |
308 | err("%s: Can't get max bus operation speed\n", __FUNCTION__); | 296 | err("%s: Can't get max bus operation speed\n", __FUNCTION__); |
309 | max_bus_speed = bus_speed; | 297 | msp = bsp; |
310 | } | ||
311 | |||
312 | if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { | ||
313 | err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); | ||
314 | pi = 1; | ||
315 | } | 298 | } |
316 | 299 | ||
317 | /* Check if there are other slots or devices on the same bus */ | 300 | /* Check if there are other slots or devices on the same bus */ |
318 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) | 301 | if (!list_empty(&ctrl->pci_dev->subordinate->devices)) |
319 | slots_not_empty = 1; | 302 | slots_not_empty = 1; |
320 | 303 | ||
321 | dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, | 304 | dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " |
322 | slots_not_empty, pi); | 305 | "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, |
323 | dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", | 306 | bsp, msp); |
324 | adapter_speed, bus_speed, max_bus_speed); | ||
325 | |||
326 | if (pi == 2) { | ||
327 | dbg("%s: In PI = %d\n", __FUNCTION__, pi); | ||
328 | if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { | ||
329 | err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); | ||
330 | mode = 0; | ||
331 | } | ||
332 | 307 | ||
333 | switch (adapter_speed) { | 308 | rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); |
334 | case PCI_SPEED_133MHz_PCIX_533: | 309 | if (rc) |
335 | case PCI_SPEED_133MHz_PCIX_266: | 310 | return rc; |
336 | if ((bus_speed != adapter_speed) && | ||
337 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
338 | return rc; | ||
339 | break; | ||
340 | case PCI_SPEED_133MHz_PCIX_ECC: | ||
341 | case PCI_SPEED_133MHz_PCIX: | ||
342 | if (mode) { /* Bus - Mode 1 ECC */ | ||
343 | if ((bus_speed != 0x7) && | ||
344 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
345 | return rc; | ||
346 | } else { | ||
347 | if ((bus_speed != 0x4) && | ||
348 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
349 | return rc; | ||
350 | } | ||
351 | break; | ||
352 | case PCI_SPEED_66MHz_PCIX_ECC: | ||
353 | case PCI_SPEED_66MHz_PCIX: | ||
354 | if (mode) { /* Bus - Mode 1 ECC */ | ||
355 | if ((bus_speed != 0x5) && | ||
356 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
357 | return rc; | ||
358 | } else { | ||
359 | if ((bus_speed != 0x2) && | ||
360 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
361 | return rc; | ||
362 | } | ||
363 | break; | ||
364 | case PCI_SPEED_66MHz: | ||
365 | if ((bus_speed != 0x1) && | ||
366 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
367 | return rc; | ||
368 | break; | ||
369 | case PCI_SPEED_33MHz: | ||
370 | if (bus_speed > 0x0) { | ||
371 | if (slots_not_empty == 0) { | ||
372 | if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) | ||
373 | return rc; | ||
374 | } else { | ||
375 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); | ||
376 | return WRONG_BUS_FREQUENCY; | ||
377 | } | ||
378 | } | ||
379 | break; | ||
380 | default: | ||
381 | err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); | ||
382 | return WRONG_BUS_FREQUENCY; | ||
383 | } | ||
384 | } else { | ||
385 | /* If adpater_speed == bus_speed, nothing to do here */ | ||
386 | dbg("%s: In PI = %d\n", __FUNCTION__, pi); | ||
387 | if ((adapter_speed != bus_speed) && | ||
388 | ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) | ||
389 | return rc; | ||
390 | } | ||
391 | 311 | ||
392 | /* turn on board, blink green LED, turn off Amber LED */ | 312 | /* turn on board, blink green LED, turn off Amber LED */ |
393 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 313 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |