Commit cb7b2d16 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents d26a9319 3e69f8b2
...@@ -381,6 +381,10 @@ config HUGETLB_PAGE_SIZE_4GB ...@@ -381,6 +381,10 @@ config HUGETLB_PAGE_SIZE_4GB
depends on MCKINLEY depends on MCKINLEY
bool "4GB" bool "4GB"
config HUGETLB_PAGE_SIZE_1GB
depends on MCKINLEY
bool "1GB"
config HUGETLB_PAGE_SIZE_256MB config HUGETLB_PAGE_SIZE_256MB
bool "256MB" bool "256MB"
......
...@@ -23,6 +23,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \ ...@@ -23,6 +23,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
CFLAGS_KERNEL := -mconstant-gp CFLAGS_KERNEL := -mconstant-gp
GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.')
GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
...@@ -35,7 +36,14 @@ $(error Sorry, you need a newer version of the assember, one that is built from ...@@ -35,7 +36,14 @@ $(error Sorry, you need a newer version of the assember, one that is built from
endif endif
ifneq ($(GCC_VERSION),2) ifneq ($(GCC_VERSION),2)
cflags-y += -frename-registers --param max-inline-insns=5000 cflags-$(CONFIG_ITANIUM) += -frename-registers
endif
ifeq ($(GCC_VERSION),3)
ifeq ($(GCC_MINOR_VERSION),4)
cflags-$(CONFIG_ITANIUM) += -mtune=merced
cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley
endif
endif endif
cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC) += -mb-step cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC) += -mb-step
...@@ -48,14 +56,14 @@ libs-y += arch/ia64/lib/ ...@@ -48,14 +56,14 @@ libs-y += arch/ia64/lib/
core-y += arch/ia64/kernel/ arch/ia64/mm/ core-y += arch/ia64/kernel/ arch/ia64/mm/
core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/
core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ arch/ia64/hp/common/ arch/ia64/hp/zx1/ \ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
arch/ia64/hp/sim/
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/ core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/
drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_PCI) += arch/ia64/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/
boot := arch/ia64/boot boot := arch/ia64/boot
tools := arch/ia64/tools tools := arch/ia64/tools
......
#define MACHVEC_PLATFORM_NAME dig #define MACHVEC_PLATFORM_NAME dig
#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig.h>
#include <asm/machvec_init.h> #include <asm/machvec_init.h>
This diff is collapsed.
...@@ -59,7 +59,7 @@ simcons_write (struct console *cons, const char *buf, unsigned count) ...@@ -59,7 +59,7 @@ simcons_write (struct console *cons, const char *buf, unsigned count)
static struct tty_driver *simcons_console_device (struct console *c, int *index) static struct tty_driver *simcons_console_device (struct console *c, int *index)
{ {
extern struct tty_driver hp_serial_driver; extern struct tty_driver hp_simserial_driver;
*index = c->index; *index = c->index;
return &hp_serial_driver; return &hp_simserial_driver;
} }
#define MACHVEC_PLATFORM_NAME hpsim #define MACHVEC_PLATFORM_NAME hpsim
#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpsim.h>
#include <asm/machvec_init.h> #include <asm/machvec_init.h>
...@@ -55,7 +55,7 @@ static int simeth_close(struct net_device *dev); ...@@ -55,7 +55,7 @@ static int simeth_close(struct net_device *dev);
static int simeth_tx(struct sk_buff *skb, struct net_device *dev); static int simeth_tx(struct sk_buff *skb, struct net_device *dev);
static int simeth_rx(struct net_device *dev); static int simeth_rx(struct net_device *dev);
static struct net_device_stats *simeth_get_stats(struct net_device *dev); static struct net_device_stats *simeth_get_stats(struct net_device *dev);
static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr);
...@@ -494,20 +494,21 @@ simeth_rx(struct net_device *dev) ...@@ -494,20 +494,21 @@ simeth_rx(struct net_device *dev)
/* /*
* Interrupt handler (Yes, we can do it too !!!) * Interrupt handler (Yes, we can do it too !!!)
*/ */
static void static irqreturn_t
simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
if ( dev == NULL ) { if ( dev == NULL ) {
printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq);
return; return IRQ_NONE;
} }
/* /*
* very simple loop because we get interrupts only when receving * very simple loop because we get interrupts only when receiving
*/ */
while (simeth_rx(dev)); while (simeth_rx(dev));
return IRQ_HANDLED;
} }
static struct net_device_stats * static struct net_device_stats *
......
...@@ -103,7 +103,8 @@ static struct serial_uart_config uart_config[] = { ...@@ -103,7 +103,8 @@ static struct serial_uart_config uart_config[] = {
{ 0, 0} { 0, 0}
}; };
static struct tty_driver hp_serial_driver, callout_driver; struct tty_driver hp_simserial_driver;
static struct tty_driver callout_driver;
static int serial_refcount; static int serial_refcount;
static struct async_struct *IRQ_ports[NR_IRQS]; static struct async_struct *IRQ_ports[NR_IRQS];
...@@ -184,7 +185,7 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs) ...@@ -184,7 +185,7 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
/* /*
* This is the serial driver's interrupt routine for a single port * This is the serial driver's interrupt routine for a single port
*/ */
static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
{ {
struct async_struct * info; struct async_struct * info;
...@@ -195,13 +196,14 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) ...@@ -195,13 +196,14 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
info = IRQ_ports[irq]; info = IRQ_ports[irq];
if (!info || !info->tty) { if (!info || !info->tty) {
printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
return; return IRQ_NONE;
} }
/* /*
* pretty simple in our case, because we only get interrupts * pretty simple in our case, because we only get interrupts
* on inbound traffic * on inbound traffic
*/ */
receive_chars(info->tty, regs); receive_chars(info->tty, regs);
return IRQ_HANDLED;
} }
/* /*
...@@ -768,7 +770,7 @@ startup(struct async_struct *info) ...@@ -768,7 +770,7 @@ startup(struct async_struct *info)
{ {
unsigned long flags; unsigned long flags;
int retval=0; int retval=0;
void (*handler)(int, void *, struct pt_regs *); irqreturn_t (*handler)(int, void *, struct pt_regs *);
struct serial_state *state= info->state; struct serial_state *state= info->state;
unsigned long page; unsigned long page;
...@@ -808,8 +810,7 @@ startup(struct async_struct *info) ...@@ -808,8 +810,7 @@ startup(struct async_struct *info)
} else } else
handler = rs_interrupt_single; handler = rs_interrupt_single;
retval = request_irq(state->irq, handler, IRQ_T(info), retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL);
"simserial", NULL);
if (retval) { if (retval) {
if (capable(CAP_SYS_ADMIN)) { if (capable(CAP_SYS_ADMIN)) {
if (info->tty) if (info->tty)
...@@ -1028,43 +1029,43 @@ simrs_init (void) ...@@ -1028,43 +1029,43 @@ simrs_init (void)
/* Initialize the tty_driver structure */ /* Initialize the tty_driver structure */
memset(&hp_serial_driver, 0, sizeof(struct tty_driver)); memset(&hp_simserial_driver, 0, sizeof(struct tty_driver));
hp_serial_driver.magic = TTY_DRIVER_MAGIC; hp_simserial_driver.magic = TTY_DRIVER_MAGIC;
hp_serial_driver.driver_name = "simserial"; hp_simserial_driver.driver_name = "simserial";
hp_serial_driver.name = "ttyS"; hp_simserial_driver.name = "ttyS";
hp_serial_driver.major = TTY_MAJOR; hp_simserial_driver.major = TTY_MAJOR;
hp_serial_driver.minor_start = 64; hp_simserial_driver.minor_start = 64;
hp_serial_driver.num = 1; hp_simserial_driver.num = 1;
hp_serial_driver.type = TTY_DRIVER_TYPE_SERIAL; hp_simserial_driver.type = TTY_DRIVER_TYPE_SERIAL;
hp_serial_driver.subtype = SERIAL_TYPE_NORMAL; hp_simserial_driver.subtype = SERIAL_TYPE_NORMAL;
hp_serial_driver.init_termios = tty_std_termios; hp_simserial_driver.init_termios = tty_std_termios;
hp_serial_driver.init_termios.c_cflag = hp_simserial_driver.init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL; B9600 | CS8 | CREAD | HUPCL | CLOCAL;
hp_serial_driver.flags = TTY_DRIVER_REAL_RAW; hp_simserial_driver.flags = TTY_DRIVER_REAL_RAW;
hp_serial_driver.refcount = &serial_refcount; hp_simserial_driver.refcount = &serial_refcount;
hp_serial_driver.table = serial_table; hp_simserial_driver.table = serial_table;
hp_serial_driver.termios = serial_termios; hp_simserial_driver.termios = serial_termios;
hp_serial_driver.termios_locked = serial_termios_locked; hp_simserial_driver.termios_locked = serial_termios_locked;
hp_serial_driver.open = rs_open; hp_simserial_driver.open = rs_open;
hp_serial_driver.close = rs_close; hp_simserial_driver.close = rs_close;
hp_serial_driver.write = rs_write; hp_simserial_driver.write = rs_write;
hp_serial_driver.put_char = rs_put_char; hp_simserial_driver.put_char = rs_put_char;
hp_serial_driver.flush_chars = rs_flush_chars; hp_simserial_driver.flush_chars = rs_flush_chars;
hp_serial_driver.write_room = rs_write_room; hp_simserial_driver.write_room = rs_write_room;
hp_serial_driver.chars_in_buffer = rs_chars_in_buffer; hp_simserial_driver.chars_in_buffer = rs_chars_in_buffer;
hp_serial_driver.flush_buffer = rs_flush_buffer; hp_simserial_driver.flush_buffer = rs_flush_buffer;
hp_serial_driver.ioctl = rs_ioctl; hp_simserial_driver.ioctl = rs_ioctl;
hp_serial_driver.throttle = rs_throttle; hp_simserial_driver.throttle = rs_throttle;
hp_serial_driver.unthrottle = rs_unthrottle; hp_simserial_driver.unthrottle = rs_unthrottle;
hp_serial_driver.send_xchar = rs_send_xchar; hp_simserial_driver.send_xchar = rs_send_xchar;
hp_serial_driver.set_termios = rs_set_termios; hp_simserial_driver.set_termios = rs_set_termios;
hp_serial_driver.stop = rs_stop; hp_simserial_driver.stop = rs_stop;
hp_serial_driver.start = rs_start; hp_simserial_driver.start = rs_start;
hp_serial_driver.hangup = rs_hangup; hp_simserial_driver.hangup = rs_hangup;
hp_serial_driver.break_ctl = rs_break; hp_simserial_driver.break_ctl = rs_break;
hp_serial_driver.wait_until_sent = rs_wait_until_sent; hp_simserial_driver.wait_until_sent = rs_wait_until_sent;
hp_serial_driver.read_proc = rs_read_proc; hp_simserial_driver.read_proc = rs_read_proc;
/* /*
* Let's have a little bit of fun ! * Let's have a little bit of fun !
...@@ -1087,14 +1088,14 @@ simrs_init (void) ...@@ -1087,14 +1088,14 @@ simrs_init (void)
* The callout device is just like normal device except for * The callout device is just like normal device except for
* major number and the subtype code. * major number and the subtype code.
*/ */
callout_driver = hp_serial_driver; callout_driver = hp_simserial_driver;
callout_driver.name = "cua"; callout_driver.name = "cua";
callout_driver.major = TTYAUX_MAJOR; callout_driver.major = TTYAUX_MAJOR;
callout_driver.subtype = SERIAL_TYPE_CALLOUT; callout_driver.subtype = SERIAL_TYPE_CALLOUT;
callout_driver.read_proc = 0; callout_driver.read_proc = 0;
callout_driver.proc_entry = 0; callout_driver.proc_entry = 0;
if (tty_register_driver(&hp_serial_driver)) if (tty_register_driver(&hp_simserial_driver))
panic("Couldn't register simserial driver\n"); panic("Couldn't register simserial driver\n");
if (tty_register_driver(&callout_driver)) if (tty_register_driver(&callout_driver))
......
...@@ -5,5 +5,4 @@ ...@@ -5,5 +5,4 @@
# Copyright (C) Alex Williamson (alex_williamson@hp.com) # Copyright (C) Alex Williamson (alex_williamson@hp.com)
# #
obj-y := hpzx1_misc.o
obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o
#define MACHVEC_PLATFORM_NAME hpzx1 #define MACHVEC_PLATFORM_NAME hpzx1
#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpzx1.h>
#include <asm/machvec_init.h> #include <asm/machvec_init.h>
/*
* Misc. support for HP zx1 chipset support
*
* Copyright (C) 2002-2003 Hewlett-Packard Co
* Alex Williamson <alex_williamson@hp.com>
* Bjorn Helgaas <bjorn_helgaas@hp.com>
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/efi.h>
#include <asm/dma.h>
#include <asm/iosapic.h>
extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, struct acpi_object_list *,
unsigned long *);
#define PFX "hpzx1: "
static int hpzx1_devices;
struct fake_pci_dev {
struct fake_pci_dev *next;
struct pci_dev *pci_dev;
unsigned long csr_base;
unsigned long csr_size;
unsigned long mapped_csrs; // ioremapped
int sizing; // in middle of BAR sizing operation?
} *fake_pci_dev_list;
static struct pci_ops *orig_pci_ops;
struct fake_pci_dev *
lookup_fake_dev (struct pci_bus *bus, unsigned int devfn)
{
struct fake_pci_dev *fake_dev;
for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next)
if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn)
return fake_dev;
return NULL;
}
static int
hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
if (!fake_dev)
return (*orig_pci_ops->read)(bus, devfn, where, size, value);
if (where == PCI_BASE_ADDRESS_0) {
if (fake_dev->sizing)
*value = ~(fake_dev->csr_size - 1);
else
*value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK)
| PCI_BASE_ADDRESS_SPACE_MEMORY);
fake_dev->sizing = 0;
return PCIBIOS_SUCCESSFUL;
}
switch (size) {
case 1: *value = readb(fake_dev->mapped_csrs + where); break;
case 2: *value = readw(fake_dev->mapped_csrs + where); break;
case 4: *value = readl(fake_dev->mapped_csrs + where); break;
default:
printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size);
break;
}
if (where == PCI_COMMAND)
*value |= PCI_COMMAND_MEMORY; /* SBA omits this */
return PCIBIOS_SUCCESSFUL;
}
static int
hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
{
struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
if (!fake_dev)
return (*orig_pci_ops->write)(bus, devfn, where, size, value);
if (where == PCI_BASE_ADDRESS_0) {
if (value == ((1UL << 8*size) - 1))
fake_dev->sizing = 1;
return PCIBIOS_SUCCESSFUL;
}
switch (size) {
case 1: writeb(value, fake_dev->mapped_csrs + where); break;
case 2: writew(value, fake_dev->mapped_csrs + where); break;
case 4: writel(value, fake_dev->mapped_csrs + where); break;
default:
printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops hp_pci_conf = {
.read = hp_cfg_read,
.write = hp_cfg_write
};
static void
hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size)
{
struct fake_pci_dev *fake;
int slot, ret;
struct pci_dev *dev;
struct pci_bus *b, *bus = NULL;
u8 hdr;
fake = kmalloc(sizeof(*fake), GFP_KERNEL);
if (!fake) {
printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, (void *) addr);
return;
}
memset(fake, 0, sizeof(*fake));
fake->csr_base = addr;
fake->csr_size = size;
fake->mapped_csrs = (unsigned long) ioremap(addr, size);
fake->sizing = 0;
pci_for_each_bus(b)
if (busnum == b->number) {
bus = b;
break;
}
if (!bus) {
printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n",
busnum, name, (void *) addr);
kfree(fake);
return;
}
for (slot = 0x1e; slot; slot--)
if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0)))
break;
if (slot < 0) {
printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n",
name, (void *) addr, busnum);
kfree(fake);
return;
}
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name, (void *) addr);
kfree(fake);
return;
}
bus->ops = &hp_pci_conf; // replace pci ops for this bus
fake->pci_dev = dev;
fake->next = fake_pci_dev_list;
fake_pci_dev_list = fake;
memset(dev, 0, sizeof(*dev));
dev->bus = bus;
dev->sysdata = fake;
dev->dev.parent = bus->dev;
dev->dev.bus = &pci_bus_type;
dev->devfn = PCI_DEVFN(slot, 0);
pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr);
dev->hdr_type = hdr & 0x7f;
pci_setup_device(dev);
// pci_insert_device() without running /sbin/hotplug
list_add_tail(&dev->bus_list, &bus->devices);
list_add_tail(&dev->global_list, &pci_devices);
strcpy(dev->dev.bus_id, dev->slot_name);
ret = device_register(&dev->dev);
if (ret < 0)
printk(KERN_INFO PFX "fake device registration failed (%d)\n", ret);
printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr, dev->slot_name);
hpzx1_devices++;
}
struct acpi_hp_vendor_long {
u8 guid_id;
u8 guid[16];
u8 csr_base[8];
u8 csr_length[8];
};
#define HP_CCSR_LENGTH 0x21
#define HP_CCSR_TYPE 0x2
#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \
0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *);
extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *);
extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int);
extern void acpi_dispose_crs(struct acpi_buffer *);
static acpi_status
hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
{
int i, offset = 0;
acpi_status status;
struct acpi_buffer buf;
struct acpi_resource_vendor *res;
struct acpi_hp_vendor_long *hp_res;
efi_guid_t vendor_guid;
*csr_base = 0;
*csr_length = 0;
status = acpi_get_crs(obj, &buf);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PFX "Unable to get _CRS data on object\n");
return status;
}
res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);
if (!res) {
printk(KERN_ERR PFX "Failed to find config space for device\n");
acpi_dispose_crs(&buf);
return AE_NOT_FOUND;
}
hp_res = (struct acpi_hp_vendor_long *)(res->reserved);
if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {
printk(KERN_ERR PFX "Unknown Vendor data\n");
acpi_dispose_crs(&buf);
return AE_TYPE; /* Revisit error? */
}
memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t));
if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {
printk(KERN_ERR PFX "Vendor GUID does not match\n");
acpi_dispose_crs(&buf);
return AE_TYPE; /* Revisit error? */
}
for (i = 0 ; i < 8 ; i++) {
*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8));
*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));
}
acpi_dispose_crs(&buf);
return AE_OK;
}
static acpi_status
hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
{
u64 csr_base = 0, csr_length = 0;
acpi_status status;
char *name = context;
char fullname[16];
status = hp_csr_space(obj, &csr_base, &csr_length);
if (ACPI_FAILURE(status))
return status;
/*
* Only SBA shows up in ACPI namespace, so its CSR space
* includes both SBA and IOC. Make SBA and IOC show up
* separately in PCI space.
*/
sprintf(fullname, "%s SBA", name);
hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000);
sprintf(fullname, "%s IOC", name);
hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000);
return AE_OK;
}
static acpi_status
hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
{
u64 csr_base = 0, csr_length = 0;
acpi_status status;
acpi_native_uint busnum;
char *name = context;
char fullname[32];
status = hp_csr_space(obj, &csr_base, &csr_length);
if (ACPI_FAILURE(status))
return status;
status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum);
if (ACPI_FAILURE(status)) {
printk(KERN_WARNING PFX "evaluate _BBN fail=0x%x\n", status);
busnum = 0; // no _BBN; stick it on bus 0
}
sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum);
hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length);
return AE_OK;
}
static void
hpzx1_acpi_dev_init(void)
{
extern struct pci_ops *pci_root_ops;
orig_pci_ops = pci_root_ops;
/*
* Make fake PCI devices for the following hardware in the
* ACPI namespace. This makes it more convenient for drivers
* because they can claim these devices based on PCI
* information, rather than needing to know about ACPI. The
* 64-bit "HPA" space for this hardware is available as BAR
* 0/1.
*
* HWP0001: Single IOC SBA w/o IOC in namespace
* HWP0002: LBA device
* HWP0003: AGP LBA device
*/
acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);
acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL);
acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL);
}
extern void sba_init(void);
static int
hpzx1_init (void)
{
/* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
MAX_DMA_ADDRESS = ~0UL;
hpzx1_acpi_dev_init();
sba_init();
return 0;
}
subsys_initcall(hpzx1_init);
...@@ -273,9 +273,9 @@ ia32_syscall_table: ...@@ -273,9 +273,9 @@ ia32_syscall_table:
data8 sys32_sigsuspend data8 sys32_sigsuspend
data8 compat_sys_sigpending data8 compat_sys_sigpending
data8 sys_sethostname data8 sys_sethostname
data8 sys32_setrlimit /* 75 */ data8 compat_sys_setrlimit /* 75 */
data8 sys32_old_getrlimit data8 compat_sys_old_getrlimit
data8 sys32_getrusage data8 compat_sys_getrusage
data8 sys32_gettimeofday data8 sys32_gettimeofday
data8 sys32_settimeofday data8 sys32_settimeofday
data8 sys32_getgroups16 /* 80 */ data8 sys32_getgroups16 /* 80 */
...@@ -312,7 +312,7 @@ ia32_syscall_table: ...@@ -312,7 +312,7 @@ ia32_syscall_table:
data8 sys_vhangup data8 sys_vhangup
data8 sys32_ni_syscall /* used to be sys_idle */ data8 sys32_ni_syscall /* used to be sys_idle */
data8 sys32_ni_syscall data8 sys32_ni_syscall
data8 sys32_wait4 data8 compat_sys_wait4
data8 sys_swapoff /* 115 */ data8 sys_swapoff /* 115 */
data8 sys32_sysinfo data8 sys32_sysinfo
data8 sys32_ipc data8 sys32_ipc
...@@ -389,7 +389,7 @@ ia32_syscall_table: ...@@ -389,7 +389,7 @@ ia32_syscall_table:
data8 sys32_ni_syscall /* streams1 */ data8 sys32_ni_syscall /* streams1 */
data8 sys32_ni_syscall /* streams2 */ data8 sys32_ni_syscall /* streams2 */
data8 sys32_vfork /* 190 */ data8 sys32_vfork /* 190 */
data8 sys32_getrlimit data8 compat_sys_getrlimit
data8 sys32_mmap2 data8 sys32_mmap2
data8 sys32_truncate64 data8 sys32_truncate64
data8 sys32_ftruncate64 data8 sys32_ftruncate64
......
...@@ -3,13 +3,16 @@ ...@@ -3,13 +3,16 @@
* *
* Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 VA Linux Co
* Copyright (C) 2000 Don Dugger <n0ano@valinux.com> * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
* Copyright (C) 2001-2002 Hewlett-Packard Co * Copyright (C) 2001-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/dirent.h> #include <linux/dirent.h>
#include <linux/fs.h> /* argh, msdos_fs.h isn't self-contained... */ #include <linux/fs.h> /* argh, msdos_fs.h isn't self-contained... */
#include <linux/signal.h> /* argh, msdos_fs.h isn't self-contained... */
#include <asm/ia32.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
#include <linux/mtio.h> #include <linux/mtio.h>
...@@ -33,8 +36,6 @@ ...@@ -33,8 +36,6 @@
#define __KERNEL__ #define __KERNEL__
#include <scsi/sg.h> #include <scsi/sg.h>
#include <asm/ia32.h>
#include <../drivers/char/drm/drm.h> #include <../drivers/char/drm/drm.h>
#include <../drivers/char/drm/mga_drm.h> #include <../drivers/char/drm/mga_drm.h>
#include <../drivers/char/drm/i810_drm.h> #include <../drivers/char/drm/i810_drm.h>
......
...@@ -103,7 +103,7 @@ ia32_exception (struct pt_regs *regs, unsigned long isr) ...@@ -103,7 +103,7 @@ ia32_exception (struct pt_regs *regs, unsigned long isr)
* C1 reg you need in case of a stack fault, 0x040 is the stack * C1 reg you need in case of a stack fault, 0x040 is the stack
* fault bit. We should only be taking one exception at a time, * fault bit. We should only be taking one exception at a time,
* so if this combination doesn't produce any single exception, * so if this combination doesn't produce any single exception,
* then we have a bad program that isn't syncronizing its FPU usage * then we have a bad program that isn't synchronizing its FPU usage
* and it will suffer the consequences since we won't be able to * and it will suffer the consequences since we won't be able to
* fully reproduce the context of the exception * fully reproduce the context of the exception
*/ */
......
...@@ -53,10 +53,10 @@ ...@@ -53,10 +53,10 @@
#include <asm/types.h> #include <asm/types.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/ia32.h>
#include <net/scm.h> #include <net/scm.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/ia32.h>
#define DEBUG 0 #define DEBUG 0
...@@ -177,7 +177,7 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf) ...@@ -177,7 +177,7 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf)
{ {
int err; int err;
if (stat->size > MAX_NON_LFS) if ((u64) stat->size > MAX_NON_LFS)
return -EOVERFLOW; return -EOVERFLOW;
if (clear_user(ubuf, sizeof(*ubuf))) if (clear_user(ubuf, sizeof(*ubuf)))
...@@ -243,8 +243,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro ...@@ -243,8 +243,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
return -ENOMEM; return -ENOMEM;
if (old_prot) if (old_prot)
if (copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE)) copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
return -EFAULT;
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
{ {
...@@ -837,8 +836,9 @@ sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timev ...@@ -837,8 +836,9 @@ sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timev
} }
} }
size = FDS_BYTES(n);
ret = -EINVAL; ret = -EINVAL;
if (n < 0) if (n < 0 || size < n)
goto out_nofds; goto out_nofds;
if (n > current->files->max_fdset) if (n > current->files->max_fdset)
...@@ -850,7 +850,6 @@ sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timev ...@@ -850,7 +850,6 @@ sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timev
* long-words. * long-words.
*/ */
ret = -ENOMEM; ret = -ENOMEM;
size = FDS_BYTES(n);
bits = kmalloc(6 * size, GFP_KERNEL); bits = kmalloc(6 * size, GFP_KERNEL);
if (!bits) if (!bits)
goto out_nofds; goto out_nofds;
...@@ -928,8 +927,7 @@ asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long) ...@@ -928,8 +927,7 @@ asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long)
static struct iovec * static struct iovec *
get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
{ {
int i; u32 i, buf, len;
u32 buf, len;
struct iovec *ivp, *iov; struct iovec *ivp, *iov;
/* Get the "struct iovec" from user memory */ /* Get the "struct iovec" from user memory */
...@@ -1005,77 +1003,6 @@ sys32_writev (int fd, struct compat_iovec *vector, u32 count) ...@@ -1005,77 +1003,6 @@ sys32_writev (int fd, struct compat_iovec *vector, u32 count)
return ret; return ret;
} }
#define RLIM_INFINITY32 0x7fffffff
#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
struct rlimit32 {
int rlim_cur;
int rlim_max;
};
extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
asmlinkage long
sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim)
{
mm_segment_t old_fs = get_fs();
struct rlimit r;
int ret;
set_fs(KERNEL_DS);
ret = sys_getrlimit(resource, &r);
set_fs(old_fs);
if (!ret) {
ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
}
return ret;
}
asmlinkage long
sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim)
{
mm_segment_t old_fs = get_fs();
struct rlimit r;
int ret;
set_fs(KERNEL_DS);
ret = sys_getrlimit(resource, &r);
set_fs(old_fs);
if (!ret) {
if (r.rlim_cur >= 0xffffffff)
r.rlim_cur = 0xffffffff;
if (r.rlim_max >= 0xffffffff)
r.rlim_max = 0xffffffff;
ret = put_user(r.rlim_cur, &rlim->rlim_cur);
ret |= put_user(r.rlim_max, &rlim->rlim_max);
}
return ret;
}
extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);
asmlinkage long
sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim)
{
struct rlimit r;
int ret;
mm_segment_t old_fs = get_fs();
if (resource >= RLIM_NLIMITS)
return -EINVAL;
if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max))
return -EFAULT;
if (r.rlim_cur == RLIM_INFINITY32)
r.rlim_cur = RLIM_INFINITY;
if (r.rlim_max == RLIM_INFINITY32)
r.rlim_max = RLIM_INFINITY;
set_fs(KERNEL_DS);
ret = sys_setrlimit(resource, &r);
set_fs(old_fs);
return ret;
}
/* /*
* sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
* *
...@@ -1648,19 +1575,35 @@ shmctl32 (int first, int second, void *uptr) ...@@ -1648,19 +1575,35 @@ shmctl32 (int first, int second, void *uptr)
return err; return err;
} }
extern int sem_ctls[];
#define sc_semopm (sem_ctls[2])
static long static long
semtimedop32(int semid, struct sembuf *tsems, int nsems, semtimedop32(int semid, struct sembuf *tsops, int nsops,
const struct compat_timespec *timeout32) struct compat_timespec *timeout32)
{ {
struct timespec t; struct timespec t;
if (get_user (t.tv_sec, &timeout32->tv_sec) || mm_segment_t oldfs;
get_user (t.tv_nsec, &timeout32->tv_nsec)) long ret;
/* parameter checking precedence should mirror sys_semtimedop() */
if (nsops < 1 || semid < 0)
return -EINVAL;
if (nsops > sc_semopm)
return -E2BIG;
if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) ||
get_compat_timespec(&t, timeout32))
return -EFAULT; return -EFAULT;
return sys_semtimedop(semid, tsems, nsems, &t);
oldfs = get_fs();
set_fs(KERNEL_DS);
ret = sys_semtimedop(semid, tsops, nsops, &t);
set_fs(oldfs);
return ret;
} }
asmlinkage long asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{ {
int version; int version;
...@@ -1668,12 +1611,15 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) ...@@ -1668,12 +1611,15 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
call &= 0xffff; call &= 0xffff;
switch (call) { switch (call) {
case SEMTIMEDOP:
if (fifth)
return semtimedop32(first, (struct sembuf *)AA(ptr),
second, (struct compat_timespec *)AA(fifth));
/* else fall through for normal semop() */
case SEMOP: case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */ /* struct sembuf is the same on 32 and 64bit :)) */
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL); return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
case SEMTIMEDOP: NULL);
return semtimedop32(first, (struct sembuf *)AA(ptr), second,
(const struct compat_timespec *)AA(fifth));
case SEMGET: case SEMGET:
return sys_semget(first, second, third); return sys_semget(first, second, third);
case SEMCTL: case SEMCTL:
...@@ -1724,98 +1670,10 @@ sys32_time (int *tloc) ...@@ -1724,98 +1670,10 @@ sys32_time (int *tloc)
return i; return i;
} }
struct rusage32 {
struct compat_timeval ru_utime;
struct compat_timeval ru_stime;
int ru_maxrss;
int ru_ixrss;
int ru_idrss;
int ru_isrss;
int ru_minflt;
int ru_majflt;
int ru_nswap;
int ru_inblock;
int ru_oublock;
int ru_msgsnd;
int ru_msgrcv;
int ru_nsignals;
int ru_nvcsw;
int ru_nivcsw;
};
static int
put_rusage (struct rusage32 *ru, struct rusage *r)
{
int err;
if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
return -EFAULT;
err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
err |= __put_user (r->ru_idrss, &ru->ru_idrss);
err |= __put_user (r->ru_isrss, &ru->ru_isrss);
err |= __put_user (r->ru_minflt, &ru->ru_minflt);
err |= __put_user (r->ru_majflt, &ru->ru_majflt);
err |= __put_user (r->ru_nswap, &ru->ru_nswap);
err |= __put_user (r->ru_inblock, &ru->ru_inblock);
err |= __put_user (r->ru_oublock, &ru->ru_oublock);
err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
return err;
}
asmlinkage long
sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
{
if (!ru)
return sys_wait4(pid, stat_addr, options, NULL);
else {
struct rusage r;
int ret;
unsigned int status;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
set_fs(old_fs);
if (put_rusage(ru, &r))
return -EFAULT;
if (stat_addr && put_user(status, stat_addr))
return -EFAULT;
return ret;
}
}
asmlinkage long asmlinkage long
sys32_waitpid (int pid, unsigned int *stat_addr, int options) sys32_waitpid (int pid, unsigned int *stat_addr, int options)
{ {
return sys32_wait4(pid, stat_addr, options, NULL); return compat_sys_wait4(pid, stat_addr, options, NULL);
}
extern asmlinkage long sys_getrusage (int who, struct rusage *ru);
asmlinkage long
sys32_getrusage (int who, struct rusage32 *ru)
{
struct rusage r;
int ret;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_getrusage(who, &r);
set_fs(old_fs);
if (put_rusage (ru, &r))
return -EFAULT;
return ret;
} }
static unsigned int static unsigned int
...@@ -2211,7 +2069,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, ...@@ -2211,7 +2069,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
ret = -EIO; ret = -EIO;
break; break;
} }
for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
put_user(getreg(child, i), (unsigned int *) A(data)); put_user(getreg(child, i), (unsigned int *) A(data));
data += sizeof(int); data += sizeof(int);
} }
...@@ -2223,7 +2081,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, ...@@ -2223,7 +2081,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
ret = -EIO; ret = -EIO;
break; break;
} }
for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
get_user(tmp, (unsigned int *) A(data)); get_user(tmp, (unsigned int *) A(data));
putreg(child, i, tmp); putreg(child, i, tmp);
data += sizeof(int); data += sizeof(int);
...@@ -2299,7 +2157,7 @@ sys32_iopl (int level) ...@@ -2299,7 +2157,7 @@ sys32_iopl (int level)
return(-EINVAL); return(-EINVAL);
/* Trying to gain more privileges? */ /* Trying to gain more privileges? */
asm volatile ("mov %0=ar.eflag ;;" : "=r"(old)); asm volatile ("mov %0=ar.eflag ;;" : "=r"(old));
if (level > ((old >> 12) & 3)) { if ((unsigned int) level > ((old >> 12) & 3)) {
if (!capable(CAP_SYS_RAWIO)) if (!capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
} }
......
...@@ -11,6 +11,8 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate.o ia64_ksyms.o irq.o irq_ia64.o ir ...@@ -11,6 +11,8 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate.o ia64_ksyms.o irq.o irq_ia64.o ir
obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_FSYS) += fsys.o obj-$(CONFIG_FSYS) += fsys.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o
obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o
obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o
obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_IOSAPIC) += iosapic.o
......
...@@ -3,69 +3,99 @@ ...@@ -3,69 +3,99 @@
* *
* Copyright (C) 2003 Hewlett-Packard * Copyright (C) 2003 Hewlett-Packard
* Copyright (C) Alex Williamson * Copyright (C) Alex Williamson
* Copyright (C) Bjorn Helgaas
* *
* Vendor specific extensions to ACPI. These are used by both * Vendor specific extensions to ACPI.
* HP and NEC.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <asm/acpi-ext.h> #include <asm/acpi-ext.h>
/* struct acpi_vendor_descriptor {
* Note: Strictly speaking, this is only needed for HP and NEC machines. u8 guid_id;
* However, NEC machines identify themselves as DIG-compliant, so there is efi_guid_t guid;
* no easy way to #ifdef this out. };
*/
struct acpi_vendor_info {
struct acpi_vendor_descriptor *descriptor;
u8 *data;
u32 length;
};
acpi_status acpi_status
hp_acpi_csr_space (acpi_handle obj, u64 *csr_base, u64 *csr_length) acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
{ {
int i, offset = 0; struct acpi_vendor_info *info = (struct acpi_vendor_info *) context;
acpi_status status; struct acpi_resource_vendor *vendor;
struct acpi_buffer buf; struct acpi_vendor_descriptor *descriptor;
struct acpi_resource_vendor *res; u32 length;
struct acpi_hp_vendor_long *hp_res;
efi_guid_t vendor_guid; if (resource->id != ACPI_RSTYPE_VENDOR)
return AE_OK;
*csr_base = 0;
*csr_length = 0; vendor = (struct acpi_resource_vendor *) &resource->data;
descriptor = (struct acpi_vendor_descriptor *) vendor->reserved;
status = acpi_get_crs(obj, &buf); if (vendor->length <= sizeof(*info->descriptor) ||
if (ACPI_FAILURE(status)) { descriptor->guid_id != info->descriptor->guid_id ||
printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); efi_guidcmp(descriptor->guid, info->descriptor->guid))
return status; return AE_OK;
}
length = vendor->length - sizeof(struct acpi_vendor_descriptor);
res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); info->data = acpi_os_allocate(length);
if (!res) { if (!info->data)
printk(KERN_ERR PREFIX "Failed to find config space for device\n"); return AE_NO_MEMORY;
acpi_dispose_crs(&buf);
memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length);
info->length = length;
return AE_CTRL_TERMINATE;
}
acpi_status
acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
u8 **data, u32 *length)
{
struct acpi_vendor_info info;
info.descriptor = id;
info.data = 0;
acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
if (!info.data)
return AE_NOT_FOUND; return AE_NOT_FOUND;
}
hp_res = (struct acpi_hp_vendor_long *)(res->reserved); *data = info.data;
*length = info.length;
return AE_OK;
}
struct acpi_vendor_descriptor hp_ccsr_descriptor = {
.guid_id = 2,
.guid = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
};
if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { acpi_status
printk(KERN_ERR PREFIX "Unknown Vendor data\n"); hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
acpi_dispose_crs(&buf); {
return AE_TYPE; /* Revisit error? */ acpi_status status;
} u8 *data;
u32 length;
int i;
memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {
printk(KERN_ERR PREFIX "Vendor GUID does not match\n");
acpi_dispose_crs(&buf);
return AE_TYPE; /* Revisit error? */
}
for (i = 0 ; i < 8 ; i++) { if (ACPI_FAILURE(status) || length != 16)
*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); return AE_NOT_FOUND;
*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));
} memcpy(csr_base, data, sizeof(*csr_base));
memcpy(csr_length, data + 8, sizeof(*csr_length));
acpi_os_free(data);
acpi_dispose_crs(&buf);
return AE_OK; return AE_OK;
} }
EXPORT_SYMBOL(hp_acpi_csr_space);
...@@ -115,134 +115,6 @@ acpi_get_sysname (void) ...@@ -115,134 +115,6 @@ acpi_get_sysname (void)
#endif #endif
} }
#ifdef CONFIG_ACPI
/**
* acpi_get_crs - Return the current resource settings for a device
* obj: A handle for this device
* buf: A buffer to be populated by this call.
*
* Pass a valid handle, typically obtained by walking the namespace and a
* pointer to an allocated buffer, and this function will fill in the buffer
* with a list of acpi_resource structures.
*/
acpi_status
acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf)
{
acpi_status result;
buf->length = 0;
buf->pointer = NULL;
result = acpi_get_current_resources(obj, buf);
if (result != AE_BUFFER_OVERFLOW)
return result;
buf->pointer = kmalloc(buf->length, GFP_KERNEL);
if (!buf->pointer)
return -ENOMEM;
return acpi_get_current_resources(obj, buf);
}
struct acpi_resource *
acpi_get_crs_next (struct acpi_buffer *buf, int *offset)
{
struct acpi_resource *res;
if (*offset >= buf->length)
return NULL;
res = buf->pointer + *offset;
*offset += res->length;
return res;
}
union acpi_resource_data *
acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type)
{
for (;;) {
struct acpi_resource *res = acpi_get_crs_next(buf, offset);
if (!res)
return NULL;
if (res->id == type)
return &res->data;
}
}
void
acpi_dispose_crs (struct acpi_buffer *buf)
{
kfree(buf->pointer);
}
void
acpi_get_crs_addr (struct acpi_buffer *buf, int type, u64 *base, u64 *size, u64 *tra)
{
int offset = 0;
struct acpi_resource_address16 *addr16;
struct acpi_resource_address32 *addr32;
struct acpi_resource_address64 *addr64;
for (;;) {
struct acpi_resource *res = acpi_get_crs_next(buf, &offset);
if (!res)
return;
switch (res->id) {
case ACPI_RSTYPE_ADDRESS16:
addr16 = (struct acpi_resource_address16 *) &res->data;
if (type == addr16->resource_type) {
*base = addr16->min_address_range;
*size = addr16->address_length;
*tra = addr16->address_translation_offset;
return;
}
break;
case ACPI_RSTYPE_ADDRESS32:
addr32 = (struct acpi_resource_address32 *) &res->data;
if (type == addr32->resource_type) {
*base = addr32->min_address_range;
*size = addr32->address_length;
*tra = addr32->address_translation_offset;
return;
}
break;
case ACPI_RSTYPE_ADDRESS64:
addr64 = (struct acpi_resource_address64 *) &res->data;
if (type == addr64->resource_type) {
*base = addr64->min_address_range;
*size = addr64->address_length;
*tra = addr64->address_translation_offset;
return;
}
break;
}
}
}
int
acpi_get_addr_space(void *obj, u8 type, u64 *base, u64 *length, u64 *tra)
{
acpi_status status;
struct acpi_buffer buf;
*base = 0;
*length = 0;
*tra = 0;
status = acpi_get_crs((acpi_handle)obj, &buf);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
return status;
}
acpi_get_crs_addr(&buf, type, base, length, tra);
acpi_dispose_crs(&buf);
return AE_OK;
}
#endif /* CONFIG_ACPI */
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
#define ACPI_MAX_PLATFORM_INTERRUPTS 256 #define ACPI_MAX_PLATFORM_INTERRUPTS 256
...@@ -324,7 +196,8 @@ acpi_parse_lsapic (acpi_table_entry_header *header) ...@@ -324,7 +196,8 @@ acpi_parse_lsapic (acpi_table_entry_header *header)
printk(" enabled"); printk(" enabled");
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid; smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid;
if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus]) if (hard_smp_processor_id()
== (unsigned int) smp_boot_data.cpu_phys_id[total_cpus])
printk(" (BSP)"); printk(" (BSP)");
#endif #endif
} }
...@@ -918,8 +791,7 @@ acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) ...@@ -918,8 +791,7 @@ acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
return 0; return 0;
/* Turn it on */ /* Turn it on */
vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, vector = iosapic_register_intr (gsi, polarity, trigger);
trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return vector; return vector;
} }
......
...@@ -59,7 +59,7 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec) ...@@ -59,7 +59,7 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
unsigned long next_ip; unsigned long next_ip;
struct siginfo siginfo; struct siginfo siginfo;
struct illegal_op_return rv; struct illegal_op_return rv;
int tmp_taken, unimplemented_address; long tmp_taken, unimplemented_address;
rv.fkt = (unsigned long) -1; rv.fkt = (unsigned long) -1;
......
...@@ -203,16 +203,16 @@ STUB_GET_NEXT_HIGH_MONO_COUNT(virt, ) ...@@ -203,16 +203,16 @@ STUB_GET_NEXT_HIGH_MONO_COUNT(virt, )
STUB_RESET_SYSTEM(virt, ) STUB_RESET_SYSTEM(virt, )
void void
efi_gettimeofday (struct timeval *tv) efi_gettimeofday (struct timespec *ts)
{ {
efi_time_t tm; efi_time_t tm;
memset(tv, 0, sizeof(tv)); memset(ts, 0, sizeof(ts));
if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS) if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
return; return;
tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
tv->tv_usec = tm.nanosecond / 1000; ts->tv_nsec = tm.nanosecond;
} }
static int static int
...@@ -512,7 +512,7 @@ efi_init (void) ...@@ -512,7 +512,7 @@ efi_init (void)
/* Show what we know for posterity */ /* Show what we know for posterity */
c16 = __va(efi.systab->fw_vendor); c16 = __va(efi.systab->fw_vendor);
if (c16) { if (c16) {
for (i = 0;i < sizeof(vendor) && *c16; ++i) for (i = 0;i < (int) sizeof(vendor) && *c16; ++i)
vendor[i] = *c16++; vendor[i] = *c16++;
vendor[i] = '\0'; vendor[i] = '\0';
} }
...@@ -520,7 +520,7 @@ efi_init (void) ...@@ -520,7 +520,7 @@ efi_init (void)
printk(KERN_INFO "EFI v%u.%.02u by %s:", printk(KERN_INFO "EFI v%u.%.02u by %s:",
efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
for (i = 0; i < efi.systab->nr_tables; i++) { for (i = 0; i < (int) efi.systab->nr_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
efi.mps = __va(config_tables[i].table); efi.mps = __va(config_tables[i].table);
printk(" MPS=0x%lx", config_tables[i].table); printk(" MPS=0x%lx", config_tables[i].table);
......
...@@ -138,8 +138,7 @@ utf8_strlen(efi_char16_t *data, unsigned long maxlength) ...@@ -138,8 +138,7 @@ utf8_strlen(efi_char16_t *data, unsigned long maxlength)
static inline unsigned long static inline unsigned long
utf8_strsize(efi_char16_t *data, unsigned long maxlength) utf8_strsize(efi_char16_t *data, unsigned long maxlength)
{ {
return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
sizeof(efi_char16_t);
} }
...@@ -170,8 +169,7 @@ efivar_create_proc_entry(unsigned long variable_name_size, ...@@ -170,8 +169,7 @@ efivar_create_proc_entry(unsigned long variable_name_size,
efi_guid_t *vendor_guid) efi_guid_t *vendor_guid)
{ {
int i, short_name_size = variable_name_size / int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
sizeof(efi_char16_t) + 38;
char *short_name; char *short_name;
efivar_entry_t *new_efivar; efivar_entry_t *new_efivar;
...@@ -192,7 +190,7 @@ efivar_create_proc_entry(unsigned long variable_name_size, ...@@ -192,7 +190,7 @@ efivar_create_proc_entry(unsigned long variable_name_size,
/* Convert Unicode to normal chars (assume top bits are 0), /* Convert Unicode to normal chars (assume top bits are 0),
ala UTF-8 */ ala UTF-8 */
for (i=0; i<variable_name_size / sizeof(efi_char16_t); i++) { for (i=0; i< (int) (variable_name_size / sizeof(efi_char16_t)); i++) {
short_name[i] = variable_name[i] & 0xFF; short_name[i] = variable_name[i] & 0xFF;
} }
......
...@@ -37,7 +37,7 @@ static char fw_mem[( sizeof(struct ia64_boot_param) ...@@ -37,7 +37,7 @@ static char fw_mem[( sizeof(struct ia64_boot_param)
+ NUM_MEM_DESCS*(sizeof(efi_memory_desc_t)) + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
+ 1024)] __attribute__ ((aligned (8))); + 1024)] __attribute__ ((aligned (8)));
#ifdef CONFIG_IA64_HP_SIM #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
/* Simulator system calls: */ /* Simulator system calls: */
...@@ -233,7 +233,7 @@ asm ( ...@@ -233,7 +233,7 @@ asm (
static efi_status_t static efi_status_t
efi_get_time (efi_time_t *tm, efi_time_cap_t *tc) efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
{ {
#ifdef CONFIG_IA64_HP_SIM #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
struct { struct {
int tv_sec; /* must be 32bits to work */ int tv_sec; /* must be 32bits to work */
int tv_usec; int tv_usec;
...@@ -255,7 +255,7 @@ efi_get_time (efi_time_t *tm, efi_time_cap_t *tc) ...@@ -255,7 +255,7 @@ efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
static void static void
efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data) efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
{ {
#ifdef CONFIG_IA64_HP_SIM #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
ssc(status, 0, 0, 0, SSC_EXIT); ssc(status, 0, 0, 0, SSC_EXIT);
#else #else
# error Not implemented yet... # error Not implemented yet...
......
...@@ -733,3 +733,82 @@ SET_REG(b4); ...@@ -733,3 +733,82 @@ SET_REG(b4);
SET_REG(b5); SET_REG(b5);
#endif /* CONFIG_IA64_BRL_EMU */ #endif /* CONFIG_IA64_BRL_EMU */
#ifdef CONFIG_SMP
/*
* This routine handles spinlock contention. It uses a non-standard calling
* convention to avoid converting leaf routines into interior routines. Because
* of this special convention, there are several restrictions:
*
* - do not use gp relative variables, this code is called from the kernel
* and from modules, r1 is undefined.
* - do not use stacked registers, the caller owns them.
* - do not use the scratch stack space, the caller owns it.
* - do not use any registers other than the ones listed below
*
* Inputs:
* ar.pfs - saved CFM of caller
* ar.ccv - 0 (and available for use)
* r28 - available for use.
* r29 - available for use.
* r30 - available for use.
* r31 - address of lock, available for use.
* b7 - return address
* p14 - available for use.
*
* If you patch this code to use more registers, do not forget to update
* the clobber lists for spin_lock() in include/asm-ia64/spinlock.h.
*/
#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4)
.prologue
.save ar.pfs, r0 // this code effectively has a zero frame size
.save rp, r28
.body
nop 0
nop 0
.restore sp // pop existing prologue after next insn
mov b6 = r28
.prologue
.save ar.pfs, r0
.altrp b6
.body
.wait:
// exponential backoff, kdb, lockmeter etc. go in here
hint @pause
ld4.bias r30=[r31]
nop 0
;;
cmp4.eq p14,p0=r30,r0
(p14) br.cond.sptk.few b6 // lock is now free, try to acquire
br.cond.sptk.few .wait
END(ia64_spinlock_contention_pre3_4)
#else
GLOBAL_ENTRY(ia64_spinlock_contention)
.prologue
.altrp b6
.body
.wait:
// exponential backoff, kdb, lockmeter etc. go in here
hint @pause
ld4.bias r30=[r31]
;;
cmp4.ne p14,p0=r30,r0
mov r30 = 1
(p14) br.cond.sptk.few .wait
;;
cmpxchg4.acq r30=[r31], r30, ar.ccv
;;
cmp4.ne p14,p0=r0,r30
(p14) br.cond.sptk.few .wait
br.ret.sptk.many b6 // lock is now taken
END(ia64_spinlock_contention)
#endif
#endif /* CONFIG_SMP */
...@@ -46,6 +46,7 @@ EXPORT_SYMBOL(ip_fast_csum); ...@@ -46,6 +46,7 @@ EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(__ia64_memcpy_fromio); EXPORT_SYMBOL(__ia64_memcpy_fromio);
EXPORT_SYMBOL(__ia64_memcpy_toio); EXPORT_SYMBOL(__ia64_memcpy_toio);
EXPORT_SYMBOL(__ia64_memset_c_io); EXPORT_SYMBOL(__ia64_memset_c_io);
EXPORT_SYMBOL(io_space);
#include <asm/semaphore.h> #include <asm/semaphore.h>
EXPORT_SYMBOL_NOVERS(__down); EXPORT_SYMBOL_NOVERS(__down);
...@@ -56,6 +57,12 @@ EXPORT_SYMBOL_NOVERS(__up); ...@@ -56,6 +57,12 @@ EXPORT_SYMBOL_NOVERS(__up);
#include <asm/page.h> #include <asm/page.h>
EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(clear_page);
#ifdef CONFIG_VIRTUAL_MEM_MAP
#include <asm/pgtable.h>
EXPORT_SYMBOL(vmalloc_end);
EXPORT_SYMBOL(ia64_pfn_valid);
#endif
#include <asm/processor.h> #include <asm/processor.h>
EXPORT_SYMBOL(cpu_info__per_cpu); EXPORT_SYMBOL(cpu_info__per_cpu);
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
...@@ -161,3 +168,11 @@ EXPORT_SYMBOL(unw_access_br); ...@@ -161,3 +168,11 @@ EXPORT_SYMBOL(unw_access_br);
EXPORT_SYMBOL(unw_access_fr); EXPORT_SYMBOL(unw_access_fr);
EXPORT_SYMBOL(unw_access_ar); EXPORT_SYMBOL(unw_access_ar);
EXPORT_SYMBOL(unw_access_pr); EXPORT_SYMBOL(unw_access_pr);
#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
extern void ia64_spinlock_contention_pre3_4 (void);
EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4);
#else
extern void ia64_spinlock_contention (void);
EXPORT_SYMBOL(ia64_spinlock_contention);
#endif
...@@ -581,9 +581,8 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, ...@@ -581,9 +581,8 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
isa_irq, gsi, isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low",
polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector);
dest, vector);
/* program the IOSAPIC routing table */ /* program the IOSAPIC routing table */
set_rte(vector, dest); set_rte(vector, dest);
...@@ -635,7 +634,6 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) ...@@ -635,7 +634,6 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
(ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
if ((gsi_base == 0) && pcat_compat) { if ((gsi_base == 0) && pcat_compat) {
/* /*
* Map the legacy ISA devices into the IOSAPIC data. Some of these may * Map the legacy ISA devices into the IOSAPIC data. Some of these may
* get reprogrammed later on with data from the ACPI Interrupt Source * get reprogrammed later on with data from the ACPI Interrupt Source
...@@ -646,20 +644,11 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) ...@@ -646,20 +644,11 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
} }
} }
static void __init void
fixup_vector (int vector, unsigned int gsi, const char *pci_id) iosapic_enable_intr (unsigned int vector)
{ {
struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
irq_desc_t *idesc;
unsigned int dest; unsigned int dest;
idesc = irq_desc(vector);
if (idesc->handler != irq_type) {
if (idesc->handler != &no_irq_type)
printk(KERN_INFO "IOSAPIC: changing vector %d from %s to %s\n",
vector, idesc->handler->typename, irq_type->typename);
idesc->handler = irq_type;
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* /*
* For platforms that do not support interrupt redirect via the XTP interface, we * For platforms that do not support interrupt redirect via the XTP interface, we
...@@ -687,10 +676,12 @@ fixup_vector (int vector, unsigned int gsi, const char *pci_id) ...@@ -687,10 +676,12 @@ fixup_vector (int vector, unsigned int gsi, const char *pci_id)
#endif #endif
set_rte(vector, dest); set_rte(vector, dest);
printk(KERN_INFO "IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n", printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n",
pci_id, gsi, dest, vector); vector, dest);
} }
#ifdef CONFIG_ACPI_PCI
void __init void __init
iosapic_parse_prt (void) iosapic_parse_prt (void)
{ {
...@@ -699,6 +690,8 @@ iosapic_parse_prt (void) ...@@ -699,6 +690,8 @@ iosapic_parse_prt (void)
unsigned int gsi; unsigned int gsi;
int vector; int vector;
char pci_id[16]; char pci_id[16];
struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
irq_desc_t *idesc;
list_for_each(node, &acpi_prt.entries) { list_for_each(node, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node); entry = list_entry(node, struct acpi_prt_entry, node);
...@@ -711,6 +704,9 @@ iosapic_parse_prt (void) ...@@ -711,6 +704,9 @@ iosapic_parse_prt (void)
vector = gsi_to_vector(gsi); vector = gsi_to_vector(gsi);
if (vector < 0) { if (vector < 0) {
if (find_iosapic(gsi) < 0)
continue;
/* allocate a vector for this interrupt line */ /* allocate a vector for this interrupt line */
if (pcat_compat && (gsi < 16)) if (pcat_compat && (gsi < 16))
vector = isa_irq_to_vector(gsi); vector = isa_irq_to_vector(gsi);
...@@ -718,11 +714,22 @@ iosapic_parse_prt (void) ...@@ -718,11 +714,22 @@ iosapic_parse_prt (void)
/* new GSI; allocate a vector for it */ /* new GSI; allocate a vector for it */
vector = ia64_alloc_vector(); vector = ia64_alloc_vector();
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
IOSAPIC_LEVEL);
} }
snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
fixup_vector(vector, gsi, pci_id); /*
* If vector was previously initialized to a different
* handler, re-initialize.
*/
idesc = irq_desc(vector);
if (idesc->handler != irq_type)
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
IOSAPIC_LEVEL);
} }
} }
#endif /* CONFIG_ACPI */
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -33,6 +32,7 @@ ...@@ -33,6 +32,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/kallsyms.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
* Linux has a controller-independent x86 interrupt architecture. * Linux has a controller-independent x86 interrupt architecture.
* every controller has a 'controller-template', that is used * every controller has a 'controller-template', that is used
* by the main code to do the right thing. Each driver-visible * by the main code to do the right thing. Each driver-visible
* interrupt source is transparently wired to the apropriate * interrupt source is transparently wired to the appropriate
* controller. Thus drivers need not be aware of the * controller. Thus drivers need not be aware of the
* interrupt-controller. * interrupt-controller.
* *
...@@ -91,7 +91,8 @@ static void register_irq_proc (unsigned int irq); ...@@ -91,7 +91,8 @@ static void register_irq_proc (unsigned int irq);
* Special irq handlers. * Special irq handlers.
*/ */
void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
{ return IRQ_NONE; }
/* /*
* Generic no controller code * Generic no controller code
...@@ -141,9 +142,11 @@ struct hw_interrupt_type no_irq_type = { ...@@ -141,9 +142,11 @@ struct hw_interrupt_type no_irq_type = {
}; };
atomic_t irq_err_count; atomic_t irq_err_count;
#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) #ifdef CONFIG_X86_IO_APIC
#ifdef APIC_MISMATCH_DEBUG
atomic_t irq_mis_count; atomic_t irq_mis_count;
#endif #endif
#endif
/* /*
* Generic, controller-independent functions: * Generic, controller-independent functions:
...@@ -178,9 +181,10 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -178,9 +181,10 @@ int show_interrupts(struct seq_file *p, void *v)
#endif #endif
seq_printf(p, " %14s", idesc->handler->typename); seq_printf(p, " %14s", idesc->handler->typename);
seq_printf(p, " %s", action->name); seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next) for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name); seq_printf(p, ", %s", action->name);
seq_putc(p, '\n'); seq_putc(p, '\n');
skip: skip:
spin_unlock_irqrestore(&idesc->lock, flags); spin_unlock_irqrestore(&idesc->lock, flags);
...@@ -190,16 +194,18 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -190,16 +194,18 @@ int show_interrupts(struct seq_file *p, void *v)
if (cpu_online(j)) if (cpu_online(j))
seq_printf(p, "%10u ", nmi_count(j)); seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n'); seq_putc(p, '\n');
#if defined(CONFIG_SMP) && defined(CONFIG_X86) #if CONFIG_X86_LOCAL_APIC
seq_puts(p, "LOC: "); seq_puts(p, "LOC: ");
for (j = 0; j < NR_CPUS; j++) for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j)) if (cpu_online(j))
seq_printf(p, "%10u ", apic_timer_irqs[j]); seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
seq_putc(p, '\n'); seq_putc(p, '\n');
#endif #endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) #ifdef CONFIG_X86_IO_APIC
#ifdef APIC_MISMATCH_DEBUG
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
#endif #endif
return 0; return 0;
} }
...@@ -219,21 +225,46 @@ inline void synchronize_irq(unsigned int irq) ...@@ -219,21 +225,46 @@ inline void synchronize_irq(unsigned int irq)
* waste of time and is not what some drivers would * waste of time and is not what some drivers would
* prefer. * prefer.
*/ */
int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) int handle_IRQ_event(unsigned int irq,
struct pt_regs *regs, struct irqaction *action)
{ {
int status = 1; /* Force the "do bottom halves" bit */ int status = 1; /* Force the "do bottom halves" bit */
int retval = 0;
struct irqaction *first_action = action;
if (!(action->flags & SA_INTERRUPT)) if (!(action->flags & SA_INTERRUPT))
local_irq_enable(); local_irq_enable();
do { do {
status |= action->flags; status |= action->flags;
action->handler(irq, action->dev_id, regs); retval |= action->handler(irq, action->dev_id, regs);
action = action->next; action = action->next;
} while (action); } while (action);
if (status & SA_SAMPLE_RANDOM) if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
local_irq_disable(); local_irq_disable();
if (retval != 1) {
static int count = 100;
if (count) {
count--;
if (retval) {
printk("irq event %d: bogus retval mask %x\n",
irq, retval);
} else {
printk("irq %d: nobody cared!\n", irq);
}
dump_stack();
printk("handlers:\n");
action = first_action;
do {
printk("[<%p>]", action->handler);
print_symbol(" (%s)",
(unsigned long)action->handler);
printk("\n");
action = action->next;
} while (action);
}
}
return status; return status;
} }
...@@ -455,7 +486,7 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs) ...@@ -455,7 +486,7 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
*/ */
int request_irq(unsigned int irq, int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *), irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, unsigned long irqflags,
const char * devname, const char * devname,
void *dev_id) void *dev_id)
...@@ -482,7 +513,7 @@ int request_irq(unsigned int irq, ...@@ -482,7 +513,7 @@ int request_irq(unsigned int irq,
return -EINVAL; return -EINVAL;
action = (struct irqaction *) action = (struct irqaction *)
kmalloc(sizeof(struct irqaction), GFP_KERNEL); kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
if (!action) if (!action)
return -ENOMEM; return -ENOMEM;
...@@ -511,10 +542,7 @@ int request_irq(unsigned int irq, ...@@ -511,10 +542,7 @@ int request_irq(unsigned int irq,
* does not return until any executing interrupts for this IRQ * does not return until any executing interrupts for this IRQ
* have completed. * have completed.
* *
* This function may be called from interrupt context. * This function must not be called from interrupt context.
*
* Bugs: Attempting to free an irq in a handler for the same irq hangs
* the machine.
*/ */
void free_irq(unsigned int irq, void *dev_id) void free_irq(unsigned int irq, void *dev_id)
...@@ -545,11 +573,8 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -545,11 +573,8 @@ void free_irq(unsigned int irq, void *dev_id)
} }
spin_unlock_irqrestore(&desc->lock,flags); spin_unlock_irqrestore(&desc->lock,flags);
#ifdef CONFIG_SMP
/* Wait to make sure it's not being used on another CPU */ /* Wait to make sure it's not being used on another CPU */
while (desc->status & IRQ_INPROGRESS) synchronize_irq(irq);
synchronize_irq(irq);
#endif
kfree(action); kfree(action);
return; return;
} }
...@@ -664,7 +689,6 @@ unsigned long probe_irq_on(void) ...@@ -664,7 +689,6 @@ unsigned long probe_irq_on(void)
* only return ISA irq numbers - just so that we reset them * only return ISA irq numbers - just so that we reset them
* all to a known state. * all to a known state.
*/ */
unsigned int probe_irq_mask(unsigned long val) unsigned int probe_irq_mask(unsigned long val)
{ {
int i; int i;
...@@ -705,7 +729,7 @@ unsigned int probe_irq_mask(unsigned long val) ...@@ -705,7 +729,7 @@ unsigned int probe_irq_mask(unsigned long val)
* The interrupt probe logic state is returned to its previous * The interrupt probe logic state is returned to its previous
* value. * value.
* *
* BUGS: When used in a module (which arguably shouldnt happen) * BUGS: When used in a module (which arguably shouldn't happen)
* nothing prevents two IRQ probe callers from overlapping. The * nothing prevents two IRQ probe callers from overlapping. The
* results of this are non-optimal. * results of this are non-optimal.
*/ */
...@@ -748,6 +772,8 @@ int setup_irq(unsigned int irq, struct irqaction * new) ...@@ -748,6 +772,8 @@ int setup_irq(unsigned int irq, struct irqaction * new)
struct irqaction *old, **p; struct irqaction *old, **p;
irq_desc_t *desc = irq_desc(irq); irq_desc_t *desc = irq_desc(irq);
if (desc->handler == &no_irq_type)
return -ENOSYS;
/* /*
* Some drivers like serial.c use request_irq() heavily, * Some drivers like serial.c use request_irq() heavily,
* so we have to be careful not to interfere with a * so we have to be careful not to interfere with a
...@@ -808,11 +834,11 @@ static struct proc_dir_entry * irq_dir [NR_IRQS]; ...@@ -808,11 +834,11 @@ static struct proc_dir_entry * irq_dir [NR_IRQS];
#define HEX_DIGITS 8 #define HEX_DIGITS 8
static int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret) static unsigned int parse_hex_value (const char *buffer,
unsigned long count, unsigned long *ret)
{ {
unsigned char hexnum [HEX_DIGITS]; unsigned char hexnum [HEX_DIGITS];
unsigned long value; unsigned long value, i;
int i;
if (!count) if (!count)
return -EINVAL; return -EINVAL;
...@@ -950,12 +976,13 @@ static void register_irq_proc (unsigned int irq) ...@@ -950,12 +976,13 @@ static void register_irq_proc (unsigned int irq)
#if CONFIG_SMP #if CONFIG_SMP
{ {
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
/* create /proc/irq/1234/smp_affinity */ /* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
if (entry) { if (entry) {
entry->nlink = 1; entry->nlink = 1;
entry->data = (void *)(unsigned long)irq; entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc; entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc; entry->write_proc = irq_affinity_write_proc;
} }
......
...@@ -145,7 +145,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) ...@@ -145,7 +145,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
static struct irqaction ipi_irqaction = { static struct irqaction ipi_irqaction = {
.handler = handle_IPI, .handler = handle_IPI,
......
#include <linux/config.h> #include <linux/config.h>
#include <asm/system.h>
#ifdef CONFIG_IA64_GENERIC #ifdef CONFIG_IA64_GENERIC
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/page.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <asm/page.h>
struct ia64_machine_vector ia64_mv; struct ia64_machine_vector ia64_mv;
...@@ -43,3 +45,9 @@ void ...@@ -43,3 +45,9 @@ void
machvec_noop (void) machvec_noop (void)
{ {
} }
void
machvec_memory_fence (void)
{
mb();
}
This diff is collapsed.
...@@ -766,8 +766,6 @@ GLOBAL_ENTRY(ia64_monarch_init_handler) ...@@ -766,8 +766,6 @@ GLOBAL_ENTRY(ia64_monarch_init_handler)
// stash the information the SAL passed to os // stash the information the SAL passed to os
SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
;; ;;
// now we want to save information so we can dump registers
SAVE_MIN_WITH_COVER SAVE_MIN_WITH_COVER
;; ;;
mov r8=cr.ifa mov r8=cr.ifa
...@@ -798,10 +796,12 @@ IVirtual_Switch: ...@@ -798,10 +796,12 @@ IVirtual_Switch:
// //
// Let's call the C handler to get the rest of the state info // Let's call the C handler to get the rest of the state info
// //
alloc r14=ar.pfs,0,0,1,0 // now it's safe (must be first in insn group!) alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
;; // ;;
adds out0=16,sp // out0 = pointer to pt_regs adds out0=16,sp // out0 = pointer to pt_regs
;; ;;
DO_SAVE_SWITCH_STACK
adds out1=16,sp // out0 = pointer to switch_stack
br.call.sptk.many rp=ia64_init_handler br.call.sptk.many rp=ia64_init_handler
.ret1: .ret1:
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,8 +25,8 @@ static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={ ...@@ -25,8 +25,8 @@ static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={
/* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -143,11 +143,8 @@ pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *va ...@@ -143,11 +143,8 @@ pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *va
case 8: val8 = *val; case 8: val8 = *val;
val13 = th->pmc[13]; val13 = th->pmc[13];
val14 = th->pmc[14]; val14 = th->pmc[14];
*val |= 1UL << 2; /* bit 2 must always be 1 */
check_case1 = 1; check_case1 = 1;
break; break;
case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */
break;
case 13: val8 = th->pmc[8]; case 13: val8 = th->pmc[8];
val13 = *val; val13 = *val;
val14 = th->pmc[14]; val14 = th->pmc[14];
......
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
#include "sigframe.h" #include "sigframe.h"
static void void
do_show_stack (struct unw_frame_info *info, void *arg) ia64_do_show_stack (struct unw_frame_info *info, void *arg)
{ {
unsigned long ip, sp, bsp; unsigned long ip, sp, bsp;
char buf[80]; /* don't make it so big that it overflows the stack! */ char buf[80]; /* don't make it so big that it overflows the stack! */
...@@ -57,7 +57,7 @@ do_show_stack (struct unw_frame_info *info, void *arg) ...@@ -57,7 +57,7 @@ do_show_stack (struct unw_frame_info *info, void *arg)
unw_get_sp(info, &sp); unw_get_sp(info, &sp);
unw_get_bsp(info, &bsp); unw_get_bsp(info, &bsp);
snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n", snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n",
ip, sp, bsp); ip, sp, bsp);
print_symbol(buf, ip); print_symbol(buf, ip);
} while (unw_unwind(info) >= 0); } while (unw_unwind(info) >= 0);
...@@ -73,12 +73,12 @@ void ...@@ -73,12 +73,12 @@ void
show_stack (struct task_struct *task) show_stack (struct task_struct *task)
{ {
if (!task) if (!task)
unw_init_running(do_show_stack, 0); unw_init_running(ia64_do_show_stack, 0);
else { else {
struct unw_frame_info info; struct unw_frame_info info;
unw_init_from_blocked_task(&info, task); unw_init_from_blocked_task(&info, task);
do_show_stack(&info, 0); ia64_do_show_stack(&info, 0);
} }
} }
...@@ -123,8 +123,8 @@ show_regs (struct pt_regs *regs) ...@@ -123,8 +123,8 @@ show_regs (struct pt_regs *regs)
if (user_mode(regs)) { if (user_mode(regs)) {
/* print the stacked registers */ /* print the stacked registers */
unsigned long val, sof, *bsp, ndirty; unsigned long val, *bsp, ndirty;
int i, is_nat = 0; int i, sof, is_nat = 0;
sof = regs->cr_ifs & 0x7f; /* size of frame */ sof = regs->cr_ifs & 0x7f; /* size of frame */
ndirty = (regs->loadrs >> 19); ndirty = (regs->loadrs >> 19);
...@@ -135,7 +135,7 @@ show_regs (struct pt_regs *regs) ...@@ -135,7 +135,7 @@ show_regs (struct pt_regs *regs)
((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
} }
} else } else
show_stack(0); show_stack(NULL);
} }
void void
...@@ -379,6 +379,7 @@ copy_thread (int nr, unsigned long clone_flags, ...@@ -379,6 +379,7 @@ copy_thread (int nr, unsigned long clone_flags,
# define THREAD_FLAGS_TO_SET 0 # define THREAD_FLAGS_TO_SET 0
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
| THREAD_FLAGS_TO_SET); | THREAD_FLAGS_TO_SET);
p->thread.last_fph_cpu = -1;
#ifdef CONFIG_IA32_SUPPORT #ifdef CONFIG_IA32_SUPPORT
/* /*
* If we're cloning an IA32 task then save the IA32 extra * If we're cloning an IA32 task then save the IA32 extra
......
...@@ -202,17 +202,16 @@ static unsigned long ...@@ -202,17 +202,16 @@ static unsigned long
get_rnat (struct pt_regs *pt, struct switch_stack *sw, get_rnat (struct pt_regs *pt, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr) unsigned long *krbs, unsigned long *urnat_addr)
{ {
unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL; unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0UL;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs; long num_regs;
kbsp = (unsigned long *) sw->ar_bspstore; kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore;
/* /*
* First, figure out which bit number slot 0 in user-land maps * First, figure out which bit number slot 0 in user-land maps to in the kernel
* to in the kernel rnat. Do this by figuring out how many * rnat. Do this by figuring out how many register slots we're beyond the user's
* register slots we're beyond the user's backingstore and * backingstore and then computing the equivalent address in kernel space.
* then computing the equivalent address in kernel space.
*/ */
num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1); num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
...@@ -222,8 +221,8 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw, ...@@ -222,8 +221,8 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
if (ubspstore + 63 > urnat_addr) { if (ubspstore + 63 > urnat_addr) {
/* some bits need to be merged in from pt->ar_rnat */ /* some bits need to be merged in from pt->ar_rnat */
kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1);
urnat = (pt->ar_rnat & ~kmask); urnat = (pt->ar_rnat & umask);
} }
if (rnat0_kaddr >= kbsp) { if (rnat0_kaddr >= kbsp) {
rnat0 = sw->ar_rnat; rnat0 = sw->ar_rnat;
...@@ -235,7 +234,7 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw, ...@@ -235,7 +234,7 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
} else if (rnat1_kaddr > krbs) { } else if (rnat1_kaddr > krbs) {
rnat1 = *rnat1_kaddr; rnat1 = *rnat1_kaddr;
} }
urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask; urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask;
return urnat; return urnat;
} }
...@@ -246,17 +245,19 @@ static void ...@@ -246,17 +245,19 @@ static void
put_rnat (struct pt_regs *pt, struct switch_stack *sw, put_rnat (struct pt_regs *pt, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat) unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat)
{ {
unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask; unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift, slot, ndirty;
long num_regs; long num_regs, nbits;
ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
nbits = ndirty % 63;
kbsp = (unsigned long *) sw->ar_bspstore; kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore;
/* /*
* First, figure out which bit number slot 0 in user-land maps * First, figure out which bit number slot 0 in user-land maps to in the kernel
* to in the kernel rnat. Do this by figuring out how many * rnat. Do this by figuring out how many register slots we're beyond the user's
* register slots we're beyond the user's backingstore and * backingstore and then computing the equivalent address in kernel space.
* then computing the equivalent address in kernel space.
*/ */
num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1); num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1);
slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
...@@ -264,29 +265,37 @@ put_rnat (struct pt_regs *pt, struct switch_stack *sw, ...@@ -264,29 +265,37 @@ put_rnat (struct pt_regs *pt, struct switch_stack *sw,
rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr); rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
rnat0_kaddr = rnat1_kaddr - 64; rnat0_kaddr = rnat1_kaddr - 64;
printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr);
if (ubspstore + 63 > urnat_addr) { if (ubspstore + 63 > urnat_addr) {
/* some bits need to be place in pt->ar_rnat: */ /* some bits need to be place in pt->ar_rnat: */
kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); slot = ia64_rse_slot_num(ubspstore);
pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask); umask = ((1UL << slot) - 1);
pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask);
nbits -= slot;
if (nbits <= 0)
return;
} }
mask = (1UL << nbits) - 1;
/* /*
* Note: Section 11.1 of the EAS guarantees that bit 63 of an * Note: Section 11.1 of the EAS guarantees that bit 63 of an
* rnat slot is ignored. so we don't have to clear it here. * rnat slot is ignored. so we don't have to clear it here.
*/ */
rnat0 = (urnat << shift); rnat0 = (urnat << shift);
mask = ~0UL << shift; m = mask << shift;
printk("%s: rnat0=%016lx, m=%016lx, rnat0_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat0, m, rnat0_kaddr, kbsp);
if (rnat0_kaddr >= kbsp) { if (rnat0_kaddr >= kbsp) {
sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask); sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m);
} else if (rnat0_kaddr > krbs) { } else if (rnat0_kaddr > krbs) {
*rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask)); *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m));
} }
rnat1 = (urnat >> (63 - shift)); rnat1 = (urnat >> (63 - shift));
mask = ~0UL >> (63 - shift); m = mask >> (63 - shift);
printk("%s: rnat1=%016lx, m=%016lx, rnat1_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat1, m, rnat1_kaddr, kbsp);
if (rnat1_kaddr >= kbsp) { if (rnat1_kaddr >= kbsp) {
sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask); sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m);
} else if (rnat1_kaddr > krbs) { } else if (rnat1_kaddr > krbs) {
*rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask)); *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m));
} }
} }
...@@ -589,6 +598,7 @@ ia64_flush_fph (struct task_struct *task) ...@@ -589,6 +598,7 @@ ia64_flush_fph (struct task_struct *task)
psr->mfh = 0; psr->mfh = 0;
ia64_save_fpu(&task->thread.fph[0]); ia64_save_fpu(&task->thread.fph[0]);
task->thread.flags |= IA64_THREAD_FPH_VALID; task->thread.flags |= IA64_THREAD_FPH_VALID;
task->thread.last_fph_cpu = smp_processor_id();
} }
} }
...@@ -608,12 +618,11 @@ ia64_sync_fph (struct task_struct *task) ...@@ -608,12 +618,11 @@ ia64_sync_fph (struct task_struct *task)
ia64_flush_fph(task); ia64_flush_fph(task);
if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) { if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) {
task->thread.flags |= IA64_THREAD_FPH_VALID; task->thread.flags |= IA64_THREAD_FPH_VALID;
task->thread.last_fph_cpu = -1; /* force reload */
memset(&task->thread.fph, 0, sizeof(task->thread.fph)); memset(&task->thread.fph, 0, sizeof(task->thread.fph));
} }
#ifndef CONFIG_SMP
if (ia64_get_fpu_owner() == task) if (ia64_get_fpu_owner() == task)
ia64_set_fpu_owner(0); ia64_set_fpu_owner(0);
#endif
psr->dfh = 1; psr->dfh = 1;
} }
...@@ -702,7 +711,9 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data ...@@ -702,7 +711,9 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data
case PT_R4: case PT_R5: case PT_R6: case PT_R7: case PT_R4: case PT_R5: case PT_R6: case PT_R7:
if (write_access) { if (write_access) {
/* read NaT bit first: */ /* read NaT bit first: */
ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, data, &nat); unsigned long dummy;
ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, &dummy, &nat);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
......
...@@ -116,7 +116,7 @@ ia64_sal_init (struct ia64_sal_systab *systab) ...@@ -116,7 +116,7 @@ ia64_sal_init (struct ia64_sal_systab *systab)
p = (char *) (systab + 1); p = (char *) (systab + 1);
for (i = 0; i < systab->entry_count; i++) { for (i = 0; i < systab->entry_count; i++) {
/* /*
* The first byte of each entry type contains the type desciptor. * The first byte of each entry type contains the type descriptor.
*/ */
switch (*p) { switch (*p) {
case SAL_DESC_ENTRY_POINT: case SAL_DESC_ENTRY_POINT:
......
...@@ -38,7 +38,7 @@ static salinfo_entry_t salinfo_entries[]={ ...@@ -38,7 +38,7 @@ static salinfo_entry_t salinfo_entries[]={
{ "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, }, { "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, },
}; };
#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t)) #define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
/* /*
* One for each feature and one more for the directory entry... * One for each feature and one more for the directory entry...
......
...@@ -59,7 +59,10 @@ unsigned long ia64_cycles_per_usec; ...@@ -59,7 +59,10 @@ unsigned long ia64_cycles_per_usec;
struct ia64_boot_param *ia64_boot_param; struct ia64_boot_param *ia64_boot_param;
struct screen_info screen_info; struct screen_info screen_info;
unsigned long ia64_max_cacheline_size;
unsigned long ia64_iobase; /* virtual address for I/O accesses */ unsigned long ia64_iobase; /* virtual address for I/O accesses */
struct io_space io_space[MAX_IO_SPACES];
unsigned int num_io_spaces;
unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */ unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */
...@@ -412,6 +415,11 @@ setup_arch (char **cmdline_p) ...@@ -412,6 +415,11 @@ setup_arch (char **cmdline_p)
} }
ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
/* setup legacy IO port space */
io_space[0].mmio_base = ia64_iobase;
io_space[0].sparse = 1;
num_io_spaces = 1;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
cpu_physical_id(0) = hard_smp_processor_id(); cpu_physical_id(0) = hard_smp_processor_id();
#endif #endif
...@@ -421,7 +429,7 @@ setup_arch (char **cmdline_p) ...@@ -421,7 +429,7 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
acpi_boot_init(); acpi_boot_init();
#endif #endif
#ifdef CONFIG_SERIAL_HCDP #ifdef CONFIG_SERIAL_8250_HCDP
if (efi.hcdp) { if (efi.hcdp) {
void setup_serial_hcdp(void *); void setup_serial_hcdp(void *);
...@@ -494,7 +502,7 @@ show_cpuinfo (struct seq_file *m, void *v) ...@@ -494,7 +502,7 @@ show_cpuinfo (struct seq_file *m, void *v)
memcpy(features, " standard", 10); memcpy(features, " standard", 10);
cp = features; cp = features;
sep = 0; sep = 0;
for (i = 0; i < sizeof(feature_bits)/sizeof(feature_bits[0]); ++i) { for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) {
if (mask & feature_bits[i].mask) { if (mask & feature_bits[i].mask) {
if (sep) if (sep)
*cp++ = sep; *cp++ = sep;
...@@ -625,6 +633,39 @@ setup_per_cpu_areas (void) ...@@ -625,6 +633,39 @@ setup_per_cpu_areas (void)
/* start_kernel() requires this... */ /* start_kernel() requires this... */
} }
static void
get_max_cacheline_size (void)
{
unsigned long line_size, max = 1;
u64 l, levels, unique_caches;
pal_cache_config_info_t cci;
s64 status;
status = ia64_pal_cache_summary(&levels, &unique_caches);
if (status != 0) {
printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
__FUNCTION__, status);
max = SMP_CACHE_BYTES;
goto out;
}
for (l = 0; l < levels; ++l) {
status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2,
&cci);
if (status != 0) {
printk(KERN_ERR
"%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n",
__FUNCTION__, l, status);
max = SMP_CACHE_BYTES;
}
line_size = 1 << cci.pcci_line_size;
if (line_size > max)
max = line_size;
}
out:
if (max > ia64_max_cacheline_size)
ia64_max_cacheline_size = max;
}
/* /*
* cpu_init() initializes state that is per-CPU. This function acts * cpu_init() initializes state that is per-CPU. This function acts
...@@ -668,6 +709,8 @@ cpu_init (void) ...@@ -668,6 +709,8 @@ cpu_init (void)
cpu_info->node_data = get_node_data_ptr(); cpu_info->node_data = get_node_data_ptr();
#endif #endif
get_max_cacheline_size();
/* /*
* We can't pass "local_cpu_data" to identify_cpu() because we haven't called * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
* ia64_mmu_init() yet. And we can't call ia64_mmu_init() first because it * ia64_mmu_init() yet. And we can't call ia64_mmu_init() first because it
......
...@@ -142,8 +142,13 @@ restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr) ...@@ -142,8 +142,13 @@ restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr)
__copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
psr->mfh = 0; /* drop signal handler's fph contents... */ psr->mfh = 0; /* drop signal handler's fph contents... */
if (!psr->dfh) if (psr->dfh)
current->thread.last_fph_cpu = -1;
else {
__ia64_load_fpu(current->thread.fph); __ia64_load_fpu(current->thread.fph);
ia64_set_fpu_owner(current);
current->thread.last_fph_cpu = smp_processor_id();
}
} }
return err; return err;
} }
...@@ -523,7 +528,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ...@@ -523,7 +528,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
else else
errno = -errno; errno = -errno;
} }
} else if (scr->pt.r10 != -1) } else if ((long) scr->pt.r10 != -1)
/* /*
* A system calls has to be restarted only if one of the error codes * A system calls has to be restarted only if one of the error codes
* ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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