diff options
author | Gustavo Pimentel <gustavo.pimentel@synopsys.com> | 2018-07-19 04:32:12 -0400 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2018-07-19 06:34:23 -0400 |
commit | 8963106eabdc56911e9b65258eb5e9a6b7b3dfda (patch) | |
tree | ad5ea11d66f9e8bd7876fdbc77bf22f1ac3b897d | |
parent | 4e965ede1856ed62c7ac8b7ad905a4a285e4a9f3 (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.txt | 2 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-ep-cfs.c | 24 | ||||
-rw-r--r-- | drivers/pci/endpoint/pci-epc-core.c | 57 | ||||
-rw-r--r-- | include/linux/pci-epc.h | 9 | ||||
-rw-r--r-- | include/linux/pci-epf.h | 1 |
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 | |||
15 | interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD | 15 | interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD |
16 | msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts | 16 | msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts |
17 | to test | 17 | to test |
18 | msix_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 | ||
289 | static 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 | |||
304 | static 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 | |||
289 | PCI_EPF_HEADER_R(vendorid) | 311 | PCI_EPF_HEADER_R(vendorid) |
290 | PCI_EPF_HEADER_W_u16(vendorid) | 312 | PCI_EPF_HEADER_W_u16(vendorid) |
291 | 313 | ||
@@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id); | |||
327 | CONFIGFS_ATTR(pci_epf_, subsys_id); | 349 | CONFIGFS_ATTR(pci_epf_, subsys_id); |
328 | CONFIGFS_ATTR(pci_epf_, interrupt_pin); | 350 | CONFIGFS_ATTR(pci_epf_, interrupt_pin); |
329 | CONFIGFS_ATTR(pci_epf_, msi_interrupts); | 351 | CONFIGFS_ATTR(pci_epf_, msi_interrupts); |
352 | CONFIGFS_ATTR(pci_epf_, msix_interrupts); | ||
330 | 353 | ||
331 | static struct configfs_attribute *pci_epf_attrs[] = { | 354 | static 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) | |||
218 | EXPORT_SYMBOL_GPL(pci_epc_set_msi); | 218 | EXPORT_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 | */ | ||
227 | int 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 | } | ||
247 | EXPORT_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 | */ | ||
257 | int 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 | } | ||
275 | EXPORT_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); |
145 | int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts); | 152 | int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts); |
146 | int pci_epc_get_msi(struct pci_epc *epc, u8 func_no); | 153 | int pci_epc_get_msi(struct pci_epc *epc, u8 func_no); |
154 | int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts); | ||
155 | int pci_epc_get_msix(struct pci_epc *epc, u8 func_no); | ||
147 | int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, | 156 | int 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); |
149 | int pci_epc_start(struct pci_epc *epc); | 158 | int 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; |