Commit 8d153155 authored by Anton Blanchard's avatar Anton Blanchard Committed by Benjamin Herrenschmidt

powerpc/pseries: Fix endian issues in MSI code

The MSI code is miscalculating quotas in little endian mode.
Add required byteswaps to fix this.

Before we claimed a quota of 65536, after the patch we
see the correct value of 256.
Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 5091f0c9
...@@ -130,7 +130,8 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name) ...@@ -130,7 +130,8 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
{ {
struct device_node *dn; struct device_node *dn;
struct pci_dn *pdn; struct pci_dn *pdn;
const u32 *req_msi; const __be32 *p;
u32 req_msi;
pdn = pci_get_pdn(pdev); pdn = pci_get_pdn(pdev);
if (!pdn) if (!pdn)
...@@ -138,19 +139,20 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name) ...@@ -138,19 +139,20 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
dn = pdn->node; dn = pdn->node;
req_msi = of_get_property(dn, prop_name, NULL); p = of_get_property(dn, prop_name, NULL);
if (!req_msi) { if (!p) {
pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name); pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
return -ENOENT; return -ENOENT;
} }
if (*req_msi < nvec) { req_msi = be32_to_cpup(p);
if (req_msi < nvec) {
pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec); pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
if (*req_msi == 0) /* Be paranoid */ if (req_msi == 0) /* Be paranoid */
return -ENOSPC; return -ENOSPC;
return *req_msi; return req_msi;
} }
return 0; return 0;
...@@ -171,7 +173,7 @@ static int check_req_msix(struct pci_dev *pdev, int nvec) ...@@ -171,7 +173,7 @@ static int check_req_msix(struct pci_dev *pdev, int nvec)
static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total) static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
{ {
struct device_node *dn; struct device_node *dn;
const u32 *p; const __be32 *p;
dn = of_node_get(pci_device_to_OF_node(dev)); dn = of_node_get(pci_device_to_OF_node(dev));
while (dn) { while (dn) {
...@@ -179,7 +181,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total) ...@@ -179,7 +181,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
if (p) { if (p) {
pr_debug("rtas_msi: found prop on dn %s\n", pr_debug("rtas_msi: found prop on dn %s\n",
dn->full_name); dn->full_name);
*total = *p; *total = be32_to_cpup(p);
return dn; return dn;
} }
...@@ -232,13 +234,13 @@ struct msi_counts { ...@@ -232,13 +234,13 @@ struct msi_counts {
static void *count_non_bridge_devices(struct device_node *dn, void *data) static void *count_non_bridge_devices(struct device_node *dn, void *data)
{ {
struct msi_counts *counts = data; struct msi_counts *counts = data;
const u32 *p; const __be32 *p;
u32 class; u32 class;
pr_debug("rtas_msi: counting %s\n", dn->full_name); pr_debug("rtas_msi: counting %s\n", dn->full_name);
p = of_get_property(dn, "class-code", NULL); p = of_get_property(dn, "class-code", NULL);
class = p ? *p : 0; class = p ? be32_to_cpup(p) : 0;
if ((class >> 8) != PCI_CLASS_BRIDGE_PCI) if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
counts->num_devices++; counts->num_devices++;
...@@ -249,7 +251,7 @@ static void *count_non_bridge_devices(struct device_node *dn, void *data) ...@@ -249,7 +251,7 @@ static void *count_non_bridge_devices(struct device_node *dn, void *data)
static void *count_spare_msis(struct device_node *dn, void *data) static void *count_spare_msis(struct device_node *dn, void *data)
{ {
struct msi_counts *counts = data; struct msi_counts *counts = data;
const u32 *p; const __be32 *p;
int req; int req;
if (dn == counts->requestor) if (dn == counts->requestor)
...@@ -260,11 +262,11 @@ static void *count_spare_msis(struct device_node *dn, void *data) ...@@ -260,11 +262,11 @@ static void *count_spare_msis(struct device_node *dn, void *data)
req = 0; req = 0;
p = of_get_property(dn, "ibm,req#msi", NULL); p = of_get_property(dn, "ibm,req#msi", NULL);
if (p) if (p)
req = *p; req = be32_to_cpup(p);
p = of_get_property(dn, "ibm,req#msi-x", NULL); p = of_get_property(dn, "ibm,req#msi-x", NULL);
if (p) if (p)
req = max(req, (int)*p); req = max(req, (int)be32_to_cpup(p));
} }
if (req < counts->quota) if (req < counts->quota)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment