aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:33 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:27 -0400
commit0366f8f7137deb072991e4c50769c6da31f8940c (patch)
tree11cb801b0fe9bc1742f1c47716a7d815b9d98dee
parentdd159eeca971d594fa30176733b66d37acda82a3 (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.c195
-rw-r--r--drivers/pci/msi.h9
-rw-r--r--include/linux/pci.h6
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 90static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
91static 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
128static 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
168static 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