aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
authorTudor Laurentiu <b10716@freescale.com>2014-08-21 05:33:53 -0400
committerScott Wood <scottwood@freescale.com>2014-09-04 19:51:45 -0400
commitc822e73731fce3b49a4887140878d084d8a44c08 (patch)
tree5ad4eccb8fb9e033eb3b379d7060bb6f6e86b2ba /arch/powerpc/sysdev/fsl_msi.c
parentde99f53d3af0e1bb9bc6c9e3107d72f3af6e05e9 (diff)
powerpc/fsl_msi: spread msi ints across different MSIRs
Allocate msis such that each time a new interrupt is requested, the SRS (MSIR register select) to be used is allocated in a round-robin fashion. The end result is that the msi interrupts will be spread across distinct MSIRs with the main benefit that now users can set affinity to each msi int through the mpic irq backing up the MSIR register. This is achieved with the help of a newly introduced msi bitmap api that allows specifying the starting point when searching for a free msi interrupt. Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@freescale.com> Cc: Scott Wood <scottwood@freescale.com> Cc: Mihai Caraman <mihai.caraman@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index e2ee226464f8..37254eff7324 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -213,6 +213,8 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
213 * available interrupt. 213 * available interrupt.
214 */ 214 */
215 list_for_each_entry(msi_data, &msi_head, list) { 215 list_for_each_entry(msi_data, &msi_head, list) {
216 int off;
217
216 /* 218 /*
217 * If the PCI node has an fsl,msi property, then we 219 * If the PCI node has an fsl,msi property, then we
218 * restrict our search to the corresponding MSI node. 220 * restrict our search to the corresponding MSI node.
@@ -224,7 +226,28 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
224 if (phandle && (phandle != msi_data->phandle)) 226 if (phandle && (phandle != msi_data->phandle))
225 continue; 227 continue;
226 228
227 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 229 /*
230 * Allocate the msi message so that it fits on distinct
231 * MSIR registers. Obviously, since MSIR registers are
232 * limited they will overlap at one point.
233 *
234 * Due to the format of the newly introduced MSIIR1 in
235 * mpic 4.3, consecutive msi message values map to
236 * distinct MSIRs, thus distinct msi irq cascades, so
237 * nothing special needs to be done in this case.
238 * On older mpic versions the chose distinct SRS
239 * values by aligning the msi message value to the
240 * SRS field shift.
241 */
242 if (msi_data->feature & FSL_PIC_FTR_MPIC_4_3) {
243 off = 0;
244 } else {
245 off = atomic_inc_return(&msi_data->msi_alloc_cnt) %
246 msi_data->msir_num;
247 off <<= msi_data->srs_shift;
248 }
249 hwirq = msi_bitmap_alloc_hwirqs_from_offset(
250 &msi_data->bitmap, off, 1);
228 if (hwirq >= 0) 251 if (hwirq >= 0)
229 break; 252 break;
230 } 253 }
@@ -464,12 +487,17 @@ static int fsl_of_msi_probe(struct platform_device *dev)
464 goto error_out; 487 goto error_out;
465 } 488 }
466 489
490 atomic_set(&msi->msi_alloc_cnt, -1);
491
467 p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); 492 p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
468 493
469 if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3") || 494 if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3") ||
470 of_device_is_compatible(dev->dev.of_node, "fsl,vmpic-msi-v4.3")) { 495 of_device_is_compatible(dev->dev.of_node, "fsl,vmpic-msi-v4.3")) {
471 msi->srs_shift = MSIIR1_SRS_SHIFT; 496 msi->srs_shift = MSIIR1_SRS_SHIFT;
472 msi->ibs_shift = MSIIR1_IBS_SHIFT; 497 msi->ibs_shift = MSIIR1_IBS_SHIFT;
498 msi->msir_num = NR_MSI_REG_MSIIR1;
499 msi->feature |= FSL_PIC_FTR_MPIC_4_3;
500
473 if (p) 501 if (p)
474 dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n", 502 dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n",
475 __func__); 503 __func__);
@@ -487,6 +515,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
487 515
488 msi->srs_shift = MSIIR_SRS_SHIFT; 516 msi->srs_shift = MSIIR_SRS_SHIFT;
489 msi->ibs_shift = MSIIR_IBS_SHIFT; 517 msi->ibs_shift = MSIIR_IBS_SHIFT;
518 msi->msir_num = NR_MSI_REG_MSIIR;
490 519
491 if (p && len % (2 * sizeof(u32)) != 0) { 520 if (p && len % (2 * sizeof(u32)) != 0) {
492 dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", 521 dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",