Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 114502
b: refs/heads/master
c: 25235f7
h: refs/heads/master
v: v3
  • Loading branch information
Michael Ellerman authored and Paul Mackerras committed Aug 20, 2008
1 parent a05a363 commit e717f4b
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 132 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: 7e7ab3677502a0f798f38bfa1a7d53dd22faa0bc
refs/heads/master: 25235f712b680d00756a73ee64289137989fc6fd
4 changes: 2 additions & 2 deletions trunk/arch/powerpc/include/asm/mpic.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/irq.h>
#include <linux/sysdev.h>
#include <asm/dcr.h>
#include <asm/msi_bitmap.h>

/*
* Global registers
Expand Down Expand Up @@ -301,8 +302,7 @@ struct mpic
#endif

#ifdef CONFIG_PCI_MSI
spinlock_t bitmap_lock;
unsigned long *hwirq_bitmap;
struct msi_bitmap msi_bitmap;
#endif

#ifdef CONFIG_MPIC_BROKEN_REGREAD
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/powerpc/sysdev/mpic.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#ifdef CONFIG_PCI_MSI
extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
extern int mpic_msi_init_allocator(struct mpic *mpic);
extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
extern int mpic_u3msi_init(struct mpic *mpic);
extern int mpic_pasemi_msi_init(struct mpic *mpic);
#else
Expand Down
123 changes: 18 additions & 105 deletions trunk/arch/powerpc/sysdev/mpic_msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,59 +15,17 @@
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/msi_bitmap.h>

#include <sysdev/mpic.h>

static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
{
pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
}

void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
{
unsigned long flags;

/* The mpic calls this even when there is no allocator setup */
if (!mpic->hwirq_bitmap)
if (!mpic->msi_bitmap.bitmap)
return;

spin_lock_irqsave(&mpic->bitmap_lock, flags);
__mpic_msi_reserve_hwirq(mpic, hwirq);
spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
}

irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
{
unsigned long flags;
int offset, order = get_count_order(num);

spin_lock_irqsave(&mpic->bitmap_lock, flags);
/*
* This is fast, but stricter than we need. We might want to add
* a fallback routine which does a linear search with no alignment.
*/
offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
order);
spin_unlock_irqrestore(&mpic->bitmap_lock, flags);

pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
num, order, offset);

return offset;
}

void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
{
unsigned long flags;
int order = get_count_order(num);

pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
num, order, offset);

spin_lock_irqsave(&mpic->bitmap_lock, flags);
bitmap_release_region(mpic->hwirq_bitmap, offset, order);
spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
}

#ifdef CONFIG_MPIC_U3_HT_IRQS
Expand All @@ -83,13 +41,13 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)

/* Reserve source numbers we know are reserved in the HW */
for (i = 0; i < 8; i++)
__mpic_msi_reserve_hwirq(mpic, i);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

for (i = 42; i < 46; i++)
__mpic_msi_reserve_hwirq(mpic, i);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

for (i = 100; i < 105; i++)
__mpic_msi_reserve_hwirq(mpic, i);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

np = NULL;
while ((np = of_find_all_nodes(np))) {
Expand All @@ -99,7 +57,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
while (of_irq_map_one(np, index++, &oirq) == 0) {
ops->xlate(mpic->irqhost, NULL, oirq.specifier,
oirq.size, &hwirq, &flags);
__mpic_msi_reserve_hwirq(mpic, hwirq);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
}
}

Expand All @@ -112,70 +70,25 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
}
#endif

static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
{
int i, len;
const u32 *p;

p = of_get_property(mpic->irqhost->of_node,
"msi-available-ranges", &len);
if (!p) {
pr_debug("mpic: no msi-available-ranges property found on %s\n",
mpic->irqhost->of_node->full_name);
return -ENODEV;
}

if (len % 8 != 0) {
printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
"property on %s\n", mpic->irqhost->of_node->full_name);
return -EINVAL;
}

bitmap_allocate_region(mpic->hwirq_bitmap, 0,
get_count_order(mpic->irq_count));

/* Format is: (<u32 start> <u32 count>)+ */
len /= sizeof(u32);
for (i = 0; i < len / 2; i++, p += 2)
mpic_msi_free_hwirqs(mpic, *p, *(p + 1));

return 0;
}

int mpic_msi_init_allocator(struct mpic *mpic)
{
int rc, size;

BUG_ON(mpic->hwirq_bitmap);
spin_lock_init(&mpic->bitmap_lock);
int rc;

size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count,
mpic->irqhost->of_node);
if (rc)
return rc;

mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);

if (!mpic->hwirq_bitmap) {
pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
return -ENOMEM;
}

memset(mpic->hwirq_bitmap, 0, size);

rc = mpic_msi_reserve_dt_hwirqs(mpic);
if (rc) {
rc = msi_bitmap_reserve_dt_hwirqs(&mpic->msi_bitmap);
if (rc > 0) {
if (mpic->flags & MPIC_U3_HT_IRQS)
rc = mpic_msi_reserve_u3_hwirqs(mpic);

if (rc)
goto out_free;
if (rc) {
msi_bitmap_free(&mpic->msi_bitmap);
return rc;
}
}

return 0;

out_free:
if (mem_init_done)
kfree(mpic->hwirq_bitmap);

mpic->hwirq_bitmap = NULL;
return rc;
}
24 changes: 13 additions & 11 deletions trunk/arch/powerpc/sysdev/mpic_pasemi_msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/msi_bitmap.h>

#include "mpic.h"

Expand Down Expand Up @@ -81,8 +82,8 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
continue;

set_irq_msi(entry->irq, NULL);
mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq),
ALLOC_CHUNK);
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
virq_to_hw(entry->irq), ALLOC_CHUNK);
irq_dispose_mapping(entry->irq);
}

Expand All @@ -91,11 +92,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)

static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{
irq_hw_number_t hwirq;
unsigned int virq;
struct msi_desc *entry;
struct msi_msg msg;
int ret;
int hwirq;

pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",
pdev, nvec, type);
Expand All @@ -109,17 +109,19 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
* few MSIs for someone, but restrictions will apply to how the
* sources can be changed independently.
*/
ret = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK);
hwirq = ret;
if (ret < 0) {
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap,
ALLOC_CHUNK);
if (hwirq < 0) {
pr_debug("pasemi_msi: failed allocating hwirq\n");
return hwirq;
}

virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
if (virq == NO_IRQ) {
pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq);
mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK);
pr_debug("pasemi_msi: failed mapping hwirq 0x%x\n",
hwirq);
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq,
ALLOC_CHUNK);
return -ENOSPC;
}

Expand All @@ -133,8 +135,8 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
set_irq_chip(virq, &mpic_pasemi_msi_chip);
set_irq_type(virq, IRQ_TYPE_EDGE_RISING);

pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%x\n",
virq, hwirq, msg.address_lo);
pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \
"addr 0x%x\n", virq, hwirq, msg.address_lo);

/* Likewise, the device writes [0...511] into the target
* register to generate MSI [512...1023]
Expand Down
22 changes: 11 additions & 11 deletions trunk/arch/powerpc/sysdev/mpic_u3msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/msi_bitmap.h>

#include "mpic.h"

Expand Down Expand Up @@ -101,7 +102,8 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
continue;

set_irq_msi(entry->irq, NULL);
mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
virq_to_hw(entry->irq), 1);
irq_dispose_mapping(entry->irq);
}

Expand All @@ -110,38 +112,36 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)

static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{
irq_hw_number_t hwirq;
unsigned int virq;
struct msi_desc *entry;
struct msi_msg msg;
u64 addr;
int ret;
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) {
ret = mpic_msi_alloc_hwirqs(msi_mpic, 1);
if (ret < 0) {
hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
if (hwirq < 0) {
pr_debug("u3msi: failed allocating hwirq\n");
return ret;
return hwirq;
}
hwirq = ret;

virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
if (virq == NO_IRQ) {
pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq);
mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
return -ENOSPC;
}

set_irq_msi(virq, entry);
set_irq_chip(virq, &mpic_u3msi_chip);
set_irq_type(virq, IRQ_TYPE_EDGE_RISING);

pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n",
virq, hwirq, addr);
pr_debug("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 e717f4b

Please sign in to comment.