aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Pimentel <gustavo.pimentel@synopsys.com>2018-07-19 04:32:12 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-07-19 06:34:23 -0400
commit8963106eabdc56911e9b65258eb5e9a6b7b3dfda (patch)
treead5ea11d66f9e8bd7876fdbc77bf22f1ac3b897d
parent4e965ede1856ed62c7ac8b7ad905a4a285e4a9f3 (diff)
PCI: endpoint: Add MSI-X interfaces
Add PCI_EPC_IRQ_MSIX type. Add MSI-X callbacks signatures to the ops structure. Add sysfs interface for set/get MSI-X capability maximum number. Update documentation accordingly. Signed-off-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r--Documentation/PCI/endpoint/function/binding/pci-test.txt2
-rw-r--r--drivers/pci/endpoint/pci-ep-cfs.c24
-rw-r--r--drivers/pci/endpoint/pci-epc-core.c57
-rw-r--r--include/linux/pci-epc.h9
-rw-r--r--include/linux/pci-epf.h1
5 files changed, 93 insertions, 0 deletions
diff --git a/Documentation/PCI/endpoint/function/binding/pci-test.txt b/Documentation/PCI/endpoint/function/binding/pci-test.txt
index 3b68b955fb50..cd76ba47394b 100644
--- a/Documentation/PCI/endpoint/function/binding/pci-test.txt
+++ b/Documentation/PCI/endpoint/function/binding/pci-test.txt
@@ -15,3 +15,5 @@ subsys_id : don't care
15interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD 15interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD
16msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts 16msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts
17 to test 17 to test
18msix_interrupts : Should be 1 to 2048 depending on the number of MSI-X
19 interrupts to test
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
index 018ea3433cb5..d1288a0bd530 100644
--- a/drivers/pci/endpoint/pci-ep-cfs.c
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
286 to_pci_epf_group(item)->epf->msi_interrupts); 286 to_pci_epf_group(item)->epf->msi_interrupts);
287} 287}
288 288
289static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
290 const char *page, size_t len)
291{
292 u16 val;
293 int ret;
294
295 ret = kstrtou16(page, 0, &val);
296 if (ret)
297 return ret;
298
299 to_pci_epf_group(item)->epf->msix_interrupts = val;
300
301 return len;
302}
303
304static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
305 char *page)
306{
307 return sprintf(page, "%d\n",
308 to_pci_epf_group(item)->epf->msix_interrupts);
309}
310
289PCI_EPF_HEADER_R(vendorid) 311PCI_EPF_HEADER_R(vendorid)
290PCI_EPF_HEADER_W_u16(vendorid) 312PCI_EPF_HEADER_W_u16(vendorid)
291 313
@@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
327CONFIGFS_ATTR(pci_epf_, subsys_id); 349CONFIGFS_ATTR(pci_epf_, subsys_id);
328CONFIGFS_ATTR(pci_epf_, interrupt_pin); 350CONFIGFS_ATTR(pci_epf_, interrupt_pin);
329CONFIGFS_ATTR(pci_epf_, msi_interrupts); 351CONFIGFS_ATTR(pci_epf_, msi_interrupts);
352CONFIGFS_ATTR(pci_epf_, msix_interrupts);
330 353
331static struct configfs_attribute *pci_epf_attrs[] = { 354static struct configfs_attribute *pci_epf_attrs[] = {
332 &pci_epf_attr_vendorid, 355 &pci_epf_attr_vendorid,
@@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = {
340 &pci_epf_attr_subsys_id, 363 &pci_epf_attr_subsys_id,
341 &pci_epf_attr_interrupt_pin, 364 &pci_epf_attr_interrupt_pin,
342 &pci_epf_attr_msi_interrupts, 365 &pci_epf_attr_msi_interrupts,
366 &pci_epf_attr_msix_interrupts,
343 NULL, 367 NULL,
344}; 368};
345 369
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index b0ee42739c3c..7d77bd0e5d4a 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -218,6 +218,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
218EXPORT_SYMBOL_GPL(pci_epc_set_msi); 218EXPORT_SYMBOL_GPL(pci_epc_set_msi);
219 219
220/** 220/**
221 * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated
222 * @epc: the EPC device to which MSI-X interrupts was requested
223 * @func_no: the endpoint function number in the EPC device
224 *
225 * Invoke to get the number of MSI-X interrupts allocated by the RC
226 */
227int pci_epc_get_msix(struct pci_epc *epc, u8 func_no)
228{
229 int interrupt;
230 unsigned long flags;
231
232 if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
233 return 0;
234
235 if (!epc->ops->get_msix)
236 return 0;
237
238 spin_lock_irqsave(&epc->lock, flags);
239 interrupt = epc->ops->get_msix(epc, func_no);
240 spin_unlock_irqrestore(&epc->lock, flags);
241
242 if (interrupt < 0)
243 return 0;
244
245 return interrupt + 1;
246}
247EXPORT_SYMBOL_GPL(pci_epc_get_msix);
248
249/**
250 * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required
251 * @epc: the EPC device on which MSI-X has to be configured
252 * @func_no: the endpoint function number in the EPC device
253 * @interrupts: number of MSI-X interrupts required by the EPF
254 *
255 * Invoke to set the required number of MSI-X interrupts.
256 */
257int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
258{
259 int ret;
260 unsigned long flags;
261
262 if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
263 interrupts < 1 || interrupts > 2048)
264 return -EINVAL;
265
266 if (!epc->ops->set_msix)
267 return 0;
268
269 spin_lock_irqsave(&epc->lock, flags);
270 ret = epc->ops->set_msix(epc, func_no, interrupts - 1);
271 spin_unlock_irqrestore(&epc->lock, flags);
272
273 return ret;
274}
275EXPORT_SYMBOL_GPL(pci_epc_set_msix);
276
277/**
221 * pci_epc_unmap_addr() - unmap CPU address from PCI address 278 * pci_epc_unmap_addr() - unmap CPU address from PCI address
222 * @epc: the EPC device on which address is allocated 279 * @epc: the EPC device on which address is allocated
223 * @func_no: the endpoint function number in the EPC device 280 * @func_no: the endpoint function number in the EPC device
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 243eaa5a66ff..89f079f582df 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -17,6 +17,7 @@ enum pci_epc_irq_type {
17 PCI_EPC_IRQ_UNKNOWN, 17 PCI_EPC_IRQ_UNKNOWN,
18 PCI_EPC_IRQ_LEGACY, 18 PCI_EPC_IRQ_LEGACY,
19 PCI_EPC_IRQ_MSI, 19 PCI_EPC_IRQ_MSI,
20 PCI_EPC_IRQ_MSIX,
20}; 21};
21 22
22/** 23/**
@@ -30,6 +31,10 @@ enum pci_epc_irq_type {
30 * capability register 31 * capability register
31 * @get_msi: ops to get the number of MSI interrupts allocated by the RC from 32 * @get_msi: ops to get the number of MSI interrupts allocated by the RC from
32 * the MSI capability register 33 * the MSI capability register
34 * @set_msix: ops to set the requested number of MSI-X interrupts in the
35 * MSI-X capability register
36 * @get_msix: ops to get the number of MSI-X interrupts allocated by the RC
37 * from the MSI-X capability register
33 * @raise_irq: ops to raise a legacy or MSI interrupt 38 * @raise_irq: ops to raise a legacy or MSI interrupt
34 * @start: ops to start the PCI link 39 * @start: ops to start the PCI link
35 * @stop: ops to stop the PCI link 40 * @stop: ops to stop the PCI link
@@ -48,6 +53,8 @@ struct pci_epc_ops {
48 phys_addr_t addr); 53 phys_addr_t addr);
49 int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts); 54 int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
50 int (*get_msi)(struct pci_epc *epc, u8 func_no); 55 int (*get_msi)(struct pci_epc *epc, u8 func_no);
56 int (*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts);
57 int (*get_msix)(struct pci_epc *epc, u8 func_no);
51 int (*raise_irq)(struct pci_epc *epc, u8 func_no, 58 int (*raise_irq)(struct pci_epc *epc, u8 func_no,
52 enum pci_epc_irq_type type, u8 interrupt_num); 59 enum pci_epc_irq_type type, u8 interrupt_num);
53 int (*start)(struct pci_epc *epc); 60 int (*start)(struct pci_epc *epc);
@@ -144,6 +151,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
144 phys_addr_t phys_addr); 151 phys_addr_t phys_addr);
145int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts); 152int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
146int pci_epc_get_msi(struct pci_epc *epc, u8 func_no); 153int pci_epc_get_msi(struct pci_epc *epc, u8 func_no);
154int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts);
155int pci_epc_get_msix(struct pci_epc *epc, u8 func_no);
147int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, 156int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
148 enum pci_epc_irq_type type, u8 interrupt_num); 157 enum pci_epc_irq_type type, u8 interrupt_num);
149int pci_epc_start(struct pci_epc *epc); 158int pci_epc_start(struct pci_epc *epc);
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 4e7764935fa8..ec02f58758c8 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -119,6 +119,7 @@ struct pci_epf {
119 struct pci_epf_header *header; 119 struct pci_epf_header *header;
120 struct pci_epf_bar bar[6]; 120 struct pci_epf_bar bar[6];
121 u8 msi_interrupts; 121 u8 msi_interrupts;
122 u16 msix_interrupts;
122 u8 func_no; 123 u8 func_no;
123 124
124 struct pci_epc *epc; 125 struct pci_epc *epc;