Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e61133dd authored by Brian King's avatar Brian King Committed by Benjamin Herrenschmidt
Browse files

powerpc/pseries: Force 32 bit MSIs for devices that require it



The following patch implements a new PAPR change which allows
the OS to force the use of 32 bit MSIs, regardless of what
the PCI capabilities indicate. This is required for some
devices that advertise support for 64 bit MSIs but don't
actually support them.

Signed-off-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent c2fd22df
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -163,6 +163,8 @@ struct pci_dn {


	int	pci_ext_config_space;	/* for pci devices */
	int	pci_ext_config_space;	/* for pci devices */


	int	force_32bit_msi:1;

	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
#ifdef CONFIG_EEH
#ifdef CONFIG_EEH
	struct eeh_dev *edev;		/* eeh device */
	struct eeh_dev *edev;		/* eeh device */
+18 −3
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ static int query_token, change_token;
#define RTAS_RESET_FN		2
#define RTAS_RESET_FN		2
#define RTAS_CHANGE_MSI_FN	3
#define RTAS_CHANGE_MSI_FN	3
#define RTAS_CHANGE_MSIX_FN	4
#define RTAS_CHANGE_MSIX_FN	4
#define RTAS_CHANGE_32MSI_FN	5


static struct pci_dn *get_pdn(struct pci_dev *pdev)
static struct pci_dn *get_pdn(struct pci_dev *pdev)
{
{
@@ -58,7 +59,8 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)


	seq_num = 1;
	seq_num = 1;
	do {
	do {
		if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN)
		if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN ||
		    func == RTAS_CHANGE_32MSI_FN)
			rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
			rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
					BUID_HI(buid), BUID_LO(buid),
					BUID_HI(buid), BUID_LO(buid),
					func, num_irqs, seq_num);
					func, num_irqs, seq_num);
@@ -426,9 +428,12 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
	 */
	 */
again:
again:
	if (type == PCI_CAP_ID_MSI) {
	if (type == PCI_CAP_ID_MSI) {
		if (pdn->force_32bit_msi)
			rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
		else
			rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
			rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);


		if (rc < 0) {
		if (rc < 0 && !pdn->force_32bit_msi) {
			pr_debug("rtas_msi: trying the old firmware call.\n");
			pr_debug("rtas_msi: trying the old firmware call.\n");
			rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
			rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
		}
		}
@@ -512,3 +517,13 @@ static int rtas_msi_init(void)
	return 0;
	return 0;
}
}
arch_initcall(rtas_msi_init);
arch_initcall(rtas_msi_init);

static void quirk_radeon(struct pci_dev *dev)
{
	struct pci_dn *pdn = get_pdn(dev);

	if (pdn)
		pdn->force_32bit_msi = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon);