aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2009-03-17 08:54:06 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-20 13:48:12 -0400
commit24d27553390c69d11cdbd930d635193956fc295f (patch)
tree1ed673378c02eba46e6f427e1ab2ca06558f9045
parentc41ade2ee1dc146d2de2ee470a87cd6b878a08f4 (diff)
PCI MSI: Replace 'type' with 'is_msix'
By changing from a 5-bit field to a 1-bit field, we free up some bits that can be used by a later patch. Also rearrange the fields for better packing on 64-bit platforms (reducing the size of msi_desc from 72 bytes to 64 bytes). Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/msi.c115
-rw-r--r--include/linux/msi.h4
2 files changed, 41 insertions, 78 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index dceea56f7342..b3db4388f974 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -111,20 +111,10 @@ static void msix_flush_writes(struct irq_desc *desc)
111 111
112 entry = get_irq_desc_msi(desc); 112 entry = get_irq_desc_msi(desc);
113 BUG_ON(!entry || !entry->dev); 113 BUG_ON(!entry || !entry->dev);
114 switch (entry->msi_attrib.type) { 114 if (entry->msi_attrib.is_msix) {
115 case PCI_CAP_ID_MSI:
116 /* nothing to do */
117 break;
118 case PCI_CAP_ID_MSIX:
119 {
120 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + 115 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
121 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; 116 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
122 readl(entry->mask_base + offset); 117 readl(entry->mask_base + offset);
123 break;
124 }
125 default:
126 BUG();
127 break;
128 } 118 }
129} 119}
130 120
@@ -143,32 +133,23 @@ static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag)
143 133
144 entry = get_irq_desc_msi(desc); 134 entry = get_irq_desc_msi(desc);
145 BUG_ON(!entry || !entry->dev); 135 BUG_ON(!entry || !entry->dev);
146 switch (entry->msi_attrib.type) { 136 if (entry->msi_attrib.is_msix) {
147 case PCI_CAP_ID_MSI:
148 if (entry->msi_attrib.maskbit) {
149 int pos;
150 u32 mask_bits;
151
152 pos = (long)entry->mask_base;
153 pci_read_config_dword(entry->dev, pos, &mask_bits);
154 mask_bits &= ~(mask);
155 mask_bits |= flag & mask;
156 pci_write_config_dword(entry->dev, pos, mask_bits);
157 } else {
158 return 0;
159 }
160 break;
161 case PCI_CAP_ID_MSIX:
162 {
163 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + 137 int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
164 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; 138 PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
165 writel(flag, entry->mask_base + offset); 139 writel(flag, entry->mask_base + offset);
166 readl(entry->mask_base + offset); 140 readl(entry->mask_base + offset);
167 break; 141 } else {
168 } 142 int pos;
169 default: 143 u32 mask_bits;
170 BUG(); 144
171 break; 145 if (!entry->msi_attrib.maskbit)
146 return 0;
147
148 pos = (long)entry->mask_base;
149 pci_read_config_dword(entry->dev, pos, &mask_bits);
150 mask_bits &= ~mask;
151 mask_bits |= flag & mask;
152 pci_write_config_dword(entry->dev, pos, mask_bits);
172 } 153 }
173 entry->msi_attrib.masked = !!flag; 154 entry->msi_attrib.masked = !!flag;
174 return 1; 155 return 1;
@@ -177,9 +158,14 @@ static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag)
177void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) 158void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
178{ 159{
179 struct msi_desc *entry = get_irq_desc_msi(desc); 160 struct msi_desc *entry = get_irq_desc_msi(desc);
180 switch(entry->msi_attrib.type) { 161 if (entry->msi_attrib.is_msix) {
181 case PCI_CAP_ID_MSI: 162 void __iomem *base = entry->mask_base +
182 { 163 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
164
165 msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
166 msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
167 msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
168 } else {
183 struct pci_dev *dev = entry->dev; 169 struct pci_dev *dev = entry->dev;
184 int pos = entry->msi_attrib.pos; 170 int pos = entry->msi_attrib.pos;
185 u16 data; 171 u16 data;
@@ -195,21 +181,6 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
195 pci_read_config_word(dev, msi_data_reg(pos, 0), &data); 181 pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
196 } 182 }
197 msg->data = data; 183 msg->data = data;
198 break;
199 }
200 case PCI_CAP_ID_MSIX:
201 {
202 void __iomem *base;
203 base = entry->mask_base +
204 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
205
206 msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
207 msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
208 msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
209 break;
210 }
211 default:
212 BUG();
213 } 184 }
214} 185}
215 186
@@ -223,9 +194,17 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
223void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) 194void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
224{ 195{
225 struct msi_desc *entry = get_irq_desc_msi(desc); 196 struct msi_desc *entry = get_irq_desc_msi(desc);
226 switch (entry->msi_attrib.type) { 197 if (entry->msi_attrib.is_msix) {
227 case PCI_CAP_ID_MSI: 198 void __iomem *base;
228 { 199 base = entry->mask_base +
200 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
201
202 writel(msg->address_lo,
203 base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
204 writel(msg->address_hi,
205 base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
206 writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
207 } else {
229 struct pci_dev *dev = entry->dev; 208 struct pci_dev *dev = entry->dev;
230 int pos = entry->msi_attrib.pos; 209 int pos = entry->msi_attrib.pos;
231 210
@@ -240,23 +219,6 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
240 pci_write_config_word(dev, msi_data_reg(pos, 0), 219 pci_write_config_word(dev, msi_data_reg(pos, 0),
241 msg->data); 220 msg->data);
242 } 221 }
243 break;
244 }
245 case PCI_CAP_ID_MSIX:
246 {
247 void __iomem *base;
248 base = entry->mask_base +
249 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
250
251 writel(msg->address_lo,
252 base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
253 writel(msg->address_hi,
254 base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
255 writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
256 break;
257 }
258 default:
259 BUG();
260 } 222 }
261 entry->msg = *msg; 223 entry->msg = *msg;
262} 224}
@@ -393,7 +355,7 @@ static int msi_capability_init(struct pci_dev *dev)
393 if (!entry) 355 if (!entry)
394 return -ENOMEM; 356 return -ENOMEM;
395 357
396 entry->msi_attrib.type = PCI_CAP_ID_MSI; 358 entry->msi_attrib.is_msix = 0;
397 entry->msi_attrib.is_64 = is_64bit_address(control); 359 entry->msi_attrib.is_64 = is_64bit_address(control);
398 entry->msi_attrib.entry_nr = 0; 360 entry->msi_attrib.entry_nr = 0;
399 entry->msi_attrib.maskbit = is_mask_bit_support(control); 361 entry->msi_attrib.maskbit = is_mask_bit_support(control);
@@ -475,7 +437,7 @@ static int msix_capability_init(struct pci_dev *dev,
475 break; 437 break;
476 438
477 j = entries[i].entry; 439 j = entries[i].entry;
478 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 440 entry->msi_attrib.is_msix = 1;
479 entry->msi_attrib.is_64 = 1; 441 entry->msi_attrib.is_64 = 1;
480 entry->msi_attrib.entry_nr = j; 442 entry->msi_attrib.entry_nr = j;
481 entry->msi_attrib.maskbit = 1; 443 entry->msi_attrib.maskbit = 1;
@@ -619,12 +581,13 @@ void pci_msi_shutdown(struct pci_dev* dev)
619 struct irq_desc *desc = irq_to_desc(dev->irq); 581 struct irq_desc *desc = irq_to_desc(dev->irq);
620 msi_set_mask_bits(desc, mask, ~mask); 582 msi_set_mask_bits(desc, mask, ~mask);
621 } 583 }
622 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) 584 if (!entry->dev || entry->msi_attrib.is_msix)
623 return; 585 return;
624 586
625 /* Restore dev->irq to its default pin-assertion irq */ 587 /* Restore dev->irq to its default pin-assertion irq */
626 dev->irq = entry->msi_attrib.default_irq; 588 dev->irq = entry->msi_attrib.default_irq;
627} 589}
590
628void pci_disable_msi(struct pci_dev* dev) 591void pci_disable_msi(struct pci_dev* dev)
629{ 592{
630 struct msi_desc *entry; 593 struct msi_desc *entry;
@@ -635,7 +598,7 @@ void pci_disable_msi(struct pci_dev* dev)
635 pci_msi_shutdown(dev); 598 pci_msi_shutdown(dev);
636 599
637 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 600 entry = list_entry(dev->msi_list.next, struct msi_desc, list);
638 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) 601 if (!entry->dev || entry->msi_attrib.is_msix)
639 return; 602 return;
640 603
641 msi_free_irqs(dev); 604 msi_free_irqs(dev);
@@ -654,7 +617,7 @@ static int msi_free_irqs(struct pci_dev* dev)
654 arch_teardown_msi_irqs(dev); 617 arch_teardown_msi_irqs(dev);
655 618
656 list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { 619 list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
657 if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { 620 if (entry->msi_attrib.is_msix) {
658 writel(1, entry->mask_base + entry->msi_attrib.entry_nr 621 writel(1, entry->mask_base + entry->msi_attrib.entry_nr
659 * PCI_MSIX_ENTRY_SIZE 622 * PCI_MSIX_ENTRY_SIZE
660 + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); 623 + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index d2b8a1e8ca11..9c5ce214fbf4 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -20,13 +20,13 @@ extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
20 20
21struct msi_desc { 21struct msi_desc {
22 struct { 22 struct {
23 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ 23 __u8 is_msix : 1;
24 __u8 maskbit : 1; /* mask-pending bit supported ? */ 24 __u8 maskbit : 1; /* mask-pending bit supported ? */
25 __u8 masked : 1; 25 __u8 masked : 1;
26 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ 26 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
27 __u8 pos; /* Location of the msi capability */ 27 __u8 pos; /* Location of the msi capability */
28 __u32 maskbits_mask; /* mask bits mask */
29 __u16 entry_nr; /* specific enabled entry */ 28 __u16 entry_nr; /* specific enabled entry */
29 __u32 maskbits_mask; /* mask bits mask */
30 unsigned default_irq; /* default pre-assigned irq */ 30 unsigned default_irq; /* default pre-assigned irq */
31 }msi_attrib; 31 }msi_attrib;
32 32