Skip to content

Commit 1b6069f

Browse files
committed
Merge branch 'pci/controller/mediatek'
- Clear MSI interrupt status before handler to avoid missing MSIs that occur after the handler (qizhong cheng) - Update mediatek-gen3 translation window setup to handle MMIO space that is not a power of two in size (Jianjun Wang) * pci/controller/mediatek: PCI: mediatek-gen3: Fix translation window size calculation PCI: mediatek: Clear interrupt status before dispatching handler
2 parents 1800c66 + 9ccc131 commit 1b6069f

File tree

2 files changed

+58
-37
lines changed

2 files changed

+58
-37
lines changed

drivers/pci/controller/pcie-mediatek-gen3.c

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -245,35 +245,60 @@ static int mtk_pcie_set_trans_table(struct mtk_gen3_pcie *pcie,
245245
resource_size_t cpu_addr,
246246
resource_size_t pci_addr,
247247
resource_size_t size,
248-
unsigned long type, int num)
248+
unsigned long type, int *num)
249249
{
250+
resource_size_t remaining = size;
251+
resource_size_t table_size;
252+
resource_size_t addr_align;
253+
const char *range_type;
250254
void __iomem *table;
251255
u32 val;
252256

253-
if (num >= PCIE_MAX_TRANS_TABLES) {
254-
dev_err(pcie->dev, "not enough translate table for addr: %#llx, limited to [%d]\n",
255-
(unsigned long long)cpu_addr, PCIE_MAX_TRANS_TABLES);
256-
return -ENODEV;
257-
}
257+
while (remaining && (*num < PCIE_MAX_TRANS_TABLES)) {
258+
/* Table size needs to be a power of 2 */
259+
table_size = BIT(fls(remaining) - 1);
260+
261+
if (cpu_addr > 0) {
262+
addr_align = BIT(ffs(cpu_addr) - 1);
263+
table_size = min(table_size, addr_align);
264+
}
265+
266+
/* Minimum size of translate table is 4KiB */
267+
if (table_size < 0x1000) {
268+
dev_err(pcie->dev, "illegal table size %#llx\n",
269+
(unsigned long long)table_size);
270+
return -EINVAL;
271+
}
258272

259-
table = pcie->base + PCIE_TRANS_TABLE_BASE_REG +
260-
num * PCIE_ATR_TLB_SET_OFFSET;
273+
table = pcie->base + PCIE_TRANS_TABLE_BASE_REG + *num * PCIE_ATR_TLB_SET_OFFSET;
274+
writel_relaxed(lower_32_bits(cpu_addr) | PCIE_ATR_SIZE(fls(table_size) - 1), table);
275+
writel_relaxed(upper_32_bits(cpu_addr), table + PCIE_ATR_SRC_ADDR_MSB_OFFSET);
276+
writel_relaxed(lower_32_bits(pci_addr), table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET);
277+
writel_relaxed(upper_32_bits(pci_addr), table + PCIE_ATR_TRSL_ADDR_MSB_OFFSET);
261278

262-
writel_relaxed(lower_32_bits(cpu_addr) | PCIE_ATR_SIZE(fls(size) - 1),
263-
table);
264-
writel_relaxed(upper_32_bits(cpu_addr),
265-
table + PCIE_ATR_SRC_ADDR_MSB_OFFSET);
266-
writel_relaxed(lower_32_bits(pci_addr),
267-
table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET);
268-
writel_relaxed(upper_32_bits(pci_addr),
269-
table + PCIE_ATR_TRSL_ADDR_MSB_OFFSET);
279+
if (type == IORESOURCE_IO) {
280+
val = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO;
281+
range_type = "IO";
282+
} else {
283+
val = PCIE_ATR_TYPE_MEM | PCIE_ATR_TLP_TYPE_MEM;
284+
range_type = "MEM";
285+
}
270286

271-
if (type == IORESOURCE_IO)
272-
val = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO;
273-
else
274-
val = PCIE_ATR_TYPE_MEM | PCIE_ATR_TLP_TYPE_MEM;
287+
writel_relaxed(val, table + PCIE_ATR_TRSL_PARAM_OFFSET);
275288

276-
writel_relaxed(val, table + PCIE_ATR_TRSL_PARAM_OFFSET);
289+
dev_dbg(pcie->dev, "set %s trans window[%d]: cpu_addr = %#llx, pci_addr = %#llx, size = %#llx\n",
290+
range_type, *num, (unsigned long long)cpu_addr,
291+
(unsigned long long)pci_addr, (unsigned long long)table_size);
292+
293+
cpu_addr += table_size;
294+
pci_addr += table_size;
295+
remaining -= table_size;
296+
(*num)++;
297+
}
298+
299+
if (remaining)
300+
dev_warn(pcie->dev, "not enough translate table for addr: %#llx, limited to [%d]\n",
301+
(unsigned long long)cpu_addr, PCIE_MAX_TRANS_TABLES);
277302

278303
return 0;
279304
}
@@ -380,30 +405,20 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
380405
resource_size_t cpu_addr;
381406
resource_size_t pci_addr;
382407
resource_size_t size;
383-
const char *range_type;
384408

385-
if (type == IORESOURCE_IO) {
409+
if (type == IORESOURCE_IO)
386410
cpu_addr = pci_pio_to_address(res->start);
387-
range_type = "IO";
388-
} else if (type == IORESOURCE_MEM) {
411+
else if (type == IORESOURCE_MEM)
389412
cpu_addr = res->start;
390-
range_type = "MEM";
391-
} else {
413+
else
392414
continue;
393-
}
394415

395416
pci_addr = res->start - entry->offset;
396417
size = resource_size(res);
397418
err = mtk_pcie_set_trans_table(pcie, cpu_addr, pci_addr, size,
398-
type, table_index);
419+
type, &table_index);
399420
if (err)
400421
return err;
401-
402-
dev_dbg(pcie->dev, "set %s trans window[%d]: cpu_addr = %#llx, pci_addr = %#llx, size = %#llx\n",
403-
range_type, table_index, (unsigned long long)cpu_addr,
404-
(unsigned long long)pci_addr, (unsigned long long)size);
405-
406-
table_index++;
407422
}
408423

409424
return 0;

drivers/pci/controller/pcie-mediatek.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,12 +617,18 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
617617
if (status & MSI_STATUS){
618618
unsigned long imsi_status;
619619

620+
/*
621+
* The interrupt status can be cleared even if the
622+
* MSI status remains pending. As such, given the
623+
* edge-triggered interrupt type, its status should
624+
* be cleared before being dispatched to the
625+
* handler of the underlying device.
626+
*/
627+
writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
620628
while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
621629
for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM)
622630
generic_handle_domain_irq(port->inner_domain, bit);
623631
}
624-
/* Clear MSI interrupt status */
625-
writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
626632
}
627633
}
628634

0 commit comments

Comments
 (0)