diff options
author | Shaohua Li <shaohua.li@intel.com> | 2006-05-25 22:58:27 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-21 15:00:00 -0400 |
commit | 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c (patch) | |
tree | 4798f39176d0f8fe06de446d74cf94ba48423aa9 /drivers/pci | |
parent | 020d502488bebdbc1b2c2828d996f04e563f082a (diff) |
[PATCH] PCI: disable msi mode in pci_disable_device
Brice said the pci_save_msi_state breaks his driver in his special usage
(not in suspend/resume), as pci_save_msi_state will disable msi mode. In
his usage, pci_save_state will be called at runtime, and later (after
the device operates for some time and has an error) pci_restore_state
will be called.
In another hand, suspend/resume needs disable msi mode, as device should
stop working completely. This patch try to workaround this issue.
Drivers are expected call pci_disable_device in suspend time after
pci_save_state.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/msi.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 9 |
2 files changed, 12 insertions, 3 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9c69b6966e79..3ec558dc6523 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -453,9 +453,11 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
453 | /* Set enabled bits to single MSI & enable MSI_enable bit */ | 453 | /* Set enabled bits to single MSI & enable MSI_enable bit */ |
454 | msi_enable(control, 1); | 454 | msi_enable(control, 1); |
455 | pci_write_config_word(dev, msi_control_reg(pos), control); | 455 | pci_write_config_word(dev, msi_control_reg(pos), control); |
456 | dev->msi_enabled = 1; | ||
456 | } else { | 457 | } else { |
457 | msix_enable(control); | 458 | msix_enable(control); |
458 | pci_write_config_word(dev, msi_control_reg(pos), control); | 459 | pci_write_config_word(dev, msi_control_reg(pos), control); |
460 | dev->msix_enabled = 1; | ||
459 | } | 461 | } |
460 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { | 462 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { |
461 | /* PCI Express Endpoint device detected */ | 463 | /* PCI Express Endpoint device detected */ |
@@ -472,9 +474,11 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
472 | /* Set enabled bits to single MSI & enable MSI_enable bit */ | 474 | /* Set enabled bits to single MSI & enable MSI_enable bit */ |
473 | msi_disable(control); | 475 | msi_disable(control); |
474 | pci_write_config_word(dev, msi_control_reg(pos), control); | 476 | pci_write_config_word(dev, msi_control_reg(pos), control); |
477 | dev->msi_enabled = 0; | ||
475 | } else { | 478 | } else { |
476 | msix_disable(control); | 479 | msix_disable(control); |
477 | pci_write_config_word(dev, msi_control_reg(pos), control); | 480 | pci_write_config_word(dev, msi_control_reg(pos), control); |
481 | dev->msix_enabled = 0; | ||
478 | } | 482 | } |
479 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { | 483 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { |
480 | /* PCI Express Endpoint device detected */ | 484 | /* PCI Express Endpoint device detected */ |
@@ -549,7 +553,6 @@ int pci_save_msi_state(struct pci_dev *dev) | |||
549 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); | 553 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); |
550 | if (control & PCI_MSI_FLAGS_MASKBIT) | 554 | if (control & PCI_MSI_FLAGS_MASKBIT) |
551 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); | 555 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); |
552 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | ||
553 | save_state->cap_nr = PCI_CAP_ID_MSI; | 556 | save_state->cap_nr = PCI_CAP_ID_MSI; |
554 | pci_add_saved_cap(dev, save_state); | 557 | pci_add_saved_cap(dev, save_state); |
555 | return 0; | 558 | return 0; |
@@ -639,7 +642,6 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
639 | } | 642 | } |
640 | dev->irq = temp; | 643 | dev->irq = temp; |
641 | 644 | ||
642 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | ||
643 | save_state->cap_nr = PCI_CAP_ID_MSIX; | 645 | save_state->cap_nr = PCI_CAP_ID_MSIX; |
644 | pci_add_saved_cap(dev, save_state); | 646 | pci_add_saved_cap(dev, save_state); |
645 | return 0; | 647 | return 0; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index aa480370ef10..d408a3c30426 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -551,7 +551,14 @@ void | |||
551 | pci_disable_device(struct pci_dev *dev) | 551 | pci_disable_device(struct pci_dev *dev) |
552 | { | 552 | { |
553 | u16 pci_command; | 553 | u16 pci_command; |
554 | 554 | ||
555 | if (dev->msi_enabled) | ||
556 | disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), | ||
557 | PCI_CAP_ID_MSI); | ||
558 | if (dev->msix_enabled) | ||
559 | disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), | ||
560 | PCI_CAP_ID_MSIX); | ||
561 | |||
555 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); | 562 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); |
556 | if (pci_command & PCI_COMMAND_MASTER) { | 563 | if (pci_command & PCI_COMMAND_MASTER) { |
557 | pci_command &= ~PCI_COMMAND_MASTER; | 564 | pci_command &= ~PCI_COMMAND_MASTER; |