diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-04 05:16:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:27 -0400 |
| commit | 0366f8f7137deb072991e4c50769c6da31f8940c (patch) | |
| tree | 11cb801b0fe9bc1742f1c47716a7d815b9d98dee | |
| parent | dd159eeca971d594fa30176733b66d37acda82a3 (diff) | |
[PATCH] genirq: msi: implement helper functions read_msi_msg and write_msi_msg
In support of this I also add a struct msi_msg that captures the the two
address and one data field ina typical msi message, and I remember the pos and
if the address is 64bit in struct msi_desc.
This makes the code a little more readable and easier to maintain, and paves
the way to further simplfications.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rajesh Shah <rajesh.shah@intel.com>
Cc: Andi Kleen <ak@muc.de>
Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/pci/msi.c | 195 | ||||
| -rw-r--r-- | drivers/pci/msi.h | 9 | ||||
| -rw-r--r-- | include/linux/pci.h | 6 |
3 files changed, 104 insertions, 106 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 75d1c0dacffa..cca6cb3ccdac 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -87,63 +87,100 @@ static void msi_set_mask_bit(unsigned int vector, int flag) | |||
| 87 | } | 87 | } |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | #ifdef CONFIG_SMP | 90 | static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
| 91 | static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | ||
| 92 | { | 91 | { |
| 93 | struct msi_desc *entry; | 92 | switch(entry->msi_attrib.type) { |
| 94 | u32 address_hi, address_lo; | 93 | case PCI_CAP_ID_MSI: |
| 95 | unsigned int irq = vector; | 94 | { |
| 96 | unsigned int dest_cpu = first_cpu(cpu_mask); | 95 | struct pci_dev *dev = entry->dev; |
| 97 | 96 | int pos = entry->msi_attrib.pos; | |
| 98 | entry = (struct msi_desc *)msi_desc[vector]; | 97 | u16 data; |
| 99 | if (!entry || !entry->dev) | 98 | |
| 100 | return; | 99 | pci_read_config_dword(dev, msi_lower_address_reg(pos), |
| 100 | &msg->address_lo); | ||
| 101 | if (entry->msi_attrib.is_64) { | ||
| 102 | pci_read_config_dword(dev, msi_upper_address_reg(pos), | ||
| 103 | &msg->address_hi); | ||
| 104 | pci_read_config_word(dev, msi_data_reg(pos, 1), &data); | ||
| 105 | } else { | ||
| 106 | msg->address_hi = 0; | ||
| 107 | pci_read_config_word(dev, msi_data_reg(pos, 1), &data); | ||
| 108 | } | ||
| 109 | msg->data = data; | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | case PCI_CAP_ID_MSIX: | ||
| 113 | { | ||
| 114 | void __iomem *base; | ||
| 115 | base = entry->mask_base + | ||
| 116 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
| 117 | |||
| 118 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
| 119 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
| 120 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | default: | ||
| 124 | BUG(); | ||
| 125 | } | ||
| 126 | } | ||
| 101 | 127 | ||
| 128 | static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | ||
| 129 | { | ||
| 102 | switch (entry->msi_attrib.type) { | 130 | switch (entry->msi_attrib.type) { |
| 103 | case PCI_CAP_ID_MSI: | 131 | case PCI_CAP_ID_MSI: |
| 104 | { | 132 | { |
| 105 | int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI); | 133 | struct pci_dev *dev = entry->dev; |
| 106 | 134 | int pos = entry->msi_attrib.pos; | |
| 107 | if (!pos) | 135 | |
| 108 | return; | 136 | pci_write_config_dword(dev, msi_lower_address_reg(pos), |
| 109 | 137 | msg->address_lo); | |
| 110 | pci_read_config_dword(entry->dev, msi_upper_address_reg(pos), | 138 | if (entry->msi_attrib.is_64) { |
| 111 | &address_hi); | 139 | pci_write_config_dword(dev, msi_upper_address_reg(pos), |
| 112 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), | 140 | msg->address_hi); |
| 113 | &address_lo); | 141 | pci_write_config_word(dev, msi_data_reg(pos, 1), |
| 114 | 142 | msg->data); | |
| 115 | msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); | 143 | } else { |
| 116 | 144 | pci_write_config_word(dev, msi_data_reg(pos, 0), | |
| 117 | pci_write_config_dword(entry->dev, msi_upper_address_reg(pos), | 145 | msg->data); |
| 118 | address_hi); | 146 | } |
| 119 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), | ||
| 120 | address_lo); | ||
| 121 | set_native_irq_info(irq, cpu_mask); | ||
| 122 | break; | 147 | break; |
| 123 | } | 148 | } |
| 124 | case PCI_CAP_ID_MSIX: | 149 | case PCI_CAP_ID_MSIX: |
| 125 | { | 150 | { |
| 126 | int offset_hi = | 151 | void __iomem *base; |
| 127 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 152 | base = entry->mask_base + |
| 128 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET; | 153 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
| 129 | int offset_lo = | 154 | |
| 130 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 155 | writel(msg->address_lo, |
| 131 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; | 156 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); |
| 132 | 157 | writel(msg->address_hi, | |
| 133 | address_hi = readl(entry->mask_base + offset_hi); | 158 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); |
| 134 | address_lo = readl(entry->mask_base + offset_lo); | 159 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); |
| 135 | |||
| 136 | msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); | ||
| 137 | |||
| 138 | writel(address_hi, entry->mask_base + offset_hi); | ||
| 139 | writel(address_lo, entry->mask_base + offset_lo); | ||
| 140 | set_native_irq_info(irq, cpu_mask); | ||
| 141 | break; | 160 | break; |
| 142 | } | 161 | } |
| 143 | default: | 162 | default: |
| 144 | break; | 163 | BUG(); |
| 145 | } | 164 | } |
| 146 | } | 165 | } |
| 166 | |||
| 167 | #ifdef CONFIG_SMP | ||
| 168 | static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | ||
| 169 | { | ||
| 170 | struct msi_desc *entry; | ||
| 171 | struct msi_msg msg; | ||
| 172 | unsigned int irq = vector; | ||
| 173 | unsigned int dest_cpu = first_cpu(cpu_mask); | ||
| 174 | |||
| 175 | entry = (struct msi_desc *)msi_desc[vector]; | ||
| 176 | if (!entry || !entry->dev) | ||
| 177 | return; | ||
| 178 | |||
| 179 | read_msi_msg(entry, &msg); | ||
| 180 | msi_ops->target(vector, dest_cpu, &msg.address_hi, &msg.address_lo); | ||
| 181 | write_msi_msg(entry, &msg); | ||
| 182 | set_native_irq_info(irq, cpu_mask); | ||
| 183 | } | ||
| 147 | #else | 184 | #else |
| 148 | #define set_msi_affinity NULL | 185 | #define set_msi_affinity NULL |
| 149 | #endif /* CONFIG_SMP */ | 186 | #endif /* CONFIG_SMP */ |
| @@ -606,23 +643,10 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
| 606 | 643 | ||
| 607 | vector = head = dev->irq; | 644 | vector = head = dev->irq; |
| 608 | while (head != tail) { | 645 | while (head != tail) { |
| 609 | int j; | ||
| 610 | void __iomem *base; | ||
| 611 | struct msi_desc *entry; | 646 | struct msi_desc *entry; |
| 612 | 647 | ||
| 613 | entry = msi_desc[vector]; | 648 | entry = msi_desc[vector]; |
| 614 | base = entry->mask_base; | 649 | read_msi_msg(entry, &entry->msg_save); |
| 615 | j = entry->msi_attrib.entry_nr; | ||
| 616 | |||
| 617 | entry->address_lo_save = | ||
| 618 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
| 619 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
| 620 | entry->address_hi_save = | ||
| 621 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
| 622 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
| 623 | entry->data_save = | ||
| 624 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
| 625 | PCI_MSIX_ENTRY_DATA_OFFSET); | ||
| 626 | 650 | ||
| 627 | tail = msi_desc[vector]->link.tail; | 651 | tail = msi_desc[vector]->link.tail; |
| 628 | vector = tail; | 652 | vector = tail; |
| @@ -639,8 +663,6 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
| 639 | u16 save; | 663 | u16 save; |
| 640 | int pos; | 664 | int pos; |
| 641 | int vector, head, tail = 0; | 665 | int vector, head, tail = 0; |
| 642 | void __iomem *base; | ||
| 643 | int j; | ||
| 644 | struct msi_desc *entry; | 666 | struct msi_desc *entry; |
| 645 | int temp; | 667 | int temp; |
| 646 | struct pci_cap_saved_state *save_state; | 668 | struct pci_cap_saved_state *save_state; |
| @@ -663,18 +685,7 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
| 663 | vector = head = dev->irq; | 685 | vector = head = dev->irq; |
| 664 | while (head != tail) { | 686 | while (head != tail) { |
| 665 | entry = msi_desc[vector]; | 687 | entry = msi_desc[vector]; |
| 666 | base = entry->mask_base; | 688 | write_msi_msg(entry, &entry->msg_save); |
| 667 | j = entry->msi_attrib.entry_nr; | ||
| 668 | |||
| 669 | writel(entry->address_lo_save, | ||
| 670 | base + j * PCI_MSIX_ENTRY_SIZE + | ||
| 671 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
| 672 | writel(entry->address_hi_save, | ||
| 673 | |||
