Commit 8963106e authored by Gustavo Pimentel's avatar Gustavo Pimentel Committed by Lorenzo Pieralisi

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: default avatarGustavo Pimentel <gustavo.pimentel@synopsys.com>
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parent 4e965ede
...@@ -15,3 +15,5 @@ subsys_id : don't care ...@@ -15,3 +15,5 @@ subsys_id : don't care
interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD 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 msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts
to test to test
msix_interrupts : Should be 1 to 2048 depending on the number of MSI-X
interrupts to test
...@@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item, ...@@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
to_pci_epf_group(item)->epf->msi_interrupts); 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_R(vendorid)
PCI_EPF_HEADER_W_u16(vendorid) PCI_EPF_HEADER_W_u16(vendorid)
...@@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id); ...@@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
CONFIGFS_ATTR(pci_epf_, subsys_id); CONFIGFS_ATTR(pci_epf_, subsys_id);
CONFIGFS_ATTR(pci_epf_, interrupt_pin); CONFIGFS_ATTR(pci_epf_, interrupt_pin);
CONFIGFS_ATTR(pci_epf_, msi_interrupts); CONFIGFS_ATTR(pci_epf_, msi_interrupts);
CONFIGFS_ATTR(pci_epf_, msix_interrupts);
static struct configfs_attribute *pci_epf_attrs[] = { static struct configfs_attribute *pci_epf_attrs[] = {
&pci_epf_attr_vendorid, &pci_epf_attr_vendorid,
...@@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = { ...@@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = {
&pci_epf_attr_subsys_id, &pci_epf_attr_subsys_id,
&pci_epf_attr_interrupt_pin, &pci_epf_attr_interrupt_pin,
&pci_epf_attr_msi_interrupts, &pci_epf_attr_msi_interrupts,
&pci_epf_attr_msix_interrupts,
NULL, NULL,
}; };
......
...@@ -217,6 +217,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) ...@@ -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); 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 * pci_epc_unmap_addr() - unmap CPU address from PCI address
* @epc: the EPC device on which address is allocated * @epc: the EPC device on which address is allocated
......
...@@ -17,6 +17,7 @@ enum pci_epc_irq_type { ...@@ -17,6 +17,7 @@ enum pci_epc_irq_type {
PCI_EPC_IRQ_UNKNOWN, PCI_EPC_IRQ_UNKNOWN,
PCI_EPC_IRQ_LEGACY, PCI_EPC_IRQ_LEGACY,
PCI_EPC_IRQ_MSI, PCI_EPC_IRQ_MSI,
PCI_EPC_IRQ_MSIX,
}; };
/** /**
...@@ -30,6 +31,10 @@ enum pci_epc_irq_type { ...@@ -30,6 +31,10 @@ enum pci_epc_irq_type {
* capability register * capability register
* @get_msi: ops to get the number of MSI interrupts allocated by the RC from * @get_msi: ops to get the number of MSI interrupts allocated by the RC from
* the MSI capability register * 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 * @raise_irq: ops to raise a legacy or MSI interrupt
* @start: ops to start the PCI link * @start: ops to start the PCI link
* @stop: ops to stop the PCI link * @stop: ops to stop the PCI link
...@@ -48,6 +53,8 @@ struct pci_epc_ops { ...@@ -48,6 +53,8 @@ struct pci_epc_ops {
phys_addr_t addr); phys_addr_t addr);
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts); int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
int (*get_msi)(struct pci_epc *epc, u8 func_no); 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, int (*raise_irq)(struct pci_epc *epc, u8 func_no,
enum pci_epc_irq_type type, u8 interrupt_num); enum pci_epc_irq_type type, u8 interrupt_num);
int (*start)(struct pci_epc *epc); int (*start)(struct pci_epc *epc);
...@@ -144,6 +151,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, ...@@ -144,6 +151,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
phys_addr_t phys_addr); phys_addr_t phys_addr);
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts); 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_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, int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
enum pci_epc_irq_type type, u8 interrupt_num); enum pci_epc_irq_type type, u8 interrupt_num);
int pci_epc_start(struct pci_epc *epc); int pci_epc_start(struct pci_epc *epc);
......
...@@ -119,6 +119,7 @@ struct pci_epf { ...@@ -119,6 +119,7 @@ struct pci_epf {
struct pci_epf_header *header; struct pci_epf_header *header;
struct pci_epf_bar bar[6]; struct pci_epf_bar bar[6];
u8 msi_interrupts; u8 msi_interrupts;
u16 msix_interrupts;
u8 func_no; u8 func_no;
struct pci_epc *epc; struct pci_epc *epc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment