Commit 8ea6091f authored by John Keller's avatar John Keller Committed by Greg Kroah-Hartman

Altix: Add initial ACPI IO support

First phase in introducing ACPI support to SN.
In this phase, when running with an ACPI capable PROM,
the DSDT will define the root busses and all SN nodes
(SGIHUB, SGITIO). An ACPI bus driver will be registered
for the node devices, with the acpi_pci_root_driver being
used for the root busses. An ACPI vendor descriptor is
now used to pass platform specific information for both
nodes and busses, eliminating the need for the current
SAL calls. Also, with ACPI support, SN fixup code is no longer
needed to initiate the PCI bus scans, as the acpi_pci_root_driver
does that.

However, to maintain backward compatibility with non-ACPI capable
PROMs, none of the current 'fixup' code can been deleted, though
much restructuring has been done. For example, the bulk of the code
in io_common.c is relocated code that is now common regardless
of what PROM is running, while io_acpi_init.c and io_init.c contain
routines specific to an ACPI or non ACPI capable PROM respectively.

A new pci bus fixup platform vector has been created to provide
a hook for invoking platform specific bus fixup from pcibios_fixup_bus().

The size of io_space[] has been increased to support systems with
large IO configurations.
Signed-off-by: default avatarJohn Keller <jpk@sgi.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e08cf02f
......@@ -469,10 +469,11 @@ pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
}
}
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
{
pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
}
EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
{
......@@ -493,6 +494,7 @@ pcibios_fixup_bus (struct pci_bus *b)
}
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
platform_pci_fixup_bus(b);
return;
}
......
......@@ -4,13 +4,14 @@
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved.
# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
#
CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
huberror.o io_acpi_init.o io_common.o \
io_init.o iomv.o klconflib.o pio_phys.o \
sn2/
obj-$(CONFIG_IA64_GENERIC) += machvec.o
obj-$(CONFIG_SGI_TIOCX) += tiocx.o
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
*/
#include <asm/sn/types.h>
#include <asm/sn/addrs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/sn_sal.h>
#include "xtalk/hubdev.h"
#include <linux/acpi.h>
/*
* The code in this file will only be executed when running with
* a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
*/
/*
* This value must match the UUID the PROM uses
* (io/acpi/defblk.c) when building a vendor descriptor.
*/
struct acpi_vendor_uuid sn_uuid = {
.subtype = 0,
.data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
};
/*
* Perform the early IO init in PROM.
*/
static s64
sal_ioif_init(u64 *result)
{
struct ia64_sal_retval isrv = {0,0,0,0};
SAL_CALL_NOLOCK(isrv,
SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
*result = isrv.v0;
return isrv.status;
}
/*
* sn_hubdev_add - The 'add' function of the acpi_sn_hubdev_driver.
* Called for every "SGIHUB" or "SGITIO" device defined
* in the ACPI namespace.
*/
static int __init
sn_hubdev_add(struct acpi_device *device)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
u64 addr;
struct hubdev_info *hubdev;
struct hubdev_info *hubdev_ptr;
int i;
u64 nasid;
struct acpi_resource *resource;
int ret = 0;
acpi_status status;
struct acpi_resource_vendor_typed *vendor;
extern void sn_common_hubdev_init(struct hubdev_info *);
status = acpi_get_vendor_resource(device->handle, METHOD_NAME__CRS,
&sn_uuid, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR
"sn_hubdev_add: acpi_get_vendor_resource() failed: %d\n",
status);
return 1;
}
resource = buffer.pointer;
vendor = &resource->data.vendor_typed;
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
sizeof(struct hubdev_info *)) {
printk(KERN_ERR
"sn_hubdev_add: Invalid vendor data length: %d\n",
vendor->byte_length);
ret = 1;
goto exit;
}
memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
hubdev_ptr = __va((struct hubdev_info *) addr);
nasid = hubdev_ptr->hdi_nasid;
i = nasid_to_cnodeid(nasid);
hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
*hubdev = *hubdev_ptr;
sn_common_hubdev_init(hubdev);
exit:
kfree(buffer.pointer);
return ret;
}
/*
* sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
* the ACPI Vendor resource for this bus.
*/
static struct pcibus_bussoft *
sn_get_bussoft_ptr(struct pci_bus *bus)
{
u64 addr;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle;
struct pcibus_bussoft *prom_bussoft_ptr;
struct acpi_resource *resource;
acpi_status status;
struct acpi_resource_vendor_typed *vendor;
handle = PCI_CONTROLLER(bus)->acpi_handle;
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
&sn_uuid, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR "get_acpi_pcibus_ptr: "
"get_acpi_bussoft_info() failed: %d\n",
status);
return NULL;
}
resource = buffer.pointer;
vendor = &resource->data.vendor_typed;
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
sizeof(struct pcibus_bussoft *)) {
printk(KERN_ERR
"get_acpi_bussoft_ptr: Invalid vendor data "
"length %d\n", vendor->byte_length);
kfree(buffer.pointer);
return NULL;
}
memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
kfree(buffer.pointer);
return prom_bussoft_ptr;
}
/*
* sn_acpi_bus_fixup
*/
void
sn_acpi_bus_fixup(struct pci_bus *bus)
{
struct pci_dev *pci_dev = NULL;
struct pcibus_bussoft *prom_bussoft_ptr;
extern void sn_common_bus_fixup(struct pci_bus *,
struct pcibus_bussoft *);
if (!bus->parent) { /* If root bus */
prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
if (prom_bussoft_ptr == NULL) {
printk(KERN_ERR
"sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
"obtain prom_bussoft_ptr\n",
pci_domain_nr(bus), bus->number);
return;
}
sn_common_bus_fixup(bus, prom_bussoft_ptr);
}
list_for_each_entry(pci_dev, &bus->devices, bus_list) {
sn_pci_fixup_slot(pci_dev);
}
}
static struct acpi_driver acpi_sn_hubdev_driver = {
.name = "SGI HUBDEV Driver",
.ids = "SGIHUB,SGITIO",
.ops = {
.add = sn_hubdev_add,
},
};
/*
* sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
* nodes and root buses in the DSDT. As a result, bus scanning
* will be initiated by the Linux ACPI code.
*/
void __init
sn_io_acpi_init(void)
{
u64 result;
s64 status;
acpi_bus_register_driver(&acpi_sn_hubdev_driver);
status = sal_ioif_init(&result);
if (status || result)
panic("sal_ioif_init failed: [%lx] %s\n",
status, ia64_sal_strerror(status));
}
This diff is collapsed.
This diff is collapsed.
......@@ -3,10 +3,11 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2000-2003, 2006 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/vga.h>
......@@ -15,6 +16,7 @@
#include <asm/sn/pda.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/shub_mmr.h>
#include <asm/sn/acpi.h>
#define IS_LEGACY_VGA_IOPORT(p) \
(((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df))
......@@ -31,10 +33,13 @@ void *sn_io_addr(unsigned long port)
{
if (!IS_RUNNING_ON_SIMULATOR()) {
if (IS_LEGACY_VGA_IOPORT(port))
port += vga_console_iobase;
return (__ia64_mk_io_addr(port));
/* On sn2, legacy I/O ports don't point at anything */
if (port < (64 * 1024))
return NULL;
if (SN_ACPI_BASE_SUPPORT())
return (__ia64_mk_io_addr(port));
else
return ((void *)(port | __IA64_UNCACHED_OFFSET));
} else {
/* but the simulator uses them... */
......
......@@ -388,6 +388,14 @@ void __init sn_setup(char **cmdline_p)
ia64_sn_plat_set_error_handling_features(); // obsolete
ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
/*
* Note: The calls to notify the PROM of ACPI and PCI Segment
* support must be done prior to acpi_load_tables(), as
* an ACPI capable PROM will rebuild the DSDT as result
* of the call.
*/
ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE);
ia64_sn_set_os_feature(OSF_ACPI_ENABLE);
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
......@@ -413,6 +421,16 @@ void __init sn_setup(char **cmdline_p)
if (! vga_console_membase)
sn_scan_pcdp();
/*
* Setup legacy IO space.
* vga_console_iobase maps to PCI IO Space address 0 on the
* bus containing the VGA console.
*/
if (vga_console_iobase) {
io_space[0].mmio_base = vga_console_iobase;
io_space[0].sparse = 0;
}
if (vga_console_membase) {
/* usable vga ... make tty0 the preferred default console */
if (!strstr(*cmdline_p, "console="))
......
......@@ -552,7 +552,7 @@ static void __exit tiocx_exit(void)
bus_unregister(&tiocx_bus_type);
}
subsys_initcall(tiocx_init);
fs_initcall(tiocx_init);
module_exit(tiocx_exit);
/************************************************************************
......
......@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2001-2004, 2006 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/interrupt.h>
......@@ -109,7 +109,6 @@ void *
pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
{
int nasid, cnode, j;
cnodeid_t near_cnode;
struct hubdev_info *hubdev_info;
struct pcibus_info *soft;
struct sn_flush_device_kernel *sn_flush_device_kernel;
......@@ -186,20 +185,6 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
return NULL;
}
if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
/* TIO PCI Bridge: find nearest node with CPUs */
int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode);
if (e < 0) {
near_cnode = (cnodeid_t)-1; /* use any node */
printk(KERN_WARNING "pcibr_bus_fixup: failed to find "
"near node with CPUs to TIO node %d, err=%d\n",
cnode, e);
}
controller->node = near_cnode;
}
else
controller->node = cnode;
return soft;
}
......
......@@ -15,7 +15,6 @@
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioce_provider.h>
#include <asm/sn/sn2/sn_hwperf.h>
/*
* 1/26/2006
......@@ -990,8 +989,6 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
static void *
tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
{
int my_nasid;
cnodeid_t my_cnode, mem_cnode;
struct tioce_common *tioce_common;
struct tioce_kernel *tioce_kern;
struct tioce __iomem *tioce_mmr;
......@@ -1035,21 +1032,6 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
tioce_common->ce_pcibus.bs_persist_segment,
tioce_common->ce_pcibus.bs_persist_busnum);
/*
* identify closest nasid for memory allocations
*/
my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base);
my_cnode = nasid_to_cnodeid(my_nasid);
if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) {
printk(KERN_WARNING "tioce_bus_fixup: failed to find "
"closest node with MEM to TIO node %d\n", my_cnode);
mem_cnode = (cnodeid_t)-1; /* use any node */
}
controller->node = mem_cnode;
return tioce_common;
}
......
......@@ -32,7 +32,7 @@
*/
#define IO_SPACE_LIMIT 0xffffffffffffffffUL
#define MAX_IO_SPACES_BITS 4
#define MAX_IO_SPACES_BITS 8
#define MAX_IO_SPACES (1UL << MAX_IO_SPACES_BITS)
#define IO_SPACE_BITS 24
#define IO_SPACE_SIZE (1UL << IO_SPACE_BITS)
......
......@@ -36,6 +36,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
u8 size);
typedef void ia64_mv_migrate_t(struct task_struct * task);
typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *);
/* DMA-mapping interface: */
typedef void ia64_mv_dma_init (void);
......@@ -95,6 +96,11 @@ machvec_noop_task (struct task_struct *task)
{
}
static inline void
machvec_noop_bus (struct pci_bus *bus)
{
}
extern void machvec_setup (char **);
extern void machvec_timer_interrupt (int, void *);
extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
......@@ -159,6 +165,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# define platform_migrate ia64_mv.migrate
# define platform_setup_msi_irq ia64_mv.setup_msi_irq
# define platform_teardown_msi_irq ia64_mv.teardown_msi_irq
# define platform_pci_fixup_bus ia64_mv.pci_fixup_bus
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
......@@ -210,6 +217,7 @@ struct ia64_machine_vector {
ia64_mv_migrate_t *migrate;
ia64_mv_setup_msi_irq_t *setup_msi_irq;
ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
ia64_mv_pci_fixup_bus_t *pci_fixup_bus;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
......@@ -257,6 +265,7 @@ struct ia64_machine_vector {
platform_migrate, \
platform_setup_msi_irq, \
platform_teardown_msi_irq, \
platform_pci_fixup_bus, \
}
extern struct ia64_machine_vector ia64_mv;
......@@ -416,5 +425,8 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size
#ifndef platform_teardown_msi_irq
# define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
#ifndef platform_pci_fixup_bus
# define platform_pci_fixup_bus machvec_noop_bus
#endif
#endif /* _ASM_IA64_MACHVEC_H */
......@@ -69,6 +69,7 @@ extern ia64_mv_dma_supported sn_dma_supported;
extern ia64_mv_migrate_t sn_migrate;
extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus;
/*
......@@ -127,6 +128,7 @@ extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
#define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
#define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
#define platform_pci_fixup_bus sn_pci_fixup_bus
#include <asm/sn/io.h>
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_ACPI_H
#define _ASM_IA64_SN_ACPI_H
#include "acpi/acglobal.h"
#define SN_ACPI_BASE_SUPPORT() (acpi_gbl_DSDT->oem_revision >= 0x20101)
#endif /* _ASM_IA64_SN_ACPI_H */
......@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_PCIDEV_H
#define _ASM_IA64_SN_PCI_PCIDEV_H
......@@ -12,31 +12,29 @@
/*
* In ia64, pci_dev->sysdata must be a *pci_controller. To provide access to
* the pcidev_info structs for all devices under a controller, we extend the
* definition of pci_controller, via sn_pci_controller, to include a list
* of pcidev_info.
* the pcidev_info structs for all devices under a controller, we keep a
* list of pcidev_info under pci_controller->platform_data.
*/
struct sn_pci_controller {
struct pci_controller pci_controller;
struct sn_platform_data {
void *provider_soft;
struct list_head pcidev_info;
};
#define SN_PCI_CONTROLLER(dev) ((struct sn_pci_controller *) dev->sysdata)
#define SN_PLATFORM_DATA(busdev) \
((struct sn_platform_data *)(PCI_CONTROLLER(busdev)->platform_data))
#define SN_PCIDEV_INFO(dev) sn_pcidev_info_get(dev)
#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
(struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
/*
* Given a pci_bus, return the sn pcibus_bussoft struct. Note that
* this only works for root busses, not for busses represented by PPB's.
*/
#define SN_PCIBUS_BUSSOFT(pci_bus) \
((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
((struct pcibus_bussoft *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
(struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
((struct pcibus_info *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
/*
* Given a struct pci_dev, return the sn pcibus_bussoft struct. Note
* that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
......@@ -72,8 +70,6 @@ extern void sn_irq_fixup(struct pci_dev *pci_dev,
struct sn_irq_info *sn_irq_info);
extern void sn_irq_unfixup(struct pci_dev *pci_dev);
extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
extern void sn_pci_controller_fixup(int segment, int busnum,
struct pci_bus *bus);
extern void sn_bus_store_sysdata(struct pci_dev *dev);
extern void sn_bus_free_sysdata(void);
extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
......
......@@ -44,8 +44,14 @@ extern int sn_prom_feature_available(int id);
* Once enabled, a feature cannot be disabled.
*
* By default, features are disabled unless explicitly enabled.
*
* These defines must be kept in sync with the corresponding
* PROM definitions in feature_sets.h.
*/
#define OSF_MCA_SLV_TO_OS_INIT_SLV 0
#define OSF_FEAT_LOG_SBES 1
#define OSF_ACPI_ENABLE 2
#define OSF_PCISEGMENT_ENABLE 3
#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
......@@ -77,6 +77,7 @@
#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated
#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a
#define SN_SAL_IOIF_INIT 0x0200005f
#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
#define SN_SAL_BTE_RECOVER 0x02000061
#define SN_SAL_RESERVED_DO_NOT_USE 0x02000062
......
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