Skip to content

Commit 8963106

Browse files
gustavoSNPSLorenzo Pieralisi
authored andcommitted
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 <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Acked-by: Kishon Vijay Abraham I <[email protected]>
1 parent 4e965ed commit 8963106

File tree

5 files changed

+93
-0
lines changed

5 files changed

+93
-0
lines changed

Documentation/PCI/endpoint/function/binding/pci-test.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ subsys_id : don't care
1515
interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD
1616
msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts
1717
to test
18+
msix_interrupts : Should be 1 to 2048 depending on the number of MSI-X
19+
interrupts to test

drivers/pci/endpoint/pci-ep-cfs.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
286286
to_pci_epf_group(item)->epf->msi_interrupts);
287287
}
288288

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+
289311
PCI_EPF_HEADER_R(vendorid)
290312
PCI_EPF_HEADER_W_u16(vendorid)
291313

@@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
327349
CONFIGFS_ATTR(pci_epf_, subsys_id);
328350
CONFIGFS_ATTR(pci_epf_, interrupt_pin);
329351
CONFIGFS_ATTR(pci_epf_, msi_interrupts);
352+
CONFIGFS_ATTR(pci_epf_, msix_interrupts);
330353

331354
static struct configfs_attribute *pci_epf_attrs[] = {
332355
&pci_epf_attr_vendorid,
@@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = {
340363
&pci_epf_attr_subsys_id,
341364
&pci_epf_attr_interrupt_pin,
342365
&pci_epf_attr_msi_interrupts,
366+
&pci_epf_attr_msix_interrupts,
343367
NULL,
344368
};
345369

drivers/pci/endpoint/pci-epc-core.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
217217
}
218218
EXPORT_SYMBOL_GPL(pci_epc_set_msi);
219219

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+
220277
/**
221278
* pci_epc_unmap_addr() - unmap CPU address from PCI address
222279
* @epc: the EPC device on which address is allocated

include/linux/pci-epc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum pci_epc_irq_type {
1717
PCI_EPC_IRQ_UNKNOWN,
1818
PCI_EPC_IRQ_LEGACY,
1919
PCI_EPC_IRQ_MSI,
20+
PCI_EPC_IRQ_MSIX,
2021
};
2122

2223
/**
@@ -30,6 +31,10 @@ enum pci_epc_irq_type {
3031
* capability register
3132
* @get_msi: ops to get the number of MSI interrupts allocated by the RC from
3233
* 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
3338
* @raise_irq: ops to raise a legacy or MSI interrupt
3439
* @start: ops to start the PCI link
3540
* @stop: ops to stop the PCI link
@@ -48,6 +53,8 @@ struct pci_epc_ops {
4853
phys_addr_t addr);
4954
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
5055
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);
5158
int (*raise_irq)(struct pci_epc *epc, u8 func_no,
5259
enum pci_epc_irq_type type, u8 interrupt_num);
5360
int (*start)(struct pci_epc *epc);
@@ -144,6 +151,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
144151
phys_addr_t phys_addr);
145152
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
146153
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);
147156
int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
148157
enum pci_epc_irq_type type, u8 interrupt_num);
149158
int pci_epc_start(struct pci_epc *epc);

include/linux/pci-epf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct pci_epf {
119119
struct pci_epf_header *header;
120120
struct pci_epf_bar bar[6];
121121
u8 msi_interrupts;
122+
u16 msix_interrupts;
122123
u8 func_no;
123124

124125
struct pci_epc *epc;

0 commit comments

Comments
 (0)