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

Commit b2ad7b5e authored by Paul Mackerras's avatar Paul Mackerras
Browse files

Allow PCI config space syscalls to be used by 64-bit processes.



The pciconfig_iobase, pciconfig_read and pciconfig_write system calls
were only implemented for 32-bit processes; for 64-bit processes they
returned an ENOSYS error.  This allows them to be used by 64-bit
processes as well.  The X server uses pciconfig_iobase at least, and
this change is necessary to allow a 64-bit X server to work on my G5.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 76637536
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1431,9 +1431,9 @@ _GLOBAL(sys_call_table)
	.llong .sys_ni_syscall		/* 195 - 32bit only stat64 */
	.llong .sys_ni_syscall		/* 32bit only lstat64 */
	.llong .sys_ni_syscall		/* 32bit only fstat64 */
	.llong .sys_ni_syscall		/* 32bit only pciconfig_read */
	.llong .sys_ni_syscall		/* 32bit only pciconfig_write */
	.llong .sys_ni_syscall		/* 32bit only pciconfig_iobase */
	.llong .sys_pciconfig_read
	.llong .sys_pciconfig_write
	.llong .sys_pciconfig_iobase	/* 200 - pciconfig_iobase */
	.llong .sys_ni_syscall		/* reserved for MacOnLinux */
	.llong .sys_getdents64
	.llong .sys_pivot_root
+60 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/syscalls.h>

#include <asm/processor.h>
#include <asm/io.h>
@@ -984,3 +985,62 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
}

#endif /* CONFIG_PPC_MULTIPLATFORM */


#define IOBASE_BRIDGE_NUMBER	0
#define IOBASE_MEMORY		1
#define IOBASE_IO		2
#define IOBASE_ISA_IO		3
#define IOBASE_ISA_MEM		4

long sys_pciconfig_iobase(long which, unsigned long in_bus,
			  unsigned long in_devfn)
{
	struct pci_controller* hose;
	struct list_head *ln;
	struct pci_bus *bus = NULL;
	struct device_node *hose_node;

	/* Argh ! Please forgive me for that hack, but that's the
	 * simplest way to get existing XFree to not lockup on some
	 * G5 machines... So when something asks for bus 0 io base
	 * (bus 0 is HT root), we return the AGP one instead.
	 */
#ifdef CONFIG_PPC_PMAC
	if (systemcfg->platform == PLATFORM_POWERMAC &&
	    machine_is_compatible("MacRISC4"))
		if (in_bus == 0)
			in_bus = 0xf0;
#endif /* CONFIG_PPC_PMAC */

	/* That syscall isn't quite compatible with PCI domains, but it's
	 * used on pre-domains setup. We return the first match
	 */

	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
		bus = pci_bus_b(ln);
		if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
			break;
		bus = NULL;
	}
	if (bus == NULL || bus->sysdata == NULL)
		return -ENODEV;

	hose_node = (struct device_node *)bus->sysdata;
	hose = PCI_DN(hose_node)->phb;

	switch (which) {
	case IOBASE_BRIDGE_NUMBER:
		return (long)hose->first_busno;
	case IOBASE_MEMORY:
		return (long)hose->pci_mem_offset;
	case IOBASE_IO:
		return (long)hose->io_base_phys;
	case IOBASE_ISA_IO:
		return (long)isa_io_base;
	case IOBASE_ISA_MEM:
		return -EINVAL;
	}

	return -EOPNOTSUPP;
}
+1 −54
Original line number Diff line number Diff line
@@ -708,62 +708,9 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
				   compat_ptr(ubuf));
}

#define IOBASE_BRIDGE_NUMBER	0
#define IOBASE_MEMORY		1
#define IOBASE_IO		2
#define IOBASE_ISA_IO		3
#define IOBASE_ISA_MEM		4

asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
{
#ifdef CONFIG_PCI
	struct pci_controller* hose;
	struct list_head *ln;
	struct pci_bus *bus = NULL;
	struct device_node *hose_node;

	/* Argh ! Please forgive me for that hack, but that's the
	 * simplest way to get existing XFree to not lockup on some
	 * G5 machines... So when something asks for bus 0 io base
	 * (bus 0 is HT root), we return the AGP one instead.
	 */
#ifdef CONFIG_PPC_PMAC
	if (systemcfg->platform == PLATFORM_POWERMAC &&
	    machine_is_compatible("MacRISC4"))
		if (in_bus == 0)
			in_bus = 0xf0;
#endif /* CONFIG_PPC_PMAC */

	/* That syscall isn't quite compatible with PCI domains, but it's
	 * used on pre-domains setup. We return the first match
	 */

	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
		bus = pci_bus_b(ln);
		if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
			break;
		bus = NULL;
	}
	if (bus == NULL || bus->sysdata == NULL)
		return -ENODEV;

	hose_node = bus->sysdata;
	hose = PCI_DN(hose_node)->phb;

	switch (which) {
	case IOBASE_BRIDGE_NUMBER:
		return (long)hose->first_busno;
	case IOBASE_MEMORY:
		return (long)hose->pci_mem_offset;
	case IOBASE_IO:
		return (long)hose->io_base_phys;
	case IOBASE_ISA_IO:
		return (long)isa_io_base;
	case IOBASE_ISA_MEM:
		return -EINVAL;
	}
#endif	/* CONFIG_PCI */
	return -EOPNOTSUPP;
	return sys_pciconfig_iobase(which, in_bus, in_devfn);
}