aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2010-04-22 04:31:39 -0400
committerKumar Gala <galak@kernel.crashing.org>2010-05-24 22:26:35 -0400
commit480599933a69a8a8dc1390c2164e49e20a1593b9 (patch)
treecf2b37f439c9e1b06cf17b6cd94559f0bfcdee13 /arch
parent061ca4adfb2e3c986a182fd30f7e939a1ff8d29d (diff)
powerpc/fsl_msi: add removal path and probe failing path
Also cleanup the probe function. Signed-off-by: Li Yang <leoli@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c36
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h1
2 files changed, 31 insertions, 6 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 1ab703915972..f7ca9e6fa5f0 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -250,6 +250,30 @@ unlock:
250 raw_spin_unlock(&desc->lock); 250 raw_spin_unlock(&desc->lock);
251} 251}
252 252
253static int fsl_of_msi_remove(struct of_device *ofdev)
254{
255 struct fsl_msi *msi = ofdev->dev.platform_data;
256 int virq, i;
257 struct fsl_msi_cascade_data *cascade_data;
258
259 if (msi->list.prev != NULL)
260 list_del(&msi->list);
261 for (i = 0; i < NR_MSI_REG; i++) {
262 virq = msi->msi_virqs[i];
263 if (virq != NO_IRQ) {
264 cascade_data = get_irq_data(virq);
265 kfree(cascade_data);
266 irq_dispose_mapping(virq);
267 }
268 }
269 if (msi->bitmap.bitmap)
270 msi_bitmap_free(&msi->bitmap);
271 iounmap(msi->msi_regs);
272 kfree(msi);
273
274 return 0;
275}
276
253static int __devinit fsl_of_msi_probe(struct of_device *dev, 277static int __devinit fsl_of_msi_probe(struct of_device *dev,
254 const struct of_device_id *match) 278 const struct of_device_id *match)
255{ 279{
@@ -269,9 +293,9 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
269 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); 293 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
270 if (!msi) { 294 if (!msi) {
271 dev_err(&dev->dev, "No memory for MSI structure\n"); 295 dev_err(&dev->dev, "No memory for MSI structure\n");
272 err = -ENOMEM; 296 return -ENOMEM;
273 goto error_out;
274 } 297 }
298 dev->dev.platform_data = msi;
275 299
276 msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR, 300 msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR,
277 NR_MSI_IRQS, &fsl_msi_host_ops, 0); 301 NR_MSI_IRQS, &fsl_msi_host_ops, 0);
@@ -328,9 +352,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
328 offset = *p / IRQS_PER_MSI_REG; 352 offset = *p / IRQS_PER_MSI_REG;
329 353
330 count /= sizeof(u32); 354 count /= sizeof(u32);
331 for (i = 0; i < count / 2; i++) { 355 for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
332 if (i > NR_MSI_REG)
333 break;
334 virt_msir = irq_of_parse_and_map(dev->node, i); 356 virt_msir = irq_of_parse_and_map(dev->node, i);
335 if (virt_msir != NO_IRQ) { 357 if (virt_msir != NO_IRQ) {
336 cascade_data = kzalloc( 358 cascade_data = kzalloc(
@@ -342,6 +364,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
342 err = -ENOMEM; 364 err = -ENOMEM;
343 goto error_out; 365 goto error_out;
344 } 366 }
367 msi->msi_virqs[i] = virt_msir;
345 cascade_data->index = i + offset; 368 cascade_data->index = i + offset;
346 cascade_data->msi_data = msi; 369 cascade_data->msi_data = msi;
347 set_irq_data(virt_msir, (void *)cascade_data); 370 set_irq_data(virt_msir, (void *)cascade_data);
@@ -363,7 +386,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
363 } 386 }
364 return 0; 387 return 0;
365error_out: 388error_out:
366 kfree(msi); 389 fsl_of_msi_remove(dev);
367 return err; 390 return err;
368} 391}
369 392
@@ -393,6 +416,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
393 .name = "fsl-msi", 416 .name = "fsl-msi",
394 .match_table = fsl_of_msi_ids, 417 .match_table = fsl_of_msi_ids,
395 .probe = fsl_of_msi_probe, 418 .probe = fsl_of_msi_probe,
419 .remove = fsl_of_msi_remove,
396}; 420};
397 421
398static __init int fsl_of_msi_init(void) 422static __init int fsl_of_msi_init(void)
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index 8fc5523d6ee3..624580c252d7 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -32,6 +32,7 @@ struct fsl_msi {
32 u32 msi_addr_hi; 32 u32 msi_addr_hi;
33 void __iomem *msi_regs; 33 void __iomem *msi_regs;
34 u32 feature; 34 u32 feature;
35 int msi_virqs[NR_MSI_REG];
35 36
36 struct msi_bitmap bitmap; 37 struct msi_bitmap bitmap;
37 38