Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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)

@@ -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,
@@ -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,
};

+57 −0
Original line number Diff line number Diff line
@@ -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
+9 −0
Original line number Diff line number Diff line
@@ -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,
};

/**
@@ -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
@@ -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);
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;