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: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
766375362a
commit
b2ad7b5e81
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue