aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/tile/gxio/iorpc_trio.c23
-rw-r--r--arch/tile/include/arch/trio.h39
-rw-r--r--arch/tile/include/gxio/iorpc_trio.h5
-rw-r--r--arch/tile/kernel/pci_gx.c59
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
62EXPORT_SYMBOL(gxio_trio_alloc_memory_maps); 62EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
63 63
64struct alloc_scatter_queues_param {
65 unsigned int count;
66 unsigned int first;
67 unsigned int flags;
68};
69
70int 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
86EXPORT_SYMBOL(gxio_trio_alloc_scatter_queues);
64 87
65struct alloc_pio_regions_param { 88struct 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__
35typedef 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
58int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
59 unsigned int count, unsigned int first,
60 unsigned int flags);
61
57int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context, 62int 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);