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 base + j * PCI_MSIX_ENTRY_SIZE +
674 PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
675 writel(entry->data_save,
676 base + j * PCI_MSIX_ENTRY_SIZE +
677 PCI_MSIX_ENTRY_DATA_OFFSET);
678 689
679 tail = msi_desc[vector]->link.tail; 690 tail = msi_desc[vector]->link.tail;
680 vector = tail; 691 vector = tail;
@@ -689,29 +700,19 @@ void pci_restore_msix_state(struct pci_dev *dev)
689static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry) 700static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
690{ 701{
691 int status; 702 int status;
692 u32 address_hi; 703 struct msi_msg msg;
693 u32 address_lo;
694 u32 data;
695 int pos, vector = dev->irq; 704 int pos, vector = dev->irq;
696 u16 control; 705 u16 control;
697 706
698 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 707 pos = entry->msi_attrib.pos;
699 pci_read_config_word(dev, msi_control_reg(pos), &control); 708 pci_read_config_word(dev, msi_control_reg(pos), &control);
700 709
701 /* Configure MSI capability structure */ 710 /* Configure MSI capability structure */
702 status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data); 711 status = msi_ops->setup(dev, vector, &msg.address_hi, &msg.address_lo, &msg.data);
703 if (status < 0) 712 if (status < 0)
704 return status; 713 return status;
705 714
706 pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo); 715 write_msi_msg(entry, &msg);
707 if (is_64bit_address(control)) {
708 pci_write_config_dword(dev,
709 msi_upper_address_reg(pos), address_hi);
710 pci_write_config_word(dev,
711 msi_data_reg(pos, 1), data);
712 } else
713 pci_write_config_word(dev,
714 msi_data_reg(pos, 0), data);
715 if (entry->msi_attrib.maskbit) { 716 if (entry->msi_attrib.maskbit) {
716 unsigned int maskbits, temp; 717 unsigned int maskbits, temp;
717 /* All MSIs are unmasked by default, Mask them all */ 718 /* All MSIs are unmasked by default, Mask them all */
@@ -761,9 +762,11 @@ static int msi_capability_init(struct pci_dev *dev)
761 entry->link.tail = vector; 762 entry->link.tail = vector;
762 entry->msi_attrib.type = PCI_CAP_ID_MSI; 763 entry->msi_attrib.type = PCI_CAP_ID_MSI;
763 entry->msi_attrib.state = 0; /* Mark it not active */ 764 entry->msi_attrib.state = 0; /* Mark it not active */
765 entry->msi_attrib.is_64 = is_64bit_address(control);
764 entry->msi_attrib.entry_nr = 0; 766 entry->msi_attrib.entry_nr = 0;
765 entry->msi_attrib.maskbit = is_mask_bit_support(control); 767 entry->msi_attrib.maskbit = is_mask_bit_support(control);
766 entry->msi_attrib.default_vector = dev->irq; /* Save IOAPIC IRQ */ 768 entry->msi_attrib.default_vector = dev->irq; /* Save IOAPIC IRQ */
769 entry->msi_attrib.pos = pos;
767 dev->irq = vector; 770 dev->irq = vector;
768 entry->dev = dev; 771 entry->dev = dev;
769 if (is_mask_bit_support(control)) { 772 if (is_mask_bit_support(control)) {
@@ -801,9 +804,7 @@ static int msix_capability_init(struct pci_dev *dev,
801 struct msix_entry *entries, int nvec) 804 struct msix_entry *entries, int nvec)
802{ 805{
803 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; 806 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
804 u32 address_hi; 807 struct msi_msg msg;
805 u32 address_lo;
806 u32 data;
807 int status; 808 int status;
808 int vector, pos, i, j, nr_entries, temp = 0; 809 int vector, pos, i, j, nr_entries, temp = 0;
809 unsigned long phys_addr; 810 unsigned long phys_addr;
@@ -840,9 +841,11 @@ static int msix_capability_init(struct pci_dev *dev,
840 entries[i].vector = vector; 841 entries[i].vector = vector;
841 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 842 entry->msi_attrib.type = PCI_CAP_ID_MSIX;
842 entry->msi_attrib.state = 0; /* Mark it not active */ 843 entry->msi_attrib.state = 0; /* Mark it not active */
844 entry->msi_attrib.is_64 = 1;
843 entry->msi_attrib.entry_nr = j; 845 entry->msi_attrib.entry_nr = j;
844 entry->msi_attrib.maskbit = 1; 846 entry->msi_attrib.maskbit = 1;
845 entry->msi_attrib.default_vector = dev->irq; 847 entry->msi_attrib.default_vector = dev->irq;
848 entry->msi_attrib.pos = pos;
846 entry->dev = dev; 849 entry->dev = dev;
847 entry->mask_base = base; 850 entry->mask_base = base;
848 if (!head) { 851 if (!head) {
@@ -861,21 +864,13 @@ static int msix_capability_init(struct pci_dev *dev,
861 irq_handler_init(PCI_CAP_ID_MSIX, vector, 1); 864 irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
862 /* Configure MSI-X capability structure */ 865 /* Configure MSI-X capability structure */
863 status = msi_ops->setup(dev, vector, 866 status = msi_ops->setup(dev, vector,
864 &address_hi, 867 &msg.address_hi,
865 &address_lo, 868 &msg.address_lo,
866 &data); 869 &msg.data);
867 if (status < 0) 870 if (status < 0)
868 break; 871 break;
869 872
870 writel(address_lo, 873 write_msi_msg(entry, &msg);
871 base + j * PCI_MSIX_ENTRY_SIZE +
872 PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
873 writel(address_hi,
874 base + j * PCI_MSIX_ENTRY_SIZE +
875 PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
876 writel(data,
877 base + j * PCI_MSIX_ENTRY_SIZE +
878 PCI_MSIX_ENTRY_DATA_OFFSET);
879 attach_msi_entry(entry, vector); 874 attach_msi_entry(entry, vector);
880 } 875 }
881 if (i != nvec) { 876 if (i != nvec) {
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 9b31d4cbbce4..62f61b61d2c9 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -130,10 +130,10 @@ struct msi_desc {
130 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ 130 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
131 __u8 maskbit : 1; /* mask-pending bit supported ? */ 131 __u8 maskbit : 1; /* mask-pending bit supported ? */
132 __u8 state : 1; /* {0: free, 1: busy} */ 132 __u8 state : 1; /* {0: free, 1: busy} */
133 __u8 reserved: 1; /* reserved */ 133 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
134 __u8 entry_nr; /* specific enabled entry */ 134 __u8 entry_nr; /* specific enabled entry */
135 __u8 default_vector; /* default pre-assigned vector */ 135 __u8 default_vector; /* default pre-assigned vector */
136 __u8 unused; /* formerly unused destination cpu*/ 136 __u8 pos; /* Location of the msi capability */
137 }msi_attrib; 137 }msi_attrib;
138 138
139 struct { 139 struct {
@@ -146,10 +146,7 @@ struct msi_desc {
146 146
147#ifdef CONFIG_PM 147#ifdef CONFIG_PM
148 /* PM save area for MSIX address/data */ 148 /* PM save area for MSIX address/data */
149 149 struct msi_msg msg_save;
150 u32 address_hi_save;
151 u32 address_lo_save;
152 u32 data_save;
153#endif 150#endif
154}; 151};
155 152
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4431ce4e1e6f..b9bb6c46e056 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -595,6 +595,12 @@ struct msix_entry {
595 u16 entry; /* driver uses to specify entry, OS writes */ 595 u16 entry; /* driver uses to specify entry, OS writes */
596}; 596};
597 597
598struct msi_msg {
599 u32 address_lo; /* low 32 bits of msi message address */
600 u32 address_hi; /* high 32 bits of msi message address */
601 u32 data; /* 16 bits of msi message data */
602};
603
598#ifndef CONFIG_PCI_MSI 604#ifndef CONFIG_PCI_MSI
599static inline void pci_scan_msi_device(struct pci_dev *dev) {} 605static inline void pci_scan_msi_device(struct pci_dev *dev) {}
600static inline int pci_enable_msi(struct pci_dev *dev) {return -1;} 606static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}