diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
commit | 478c6a43fcbc6c11609f8cee7c7b57223907754f (patch) | |
tree | a7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/pci/pci.c | |
parent | 8a3f257c704e02aee9869decd069a806b45be3f1 (diff) | |
parent | 6bb597507f9839b13498781e481f5458aea33620 (diff) |
Merge branch 'linus' into release
Conflicts:
arch/x86/kernel/cpu/cpufreq/longhaul.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 337 |
1 files changed, 237 insertions, 100 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6d6120007af4..445fb6f7ea3f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/pm_wakeup.h> | 20 | #include <linux/pm_wakeup.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
23 | #include <linux/device.h> | ||
24 | #include <asm/setup.h> | ||
23 | #include "pci.h" | 25 | #include "pci.h" |
24 | 26 | ||
25 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; | 27 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; |
@@ -426,7 +428,6 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
426 | * given PCI device | 428 | * given PCI device |
427 | * @dev: PCI device to handle. | 429 | * @dev: PCI device to handle. |
428 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | 430 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. |
429 | * @wait: If 'true', wait for the device to change its power state | ||
430 | * | 431 | * |
431 | * RETURN VALUE: | 432 | * RETURN VALUE: |
432 | * -EINVAL if the requested state is invalid. | 433 | * -EINVAL if the requested state is invalid. |
@@ -435,12 +436,15 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
435 | * 0 if device already is in the requested state. | 436 | * 0 if device already is in the requested state. |
436 | * 0 if device's power state has been successfully changed. | 437 | * 0 if device's power state has been successfully changed. |
437 | */ | 438 | */ |
438 | static int | 439 | static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) |
439 | pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | ||
440 | { | 440 | { |
441 | u16 pmcsr; | 441 | u16 pmcsr; |
442 | bool need_restore = false; | 442 | bool need_restore = false; |
443 | 443 | ||
444 | /* Check if we're already there */ | ||
445 | if (dev->current_state == state) | ||
446 | return 0; | ||
447 | |||
444 | if (!dev->pm_cap) | 448 | if (!dev->pm_cap) |
445 | return -EIO; | 449 | return -EIO; |
446 | 450 | ||
@@ -451,10 +455,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
451 | * Can enter D0 from any state, but if we can only go deeper | 455 | * Can enter D0 from any state, but if we can only go deeper |
452 | * to sleep if we're already in a low power state | 456 | * to sleep if we're already in a low power state |
453 | */ | 457 | */ |
454 | if (dev->current_state == state) { | 458 | if (state != PCI_D0 && dev->current_state <= PCI_D3cold |
455 | /* we're already there */ | ||
456 | return 0; | ||
457 | } else if (state != PCI_D0 && dev->current_state <= PCI_D3cold | ||
458 | && dev->current_state > state) { | 459 | && dev->current_state > state) { |
459 | dev_err(&dev->dev, "invalid power transition " | 460 | dev_err(&dev->dev, "invalid power transition " |
460 | "(from state %d to %d)\n", dev->current_state, state); | 461 | "(from state %d to %d)\n", dev->current_state, state); |
@@ -481,10 +482,8 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
481 | break; | 482 | break; |
482 | case PCI_UNKNOWN: /* Boot-up */ | 483 | case PCI_UNKNOWN: /* Boot-up */ |
483 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | 484 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot |
484 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { | 485 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) |
485 | need_restore = true; | 486 | need_restore = true; |
486 | wait = true; | ||
487 | } | ||
488 | /* Fall-through: force to D0 */ | 487 | /* Fall-through: force to D0 */ |
489 | default: | 488 | default: |
490 | pmcsr = 0; | 489 | pmcsr = 0; |
@@ -494,9 +493,6 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
494 | /* enter specified state */ | 493 | /* enter specified state */ |
495 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | 494 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); |
496 | 495 | ||
497 | if (!wait) | ||
498 | return 0; | ||
499 | |||
500 | /* Mandatory power management transition delays */ | 496 | /* Mandatory power management transition delays */ |
501 | /* see PCI PM 1.1 5.6.1 table 18 */ | 497 | /* see PCI PM 1.1 5.6.1 table 18 */ |
502 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 498 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
@@ -521,7 +517,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
521 | if (need_restore) | 517 | if (need_restore) |
522 | pci_restore_bars(dev); | 518 | pci_restore_bars(dev); |
523 | 519 | ||
524 | if (wait && dev->bus->self) | 520 | if (dev->bus->self) |
525 | pcie_aspm_pm_state_change(dev->bus->self); | 521 | pcie_aspm_pm_state_change(dev->bus->self); |
526 | 522 | ||
527 | return 0; | 523 | return 0; |
@@ -546,11 +542,58 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state) | |||
546 | } | 542 | } |
547 | 543 | ||
548 | /** | 544 | /** |
545 | * pci_platform_power_transition - Use platform to change device power state | ||
546 | * @dev: PCI device to handle. | ||
547 | * @state: State to put the device into. | ||
548 | */ | ||
549 | static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) | ||
550 | { | ||
551 | int error; | ||
552 | |||
553 | if (platform_pci_power_manageable(dev)) { | ||
554 | error = platform_pci_set_power_state(dev, state); | ||
555 | if (!error) | ||
556 | pci_update_current_state(dev, state); | ||
557 | } else { | ||
558 | error = -ENODEV; | ||
559 | /* Fall back to PCI_D0 if native PM is not supported */ | ||
560 | pci_update_current_state(dev, PCI_D0); | ||
561 | } | ||
562 | |||
563 | return error; | ||
564 | } | ||
565 | |||
566 | /** | ||
567 | * __pci_start_power_transition - Start power transition of a PCI device | ||
568 | * @dev: PCI device to handle. | ||
569 | * @state: State to put the device into. | ||
570 | */ | ||
571 | static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state) | ||
572 | { | ||
573 | if (state == PCI_D0) | ||
574 | pci_platform_power_transition(dev, PCI_D0); | ||
575 | } | ||
576 | |||
577 | /** | ||
578 | * __pci_complete_power_transition - Complete power transition of a PCI device | ||
579 | * @dev: PCI device to handle. | ||
580 | * @state: State to put the device into. | ||
581 | * | ||
582 | * This function should not be called directly by device drivers. | ||
583 | */ | ||
584 | int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state) | ||
585 | { | ||
586 | return state > PCI_D0 ? | ||
587 | pci_platform_power_transition(dev, state) : -EINVAL; | ||
588 | } | ||
589 | EXPORT_SYMBOL_GPL(__pci_complete_power_transition); | ||
590 | |||
591 | /** | ||
549 | * pci_set_power_state - Set the power state of a PCI device | 592 | * pci_set_power_state - Set the power state of a PCI device |
550 | * @dev: PCI device to handle. | 593 | * @dev: PCI device to handle. |
551 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | 594 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. |
552 | * | 595 | * |
553 | * Transition a device to a new power state, using the platform formware and/or | 596 | * Transition a device to a new power state, using the platform firmware and/or |
554 | * the device's PCI PM registers. | 597 | * the device's PCI PM registers. |
555 | * | 598 | * |
556 | * RETURN VALUE: | 599 | * RETURN VALUE: |
@@ -577,30 +620,21 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
577 | */ | 620 | */ |
578 | return 0; | 621 | return 0; |
579 | 622 | ||
580 | if (state == PCI_D0 && platform_pci_power_manageable(dev)) { | 623 | /* Check if we're already there */ |
581 | /* | 624 | if (dev->current_state == state) |
582 | * Allow the platform to change the state, for example via ACPI | 625 | return 0; |
583 | * _PR0, _PS0 and some such, but do not trust it. | 626 | |
584 | */ | 627 | __pci_start_power_transition(dev, state); |
585 | int ret = platform_pci_set_power_state(dev, PCI_D0); | 628 | |
586 | if (!ret) | ||
587 | pci_update_current_state(dev, PCI_D0); | ||
588 | } | ||
589 | /* This device is quirked not to be put into D3, so | 629 | /* This device is quirked not to be put into D3, so |
590 | don't put it in D3 */ | 630 | don't put it in D3 */ |
591 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | 631 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) |
592 | return 0; | 632 | return 0; |
593 | 633 | ||
594 | error = pci_raw_set_power_state(dev, state, true); | 634 | error = pci_raw_set_power_state(dev, state); |
595 | 635 | ||
596 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { | 636 | if (!__pci_complete_power_transition(dev, state)) |
597 | /* Allow the platform to finalize the transition */ | 637 | error = 0; |
598 | int ret = platform_pci_set_power_state(dev, state); | ||
599 | if (!ret) { | ||
600 | pci_update_current_state(dev, state); | ||
601 | error = 0; | ||
602 | } | ||
603 | } | ||
604 | 638 | ||
605 | return error; | 639 | return error; |
606 | } | 640 | } |
@@ -645,6 +679,8 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
645 | 679 | ||
646 | EXPORT_SYMBOL(pci_choose_state); | 680 | EXPORT_SYMBOL(pci_choose_state); |
647 | 681 | ||
682 | #define PCI_EXP_SAVE_REGS 7 | ||
683 | |||
648 | static int pci_save_pcie_state(struct pci_dev *dev) | 684 | static int pci_save_pcie_state(struct pci_dev *dev) |
649 | { | 685 | { |
650 | int pos, i = 0; | 686 | int pos, i = 0; |
@@ -657,7 +693,7 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
657 | 693 | ||
658 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | 694 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); |
659 | if (!save_state) { | 695 | if (!save_state) { |
660 | dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__); | 696 | dev_err(&dev->dev, "buffer not found in %s\n", __func__); |
661 | return -ENOMEM; | 697 | return -ENOMEM; |
662 | } | 698 | } |
663 | cap = (u16 *)&save_state->data[0]; | 699 | cap = (u16 *)&save_state->data[0]; |
@@ -666,6 +702,9 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
666 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); | 702 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); |
667 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | 703 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); |
668 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | 704 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); |
705 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); | ||
706 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); | ||
707 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); | ||
669 | 708 | ||
670 | return 0; | 709 | return 0; |
671 | } | 710 | } |
@@ -686,6 +725,9 @@ static void pci_restore_pcie_state(struct pci_dev *dev) | |||
686 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); | 725 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); |
687 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); | 726 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); |
688 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); | 727 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); |
728 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); | ||
729 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); | ||
730 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); | ||
689 | } | 731 | } |
690 | 732 | ||
691 | 733 | ||
@@ -700,7 +742,7 @@ static int pci_save_pcix_state(struct pci_dev *dev) | |||
700 | 742 | ||
701 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); | 743 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); |
702 | if (!save_state) { | 744 | if (!save_state) { |
703 | dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__); | 745 | dev_err(&dev->dev, "buffer not found in %s\n", __func__); |
704 | return -ENOMEM; | 746 | return -ENOMEM; |
705 | } | 747 | } |
706 | 748 | ||
@@ -773,6 +815,7 @@ pci_restore_state(struct pci_dev *dev) | |||
773 | } | 815 | } |
774 | pci_restore_pcix_state(dev); | 816 | pci_restore_pcix_state(dev); |
775 | pci_restore_msi_state(dev); | 817 | pci_restore_msi_state(dev); |
818 | pci_restore_iov_state(dev); | ||
776 | 819 | ||
777 | return 0; | 820 | return 0; |
778 | } | 821 | } |
@@ -1231,7 +1274,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1231 | if (target_state == PCI_POWER_ERROR) | 1274 | if (target_state == PCI_POWER_ERROR) |
1232 | return -EIO; | 1275 | return -EIO; |
1233 | 1276 | ||
1234 | pci_enable_wake(dev, target_state, true); | 1277 | pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); |
1235 | 1278 | ||
1236 | error = pci_set_power_state(dev, target_state); | 1279 | error = pci_set_power_state(dev, target_state); |
1237 | 1280 | ||
@@ -1369,7 +1412,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1369 | { | 1412 | { |
1370 | int error; | 1413 | int error; |
1371 | 1414 | ||
1372 | error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, 4 * sizeof(u16)); | 1415 | error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, |
1416 | PCI_EXP_SAVE_REGS * sizeof(u16)); | ||
1373 | if (error) | 1417 | if (error) |
1374 | dev_err(&dev->dev, | 1418 | dev_err(&dev->dev, |
1375 | "unable to preallocate PCI Express save buffer\n"); | 1419 | "unable to preallocate PCI Express save buffer\n"); |
@@ -1381,50 +1425,6 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1381 | } | 1425 | } |
1382 | 1426 | ||
1383 | /** | 1427 | /** |
1384 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
1385 | * @dev: PCI device to handle | ||
1386 | * | ||
1387 | * This function assumes that the device's configuration space is accessible. | ||
1388 | * If the device needs to be powered up, the function will wait for it to | ||
1389 | * change the state. | ||
1390 | */ | ||
1391 | int pci_restore_standard_config(struct pci_dev *dev) | ||
1392 | { | ||
1393 | pci_power_t prev_state; | ||
1394 | int error; | ||
1395 | |||
1396 | pci_update_current_state(dev, PCI_D0); | ||
1397 | |||
1398 | prev_state = dev->current_state; | ||
1399 | if (prev_state == PCI_D0) | ||
1400 | goto Restore; | ||
1401 | |||
1402 | error = pci_raw_set_power_state(dev, PCI_D0, false); | ||
1403 | if (error) | ||
1404 | return error; | ||
1405 | |||
1406 | /* | ||
1407 | * This assumes that we won't get a bus in B2 or B3 from the BIOS, but | ||
1408 | * we've made this assumption forever and it appears to be universally | ||
1409 | * satisfied. | ||
1410 | */ | ||
1411 | switch(prev_state) { | ||
1412 | case PCI_D3cold: | ||
1413 | case PCI_D3hot: | ||
1414 | mdelay(pci_pm_d3_delay); | ||
1415 | break; | ||
1416 | case PCI_D2: | ||
1417 | udelay(PCI_PM_D2_DELAY); | ||
1418 | break; | ||
1419 | } | ||
1420 | |||
1421 | pci_update_current_state(dev, PCI_D0); | ||
1422 | |||
1423 | Restore: | ||
1424 | return dev->state_saved ? pci_restore_state(dev) : 0; | ||
1425 | } | ||
1426 | |||
1427 | /** | ||
1428 | * pci_enable_ari - enable ARI forwarding if hardware support it | 1428 | * pci_enable_ari - enable ARI forwarding if hardware support it |
1429 | * @dev: the PCI device | 1429 | * @dev: the PCI device |
1430 | */ | 1430 | */ |
@@ -1484,7 +1484,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) | |||
1484 | if (!pin) | 1484 | if (!pin) |
1485 | return -1; | 1485 | return -1; |
1486 | 1486 | ||
1487 | while (dev->bus->self) { | 1487 | while (dev->bus->parent) { |
1488 | pin = pci_swizzle_interrupt_pin(dev, pin); | 1488 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1489 | dev = dev->bus->self; | 1489 | dev = dev->bus->self; |
1490 | } | 1490 | } |
@@ -1504,7 +1504,7 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp) | |||
1504 | { | 1504 | { |
1505 | u8 pin = *pinp; | 1505 | u8 pin = *pinp; |
1506 | 1506 | ||
1507 | while (dev->bus->self) { | 1507 | while (dev->bus->parent) { |
1508 | pin = pci_swizzle_interrupt_pin(dev, pin); | 1508 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1509 | dev = dev->bus->self; | 1509 | dev = dev->bus->self; |
1510 | } | 1510 | } |
@@ -2028,18 +2028,24 @@ static int __pcie_flr(struct pci_dev *dev, int probe) | |||
2028 | pci_block_user_cfg_access(dev); | 2028 | pci_block_user_cfg_access(dev); |
2029 | 2029 | ||
2030 | /* Wait for Transaction Pending bit clean */ | 2030 | /* Wait for Transaction Pending bit clean */ |
2031 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | ||
2032 | if (!(status & PCI_EXP_DEVSTA_TRPND)) | ||
2033 | goto transaction_done; | ||
2034 | |||
2031 | msleep(100); | 2035 | msleep(100); |
2032 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | 2036 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); |
2033 | if (status & PCI_EXP_DEVSTA_TRPND) { | 2037 | if (!(status & PCI_EXP_DEVSTA_TRPND)) |
2034 | dev_info(&dev->dev, "Busy after 100ms while trying to reset; " | 2038 | goto transaction_done; |
2039 | |||
2040 | dev_info(&dev->dev, "Busy after 100ms while trying to reset; " | ||
2035 | "sleeping for 1 second\n"); | 2041 | "sleeping for 1 second\n"); |
2036 | ssleep(1); | 2042 | ssleep(1); |
2037 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | 2043 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); |
2038 | if (status & PCI_EXP_DEVSTA_TRPND) | 2044 | if (status & PCI_EXP_DEVSTA_TRPND) |
2039 | dev_info(&dev->dev, "Still busy after 1s; " | 2045 | dev_info(&dev->dev, "Still busy after 1s; " |
2040 | "proceeding with reset anyway\n"); | 2046 | "proceeding with reset anyway\n"); |
2041 | } | ||
2042 | 2047 | ||
2048 | transaction_done: | ||
2043 | pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL, | 2049 | pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL, |
2044 | PCI_EXP_DEVCTL_BCR_FLR); | 2050 | PCI_EXP_DEVCTL_BCR_FLR); |
2045 | mdelay(100); | 2051 | mdelay(100); |
@@ -2066,18 +2072,24 @@ static int __pci_af_flr(struct pci_dev *dev, int probe) | |||
2066 | pci_block_user_cfg_access(dev); | 2072 | pci_block_user_cfg_access(dev); |
2067 | 2073 | ||
2068 | /* Wait for Transaction Pending bit clean */ | 2074 | /* Wait for Transaction Pending bit clean */ |
2075 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); | ||
2076 | if (!(status & PCI_AF_STATUS_TP)) | ||
2077 | goto transaction_done; | ||
2078 | |||
2069 | msleep(100); | 2079 | msleep(100); |
2070 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); | 2080 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); |
2071 | if (status & PCI_AF_STATUS_TP) { | 2081 | if (!(status & PCI_AF_STATUS_TP)) |
2072 | dev_info(&dev->dev, "Busy after 100ms while trying to" | 2082 | goto transaction_done; |
2073 | " reset; sleeping for 1 second\n"); | 2083 | |
2074 | ssleep(1); | 2084 | dev_info(&dev->dev, "Busy after 100ms while trying to" |
2075 | pci_read_config_byte(dev, | 2085 | " reset; sleeping for 1 second\n"); |
2076 | cappos + PCI_AF_STATUS, &status); | 2086 | ssleep(1); |
2077 | if (status & PCI_AF_STATUS_TP) | 2087 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); |
2078 | dev_info(&dev->dev, "Still busy after 1s; " | 2088 | if (status & PCI_AF_STATUS_TP) |
2079 | "proceeding with reset anyway\n"); | 2089 | dev_info(&dev->dev, "Still busy after 1s; " |
2080 | } | 2090 | "proceeding with reset anyway\n"); |
2091 | |||
2092 | transaction_done: | ||
2081 | pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); | 2093 | pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); |
2082 | mdelay(100); | 2094 | mdelay(100); |
2083 | 2095 | ||
@@ -2346,18 +2358,140 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags) | |||
2346 | */ | 2358 | */ |
2347 | int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) | 2359 | int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) |
2348 | { | 2360 | { |
2361 | int reg; | ||
2362 | |||
2349 | if (resno < PCI_ROM_RESOURCE) { | 2363 | if (resno < PCI_ROM_RESOURCE) { |
2350 | *type = pci_bar_unknown; | 2364 | *type = pci_bar_unknown; |
2351 | return PCI_BASE_ADDRESS_0 + 4 * resno; | 2365 | return PCI_BASE_ADDRESS_0 + 4 * resno; |
2352 | } else if (resno == PCI_ROM_RESOURCE) { | 2366 | } else if (resno == PCI_ROM_RESOURCE) { |
2353 | *type = pci_bar_mem32; | 2367 | *type = pci_bar_mem32; |
2354 | return dev->rom_base_reg; | 2368 | return dev->rom_base_reg; |
2369 | } else if (resno < PCI_BRIDGE_RESOURCES) { | ||
2370 | /* device specific resource */ | ||
2371 | reg = pci_iov_resource_bar(dev, resno, type); | ||
2372 | if (reg) | ||
2373 | return reg; | ||
2355 | } | 2374 | } |
2356 | 2375 | ||
2357 | dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); | 2376 | dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); |
2358 | return 0; | 2377 | return 0; |
2359 | } | 2378 | } |
2360 | 2379 | ||
2380 | #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE | ||
2381 | static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; | ||
2382 | spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; | ||
2383 | |||
2384 | /** | ||
2385 | * pci_specified_resource_alignment - get resource alignment specified by user. | ||
2386 | * @dev: the PCI device to get | ||
2387 | * | ||
2388 | * RETURNS: Resource alignment if it is specified. | ||
2389 | * Zero if it is not specified. | ||
2390 | */ | ||
2391 | resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) | ||
2392 | { | ||
2393 | int seg, bus, slot, func, align_order, count; | ||
2394 | resource_size_t align = 0; | ||
2395 | char *p; | ||
2396 | |||
2397 | spin_lock(&resource_alignment_lock); | ||
2398 | p = resource_alignment_param; | ||
2399 | while (*p) { | ||
2400 | count = 0; | ||
2401 | if (sscanf(p, "%d%n", &align_order, &count) == 1 && | ||
2402 | p[count] == '@') { | ||
2403 | p += count + 1; | ||
2404 | } else { | ||
2405 | align_order = -1; | ||
2406 | } | ||
2407 | if (sscanf(p, "%x:%x:%x.%x%n", | ||
2408 | &seg, &bus, &slot, &func, &count) != 4) { | ||
2409 | seg = 0; | ||
2410 | if (sscanf(p, "%x:%x.%x%n", | ||
2411 | &bus, &slot, &func, &count) != 3) { | ||
2412 | /* Invalid format */ | ||
2413 | printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n", | ||
2414 | p); | ||
2415 | break; | ||
2416 | } | ||
2417 | } | ||
2418 | p += count; | ||
2419 | if (seg == pci_domain_nr(dev->bus) && | ||
2420 | bus == dev->bus->number && | ||
2421 | slot == PCI_SLOT(dev->devfn) && | ||
2422 | func == PCI_FUNC(dev->devfn)) { | ||
2423 | if (align_order == -1) { | ||
2424 | align = PAGE_SIZE; | ||
2425 | } else { | ||
2426 | align = 1 << align_order; | ||
2427 | } | ||
2428 | /* Found */ | ||
2429 | break; | ||
2430 | } | ||
2431 | if (*p != ';' && *p != ',') { | ||
2432 | /* End of param or invalid format */ | ||
2433 | break; | ||
2434 | } | ||
2435 | p++; | ||
2436 | } | ||
2437 | spin_unlock(&resource_alignment_lock); | ||
2438 | return align; | ||
2439 | } | ||
2440 | |||
2441 | /** | ||
2442 | * pci_is_reassigndev - check if specified PCI is target device to reassign | ||
2443 | * @dev: the PCI device to check | ||
2444 | * | ||
2445 | * RETURNS: non-zero for PCI device is a target device to reassign, | ||
2446 | * or zero is not. | ||
2447 | */ | ||
2448 | int pci_is_reassigndev(struct pci_dev *dev) | ||
2449 | { | ||
2450 | return (pci_specified_resource_alignment(dev) != 0); | ||
2451 | } | ||
2452 | |||
2453 | ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) | ||
2454 | { | ||
2455 | if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) | ||
2456 | count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1; | ||
2457 | spin_lock(&resource_alignment_lock); | ||
2458 | strncpy(resource_alignment_param, buf, count); | ||
2459 | resource_alignment_param[count] = '\0'; | ||
2460 | spin_unlock(&resource_alignment_lock); | ||
2461 | return count; | ||
2462 | } | ||
2463 | |||
2464 | ssize_t pci_get_resource_alignment_param(char *buf, size_t size) | ||
2465 | { | ||
2466 | size_t count; | ||
2467 | spin_lock(&resource_alignment_lock); | ||
2468 | count = snprintf(buf, size, "%s", resource_alignment_param); | ||
2469 | spin_unlock(&resource_alignment_lock); | ||
2470 | return count; | ||
2471 | } | ||
2472 | |||
2473 | static ssize_t pci_resource_alignment_show(struct bus_type *bus, char *buf) | ||
2474 | { | ||
2475 | return pci_get_resource_alignment_param(buf, PAGE_SIZE); | ||
2476 | } | ||
2477 | |||
2478 | static ssize_t pci_resource_alignment_store(struct bus_type *bus, | ||
2479 | const char *buf, size_t count) | ||
2480 | { | ||
2481 | return pci_set_resource_alignment_param(buf, count); | ||
2482 | } | ||
2483 | |||
2484 | BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show, | ||
2485 | pci_resource_alignment_store); | ||
2486 | |||
2487 | static int __init pci_resource_alignment_sysfs_init(void) | ||
2488 | { | ||
2489 | return bus_create_file(&pci_bus_type, | ||
2490 | &bus_attr_resource_alignment); | ||
2491 | } | ||
2492 | |||
2493 | late_initcall(pci_resource_alignment_sysfs_init); | ||
2494 | |||
2361 | static void __devinit pci_no_domains(void) | 2495 | static void __devinit pci_no_domains(void) |
2362 | { | 2496 | { |
2363 | #ifdef CONFIG_PCI_DOMAINS | 2497 | #ifdef CONFIG_PCI_DOMAINS |
@@ -2406,6 +2540,9 @@ static int __init pci_setup(char *str) | |||
2406 | pci_cardbus_io_size = memparse(str + 9, &str); | 2540 | pci_cardbus_io_size = memparse(str + 9, &str); |
2407 | } else if (!strncmp(str, "cbmemsize=", 10)) { | 2541 | } else if (!strncmp(str, "cbmemsize=", 10)) { |
2408 | pci_cardbus_mem_size = memparse(str + 10, &str); | 2542 | pci_cardbus_mem_size = memparse(str + 10, &str); |
2543 | } else if (!strncmp(str, "resource_alignment=", 19)) { | ||
2544 | pci_set_resource_alignment_param(str + 19, | ||
2545 | strlen(str + 19)); | ||
2409 | } else { | 2546 | } else { |
2410 | printk(KERN_ERR "PCI: Unknown option `%s'\n", | 2547 | printk(KERN_ERR "PCI: Unknown option `%s'\n", |
2411 | str); | 2548 | str); |