diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 09:31:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 09:31:43 -0400 |
commit | 0a95d92c0054e74fb79607ac2df958b7bf295706 (patch) | |
tree | e2c5f836e799dcfd72904949be47595af91432e7 /arch/powerpc/sysdev/fsl_msi.c | |
parent | 08351fc6a75731226e1112fc7254542bd3a2912e (diff) | |
parent | 831532035b12a5f7b600515a6f4da0b207b82d6e (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (62 commits)
powerpc/85xx: Fix signedness bug in cache-sram
powerpc/fsl: 85xx: document cache sram bindings
powerpc/fsl: define binding for fsl mpic interrupt controllers
powerpc/fsl_msi: Handle msi-available-ranges better
drivers/serial/ucc_uart.c: Add of_node_put to avoid memory leak
powerpc/85xx: Fix SPE float to integer conversion failure
powerpc/85xx: Update sata controller compatible for p1022ds board
ATA: Add FSL sata v2 controller support
powerpc/mpc8xxx_gpio: simplify searching for 'fsl, qoriq-gpio' compatiable
powerpc/8xx: remove obsolete mgsuvd board
powerpc/82xx: rename and update mgcoge board support
powerpc/83xx: rename and update kmeter1
powerpc/85xx: Workaroudn e500 CPU erratum A005
powerpc/fsl_pci: Add support for FSL PCIe controllers v2.x
powerpc/85xx: Fix writing to spin table 'cpu-release-addr' on ppc64e
powerpc/pseries: Disable MSI using new interface if possible
powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED.
powerpc: core irq_data conversion.
powerpc: sysdev/xilinx_intc irq_data conversion.
powerpc: sysdev/uic irq_data conversion.
...
Fix up conflicts in arch/powerpc/sysdev/fsl_msi.c (due to getting rid of
of_platform_driver in arch/powerpc)
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 111 |
1 files changed, 66 insertions, 45 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ee6a8a52ac71..58e09b2833f2 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. | 2 | * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * Author: Tony Li <tony.li@freescale.com> | 4 | * Author: Tony Li <tony.li@freescale.com> |
5 | * Jason Jin <Jason.jin@freescale.com> | 5 | * Jason Jin <Jason.jin@freescale.com> |
@@ -47,14 +47,14 @@ static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) | |||
47 | * We do not need this actually. The MSIR register has been read once | 47 | * We do not need this actually. The MSIR register has been read once |
48 | * in the cascade interrupt. So, this MSI interrupt has been acked | 48 | * in the cascade interrupt. So, this MSI interrupt has been acked |
49 | */ | 49 | */ |
50 | static void fsl_msi_end_irq(unsigned int virq) | 50 | static void fsl_msi_end_irq(struct irq_data *d) |
51 | { | 51 | { |
52 | } | 52 | } |
53 | 53 | ||
54 | static struct irq_chip fsl_msi_chip = { | 54 | static struct irq_chip fsl_msi_chip = { |
55 | .irq_mask = mask_msi_irq, | 55 | .irq_mask = mask_msi_irq, |
56 | .irq_unmask = unmask_msi_irq, | 56 | .irq_unmask = unmask_msi_irq, |
57 | .ack = fsl_msi_end_irq, | 57 | .irq_ack = fsl_msi_end_irq, |
58 | .name = "FSL-MSI", | 58 | .name = "FSL-MSI", |
59 | }; | 59 | }; |
60 | 60 | ||
@@ -183,6 +183,7 @@ out_free: | |||
183 | 183 | ||
184 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | 184 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) |
185 | { | 185 | { |
186 | struct irq_chip *chip = get_irq_desc_chip(desc); | ||
186 | unsigned int cascade_irq; | 187 | unsigned int cascade_irq; |
187 | struct fsl_msi *msi_data; | 188 | struct fsl_msi *msi_data; |
188 | int msir_index = -1; | 189 | int msir_index = -1; |
@@ -196,11 +197,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
196 | 197 | ||
197 | raw_spin_lock(&desc->lock); | 198 | raw_spin_lock(&desc->lock); |
198 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { | 199 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { |
199 | if (desc->chip->mask_ack) | 200 | if (chip->irq_mask_ack) |
200 | desc->chip->mask_ack(irq); | 201 | chip->irq_mask_ack(&desc->irq_data); |
201 | else { | 202 | else { |
202 | desc->chip->mask(irq); | 203 | chip->irq_mask(&desc->irq_data); |
203 | desc->chip->ack(irq); | 204 | chip->irq_ack(&desc->irq_data); |
204 | } | 205 | } |
205 | } | 206 | } |
206 | 207 | ||
@@ -238,11 +239,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
238 | 239 | ||
239 | switch (msi_data->feature & FSL_PIC_IP_MASK) { | 240 | switch (msi_data->feature & FSL_PIC_IP_MASK) { |
240 | case FSL_PIC_IP_MPIC: | 241 | case FSL_PIC_IP_MPIC: |
241 | desc->chip->eoi(irq); | 242 | chip->irq_eoi(&desc->irq_data); |
242 | break; | 243 | break; |
243 | case FSL_PIC_IP_IPIC: | 244 | case FSL_PIC_IP_IPIC: |
244 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | 245 | if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask) |
245 | desc->chip->unmask(irq); | 246 | chip->irq_unmask(&desc->irq_data); |
246 | break; | 247 | break; |
247 | } | 248 | } |
248 | unlock: | 249 | unlock: |
@@ -273,18 +274,46 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) | |||
273 | return 0; | 274 | return 0; |
274 | } | 275 | } |
275 | 276 | ||
277 | static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi, | ||
278 | struct platform_device *dev, | ||
279 | int offset, int irq_index) | ||
280 | { | ||
281 | struct fsl_msi_cascade_data *cascade_data = NULL; | ||
282 | int virt_msir; | ||
283 | |||
284 | virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index); | ||
285 | if (virt_msir == NO_IRQ) { | ||
286 | dev_err(&dev->dev, "%s: Cannot translate IRQ index %d\n", | ||
287 | __func__, irq_index); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | cascade_data = kzalloc(sizeof(struct fsl_msi_cascade_data), GFP_KERNEL); | ||
292 | if (!cascade_data) { | ||
293 | dev_err(&dev->dev, "No memory for MSI cascade data\n"); | ||
294 | return -ENOMEM; | ||
295 | } | ||
296 | |||
297 | msi->msi_virqs[irq_index] = virt_msir; | ||
298 | cascade_data->index = offset + irq_index; | ||
299 | cascade_data->msi_data = msi; | ||
300 | set_irq_data(virt_msir, cascade_data); | ||
301 | set_irq_chained_handler(virt_msir, fsl_msi_cascade); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
276 | static int __devinit fsl_of_msi_probe(struct platform_device *dev) | 306 | static int __devinit fsl_of_msi_probe(struct platform_device *dev) |
277 | { | 307 | { |
278 | struct fsl_msi *msi; | 308 | struct fsl_msi *msi; |
279 | struct resource res; | 309 | struct resource res; |
280 | int err, i, count; | 310 | int err, i, j, irq_index, count; |
281 | int rc; | 311 | int rc; |
282 | int virt_msir; | ||
283 | const u32 *p; | 312 | const u32 *p; |
284 | struct fsl_msi_feature *features; | 313 | struct fsl_msi_feature *features; |
285 | struct fsl_msi_cascade_data *cascade_data = NULL; | ||
286 | int len; | 314 | int len; |
287 | u32 offset; | 315 | u32 offset; |
316 | static const u32 all_avail[] = { 0, NR_MSI_IRQS }; | ||
288 | 317 | ||
289 | if (!dev->dev.of_match) | 318 | if (!dev->dev.of_match) |
290 | return -EINVAL; | 319 | return -EINVAL; |
@@ -335,42 +364,34 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
335 | goto error_out; | 364 | goto error_out; |
336 | } | 365 | } |
337 | 366 | ||
338 | p = of_get_property(dev->dev.of_node, "interrupts", &count); | 367 | p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); |
339 | if (!p) { | 368 | if (p && len % (2 * sizeof(u32)) != 0) { |
340 | dev_err(&dev->dev, "no interrupts property found on %s\n", | 369 | dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", |
341 | dev->dev.of_node->full_name); | 370 | __func__); |
342 | err = -ENODEV; | ||
343 | goto error_out; | ||
344 | } | ||
345 | if (count % 8 != 0) { | ||
346 | dev_err(&dev->dev, "Malformed interrupts property on %s\n", | ||
347 | dev->dev.of_node->full_name); | ||
348 | err = -EINVAL; | 371 | err = -EINVAL; |
349 | goto error_out; | 372 | goto error_out; |
350 | } | 373 | } |
351 | offset = 0; | 374 | |
352 | p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); | 375 | if (!p) |
353 | if (p) | 376 | p = all_avail; |
354 | offset = *p / IRQS_PER_MSI_REG; | 377 | |
355 | 378 | for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { | |
356 | count /= sizeof(u32); | 379 | if (p[i * 2] % IRQS_PER_MSI_REG || |
357 | for (i = 0; i < min(count / 2, NR_MSI_REG); i++) { | 380 | p[i * 2 + 1] % IRQS_PER_MSI_REG) { |
358 | virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); | 381 | printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n", |
359 | if (virt_msir != NO_IRQ) { | 382 | __func__, dev->dev.of_node->full_name, |
360 | cascade_data = kzalloc( | 383 | p[i * 2 + 1], p[i * 2]); |
361 | sizeof(struct fsl_msi_cascade_data), | 384 | err = -EINVAL; |
362 | GFP_KERNEL); | 385 | goto error_out; |
363 | if (!cascade_data) { | 386 | } |
364 | dev_err(&dev->dev, | 387 | |
365 | "No memory for MSI cascade data\n"); | 388 | offset = p[i * 2] / IRQS_PER_MSI_REG; |
366 | err = -ENOMEM; | 389 | count = p[i * 2 + 1] / IRQS_PER_MSI_REG; |
390 | |||
391 | for (j = 0; j < count; j++, irq_index++) { | ||
392 | err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index); | ||
393 | if (err) | ||
367 | goto error_out; | 394 | goto error_out; |
368 | } | ||
369 | msi->msi_virqs[i] = virt_msir; | ||
370 | cascade_data->index = i + offset; | ||
371 | cascade_data->msi_data = msi; | ||
372 | set_irq_data(virt_msir, (void *)cascade_data); | ||
373 | set_irq_chained_handler(virt_msir, fsl_msi_cascade); | ||
374 | } | 395 | } |
375 | } | 396 | } |
376 | 397 | ||