diff options
-rw-r--r-- | arch/tile/gxio/iorpc_trio.c | 23 | ||||
-rw-r--r-- | arch/tile/include/arch/trio.h | 39 | ||||
-rw-r--r-- | arch/tile/include/gxio/iorpc_trio.h | 5 | ||||
-rw-r--r-- | arch/tile/kernel/pci_gx.c | 59 |
4 files changed, 106 insertions, 20 deletions
diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c index cef4b2209cda..da6e18e049c3 100644 --- a/arch/tile/gxio/iorpc_trio.c +++ b/arch/tile/gxio/iorpc_trio.c | |||
@@ -61,6 +61,29 @@ int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context, | |||
61 | 61 | ||
62 | EXPORT_SYMBOL(gxio_trio_alloc_memory_maps); | 62 | EXPORT_SYMBOL(gxio_trio_alloc_memory_maps); |
63 | 63 | ||
64 | struct alloc_scatter_queues_param { | ||
65 | unsigned int count; | ||
66 | unsigned int first; | ||
67 | unsigned int flags; | ||
68 | }; | ||
69 | |||
70 | int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context, | ||
71 | unsigned int count, unsigned int first, | ||
72 | unsigned int flags) | ||
73 | { | ||
74 | struct alloc_scatter_queues_param temp; | ||
75 | struct alloc_scatter_queues_param *params = &temp; | ||
76 | |||
77 | params->count = count; | ||
78 | params->first = first; | ||
79 | params->flags = flags; | ||
80 | |||
81 | return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, | ||
82 | sizeof(*params), | ||
83 | GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES); | ||
84 | } | ||
85 | |||
86 | EXPORT_SYMBOL(gxio_trio_alloc_scatter_queues); | ||
64 | 87 | ||
65 | struct alloc_pio_regions_param { | 88 | struct alloc_pio_regions_param { |
66 | unsigned int count; | 89 | unsigned int count; |
diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h index d3000a871a21..c0ddedcae085 100644 --- a/arch/tile/include/arch/trio.h +++ b/arch/tile/include/arch/trio.h | |||
@@ -23,6 +23,45 @@ | |||
23 | #ifndef __ASSEMBLER__ | 23 | #ifndef __ASSEMBLER__ |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Map SQ Doorbell Format. | ||
27 | * This describes the format of the write-only doorbell register that exists | ||
28 | * in the last 8-bytes of the MAP_SQ_BASE/LIM range. This register is only | ||
29 | * writable from PCIe space. Writes to this register will not be written to | ||
30 | * Tile memory space and thus no IO VA translation is required if the last | ||
31 | * page of the BASE/LIM range is not otherwise written. | ||
32 | */ | ||
33 | |||
34 | __extension__ | ||
35 | typedef union | ||
36 | { | ||
37 | struct | ||
38 | { | ||
39 | #ifndef __BIG_ENDIAN__ | ||
40 | /* | ||
41 | * When written with a 1, the associated MAP_SQ region's doorbell | ||
42 | * interrupt will be triggered once all previous writes are visible to | ||
43 | * Tile software. | ||
44 | */ | ||
45 | uint_reg_t doorbell : 1; | ||
46 | /* | ||
47 | * When written with a 1, the descriptor at the head of the associated | ||
48 | * MAP_SQ's FIFO will be dequeued. | ||
49 | */ | ||
50 | uint_reg_t pop : 1; | ||
51 | /* Reserved. */ | ||
52 | uint_reg_t __reserved : 62; | ||
53 | #else /* __BIG_ENDIAN__ */ | ||
54 | uint_reg_t __reserved : 62; | ||
55 | uint_reg_t pop : 1; | ||
56 | uint_reg_t doorbell : 1; | ||
57 | #endif | ||
58 | }; | ||
59 | |||
60 | uint_reg_t word; | ||
61 | } TRIO_MAP_SQ_DOORBELL_FMT_t; | ||
62 | |||
63 | |||
64 | /* | ||
26 | * Tile PIO Region Configuration - CFG Address Format. | 65 | * Tile PIO Region Configuration - CFG Address Format. |
27 | * This register describes the address format for PIO accesses when the | 66 | * This register describes the address format for PIO accesses when the |
28 | * associated region is setup with TYPE=CFG. | 67 | * associated region is setup with TYPE=CFG. |
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h index 58105c31228b..d95b96fd6c93 100644 --- a/arch/tile/include/gxio/iorpc_trio.h +++ b/arch/tile/include/gxio/iorpc_trio.h | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404) | 31 | #define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404) |
32 | 32 | ||
33 | #define GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e) | ||
33 | #define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412) | 34 | #define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412) |
34 | 35 | ||
35 | #define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414) | 36 | #define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414) |
@@ -54,6 +55,10 @@ int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context, | |||
54 | unsigned int flags); | 55 | unsigned int flags); |
55 | 56 | ||
56 | 57 | ||
58 | int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context, | ||
59 | unsigned int count, unsigned int first, | ||
60 | unsigned int flags); | ||
61 | |||
57 | int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context, | 62 | int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context, |
58 | unsigned int count, unsigned int first, | 63 | unsigned int count, unsigned int first, |
59 | unsigned int flags); | 64 | unsigned int flags); |
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index 2cc3e64ab0df..e0d666483e13 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c | |||
@@ -1474,32 +1474,55 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | |||
1474 | trio_context = controller->trio; | 1474 | trio_context = controller->trio; |
1475 | 1475 | ||
1476 | /* | 1476 | /* |
1477 | * Allocate the Mem-Map that will accept the MSI write and | 1477 | * Allocate a scatter-queue that will accept the MSI write and |
1478 | * trigger the TILE-side interrupts. | 1478 | * trigger the TILE-side interrupts. We use the scatter-queue regions |
1479 | * before the mem map regions, because the latter are needed by more | ||
1480 | * applications. | ||
1479 | */ | 1481 | */ |
1480 | mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0); | 1482 | mem_map = gxio_trio_alloc_scatter_queues(trio_context, 1, 0, 0); |
1481 | if (mem_map < 0) { | 1483 | if (mem_map >= 0) { |
1482 | dev_printk(KERN_INFO, &pdev->dev, | 1484 | TRIO_MAP_SQ_DOORBELL_FMT_t doorbell_template = {{ |
1483 | "%s Mem-Map alloc failure. " | 1485 | .pop = 0, |
1484 | "Failed to initialize MSI interrupts. " | 1486 | .doorbell = 1, |
1485 | "Falling back to legacy interrupts.\n", | 1487 | }}; |
1486 | desc->msi_attrib.is_msix ? "MSI-X" : "MSI"); | 1488 | |
1489 | mem_map += TRIO_NUM_MAP_MEM_REGIONS; | ||
1490 | mem_map_base = MEM_MAP_INTR_REGIONS_BASE + | ||
1491 | mem_map * MEM_MAP_INTR_REGION_SIZE; | ||
1492 | mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1; | ||
1493 | |||
1494 | msi_addr = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 8; | ||
1495 | msg.data = (unsigned int)doorbell_template.word; | ||
1496 | } else { | ||
1497 | /* SQ regions are out, allocate from map mem regions. */ | ||
1498 | mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0); | ||
1499 | if (mem_map < 0) { | ||
1500 | dev_printk(KERN_INFO, &pdev->dev, | ||
1501 | "%s Mem-Map alloc failure. " | ||
1502 | "Failed to initialize MSI interrupts. " | ||
1503 | "Falling back to legacy interrupts.\n", | ||
1504 | desc->msi_attrib.is_msix ? "MSI-X" : "MSI"); | ||
1505 | ret = -ENOMEM; | ||
1506 | goto msi_mem_map_alloc_failure; | ||
1507 | } | ||
1487 | 1508 | ||
1488 | ret = -ENOMEM; | 1509 | mem_map_base = MEM_MAP_INTR_REGIONS_BASE + |
1489 | goto msi_mem_map_alloc_failure; | 1510 | mem_map * MEM_MAP_INTR_REGION_SIZE; |
1511 | mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1; | ||
1512 | |||
1513 | msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - | ||
1514 | TRIO_MAP_MEM_REG_INT0; | ||
1515 | |||
1516 | msg.data = mem_map; | ||
1490 | } | 1517 | } |
1491 | 1518 | ||
1492 | /* We try to distribute different IRQs to different tiles. */ | 1519 | /* We try to distribute different IRQs to different tiles. */ |
1493 | cpu = tile_irq_cpu(irq); | 1520 | cpu = tile_irq_cpu(irq); |
1494 | 1521 | ||
1495 | /* | 1522 | /* |
1496 | * Now call up to the HV to configure the Mem-Map interrupt and | 1523 | * Now call up to the HV to configure the MSI interrupt and |
1497 | * set up the IPI binding. | 1524 | * set up the IPI binding. |
1498 | */ | 1525 | */ |
1499 | mem_map_base = MEM_MAP_INTR_REGIONS_BASE + | ||
1500 | mem_map * MEM_MAP_INTR_REGION_SIZE; | ||
1501 | mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1; | ||
1502 | |||
1503 | ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu), | 1526 | ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu), |
1504 | KERNEL_PL, irq, controller->mac, | 1527 | KERNEL_PL, irq, controller->mac, |
1505 | mem_map, mem_map_base, mem_map_limit, | 1528 | mem_map, mem_map_base, mem_map_limit, |
@@ -1512,13 +1535,9 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | |||
1512 | 1535 | ||
1513 | irq_set_msi_desc(irq, desc); | 1536 | irq_set_msi_desc(irq, desc); |
1514 | 1537 | ||
1515 | msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - TRIO_MAP_MEM_REG_INT0; | ||
1516 | |||
1517 | msg.address_hi = msi_addr >> 32; | 1538 | msg.address_hi = msi_addr >> 32; |
1518 | msg.address_lo = msi_addr & 0xffffffff; | 1539 | msg.address_lo = msi_addr & 0xffffffff; |
1519 | 1540 | ||
1520 | msg.data = mem_map; | ||
1521 | |||
1522 | write_msi_msg(irq, &msg); | 1541 | write_msi_msg(irq, &msg); |
1523 | irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq); | 1542 | irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq); |
1524 | irq_set_handler_data(irq, controller); | 1543 | irq_set_handler_data(irq, controller); |