diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 0884bedcfc7a..cd3f748b761e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -31,6 +31,25 @@ int pci_msi_ignore_mask; #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) +static bool is_nvme(struct device *dev) +{ + bool ret = false; + u32 i; + char *dev_names[] = { + "0000:02:00.0", + }; + const char *name = dev_name(dev); + + for (i = 0; i < 1; i++) { + if (!strncmp(dev_names[i], name, strlen(dev_names[i]))) { + ret = true; + break; + } + } + + return ret; +} + #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { @@ -206,7 +225,7 @@ static void __iomem *pci_msix_desc_addr(struct msi_desc *desc) * file. This saves a few milliseconds when initialising devices with lots * of MSI-X interrupts. */ -u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag) +u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag, u8 restore) { u32 mask_bits = desc->masked; void __iomem *desc_addr; @@ -218,17 +237,27 @@ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag) return 0; mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; - if (flag) - mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; - + if (flag) { + if(is_nvme(desc->dev) && restore) { + dev_err(desc->dev, "%s: 0x%02lx origianl value 0x%08x, going to write 0x%08x. However, %s is nvme, so skip\n", + __func__, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL - desc->mask_base, readl(desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL), + mask_bits | PCI_MSIX_ENTRY_CTRL_MASKBIT, dev_name(desc->dev)); + } + else { + mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; + } + } writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); return mask_bits; } -static void msix_mask_irq(struct msi_desc *desc, u32 flag) +static void msix_mask_irq(struct msi_desc *desc, u32 flag, u8 restore) { - desc->masked = __pci_msix_desc_mask_irq(desc, flag); + desc->masked = __pci_msix_desc_mask_irq(desc, flag, restore); + if (is_nvme(desc->dev)) { + dev_err(desc->dev, "%s: %s called with flag is %s, new masked value is 0x%08x\n", __func__, dev_name(desc->dev), flag ? "True" : "False", desc->masked); + } } static void msi_set_mask_bit(struct irq_data *data, u32 flag) @@ -236,7 +265,7 @@ static void msi_set_mask_bit(struct irq_data *data, u32 flag) struct msi_desc *desc = irq_data_get_msi_desc(data); if (desc->msi_attrib.is_msix) { - msix_mask_irq(desc, flag); + msix_mask_irq(desc, flag, 0); readl(desc->mask_base); /* Flush write to device */ } else { unsigned offset = data->irq - desc->irq; @@ -445,8 +474,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) arch_restore_msi_irqs(dev); for_each_pci_msi_entry(entry, dev) - msix_mask_irq(entry, entry->masked); - + msix_mask_irq(entry, entry->masked, 1); pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); } @@ -755,7 +783,7 @@ static void msix_program_entries(struct pci_dev *dev, else entry->masked = 0; - msix_mask_irq(entry, 1); + msix_mask_irq(entry, 1, 0); } } @@ -1016,7 +1044,7 @@ static void pci_msix_shutdown(struct pci_dev *dev) /* Return the device with MSI-X masked as initial states */ for_each_pci_msi_entry(entry, dev) { /* Keep cached states to be restored */ - __pci_msix_desc_mask_irq(entry, 1); + __pci_msix_desc_mask_irq(entry, 1, 0); } pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); diff --git a/include/linux/msi.h b/include/linux/msi.h index 8ad679e9d9c0..1ae95072b299 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -187,7 +187,7 @@ void free_msi_entry(struct msi_desc *entry); void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); -u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag); +u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag, u8 restore); u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag); void pci_msi_mask_irq(struct irq_data *data); void pci_msi_unmask_irq(struct irq_data *data);