diff options
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 29 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 2 |
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 | |||
30 | struct fsl_msi_cascade_data; | 32 | struct fsl_msi_cascade_data; |
31 | 33 | ||
32 | struct fsl_msi { | 34 | struct fsl_msi { |