Commit 7e7ab367 authored by Michael Ellerman's avatar Michael Ellerman Committed by Paul Mackerras

powerpc: Convert the FSL MSI code to use msi_bitmap

This is 90% straight forward, although we have to change a few
printk format strings as well because of the change in type of hwirq.
Signed-off-by: default avatarMichael Ellerman <michael@ellerman.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 7e302869
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
*/ */
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/bitmap.h>
#include <linux/msi.h> #include <linux/msi.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -67,96 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = { ...@@ -67,96 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = {
.map = fsl_msi_host_map, .map = fsl_msi_host_map,
}; };
static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num)
{
unsigned long flags;
int order = get_count_order(num);
int offset;
spin_lock_irqsave(&msi->bitmap_lock, flags);
offset = bitmap_find_free_region(msi->fsl_msi_bitmap,
NR_MSI_IRQS, order);
spin_unlock_irqrestore(&msi->bitmap_lock, flags);
pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n",
__func__, num, order, offset);
return offset;
}
static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num)
{
unsigned long flags;
int order = get_count_order(num);
pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n",
__func__, num, order, offset);
spin_lock_irqsave(&msi->bitmap_lock, flags);
bitmap_release_region(msi->fsl_msi_bitmap, offset, order);
spin_unlock_irqrestore(&msi->bitmap_lock, flags);
}
static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi)
{
int i;
int len;
const u32 *p;
bitmap_allocate_region(msi->fsl_msi_bitmap, 0,
get_count_order(NR_MSI_IRQS));
p = of_get_property(msi->irqhost->of_node, "msi-available-ranges",
&len);
if (!p) {
/* No msi-available-ranges property,
* All the 256 MSI interrupts can be used
*/
fsl_msi_free_hwirqs(msi, 0, 0x100);
return 0;
}
if ((len % (2 * sizeof(u32))) != 0) {
printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges "
"property on %s\n", msi->irqhost->of_node->full_name);
return -EINVAL;
}
/* Format is: (<u32 start> <u32 count>)+ */
len /= 2 * sizeof(u32);
for (i = 0; i < len; i++, p += 2)
fsl_msi_free_hwirqs(msi, *p, *(p + 1));
return 0;
}
static int fsl_msi_init_allocator(struct fsl_msi *msi_data) static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
{ {
int rc; int rc;
int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32);
msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL);
if (msi_data->fsl_msi_bitmap == NULL) {
pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
__func__);
return -ENOMEM;
}
rc = fsl_msi_free_dt_hwirqs(msi_data); rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
msi_data->irqhost->of_node);
if (rc) if (rc)
goto out_free; return rc;
return 0;
out_free:
kfree(msi_data->fsl_msi_bitmap);
msi_data->fsl_msi_bitmap = NULL; rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
if (rc < 0) {
msi_bitmap_free(&msi_data->bitmap);
return rc; return rc;
}
return 0;
} }
static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
...@@ -176,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) ...@@ -176,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
if (entry->irq == NO_IRQ) if (entry->irq == NO_IRQ)
continue; continue;
set_irq_msi(entry->irq, NULL); set_irq_msi(entry->irq, NULL);
fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); msi_bitmap_free_hwirqs(&msi_data->bitmap,
virq_to_hw(entry->irq), 1);
irq_dispose_mapping(entry->irq); irq_dispose_mapping(entry->irq);
} }
...@@ -198,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, ...@@ -198,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{ {
irq_hw_number_t hwirq; int rc, hwirq;
int rc;
unsigned int virq; unsigned int virq;
struct msi_desc *entry; struct msi_desc *entry;
struct msi_msg msg; struct msi_msg msg;
struct fsl_msi *msi_data = fsl_msi; struct fsl_msi *msi_data = fsl_msi;
list_for_each_entry(entry, &pdev->msi_list, list) { list_for_each_entry(entry, &pdev->msi_list, list) {
hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
if (hwirq < 0) { if (hwirq < 0) {
rc = hwirq; rc = hwirq;
pr_debug("%s: fail allocating msi interrupt\n", pr_debug("%s: fail allocating msi interrupt\n",
...@@ -217,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) ...@@ -217,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
virq = irq_create_mapping(msi_data->irqhost, hwirq); virq = irq_create_mapping(msi_data->irqhost, hwirq);
if (virq == NO_IRQ) { if (virq == NO_IRQ) {
pr_debug("%s: fail mapping hwirq 0x%lx\n", pr_debug("%s: fail mapping hwirq 0x%x\n",
__func__, hwirq); __func__, hwirq);
fsl_msi_free_hwirqs(msi_data, hwirq, 1); msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
rc = -ENOSPC; rc = -ENOSPC;
goto out_free; goto out_free;
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#ifndef _POWERPC_SYSDEV_FSL_MSI_H #ifndef _POWERPC_SYSDEV_FSL_MSI_H
#define _POWERPC_SYSDEV_FSL_MSI_H #define _POWERPC_SYSDEV_FSL_MSI_H
#include <asm/msi_bitmap.h>
#define NR_MSI_REG 8 #define NR_MSI_REG 8
#define IRQS_PER_MSI_REG 32 #define IRQS_PER_MSI_REG 32
#define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG)
...@@ -31,8 +33,7 @@ struct fsl_msi { ...@@ -31,8 +33,7 @@ struct fsl_msi {
void __iomem *msi_regs; void __iomem *msi_regs;
u32 feature; u32 feature;
unsigned long *fsl_msi_bitmap; struct msi_bitmap bitmap;
spinlock_t bitmap_lock;
}; };
#endif /* _POWERPC_SYSDEV_FSL_MSI_H */ #endif /* _POWERPC_SYSDEV_FSL_MSI_H */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment