aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c195
1 files changed, 95 insertions, 100 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) {