Skip to content

Commit 83153d9

Browse files
kishonLorenzo Pieralisi
authored andcommitted
PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
commit 8963106 ("PCI: endpoint: Add MSI-X interfaces") while adding support to raise MSI-X interrupts from endpoint didn't include BAR Indicator register (BIR) configuration and MSI-X table offset as arguments in pci_epc_set_msix(). This would result in endpoint controller register using random BAR indicator register, the memory for which might not be allocated by the endpoint function driver. Add BAR indicator register and MSI-X table offset as arguments in pci_epc_set_msix() and allocate space for MSI-X table and pending bit array (PBA) in pci-epf-test endpoint function driver. Fixes: 8963106 ("PCI: endpoint: Add MSI-X interfaces") Signed-off-by: Kishon Vijay Abraham I <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]>
1 parent cf376b4 commit 83153d9

File tree

4 files changed

+48
-12
lines changed

4 files changed

+48
-12
lines changed

drivers/pci/controller/dwc/pcie-designware-ep.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
278278
return val;
279279
}
280280

281-
static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
281+
static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
282+
enum pci_barno bir, u32 offset)
282283
{
283284
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
284285
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@ -287,12 +288,22 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
287288
if (!ep->msix_cap)
288289
return -EINVAL;
289290

291+
dw_pcie_dbi_ro_wr_en(pci);
292+
290293
reg = ep->msix_cap + PCI_MSIX_FLAGS;
291294
val = dw_pcie_readw_dbi(pci, reg);
292295
val &= ~PCI_MSIX_FLAGS_QSIZE;
293296
val |= interrupts;
294-
dw_pcie_dbi_ro_wr_en(pci);
295297
dw_pcie_writew_dbi(pci, reg, val);
298+
299+
reg = ep->msix_cap + PCI_MSIX_TABLE;
300+
val = offset | bir;
301+
dw_pcie_writel_dbi(pci, reg, val);
302+
303+
reg = ep->msix_cap + PCI_MSIX_PBA;
304+
val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
305+
dw_pcie_writel_dbi(pci, reg, val);
306+
296307
dw_pcie_dbi_ro_wr_dis(pci);
297308

298309
return 0;

drivers/pci/endpoint/functions/pci-epf-test.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct pci_epf_test {
5050
void *reg[PCI_STD_NUM_BARS];
5151
struct pci_epf *epf;
5252
enum pci_barno test_reg_bar;
53+
size_t msix_table_offset;
5354
struct delayed_work cmd_handler;
5455
struct dma_chan *dma_chan;
5556
struct completion transfer_complete;
@@ -659,6 +660,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
659660

660661
static int pci_epf_test_core_init(struct pci_epf *epf)
661662
{
663+
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
662664
struct pci_epf_header *header = epf->header;
663665
const struct pci_epc_features *epc_features;
664666
struct pci_epc *epc = epf->epc;
@@ -692,7 +694,9 @@ static int pci_epf_test_core_init(struct pci_epf *epf)
692694
}
693695

694696
if (msix_capable) {
695-
ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts);
697+
ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts,
698+
epf_test->test_reg_bar,
699+
epf_test->msix_table_offset);
696700
if (ret) {
697701
dev_err(dev, "MSI-X configuration failed\n");
698702
return ret;
@@ -734,6 +738,10 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
734738
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
735739
struct device *dev = &epf->dev;
736740
struct pci_epf_bar *epf_bar;
741+
size_t msix_table_size = 0;
742+
size_t test_reg_bar_size;
743+
size_t pba_size = 0;
744+
bool msix_capable;
737745
void *base;
738746
int bar, add;
739747
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
@@ -742,13 +750,25 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
742750

743751
epc_features = epf_test->epc_features;
744752

745-
if (epc_features->bar_fixed_size[test_reg_bar])
753+
test_reg_bar_size = ALIGN(sizeof(struct pci_epf_test_reg), 128);
754+
755+
msix_capable = epc_features->msix_capable;
756+
if (msix_capable) {
757+
msix_table_size = PCI_MSIX_ENTRY_SIZE * epf->msix_interrupts;
758+
epf_test->msix_table_offset = test_reg_bar_size;
759+
/* Align to QWORD or 8 Bytes */
760+
pba_size = ALIGN(DIV_ROUND_UP(epf->msix_interrupts, 8), 8);
761+
}
762+
test_reg_size = test_reg_bar_size + msix_table_size + pba_size;
763+
764+
if (epc_features->bar_fixed_size[test_reg_bar]) {
765+
if (test_reg_size > bar_size[test_reg_bar])
766+
return -ENOMEM;
746767
test_reg_size = bar_size[test_reg_bar];
747-
else
748-
test_reg_size = sizeof(struct pci_epf_test_reg);
768+
}
749769

750-
base = pci_epf_alloc_space(epf, test_reg_size,
751-
test_reg_bar, epc_features->align);
770+
base = pci_epf_alloc_space(epf, test_reg_size, test_reg_bar,
771+
epc_features->align);
752772
if (!base) {
753773
dev_err(dev, "Failed to allocated register space\n");
754774
return -ENOMEM;

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,13 @@ EXPORT_SYMBOL_GPL(pci_epc_get_msix);
297297
* @epc: the EPC device on which MSI-X has to be configured
298298
* @func_no: the endpoint function number in the EPC device
299299
* @interrupts: number of MSI-X interrupts required by the EPF
300+
* @bir: BAR where the MSI-X table resides
301+
* @offset: Offset pointing to the start of MSI-X table
300302
*
301303
* Invoke to set the required number of MSI-X interrupts.
302304
*/
303-
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
305+
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
306+
enum pci_barno bir, u32 offset)
304307
{
305308
int ret;
306309

@@ -312,7 +315,7 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
312315
return 0;
313316

314317
mutex_lock(&epc->lock);
315-
ret = epc->ops->set_msix(epc, func_no, interrupts - 1);
318+
ret = epc->ops->set_msix(epc, func_no, interrupts - 1, bir, offset);
316319
mutex_unlock(&epc->lock);
317320

318321
return ret;

include/linux/pci-epc.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ struct pci_epc_ops {
5353
phys_addr_t addr);
5454
int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
5555
int (*get_msi)(struct pci_epc *epc, u8 func_no);
56-
int (*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts);
56+
int (*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts,
57+
enum pci_barno, u32 offset);
5758
int (*get_msix)(struct pci_epc *epc, u8 func_no);
5859
int (*raise_irq)(struct pci_epc *epc, u8 func_no,
5960
enum pci_epc_irq_type type, u16 interrupt_num);
@@ -180,7 +181,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
180181
phys_addr_t phys_addr);
181182
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
182183
int pci_epc_get_msi(struct pci_epc *epc, u8 func_no);
183-
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts);
184+
int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
185+
enum pci_barno, u32 offset);
184186
int pci_epc_get_msix(struct pci_epc *epc, u8 func_no);
185187
int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
186188
enum pci_epc_irq_type type, u16 interrupt_num);

0 commit comments

Comments
 (0)