diff options
author | Li Yang <leoli@freescale.com> | 2010-04-22 04:31:39 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2010-05-24 22:26:35 -0400 |
commit | 480599933a69a8a8dc1390c2164e49e20a1593b9 (patch) | |
tree | cf2b37f439c9e1b06cf17b6cd94559f0bfcdee13 /arch/powerpc | |
parent | 061ca4adfb2e3c986a182fd30f7e939a1ff8d29d (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/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 36 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 1 |
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 | ||
253 | static 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 | |||
253 | static int __devinit fsl_of_msi_probe(struct of_device *dev, | 277 | static 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; |
365 | error_out: | 388 | error_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 | ||
398 | static __init int fsl_of_msi_init(void) | 422 | static __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 | ||