Commit 48059993 authored by Li Yang's avatar Li Yang Committed by Kumar Gala

powerpc/fsl_msi: add removal path and probe failing path

Also cleanup the probe function.
Signed-off-by: default avatarLi Yang <leoli@freescale.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent 061ca4ad
...@@ -250,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) ...@@ -250,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
raw_spin_unlock(&desc->lock); raw_spin_unlock(&desc->lock);
} }
static int fsl_of_msi_remove(struct of_device *ofdev)
{
struct fsl_msi *msi = ofdev->dev.platform_data;
int virq, i;
struct fsl_msi_cascade_data *cascade_data;
if (msi->list.prev != NULL)
list_del(&msi->list);
for (i = 0; i < NR_MSI_REG; i++) {
virq = msi->msi_virqs[i];
if (virq != NO_IRQ) {
cascade_data = get_irq_data(virq);
kfree(cascade_data);
irq_dispose_mapping(virq);
}
}
if (msi->bitmap.bitmap)
msi_bitmap_free(&msi->bitmap);
iounmap(msi->msi_regs);
kfree(msi);
return 0;
}
static int __devinit fsl_of_msi_probe(struct of_device *dev, static int __devinit fsl_of_msi_probe(struct of_device *dev,
const struct of_device_id *match) const struct of_device_id *match)
{ {
...@@ -269,9 +293,9 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -269,9 +293,9 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
if (!msi) { if (!msi) {
dev_err(&dev->dev, "No memory for MSI structure\n"); dev_err(&dev->dev, "No memory for MSI structure\n");
err = -ENOMEM; return -ENOMEM;
goto error_out;
} }
dev->dev.platform_data = msi;
msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR, msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR,
NR_MSI_IRQS, &fsl_msi_host_ops, 0); NR_MSI_IRQS, &fsl_msi_host_ops, 0);
...@@ -328,9 +352,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -328,9 +352,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
offset = *p / IRQS_PER_MSI_REG; offset = *p / IRQS_PER_MSI_REG;
count /= sizeof(u32); count /= sizeof(u32);
for (i = 0; i < count / 2; i++) { for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
if (i > NR_MSI_REG)
break;
virt_msir = irq_of_parse_and_map(dev->node, i); virt_msir = irq_of_parse_and_map(dev->node, i);
if (virt_msir != NO_IRQ) { if (virt_msir != NO_IRQ) {
cascade_data = kzalloc( cascade_data = kzalloc(
...@@ -342,6 +364,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -342,6 +364,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
err = -ENOMEM; err = -ENOMEM;
goto error_out; goto error_out;
} }
msi->msi_virqs[i] = virt_msir;
cascade_data->index = i + offset; cascade_data->index = i + offset;
cascade_data->msi_data = msi; cascade_data->msi_data = msi;
set_irq_data(virt_msir, (void *)cascade_data); set_irq_data(virt_msir, (void *)cascade_data);
...@@ -363,7 +386,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -363,7 +386,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
} }
return 0; return 0;
error_out: error_out:
kfree(msi); fsl_of_msi_remove(dev);
return err; return err;
} }
...@@ -393,6 +416,7 @@ static struct of_platform_driver fsl_of_msi_driver = { ...@@ -393,6 +416,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
.name = "fsl-msi", .name = "fsl-msi",
.match_table = fsl_of_msi_ids, .match_table = fsl_of_msi_ids,
.probe = fsl_of_msi_probe, .probe = fsl_of_msi_probe,
.remove = fsl_of_msi_remove,
}; };
static __init int fsl_of_msi_init(void) static __init int fsl_of_msi_init(void)
......
...@@ -32,6 +32,7 @@ struct fsl_msi { ...@@ -32,6 +32,7 @@ struct fsl_msi {
u32 msi_addr_hi; u32 msi_addr_hi;
void __iomem *msi_regs; void __iomem *msi_regs;
u32 feature; u32 feature;
int msi_virqs[NR_MSI_REG];
struct msi_bitmap bitmap; struct msi_bitmap bitmap;
......
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