aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2011-02-18 11:43:32 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-03-10 14:44:40 -0500
commitbf480d952bcf25e8ff7e95d2a23964107513ac51 (patch)
treeb2d1a75e39bfdf82021ccdefb5f9613a17087040 /arch
parent5cad61a6ba6f4956a218ffbb64cafcc1daefaca0 (diff)
xen: events: separate MSI PIRQ allocation from PIRQ binding to IRQ
Split the binding aspect of xen_allocate_pirq_msi out into a new xen_bind_pirq_to_irq function. In xen_hvm_setup_msi_irq when allocating a pirq write the MSI message to signal the PIRQ as soon as the pirq is obtained. There is no way to free the pirq back so if the subsequent binding to an IRQ fails we want to ensure that we will reuse the PIRQ next time rather than leak it. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/pci/xen.c68
1 files changed, 26 insertions, 42 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 0d5087eeced8..93e42152d8d0 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -86,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
86 86
87static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 87static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
88{ 88{
89 int irq, pirq, ret = 0; 89 int irq, pirq;
90 struct msi_desc *msidesc; 90 struct msi_desc *msidesc;
91 struct msi_msg msg; 91 struct msi_msg msg;
92 92
@@ -94,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
94 __read_msi_msg(msidesc, &msg); 94 __read_msi_msg(msidesc, &msg);
95 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | 95 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
96 ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); 96 ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
97 if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { 97 if (msg.data != XEN_PIRQ_MSI_DATA ||
98 irq = xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? 98 xen_irq_from_pirq(pirq) < 0) {
99 "msi-x" : "msi", &pirq, 0); 99 pirq = xen_allocate_pirq_msi(dev, msidesc);
100 if (irq < 0) 100 if (pirq < 0)
101 goto error; 101 goto error;
102 ret = set_irq_msi(irq, msidesc); 102 xen_msi_compose_msg(dev, pirq, &msg);
103 if (ret < 0) 103 __write_msi_msg(msidesc, &msg);
104 goto error_while; 104 dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
105 printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" 105 } else {
106 " pirq=%d\n", irq, pirq); 106 dev_dbg(&dev->dev,
107 return 0; 107 "xen: msi already bound to pirq=%d\n", pirq);
108 } 108 }
109 irq = xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? 109 irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
110 "msi-x" : "msi", &pirq, 1); 110 (type == PCI_CAP_ID_MSIX) ?
111 if (irq < 0 || pirq < 0) 111 "msi-x" : "msi");
112 if (irq < 0)
112 goto error; 113 goto error;
113 printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); 114 dev_dbg(&dev->dev,
114 xen_msi_compose_msg(dev, pirq, &msg); 115 "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
115 ret = set_irq_msi(irq, msidesc);
116 if (ret < 0)
117 goto error_while;
118 write_msi_msg(irq, &msg);
119 } 116 }
120 return 0; 117 return 0;
121 118
122error_while:
123 unbind_from_irqhandler(irq, NULL);
124error: 119error:
125 if (ret == -ENODEV) 120 dev_err(&dev->dev,
126 dev_err(&dev->dev, "Xen PCI frontend has not registered" \ 121 "Xen PCI frontend has not registered MSI/MSI-X support!\n");
127 " MSI/MSI-X support!\n"); 122 return -ENODEV;
128
129 return ret;
130} 123}
131 124
132/* 125/*
@@ -152,28 +145,19 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
152 goto error; 145 goto error;
153 i = 0; 146 i = 0;
154 list_for_each_entry(msidesc, &dev->msi_list, list) { 147 list_for_each_entry(msidesc, &dev->msi_list, list) {
155 irq = xen_allocate_pirq_msi( 148 irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
156 (type == PCI_CAP_ID_MSIX) ? 149 (type == PCI_CAP_ID_MSIX) ?
157 "pcifront-msi-x" : "pcifront-msi", 150 "pcifront-msi-x" :
158 &v[i], 0); 151 "pcifront-msi");
159 if (irq < 0) { 152 if (irq < 0)
160 ret = -1;
161 goto free; 153 goto free;
162 }
163 ret = set_irq_msi(irq, msidesc);
164 if (ret)
165 goto error_while;
166 i++; 154 i++;
167 } 155 }
168 kfree(v); 156 kfree(v);
169 return 0; 157 return 0;
170 158
171error_while:
172 unbind_from_irqhandler(irq, NULL);
173error: 159error:
174 if (ret == -ENODEV) 160 dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
175 dev_err(&dev->dev, "Xen PCI frontend has not registered" \
176 " MSI/MSI-X support!\n");
177free: 161free:
178 kfree(v); 162 kfree(v);
179 return ret; 163 return ret;