Skip to contentSkip to conversation

PCI: endpoint: IRQ callback fixes and cleanups

PATCH Superseded Niklas Cassel 4 participants 14 messages May 13, 2025 – May 14, 2025

Subsystems (10)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover PCI: endpoint: IRQ callback fixes and cleanups

Hello all,

The first two patches in this series are IRQ callback fixes that should get backported.

The reason why the bugs existed in the first place is because the APIs are very confusing. The rest of the patches are cleanups of the APIs. These cleanups should not get backported.

Changes since v1:
-Improved commit message of the fix patches.
-Picked up tags on the fix patches.
-Added cleanups patches.

Niklas Cassel (6):
PCI: dwc: ep: Fix broken set_msix() callback
PCI: cadence-ep: Fix broken set_msix() callback
PCI: endpoint: cleanup get_msi() callback
PCI: endpoint: cleanup set_msi() callback
PCI: endpoint: cleanup get_msix() callback
PCI: endpoint: cleanup set_msix() callback

 drivers/pci/controller/cadence/pcie-cadence-ep.c | 10 ++++++----
 drivers/pci/controller/dwc/pcie-designware-ep.c  |  9 +++++----
 drivers/pci/controller/pcie-rcar-ep.c            |  5 +++--
 drivers/pci/controller/pcie-rockchip-ep.c        |  9 +++++----
 drivers/pci/endpoint/pci-epc-core.c              | 11 +++--------
 5 files changed, 22 insertions(+), 22 deletions(-)
Signature · 1 line
2.49.0
#1 lore raw

PATCH v2 1/6 PCI: dwc: ep: Fix broken set_msix() callback

While the set_msix() callback function in pcie-designware-ep writes the Table Size field correctly (N-1), the calculation of the PBA offset is wrong because it calculates space for (N-1) entries instead of N.

This results in e.g. the following error when using QEMU with PCI
passthrough on a device which relies on the PCI endpoint subsystem:
failed to add PCI capability 0x11[0x50]@0xb0: table & pba overlap, or they don't fit in BARs, or don't align

Fix the calculation of PBA offset in the MSI-X capability.

Fixes 83153d9f36e2 ("PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments")
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pci/controller/dwc/pcie-designware-ep.c +3 -2
index 1a0bf9341542..24026f3f3413 100644
@@ -585,6 +585,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 	struct dw_pcie_ep_func *ep_func;
 	u32 val, reg;
+	u16 actual_interrupts = interrupts + 1;
 
 	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
 	if (!ep_func || !ep_func->msix_cap)
@@ -595,7 +596,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	reg = ep_func->msix_cap + PCI_MSIX_FLAGS;
 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg);
 	val &= ~PCI_MSIX_FLAGS_QSIZE;
-	val |= interrupts;
+	val |= interrupts; /* 0's based value */
 	dw_pcie_writew_dbi(pci, reg, val);
 
 	reg = ep_func->msix_cap + PCI_MSIX_TABLE;
@@ -603,7 +604,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
 
 	reg = ep_func->msix_cap + PCI_MSIX_PBA;
-	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	val = (offset + (actual_interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
 	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
 
 	dw_pcie_dbi_ro_wr_dis(pci);
Signature · 1 line
2.49.0
#2 lore raw

PATCH v2 2/6 PCI: cadence-ep: Fix broken set_msix() callback

In reply to Niklas Cassel

While the set_msix() callback function in pcie-cadence-ep writes the Table Size field correctly (N-1), the calculation of the PBA offset is wrong because it calculates space for (N-1) entries instead of N.

This results in e.g. the following error when using QEMU with PCI
passthrough on a device which relies on the PCI endpoint subsystem:
failed to add PCI capability 0x11[0x50]@0xb0: table & pba overlap, or they don't fit in BARs, or don't align

Fix the calculation of PBA offset in the MSI-X capability.

Fixes 3ef5d16f50f8 ("PCI: cadence: Add MSI-X support to Endpoint driver")
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +3 -2
index 599ec4b1223e..112ae200b393 100644
@@ -292,13 +292,14 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
 	struct cdns_pcie *pcie = &ep->pcie;
 	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 	u32 val, reg;
+	u16 actual_interrupts = interrupts + 1;
 
 	fn = cdns_pcie_get_fn_from_vfn(pcie, fn, vfn);
 
 	reg = cap + PCI_MSIX_FLAGS;
 	val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
 	val &= ~PCI_MSIX_FLAGS_QSIZE;
-	val |= interrupts;
+	val |= interrupts; /* 0's based value */
 	cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
 
 	/* Set MSI-X BAR and offset */
@@ -308,7 +309,7 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
 
 	/* Set PBA BAR and offset.  BAR must match MSI-X BAR */
 	reg = cap + PCI_MSIX_PBA;
-	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	val = (offset + (actual_interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
 	cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
 
 	return 0;
Signature · 1 line
2.49.0
#3 lore raw

PATCH v2 3/6 PCI: endpoint: cleanup get_msi() callback

In reply to Niklas Cassel

The kdoc for pci_epc_get_msi() says:
"Invoke to get the number of MSI interrupts allocated by the RC" the kdoc for the callback pci_epc_ops->get_msi() says:
"ops to get the number of MSI interrupts allocated by the RC from the MSI capability register"

pci_epc_ops->get_msi() does however return the number of interrupts in the encoding as defined by the MME Multiple Message Enable field.

Nowhere in the kdoc does it say that the returned number of interrupts is in MME encoding.

Thus, it is very confusing that the wrapper function (pci_epc_get_msi()) and the callback function (pci_epc_ops->get_msi()) don't return the same value.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Cc <[email protected]> # this is simply a cleanup
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 2 +-
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 2 +-
 drivers/pci/controller/pcie-rcar-ep.c            | 2 +-
 drivers/pci/controller/pcie-rockchip-ep.c        | 4 ++--
 drivers/pci/endpoint/pci-epc-core.c              | 2 --
 5 files changed, 5 insertions(+), 7 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +1 -1
index 112ae200b393..78b4d009cd04 100644
@@ -262,7 +262,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
 	 */
 	mme = FIELD_GET(PCI_MSI_FLAGS_QSIZE, flags);
 
-	return mme;
+	return 1 << mme;
 }
 
 static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
drivers/pci/controller/dwc/pcie-designware-ep.c +1 -1
index 24026f3f3413..03597551f4cd 100644
@@ -532,7 +532,7 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 
 	val = FIELD_GET(PCI_MSI_FLAGS_QSIZE, val);
 
-	return val;
+	return 1 << val;
 }
 
 static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
drivers/pci/controller/pcie-rcar-ep.c +1 -1
index c5e0d025bc43..9da39a4617b6 100644
@@ -280,7 +280,7 @@ static int rcar_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
 	if (!(flags & MSICAP0_MSIE))
 		return -EINVAL;
 
-	return ((flags & MSICAP0_MMESE_MASK) >> MSICAP0_MMESE_OFFSET);
+	return 1 << ((flags & MSICAP0_MMESE_MASK) >> MSICAP0_MMESE_OFFSET);
 }
 
 static int rcar_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
drivers/pci/controller/pcie-rockchip-ep.c +2 -2
index 85ea36df2f59..85ca7d9b4c77 100644
@@ -340,8 +340,8 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
 	if (!(flags & ROCKCHIP_PCIE_EP_MSI_CTRL_ME))
 		return -EINVAL;
 
-	return ((flags & ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK) >>
-			ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET);
+	return 1 << ((flags & ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK) >>
+		     ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET);
 }
 
 static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,
drivers/pci/endpoint/pci-epc-core.c +0 -2
index beabea00af91..cc1456bd188e 100644
@@ -293,8 +293,6 @@ int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 	if (interrupt < 0)
 		return 0;
 
-	interrupt = 1 << interrupt;
-
 	return interrupt;
 }
 EXPORT_SYMBOL_GPL(pci_epc_get_msi);
Signature · 1 line
2.49.0
Reviewed-by on v2 3/6
#4 lore raw

Re: [PATCH v2 3/6] PCI: endpoint: cleanup get_msi() callback

Quoted 12 lines · Niklas Cassel

The kdoc for pci_epc_get_msi() says:
"Invoke to get the number of MSI interrupts allocated by the RC" the kdoc for the callback pci_epc_ops->get_msi() says:
"ops to get the number of MSI interrupts allocated by the RC from the MSI capability register"

pci_epc_ops->get_msi() does however return the number of interrupts in the encoding as defined by the MME Multiple Message Enable field.

Nowhere in the kdoc does it say that the returned number of interrupts is in MME encoding.

Quoted 6 lines

Thus, it is very confusing that the wrapper function (pci_epc_get_msi()) and the callback function (pci_epc_ops->get_msi()) don't return the same value.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Nit: please mention which semantic this patch changes the API to use, that is, to follow the kdoc and return the number of interrupts, regardless of the internal encoding of that value.

Other than that, looks good to me.

Signature · 2 lines
Damien Le Moal
Western Digital Research
#5 lore raw

PATCH v2 4/6 PCI: endpoint: cleanup set_msi() callback

In reply to Niklas Cassel

The kdoc for pci_epc_set_msi() says:
"Invoke to set the required number of MSI interrupts."
the kdoc for the callback pci_epc_ops->set_msi() says:
"ops to set the requested number of MSI interrupts in the MSI capability register"

pci_epc_ops->set_msi() does however expect the parameter 'interrupts' to be in the encoding as defined by the MMC Multiple Message Capable field.

Nowhere in the kdoc does it say that the number of interrupts should be in MMC encoding.

Thus, it is very confusing that the wrapper function (pci_epc_set_msi()) and the callback function (pci_epc_ops->set_msi()) both take a parameter named interrupts, but they both expect completely different encodings.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Cc <[email protected]> # this is simply a cleanup
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 4 +++-
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 3 ++-
 drivers/pci/controller/pcie-rcar-ep.c            | 3 ++-
 drivers/pci/controller/pcie-rockchip-ep.c        | 5 +++--
 drivers/pci/endpoint/pci-epc-core.c              | 5 +----
 5 files changed, 11 insertions(+), 9 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +3 -1
index 78b4d009cd04..f307256826e6 100644
@@ -220,10 +220,12 @@ static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
 	clear_bit(r, &ep->ob_region_map);
 }
 
-static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 mmc)
+static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
+				u8 interrupts)
 {
 	struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
 	struct cdns_pcie *pcie = &ep->pcie;
+	u8 mmc = order_base_2(interrupts);
 	u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET;
 	u16 flags;
 
drivers/pci/controller/dwc/pcie-designware-ep.c +2 -1
index 03597551f4cd..e7a916bf6b2c 100644
@@ -541,6 +541,7 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 	struct dw_pcie_ep_func *ep_func;
+	u8 mmc = order_base_2(interrupts);
 	u32 val, reg;
 
 	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
@@ -550,7 +551,7 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	reg = ep_func->msi_cap + PCI_MSI_FLAGS;
 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg);
 	val &= ~PCI_MSI_FLAGS_QMASK;
-	val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, interrupts);
+	val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, mmc);
 	dw_pcie_dbi_ro_wr_en(pci);
 	dw_pcie_ep_writew_dbi(ep, func_no, reg, val);
 	dw_pcie_dbi_ro_wr_dis(pci);
drivers/pci/controller/pcie-rcar-ep.c +2 -1
index 9da39a4617b6..b25ad23bedb7 100644
@@ -261,10 +261,11 @@ static int rcar_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
 {
 	struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc);
 	struct rcar_pcie *pcie = &ep->pcie;
+	u8 mmc = order_base_2(interrupts);
 	u32 flags;
 
 	flags = rcar_pci_read_reg(pcie, MSICAP(fn));
-	flags |= interrupts << MSICAP0_MMESCAP_OFFSET;
+	flags |= mmc << MSICAP0_MMESCAP_OFFSET;
 	rcar_pci_write_reg(pcie, flags, MSICAP(fn));
 
 	return 0;
drivers/pci/controller/pcie-rockchip-ep.c +3 -2
index 85ca7d9b4c77..2fb50a35146c 100644
@@ -308,10 +308,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
 }
 
 static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
-				    u8 multi_msg_cap)
+				    u8 interrupts)
 {
 	struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
 	struct rockchip_pcie *rockchip = &ep->rockchip;
+	u8 mmc = order_base_2(interrupts);
 	u32 flags;
 
 	flags = rockchip_pcie_read(rockchip,
@@ -319,7 +320,7 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
 				   ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
 	flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK;
 	flags |=
-	   (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
+	   (mmc << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
 	   (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET);
 	flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP;
 	rockchip_pcie_write(rockchip, flags,
drivers/pci/endpoint/pci-epc-core.c +1 -4
index cc1456bd188e..cc012373293a 100644
@@ -309,7 +309,6 @@ EXPORT_SYMBOL_GPL(pci_epc_get_msi);
 int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 interrupts)
 {
 	int ret;
-	u8 encode_int;
 
 	if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
 		return -EINVAL;
@@ -320,10 +319,8 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 interrupts)
 	if (!epc->ops->set_msi)
 		return 0;
 
-	encode_int = order_base_2(interrupts);
-
 	mutex_lock(&epc->lock);
-	ret = epc->ops->set_msi(epc, func_no, vfunc_no, encode_int);
+	ret = epc->ops->set_msi(epc, func_no, vfunc_no, interrupts);
 	mutex_unlock(&epc->lock);
 
 	return ret;
Signature · 1 line
2.49.0
Reviewed-by on v2 4/6
#6 lore raw

Re: [PATCH v2 4/6] PCI: endpoint: cleanup set_msi() callback

Quoted 12 lines · Niklas Cassel

The kdoc for pci_epc_set_msi() says:
"Invoke to set the required number of MSI interrupts."
the kdoc for the callback pci_epc_ops->set_msi() says:
"ops to set the requested number of MSI interrupts in the MSI capability register"

pci_epc_ops->set_msi() does however expect the parameter 'interrupts' to be in the encoding as defined by the MMC Multiple Message Capable field.

Nowhere in the kdoc does it say that the number of interrupts should be in MMC encoding.

Quoted 6 lines

Thus, it is very confusing that the wrapper function (pci_epc_set_msi()) and the callback function (pci_epc_ops->set_msi()) both take a parameter named interrupts, but they both expect completely different encodings.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Same comment as patch 3. Mention the semantic the patch implements.

Quoted 3 lines
Cc <[email protected]> # this is simply a cleanup

A few nits below, but other than that, looks good to me.

Quoted 13 lines
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 4 +++-
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 3 ++-
 drivers/pci/controller/pcie-rcar-ep.c            | 3 ++-
 drivers/pci/controller/pcie-rockchip-ep.c        | 5 +++--
 drivers/pci/endpoint/pci-epc-core.c              | 5 +----
 5 files changed, 11 insertions(+), 9 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +0 -0
index 78b4d009cd04..f307256826e6 100644

drivers/pci/controller/cadence/pcie-cadence-ep.c static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn, · line 224

Quoted 6 lines
drivers/pci/controller/cadence/pcie-cadence-ep.c +2 -1
@@ -220,10 +220,12 @@ static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
 	clear_bit(r, &ep->ob_region_map);
 }
 
-static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 mmc)
+static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
+				u8 interrupts)

To be extra clear, I would rename this num_interrupts or nr_interrupts. No confusion possible with such name.

drivers/pci/controller/pcie-rcar-ep.c static int rcar_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, · line 264

Quoted 9 lines
drivers/pci/controller/pcie-rcar-ep.c +1 -0
index 9da39a4617b6..b25ad23bedb7 100644
@@ -261,10 +261,11 @@ static int rcar_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
 {
 	struct rcar_pcie_endpoint *ep = epc_get_drvdata(epc);
 	struct rcar_pcie *pcie = &ep->pcie;
+	u8 mmc = order_base_2(interrupts);

Same rename suggested here and for the other drivers.

Signature · 2 lines
Damien Le Moal
Western Digital Research
#7 lore raw

PATCH v2 5/6 PCI: endpoint: cleanup get_msix() callback

In reply to Niklas Cassel

The kdoc for pci_epc_get_msix() says:
"Invoke to get the number of MSI-X interrupts allocated by the RC" the kdoc for the callback pci_epc_ops->get_msix() says:
"ops to get the number of MSI-X interrupts allocated by the RC from the MSI-X capability register"

pci_epc_ops->get_msix() does however return the number of interrupts in the encoding as defined by the Table Size field.

Nowhere in the kdoc does it say that the returned number of interrupts is in Table Size encoding.

Thus, it is very confusing that the wrapper function (pci_epc_get_msix()) and the callback function (pci_epc_ops->get_msix()) don't return the same value.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Cc <[email protected]> # this is simply a cleanup
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 2 +-
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 2 +-
 drivers/pci/endpoint/pci-epc-core.c              | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +1 -1
index f307256826e6..bbb310135977 100644
@@ -283,7 +283,7 @@ static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 
 	val &= PCI_MSIX_FLAGS_QSIZE;
 
-	return val;
+	return val + 1;
 }
 
 static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
drivers/pci/controller/dwc/pcie-designware-ep.c +1 -1
index e7a916bf6b2c..d74d21c42559 100644
@@ -576,7 +576,7 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 
 	val &= PCI_MSIX_FLAGS_QSIZE;
 
-	return val;
+	return val + 1;
 }
 
 static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
drivers/pci/endpoint/pci-epc-core.c +1 -1
index cc012373293a..7b4a9292f801 100644
@@ -352,7 +352,7 @@ int pci_epc_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 	if (interrupt < 0)
 		return 0;
 
-	return interrupt + 1;
+	return interrupt;
 }
 EXPORT_SYMBOL_GPL(pci_epc_get_msix);
 
Signature · 1 line
2.49.0
Reviewed-by on v2 5/6
#8 lore raw

Re: [PATCH v2 5/6] PCI: endpoint: cleanup get_msix() callback

Quoted 12 lines · Niklas Cassel

The kdoc for pci_epc_get_msix() says:
"Invoke to get the number of MSI-X interrupts allocated by the RC" the kdoc for the callback pci_epc_ops->get_msix() says:
"ops to get the number of MSI-X interrupts allocated by the RC from the MSI-X capability register"

pci_epc_ops->get_msix() does however return the number of interrupts in the encoding as defined by the Table Size field.

Nowhere in the kdoc does it say that the returned number of interrupts is in Table Size encoding.

Quoted 6 lines

Thus, it is very confusing that the wrapper function (pci_epc_get_msix()) and the callback function (pci_epc_ops->get_msix()) don't return the same value.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Same comment as previous patches. Mention the semantic.

But looks good.

Signature · 2 lines
Damien Le Moal
Western Digital Research
#9 lore raw

PATCH v2 6/6 PCI: endpoint: cleanup set_msix() callback

In reply to Niklas Cassel

The kdoc for pci_epc_set_msix() says:
"Invoke to set the required number of MSI-X interrupts." the kdoc for the callback pci_epc_ops->set_msix() says:
"ops to set the requested number of MSI-X interrupts in the MSI-X capability register"

pci_epc_ops->set_msix() does however expect the parameter 'interrupts' to be in the encoding as defined by the Table Size field.

Nowhere in the kdoc does it say that the number of interrupts should be in Table Size encoding.

Thus, it is very confusing that the wrapper function (pci_epc_set_msix()) and the callback function (pci_epc_ops->set_msix()) both take a parameter named interrupts, but they both expect completely different encodings.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Cc <[email protected]> # this is simply a cleanup
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 5 ++---
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 5 ++---
 drivers/pci/endpoint/pci-epc-core.c              | 2 +-
 3 files changed, 5 insertions(+), 7 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +2 -3
index bbb310135977..542533a8c56a 100644
@@ -294,14 +294,13 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
 	struct cdns_pcie *pcie = &ep->pcie;
 	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 	u32 val, reg;
-	u16 actual_interrupts = interrupts + 1;
 
 	fn = cdns_pcie_get_fn_from_vfn(pcie, fn, vfn);
 
 	reg = cap + PCI_MSIX_FLAGS;
 	val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
 	val &= ~PCI_MSIX_FLAGS_QSIZE;
-	val |= interrupts; /* 0's based value */
+	val |= interrupts - 1; /* encoded as N-1 */
 	cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
 
 	/* Set MSI-X BAR and offset */
@@ -311,7 +310,7 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
 
 	/* Set PBA BAR and offset.  BAR must match MSI-X BAR */
 	reg = cap + PCI_MSIX_PBA;
-	val = (offset + (actual_interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
 	cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
 
 	return 0;
drivers/pci/controller/dwc/pcie-designware-ep.c +2 -3
index d74d21c42559..0d204149a6e2 100644
@@ -586,7 +586,6 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 	struct dw_pcie_ep_func *ep_func;
 	u32 val, reg;
-	u16 actual_interrupts = interrupts + 1;
 
 	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
 	if (!ep_func || !ep_func->msix_cap)
@@ -597,7 +596,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	reg = ep_func->msix_cap + PCI_MSIX_FLAGS;
 	val = dw_pcie_ep_readw_dbi(ep, func_no, reg);
 	val &= ~PCI_MSIX_FLAGS_QSIZE;
-	val |= interrupts; /* 0's based value */
+	val |= interrupts - 1; /* encoded as N-1 */
 	dw_pcie_writew_dbi(pci, reg, val);
 
 	reg = ep_func->msix_cap + PCI_MSIX_TABLE;
@@ -605,7 +604,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
 
 	reg = ep_func->msix_cap + PCI_MSIX_PBA;
-	val = (offset + (actual_interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
 	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);
 
 	dw_pcie_dbi_ro_wr_dis(pci);
drivers/pci/endpoint/pci-epc-core.c +1 -1
index 7b4a9292f801..ea4e64249949 100644
@@ -382,7 +382,7 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
 		return 0;
 
 	mutex_lock(&epc->lock);
-	ret = epc->ops->set_msix(epc, func_no, vfunc_no, interrupts - 1, bir,
+	ret = epc->ops->set_msix(epc, func_no, vfunc_no, interrupts, bir,
 				 offset);
 	mutex_unlock(&epc->lock);
 
Signature · 1 line
2.49.0
Reviewed-by on v2 6/6
#10 lore raw

Re: [PATCH v2 6/6] PCI: endpoint: cleanup set_msix() callback

Quoted 12 lines · Niklas Cassel

The kdoc for pci_epc_set_msix() says:
"Invoke to set the required number of MSI-X interrupts." the kdoc for the callback pci_epc_ops->set_msix() says:
"ops to set the requested number of MSI-X interrupts in the MSI-X capability register"

pci_epc_ops->set_msix() does however expect the parameter 'interrupts' to be in the encoding as defined by the Table Size field.

Nowhere in the kdoc does it say that the number of interrupts should be in Table Size encoding.

Quoted 6 lines

Thus, it is very confusing that the wrapper function (pci_epc_set_msix()) and the callback function (pci_epc_ops->set_msix()) both take a parameter named interrupts, but they both expect completely different encodings.

Cleanup the API so that the wrapper function and the callback function will have the same semantics.

Again... :)

Quoted 3 lines
Cc <[email protected]> # this is simply a cleanup

A nit below, but looks good.

Quoted 11 lines
---
 drivers/pci/controller/cadence/pcie-cadence-ep.c | 5 ++---
 drivers/pci/controller/dwc/pcie-designware-ep.c  | 5 ++---
 drivers/pci/endpoint/pci-epc-core.c              | 2 +-
 3 files changed, 5 insertions(+), 7 deletions(-)
drivers/pci/controller/cadence/pcie-cadence-ep.c +0 -0
index bbb310135977..542533a8c56a 100644

drivers/pci/controller/cadence/pcie-cadence-ep.c static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn, · line 297

Quoted 4 lines
drivers/pci/controller/cadence/pcie-cadence-ep.c +0 -1
@@ -294,14 +294,13 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
 	struct cdns_pcie *pcie = &ep->pcie;
 	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 	u32 val, reg;
-	u16 actual_interrupts = interrupts + 1;

Again suggest renaming interrupts to num_interrupts or nr_interrupts to avoid any confusion.

Signature · 2 lines
Damien Le Moal
Western Digital Research
#11 lore raw
In reply to Niklas Cassel

Hello,

Quoted 6 lines

PCI: dwc: ep: Fix broken set_msix() callback
PCI: cadence-ep: Fix broken set_msix() callback
PCI: endpoint: cleanup get_msi() callback
PCI: endpoint: cleanup set_msi() callback
PCI: endpoint: cleanup get_msix() callback
PCI: endpoint: cleanup set_msix() callback

Note that PCI prefers to capitalise first letter of the subject.

Thank you!

Krzysztof

#12 lore raw
Quoted 1 line · Krzysztof Wilczyński

Hello,

Hello

Quoted 9 lines
Quoted 7 lines

PCI: dwc: ep: Fix broken set_msix() callback
PCI: cadence-ep: Fix broken set_msix() callback
PCI: endpoint: cleanup get_msi() callback
PCI: endpoint: cleanup set_msi() callback
PCI: endpoint: cleanup get_msix() callback
PCI: endpoint: cleanup set_msix() callback

Note that PCI prefers to capitalise first letter of the subject.

Do I need to resend or can some of the maintainers fix this up while applying?

#13 lore raw
Quoted 13 lines · Niklas Cassel
Quoted 1 line · Krzysztof Wilczyński

Hello,

Hello

Quoted 8 lines
Quoted 7 lines

PCI: dwc: ep: Fix broken set_msix() callback
PCI: cadence-ep: Fix broken set_msix() callback
PCI: endpoint: cleanup get_msi() callback
PCI: endpoint: cleanup set_msi() callback
PCI: endpoint: cleanup get_msix() callback
PCI: endpoint: cleanup set_msix() callback

Quoted 3 lines
Quoted 1 line

Note that PCI prefers to capitalise first letter of the subject.

Do I need to resend or can some of the maintainers fix this up while applying?

I will fix it up while applying.

- Mani

Signature · 1 line
மணிவண்ணன் சதாசிவம்