summaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
authorTudor Laurentiu <b10716@freescale.com>2014-08-21 09:33:53 (GMT)
committerScott Wood <scottwood@freescale.com>2014-09-04 23:51:45 (GMT)
commitc822e73731fce3b49a4887140878d084d8a44c08 (patch)
tree5ad4eccb8fb9e033eb3b379d7060bb6f6e86b2ba /arch/powerpc/sysdev/fsl_msi.c
parentde99f53d3af0e1bb9bc6c9e3107d72f3af6e05e9 (diff)
downloadlinux-c822e73731fce3b49a4887140878d084d8a44c08.tar.xz
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 e2ee226..37254ef 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)
* available interrupt.
*/
list_for_each_entry(msi_data, &msi_head, list) {
+ int off;
+
/*
* If the PCI node has an fsl,msi property, then we
* 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)
if (phandle && (phandle != msi_data->phandle))
continue;
- hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
+ /*
+ * Allocate the msi message so that it fits on distinct
+ * MSIR registers. Obviously, since MSIR registers are
+ * limited they will overlap at one point.
+ *
+ * Due to the format of the newly introduced MSIIR1 in
+ * mpic 4.3, consecutive msi message values map to
+ * distinct MSIRs, thus distinct msi irq cascades, so
+ * nothing special needs to be done in this case.
+ * On older mpic versions the chose distinct SRS
+ * values by aligning the msi message value to the
+ * SRS field shift.
+ */
+ if (msi_data->feature & FSL_PIC_FTR_MPIC_4_3) {
+ off = 0;
+ } else {
+ off = atomic_inc_return(&msi_data->msi_alloc_cnt) %
+ msi_data->msir_num;
+ off <<= msi_data->srs_shift;
+ }
+ hwirq = msi_bitmap_alloc_hwirqs_from_offset(
+ &msi_data->bitmap, off, 1);
if (hwirq >= 0)
break;
}
@@ -464,12 +487,17 @@ static int fsl_of_msi_probe(struct platform_device *dev)
goto error_out;
}
+ atomic_set(&msi->msi_alloc_cnt, -1);
+
p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3") ||
of_device_is_compatible(dev->dev.of_node, "fsl,vmpic-msi-v4.3")) {
msi->srs_shift = MSIIR1_SRS_SHIFT;
msi->ibs_shift = MSIIR1_IBS_SHIFT;
+ msi->msir_num = NR_MSI_REG_MSIIR1;
+ msi->feature |= FSL_PIC_FTR_MPIC_4_3;
+
if (p)
dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n",
__func__);
@@ -487,6 +515,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
msi->srs_shift = MSIIR_SRS_SHIFT;
msi->ibs_shift = MSIIR_IBS_SHIFT;
+ msi->msir_num = NR_MSI_REG_MSIIR;
if (p && len % (2 * sizeof(u32)) != 0) {
dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",