aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c29
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h2
2 files changed, 28 insertions, 3 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 4bbb4b8dfd09..f086c6f22dc9 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -162,7 +162,17 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
162 msg->address_lo = lower_32_bits(address); 162 msg->address_lo = lower_32_bits(address);
163 msg->address_hi = upper_32_bits(address); 163 msg->address_hi = upper_32_bits(address);
164 164
165 msg->data = hwirq; 165 /*
166 * MPIC version 2.0 has erratum PIC1. It causes
167 * that neither MSI nor MSI-X can work fine.
168 * This is a workaround to allow MSI-X to function
169 * properly. It only works for MSI-X, we prevent
170 * MSI on buggy chips in fsl_setup_msi_irqs().
171 */
172 if (msi_data->feature & MSI_HW_ERRATA_ENDIAN)
173 msg->data = __swab32(hwirq);
174 else
175 msg->data = hwirq;
166 176
167 pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__, 177 pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__,
168 (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK, 178 (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK,
@@ -180,8 +190,16 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
180 struct msi_msg msg; 190 struct msi_msg msg;
181 struct fsl_msi *msi_data; 191 struct fsl_msi *msi_data;
182 192
183 if (type == PCI_CAP_ID_MSIX) 193 if (type == PCI_CAP_ID_MSI) {
184 pr_debug("fslmsi: MSI-X untested, trying anyway.\n"); 194 /*
195 * MPIC version 2.0 has erratum PIC1. For now MSI
196 * could not work. So check to prevent MSI from
197 * being used on the board with this erratum.
198 */
199 list_for_each_entry(msi_data, &msi_head, list)
200 if (msi_data->feature & MSI_HW_ERRATA_ENDIAN)
201 return -EINVAL;
202 }
185 203
186 /* 204 /*
187 * If the PCI node has an fsl,msi property, then we need to use it 205 * If the PCI node has an fsl,msi property, then we need to use it
@@ -446,6 +464,11 @@ static int fsl_of_msi_probe(struct platform_device *dev)
446 464
447 msi->feature = features->fsl_pic_ip; 465 msi->feature = features->fsl_pic_ip;
448 466
467 /* For erratum PIC1 on MPIC version 2.0*/
468 if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) == FSL_PIC_IP_MPIC
469 && (fsl_mpic_primary_get_version() == 0x0200))
470 msi->feature |= MSI_HW_ERRATA_ENDIAN;
471
449 /* 472 /*
450 * Remember the phandle, so that we can match with any PCI nodes 473 * Remember the phandle, so that we can match with any PCI nodes
451 * that have an "fsl,msi" property. 474 * that have an "fsl,msi" property.
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index 420cfcbdac01..a67359d993e5 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -27,6 +27,8 @@
27#define FSL_PIC_IP_IPIC 0x00000002 27#define FSL_PIC_IP_IPIC 0x00000002
28#define FSL_PIC_IP_VMPIC 0x00000003 28#define FSL_PIC_IP_VMPIC 0x00000003
29 29
30#define MSI_HW_ERRATA_ENDIAN 0x00000010
31
30struct fsl_msi_cascade_data; 32struct fsl_msi_cascade_data;
31 33
32struct fsl_msi { 34struct fsl_msi {