Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 178175
b: refs/heads/master
c: 7a96c6b
h: refs/heads/master
i:
  178173: b598e33
  178171: 66ffab7
  178167: a6e9344
  178159: 6c43524
  178143: 317b2d8
  178111: 18fece4
  178047: cffdf18
  177919: 9c7efbf
  177663: b4eb24f
  177151: 4efd7d3
  176127: a3c9286
v: v3
  • Loading branch information
Benjamin Herrenschmidt committed Dec 18, 2009
1 parent c8b3f5e commit 9822ac4
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bb7f20b1c639606def3b91f4e4aca6daeee5d80a
refs/heads/master: 7a96c6b22efbd84e195836e192a3ce478cd6e14c
11 changes: 10 additions & 1 deletion trunk/arch/powerpc/sysdev/mpic_msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)

pr_debug("mpic: found U3, guessing msi allocator setup\n");

/* Reserve source numbers we know are reserved in the HW */
/* Reserve source numbers we know are reserved in the HW.
*
* This is a bit of a mix of U3 and U4 reserves but that's going
* to work fine, we have plenty enugh numbers left so let's just
* mark anything we don't like reserved.
*/
for (i = 0; i < 8; i++)
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

Expand All @@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
for (i = 100; i < 105; i++)
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

for (i = 124; i < mpic->irq_count; i++)
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);


np = NULL;
while ((np = of_find_all_nodes(np))) {
pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
Expand Down
46 changes: 39 additions & 7 deletions trunk/arch/powerpc/sysdev/mpic_u3msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
return addr;
}

static u64 find_ht_magic_addr(struct pci_dev *pdev)
static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
{
struct pci_bus *bus;
unsigned int pos;

for (bus = pdev->bus; bus; bus = bus->parent) {
for (bus = pdev->bus; bus && bus->self; bus = bus->parent) {
pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
if (pos)
return read_ht_magic_addr(bus->self, pos);
Expand All @@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev)
return 0;
}

static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
{
struct pci_controller *hose = pci_bus_to_host(pdev->bus);

/* U4 PCIe MSIs need to write to the special register in
* the bridge that generates interrupts. There should be
* theorically a register at 0xf8005000 where you just write
* the MSI number and that triggers the right interrupt, but
* unfortunately, this is busted in HW, the bridge endian swaps
* the value and hits the wrong nibble in the register.
*
* So instead we use another register set which is used normally
* for converting HT interrupts to MPIC interrupts, which decodes
* the interrupt number as part of the low address bits
*
* This will not work if we ever use more than one legacy MSI in
* a block but we never do. For one MSI or multiple MSI-X where
* each interrupt address can be specified separately, it works
* just fine.
*/
if (of_device_is_compatible(hose->dn, "u4-pcie") ||
of_device_is_compatible(hose->dn, "U4-pcie"))
return 0xf8004000 | (hwirq << 4);

return 0;
}

static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
pr_debug("u3msi: MSI-X untested, trying anyway.\n");

/* If we can't find a magic address then MSI ain't gonna work */
if (find_ht_magic_addr(pdev) == 0) {
if (find_ht_magic_addr(pdev, 0) == 0 &&
find_u4_magic_addr(pdev, 0) == 0) {
pr_debug("u3msi: no magic address found for %s\n",
pci_name(pdev));
return -ENXIO;
Expand Down Expand Up @@ -118,17 +146,19 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
u64 addr;
int hwirq;

addr = find_ht_magic_addr(pdev);
msg.address_lo = addr & 0xFFFFFFFF;
msg.address_hi = addr >> 32;

list_for_each_entry(entry, &pdev->msi_list, list) {
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
if (hwirq < 0) {
pr_debug("u3msi: failed allocating hwirq\n");
return hwirq;
}

addr = find_ht_magic_addr(pdev, hwirq);
if (addr == 0)
addr = find_u4_magic_addr(pdev, hwirq);
msg.address_lo = addr & 0xFFFFFFFF;
msg.address_hi = addr >> 32;

virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
if (virq == NO_IRQ) {
pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
Expand All @@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
virq, hwirq, (unsigned long)addr);

printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
virq, hwirq, (unsigned long)addr);
msg.data = hwirq;
write_msi_msg(virq, &msg);

Expand Down

0 comments on commit 9822ac4

Please sign in to comment.