Skip to content

Commit

Permalink
PCI: endpoint: Add MSI-X interfaces
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
gustavoSNPS authored and Lorenzo Pieralisi committed Jul 19, 2018
1 parent 4e965ed commit 8963106
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Documentation/PCI/endpoint/function/binding/pci-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ subsys_id : don't care
interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD
msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts
to test
msix_interrupts : Should be 1 to 2048 depending on the number of MSI-X
interrupts to test
24 changes: 24 additions & 0 deletions drivers/pci/endpoint/pci-ep-cfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
to_pci_epf_group(item)->epf->msi_interrupts);
}

static ssize_t pci_epf_msix_interrupts_store(struct config_item *item,
const char *page, size_t len)
{
u16 val;
int ret;

ret = kstrtou16(page, 0, &val);
if (ret)
return ret;

to_pci_epf_group(item)->epf->msix_interrupts = val;

return len;
}

static ssize_t pci_epf_msix_interrupts_show(struct config_item *item,
char *page)
{
return sprintf(page, "%d\n",
to_pci_epf_group(item)->epf->msix_interrupts);
}

PCI_EPF_HEADER_R(vendorid)
PCI_EPF_HEADER_W_u16(vendorid)

Expand Down Expand Up @@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
CONFIGFS_ATTR(pci_epf_, subsys_id);
CONFIGFS_ATTR(pci_epf_, interrupt_pin);
CONFIGFS_ATTR(pci_epf_, msi_interrupts);
CONFIGFS_ATTR(pci_epf_, msix_interrupts);

static struct configfs_attribute *pci_epf_attrs[] = {
&pci_epf_attr_vendorid,
Expand All @@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = {
&pci_epf_attr_subsys_id,
&pci_epf_attr_interrupt_pin,
&pci_epf_attr_msi_interrupts,
&pci_epf_attr_msix_interrupts,
NULL,
};

Expand Down
57 changes: 57 additions & 0 deletions drivers/pci/endpoint/pci-epc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
}
EXPORT_SYMBOL_GPL(pci_epc_set_msi);

/**
* pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated
* @epc: the EPC device to which MSI-X interrupts was requested
* @func_no: the endpoint function number in the EPC device
*
* Invoke to get the number of MSI-X interrupts allocated by the RC
*/
int pci_epc_get_msix(struct pci_epc *epc, u8 func_no)
{
int interrupt;
unsigned long flags;

if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
return 0;

if (!epc->ops->get_msix)
return 0;

spin_lock_irqsave(&epc->lock, flags);
interrupt = epc->ops->get_msix(epc, func_no);
spin_unlock_irqrestore(&epc->lock, flags);

if (interrupt < 0)
return 0;

return interrupt + 1;
}
EXPORT_SYMBOL_GPL(pci_epc_get_msix);

/**
* pci_epc_set_msix() - set the number of MSI-X interrupt numbers required
* @epc: the EPC device on which MSI-X has to be configured
* @func_no: the endpoint function number in the EPC device
* @interrupts: number of MSI-X interrupts required by the EPF
*
* Invoke to set the required number of MSI-X interrupts.
*/
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
{
int ret;
unsigned long flags;

if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
interrupts < 1 || interrupts > 2048)
return -EINVAL;

if (!epc->ops->set_msix)
return 0;

spin_lock_irqsave(&epc->lock, flags);
ret = epc->ops->set_msix(epc, func_no, interrupts - 1);
spin_unlock_irqrestore(&epc->lock, flags);

return ret;
}
EXPORT_SYMBOL_GPL(pci_epc_set_msix);

/**
* pci_epc_unmap_addr() - unmap CPU address from PCI address
* @epc: the EPC device on which address is allocated
Expand Down
9 changes: 9 additions & 0 deletions include/linux/pci-epc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum pci_epc_irq_type {
PCI_EPC_IRQ_UNKNOWN,
PCI_EPC_IRQ_LEGACY,
PCI_EPC_IRQ_MSI,
PCI_EPC_IRQ_MSIX,
};

/**
Expand All @@ -30,6 +31,10 @@ enum pci_epc_irq_type {
* capability register
* @get_msi: ops to get the number of MSI interrupts allocated by the RC from
* the MSI capability register
* @set_msix: ops to set the requested number of MSI-X interrupts in the
* MSI-X capability register
* @get_msix: ops to get the number of MSI-X interrupts allocated by the RC
* from the MSI-X capability register
* @raise_irq: ops to raise a legacy or MSI interrupt
* @start: ops to start the PCI link
* @stop: ops to stop the PCI link
Expand All @@ -48,6 +53,8 @@ struct pci_epc_ops {
phys_addr_t addr);
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
int (*get_msi)(struct pci_epc *epc, u8 func_no);
int (*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts);
int (*get_msix)(struct pci_epc *epc, u8 func_no);
int (*raise_irq)(struct pci_epc *epc, u8 func_no,
enum pci_epc_irq_type type, u8 interrupt_num);
int (*start)(struct pci_epc *epc);
Expand Down Expand Up @@ -144,6 +151,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
phys_addr_t phys_addr);
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
int pci_epc_get_msi(struct pci_epc *epc, u8 func_no);
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts);
int pci_epc_get_msix(struct pci_epc *epc, u8 func_no);
int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
enum pci_epc_irq_type type, u8 interrupt_num);
int pci_epc_start(struct pci_epc *epc);
Expand Down
1 change: 1 addition & 0 deletions include/linux/pci-epf.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct pci_epf {
struct pci_epf_header *header;
struct pci_epf_bar bar[6];
u8 msi_interrupts;
u16 msix_interrupts;
u8 func_no;

struct pci_epc *epc;
Expand Down

0 comments on commit 8963106

Please sign in to comment.