Hi,
It appears pci_enable_msi doesn't reconfigure msi registers if it
successfully look up a msi for a device. It assumes the data and address
registers unchanged after calling pci_disable_msi. But this isn't always
true, such as in a suspend/resume circle. In my test system, the
registers unsurprised become zero after a S3 resume. This patch fixes my
problem, please look at it. MSIX might have the same issue, but I
haven't taken a close look.

Thanks,
Shaohua
---

 linux-2.6.13-rc6-root/drivers/pci/msi.c |   72 +++++++++++++++++++-------------
 1 files changed, 43 insertions(+), 29 deletions(-)

diff -puN drivers/pci/msi.c~pci-msi drivers/pci/msi.c
--- linux-2.6.13-rc6/drivers/pci/msi.c~pci-msi  2005-08-18 12:58:45.032124008 
+0800
+++ linux-2.6.13-rc6-root/drivers/pci/msi.c     2005-08-18 13:06:02.080682528 
+0800
@@ -508,6 +508,45 @@ void pci_scan_msi_device(struct pci_dev 
                nr_reserved_vectors++;
 }
 
+static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
+{
+       struct msg_address address;
+       struct msg_data data;
+       int pos, vector = dev->irq;
+       u16 control;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       pci_read_config_word(dev, msi_control_reg(pos), &control);
+       /* Configure MSI capability structure */
+       msi_address_init(&address);
+       msi_data_init(&data, vector);
+       entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+                               MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+       pci_write_config_dword(dev, msi_lower_address_reg(pos),
+                       address.lo_address.value);
+       if (is_64bit_address(control)) {
+               pci_write_config_dword(dev,
+                       msi_upper_address_reg(pos), address.hi_address);
+               pci_write_config_word(dev,
+                       msi_data_reg(pos, 1), *((u32*)&data));
+       } else
+               pci_write_config_word(dev,
+                       msi_data_reg(pos, 0), *((u32*)&data));
+       if (entry->msi_attrib.maskbit) {
+               unsigned int maskbits, temp;
+               /* All MSIs are unmasked by default, Mask them all */
+               pci_read_config_dword(dev,
+                       msi_mask_bits_reg(pos, is_64bit_address(control)),
+                       &maskbits);
+               temp = (1 << multi_msi_capable(control));
+               temp = ((temp - 1) & ~temp);
+               maskbits |= temp;
+               pci_write_config_dword(dev,
+                       msi_mask_bits_reg(pos, is_64bit_address(control)),
+                       maskbits);
+       }
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -520,8 +559,6 @@ void pci_scan_msi_device(struct pci_dev 
 static int msi_capability_init(struct pci_dev *dev)
 {
        struct msi_desc *entry;
-       struct msg_address address;
-       struct msg_data data;
        int pos, vector;
        u16 control;
 
@@ -551,33 +588,8 @@ static int msi_capability_init(struct pc
        /* Replace with MSI handler */
        irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
        /* Configure MSI capability structure */
-       msi_address_init(&address);
-       msi_data_init(&data, vector);
-       entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
-                               MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
-       pci_write_config_dword(dev, msi_lower_address_reg(pos),
-                       address.lo_address.value);
-       if (is_64bit_address(control)) {
-               pci_write_config_dword(dev,
-                       msi_upper_address_reg(pos), address.hi_address);
-               pci_write_config_word(dev,
-                       msi_data_reg(pos, 1), *((u32*)&data));
-       } else
-               pci_write_config_word(dev,
-                       msi_data_reg(pos, 0), *((u32*)&data));
-       if (entry->msi_attrib.maskbit) {
-               unsigned int maskbits, temp;
-               /* All MSIs are unmasked by default, Mask them all */
-               pci_read_config_dword(dev,
-                       msi_mask_bits_reg(pos, is_64bit_address(control)),
-                       &maskbits);
-               temp = (1 << multi_msi_capable(control));
-               temp = ((temp - 1) & ~temp);
-               maskbits |= temp;
-               pci_write_config_dword(dev,
-                       msi_mask_bits_reg(pos, is_64bit_address(control)),
-                       maskbits);
-       }
+       msi_register_init(dev, entry);
+
        attach_msi_entry(entry, vector);
        /* Set MSI enabled bits  */
        enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
@@ -721,6 +733,8 @@ int pci_enable_msi(struct pci_dev* dev)
                        vector_irq[dev->irq] = -1;
                        nr_released_vectors--;
                        spin_unlock_irqrestore(&msi_lock, flags);
+
+                       msi_register_init(dev, msi_desc[dev->irq]);
                        enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
                        return 0;
                }
_


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to