aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 09:31:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 09:31:43 -0400
commit0a95d92c0054e74fb79607ac2df958b7bf295706 (patch)
treee2c5f836e799dcfd72904949be47595af91432e7 /arch/powerpc/sysdev/fsl_msi.c
parent08351fc6a75731226e1112fc7254542bd3a2912e (diff)
parent831532035b12a5f7b600515a6f4da0b207b82d6e (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.c111
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*/
50static void fsl_msi_end_irq(unsigned int virq) 50static void fsl_msi_end_irq(struct irq_data *d)
51{ 51{
52} 52}
53 53
54static struct irq_chip fsl_msi_chip = { 54static 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
184static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 184static 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 }
248unlock: 249unlock:
@@ -273,18 +274,46 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
273 return 0; 274 return 0;
274} 275}
275 276
277static 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
276static int __devinit fsl_of_msi_probe(struct platform_device *dev) 306static 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