summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJody McIntyre <scjody@modernduck.com>2005-12-17 01:10:35 +0300
committerJody McIntyre <scjody@modernduck.com>2005-12-17 01:10:35 +0300
commit16e842a62a8ffcc2e51def6ef9fd6e0926539bc5 (patch)
tree2cf6c23ab195e68712bca51351c1d37ed950c55d /arch
parent525352eb6d355bef6adf597252fc6d04f2dbe66c (diff)
parent42245e65f356ed54fdf7a1f9a0095e0bc40f73a3 (diff)
downloadlinux-16e842a62a8ffcc2e51def6ef9fd6e0926539bc5.tar.xz
Merge with http://kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/machvec_impl.h2
-rw-r--r--arch/arm/kernel/module.c2
-rw-r--r--arch/arm/mach-pxa/pm.c9
-rw-r--r--arch/i386/kernel/smpboot.c3
-rw-r--r--arch/i386/mm/ioremap.c37
-rw-r--r--arch/i386/pci/direct.c4
-rw-r--r--arch/i386/pci/mmconfig.c65
-rw-r--r--arch/i386/pci/pci.h7
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_reg.c48
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c12
-rw-r--r--arch/powerpc/kernel/syscalls.c2
-rw-r--r--arch/sparc/kernel/ebus.c24
-rw-r--r--arch/sparc/kernel/led.c2
-rw-r--r--arch/sparc/kernel/pcic.c2
-rw-r--r--arch/sparc/kernel/time.c4
-rw-r--r--arch/sparc/mm/sun4c.c2
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c3
-rw-r--r--arch/x86_64/kernel/smpboot.c2
-rw-r--r--arch/x86_64/kernel/time.c6
-rw-r--r--arch/x86_64/mm/ioremap.c37
-rw-r--r--arch/x86_64/mm/numa.c4
-rw-r--r--arch/x86_64/pci/mmconfig.c65
23 files changed, 247 insertions, 97 deletions
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 4959b7a3e1e6..11f996f24fde 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -41,7 +41,7 @@
#define CAT1(x,y) x##y
#define CAT(x,y) CAT1(x,y)
-#define DO_DEFAULT_RTC rtc_port: 0x70
+#define DO_DEFAULT_RTC .rtc_port = 0x70
#define DO_EV4_MMU \
.max_asn = EV4_MAX_ASN, \
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 6055e1427ba3..055bf5d28894 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -101,6 +101,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
break;
case R_ARM_PC24:
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
offset = (*(u32 *)loc & 0x00ffffff) << 2;
if (offset & 0x02000000)
offset -= 0x04000000;
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index f74b9af112dc..852ea72d8c80 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -155,19 +155,20 @@ int pxa_pm_enter(suspend_state_t state)
PSPR = 0;
/* restore registers */
+ RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
+ RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
- RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
- RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
#ifdef CONFIG_PXA27x
RESTORE(MDREFR);
- RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
- RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
+ RESTORE_GPLEVEL(3); RESTORE(GPDR3);
+ RESTORE(GAFR3_L); RESTORE(GAFR3_U);
+ RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
RESTORE(PFER); RESTORE(PKWR);
#endif
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index d16520da4550..9ed449af8e9f 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1338,8 +1338,7 @@ int __cpu_disable(void)
if (cpu == 0)
return -EBUSY;
- /* We enable the timer again on the exit path of the death loop */
- disable_APIC_timer();
+ clear_local_APIC();
/* Allow any queued timer interrupts to get serviced */
local_irq_enable();
mdelay(1);
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 5d09de8d1c6b..247fde76aaed 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -223,9 +223,15 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
}
EXPORT_SYMBOL(ioremap_nocache);
+/**
+ * iounmap - Free a IO remapping
+ * @addr: virtual address from ioremap_*
+ *
+ * Caller must ensure there is only one unmapping for the same pointer.
+ */
void iounmap(volatile void __iomem *addr)
{
- struct vm_struct *p;
+ struct vm_struct *p, *o;
if ((void __force *)addr <= high_memory)
return;
@@ -239,22 +245,37 @@ void iounmap(volatile void __iomem *addr)
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- write_lock(&vmlist_lock);
- p = __remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
- if (!p) {
- printk(KERN_WARNING "iounmap: bad address %p\n", addr);
+ addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
+
+ /* Use the vm area unlocked, assuming the caller
+ ensures there isn't another iounmap for the same address
+ in parallel. Reuse of the virtual address is prevented by
+ leaving it in the global lists until we're done with it.
+ cpa takes care of the direct mappings. */
+ read_lock(&vmlist_lock);
+ for (p = vmlist; p; p = p->next) {
+ if (p->addr == addr)
+ break;
+ }
+ read_unlock(&vmlist_lock);
+
+ if (!p) {
+ printk("iounmap: bad address %p\n", addr);
dump_stack();
- goto out_unlock;
+ return;
}
+ /* Reset the direct mapping. Can block */
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
}
-out_unlock:
- write_unlock(&vmlist_lock);
+
+ /* Finally remove it */
+ o = remove_vm_area((void *)addr);
+ BUG_ON(p != o || o == NULL);
kfree(p);
}
EXPORT_SYMBOL(iounmap);
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 94331d6be7a3..e3ac502bf2fb 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -13,7 +13,7 @@
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
-static int pci_conf1_read(unsigned int seg, unsigned int bus,
+int pci_conf1_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
@@ -42,7 +42,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus,
return 0;
}
-static int pci_conf1_write(unsigned int seg, unsigned int bus,
+int pci_conf1_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index dfbf80cff834..4bb4d4b0f73a 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -19,21 +19,25 @@
/* The base address of the last MMCONFIG device accessed */
static u32 mmcfg_last_accessed_device;
+static DECLARE_BITMAP(fallback_slots, 32);
+
/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
*/
-static u32 get_base_addr(unsigned int seg, int bus)
+static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
{
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;
+ if (seg == 0 && bus == 0 &&
+ test_bit(PCI_SLOT(devfn), fallback_slots))
+ return 0;
+
while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
- /* something bad is going on, no cfg table is found. */
- /* so we fall back to the old way we used to do this */
- /* and just rely on the first entry to be correct. */
- return pci_mmcfg_config[0].base_address;
+ /* Not found - fallback to type 1 */
+ return 0;
}
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment_group_number != seg)
@@ -44,9 +48,9 @@ static u32 get_base_addr(unsigned int seg, int bus)
}
}
-static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)
+static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
{
- u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);
+ u32 dev_base = base | (bus << 20) | (devfn << 12);
if (dev_base != mmcfg_last_accessed_device) {
mmcfg_last_accessed_device = dev_base;
set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
@@ -57,13 +61,18 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
+ u32 base;
if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;
+ base = get_base_addr(seg, bus, devfn);
+ if (!base)
+ return pci_conf1_read(seg,bus,devfn,reg,len,value);
+
spin_lock_irqsave(&pci_config_lock, flags);
- pci_exp_set_dev_base(seg, bus, devfn);
+ pci_exp_set_dev_base(base, bus, devfn);
switch (len) {
case 1:
@@ -86,13 +95,18 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
+ u32 base;
if ((bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;
+ base = get_base_addr(seg, bus, devfn);
+ if (!base)
+ return pci_conf1_write(seg,bus,devfn,reg,len,value);
+
spin_lock_irqsave(&pci_config_lock, flags);
- pci_exp_set_dev_base(seg, bus, devfn);
+ pci_exp_set_dev_base(base, bus, devfn);
switch (len) {
case 1:
@@ -116,6 +130,37 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};
+/* K8 systems have some devices (typically in the builtin northbridge)
+ that are only accessible using type1
+ Normally this can be expressed in the MCFG by not listing them
+ and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+ Instead try to discover all devices on bus 0 that are unreachable using MM
+ and fallback for them.
+ We only do this for bus 0/seg 0 */
+static __init void unreachable_devices(void)
+{
+ int i;
+ unsigned long flags;
+
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ u32 addr;
+
+ pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+
+ /* Locking probably not needed, but safer */
+ spin_lock_irqsave(&pci_config_lock, flags);
+ addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
+ if (addr != 0)
+ pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
+ if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
+ set_bit(i, fallback_slots);
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+ }
+}
+
static int __init pci_mmcfg_init(void)
{
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
@@ -131,6 +176,8 @@ static int __init pci_mmcfg_init(void)
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+ unreachable_devices();
+
out:
return 0;
}
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 127d53ad16be..f550781ec310 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -74,3 +74,10 @@ extern spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
+
+extern int pci_conf1_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value);
+extern int pci_conf1_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value);
+
+
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index a4da715a360c..e9904c74d2ba 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -721,11 +721,13 @@ flush_thread (void)
/* drop floating-point and debug-register state if it exists: */
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
ia64_drop_fpu(current);
+#ifdef CONFIG_IA32_SUPPORT
if (IS_IA32_PROCESS(ia64_task_regs(current))) {
ia32_drop_partial_page_list(current);
current->thread.task_size = IA32_PAGE_OFFSET;
set_fs(USER_DS);
}
+#endif
}
/*
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
index 5d534091262c..79fdb91d7259 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
@@ -25,7 +25,7 @@ union br_ptr {
*/
void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -38,14 +38,14 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
default:
panic
("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -58,7 +58,7 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
default:
panic
("pcireg_control_bit_set: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
@@ -68,7 +68,7 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
*/
uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
uint64_t ret = 0;
if (pcibus_info) {
@@ -82,7 +82,7 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
default:
panic
("pcireg_tflush_get: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
@@ -98,7 +98,7 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
*/
uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
uint64_t ret = 0;
if (pcibus_info) {
@@ -112,7 +112,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
default:
panic
("pcireg_intr_status_get: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
return ret;
@@ -123,7 +123,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
*/
void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -136,14 +136,14 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
default:
panic
("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -156,7 +156,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
default:
panic
("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
@@ -167,7 +167,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
uint64_t addr)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -186,7 +186,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
default:
panic
("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
@@ -196,7 +196,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
*/
void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -209,7 +209,7 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
default:
panic
("pcireg_force_intr_set: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
@@ -219,7 +219,7 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
*/
uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
uint64_t ret = 0;
if (pcibus_info) {
@@ -233,7 +233,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
__sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
break;
default:
- panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr);
+ panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr);
}
}
@@ -244,7 +244,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
uint64_t val)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -257,15 +257,15 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
default:
panic
("pcireg_int_ate_set: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
}
-uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
+uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
{
- union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
- uint64_t *ret = (uint64_t *) 0;
+ union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
+ uint64_t __iomem *ret = NULL;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -278,7 +278,7 @@ uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
default:
panic
("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p",
- (void *)ptr);
+ ptr);
}
}
return ret;
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 46b646a6d345..27aa1842dacc 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -38,10 +38,10 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
uint64_t offset;
struct page *tmp;
struct tioca_common *tioca_common;
- struct tioca *ca_base;
+ struct tioca __iomem *ca_base;
tioca_common = tioca_kern->ca_common;
- ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+ ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
if (list_empty(tioca_kern->ca_devices))
return 0;
@@ -215,7 +215,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
{
int cap_ptr;
uint32_t reg;
- struct tioca *tioca_base;
+ struct tioca __iomem *tioca_base;
struct pci_dev *pdev;
struct tioca_common *common;
@@ -257,7 +257,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
* Set ca's fw to match
*/
- tioca_base = (struct tioca *)common->ca_common.bs_base;
+ tioca_base = (struct tioca __iomem*)common->ca_common.bs_base;
__sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);
}
@@ -322,7 +322,7 @@ static uint64_t
tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
{
struct tioca_common *tioca_common;
- struct tioca *ca_base;
+ struct tioca __iomem *ca_base;
uint64_t ct_addr;
dma_addr_t bus_addr;
uint32_t node_upper;
@@ -330,7 +330,7 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
- ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+ ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
ct_addr = PHYS_TO_TIODMA(paddr);
if (!ct_addr)
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index f72ced11212d..91b93d917b64 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -247,7 +247,7 @@ long ppc64_personality(unsigned long personality)
#define OVERRIDE_MACHINE 0
#endif
-static inline int override_machine(char *mach)
+static inline int override_machine(char __user *mach)
{
if (OVERRIDE_MACHINE) {
/* change ppc64 to ppc */
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 1754192c69d0..5c3529ceb5d6 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -22,7 +22,7 @@
#include <asm/oplib.h>
#include <asm/bpp.h>
-struct linux_ebus *ebus_chain = 0;
+struct linux_ebus *ebus_chain = NULL;
/* We are together with pcic.c under CONFIG_PCI. */
extern unsigned int pcic_pin_to_irq(unsigned int, char *name);
@@ -46,7 +46,7 @@ static struct ebus_device_irq je1_1[] = {
{ "SUNW,CS4231", 0 },
{ "parallel", 0 },
{ "se", 2 },
- { 0, 0 }
+ { NULL, 0 }
};
/*
@@ -55,7 +55,7 @@ static struct ebus_device_irq je1_1[] = {
*/
static struct ebus_system_entry ebus_blacklist[] = {
{ "SUNW,JavaEngine1", je1_1 },
- { 0, 0 }
+ { NULL, NULL }
};
static struct ebus_device_irq *ebus_blackp = NULL;
@@ -233,7 +233,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
ebus_alloc(sizeof(struct linux_ebus_child));
child = dev->children;
- child->next = 0;
+ child->next = NULL;
child->parent = dev;
child->bus = dev->bus;
fill_ebus_child(node, &regs[0], child);
@@ -243,7 +243,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
ebus_alloc(sizeof(struct linux_ebus_child));
child = child->next;
- child->next = 0;
+ child->next = NULL;
child->parent = dev;
child->bus = dev->bus;
fill_ebus_child(node, &regs[0], child);
@@ -275,7 +275,7 @@ void __init ebus_init(void)
}
}
- pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
+ pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL);
if (!pdev) {
return;
}
@@ -284,7 +284,7 @@ void __init ebus_init(void)
ebus_chain = ebus = (struct linux_ebus *)
ebus_alloc(sizeof(struct linux_ebus));
- ebus->next = 0;
+ ebus->next = NULL;
while (ebusnd) {
@@ -325,8 +325,8 @@ void __init ebus_init(void)
ebus_alloc(sizeof(struct linux_ebus_device));
dev = ebus->devices;
- dev->next = 0;
- dev->children = 0;
+ dev->next = NULL;
+ dev->children = NULL;
dev->bus = ebus;
fill_ebus_device(nd, dev);
@@ -335,8 +335,8 @@ void __init ebus_init(void)
ebus_alloc(sizeof(struct linux_ebus_device));
dev = dev->next;
- dev->next = 0;
- dev->children = 0;
+ dev->next = NULL;
+ dev->children = NULL;
dev->bus = ebus;
fill_ebus_device(nd, dev);
}
@@ -353,7 +353,7 @@ void __init ebus_init(void)
ebus->next = (struct linux_ebus *)
ebus_alloc(sizeof(struct linux_ebus));
ebus = ebus->next;
- ebus->next = 0;
+ ebus->next = NULL;
++num_ebus;
}
if (pdev)
diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c
index 2a3afca453c9..313d1620ae8e 100644
--- a/arch/sparc/kernel/led.c
+++ b/arch/sparc/kernel/led.c
@@ -55,7 +55,7 @@ static int led_read_proc(char *buf, char **start, off_t offset, int count,
return len;
}
-static int led_write_proc(struct file *file, const char *buffer,
+static int led_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char *buf = NULL;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index cccfc12802ed..42002b742deb 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -161,7 +161,7 @@ static struct pcic_sn2list pcic_known_sysnames[] = {
static int pcic0_up;
static struct linux_pcic pcic0;
-void * __iomem pcic_regs;
+void __iomem *pcic_regs;
volatile int pcic_speculative;
volatile int pcic_trapped;
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 24814d58f9e1..7dadcdb4ca42 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -49,7 +49,7 @@ DEFINE_SPINLOCK(rtc_lock);
enum sparc_clock_type sp_clock_typ;
DEFINE_SPINLOCK(mostek_lock);
void __iomem *mstk48t02_regs = NULL;
-static struct mostek48t08 *mstk48t08_regs = NULL;
+static struct mostek48t08 __iomem *mstk48t08_regs = NULL;
static int set_rtc_mmss(unsigned long);
static int sbus_do_settimeofday(struct timespec *tv);
@@ -342,7 +342,7 @@ static __inline__ void clock_probe(void)
/* XXX r/o attribute is somewhere in r.flags */
r.flags = clk_reg[0].which_io;
r.start = clk_reg[0].phys_addr;
- mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0,
+ mstk48t08_regs = sbus_ioremap(&r, 0,
sizeof(struct mostek48t08), "mk48t08");
mstk48t02_regs = &mstk48t08_regs->regs;
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 1d560390e282..731f19603cad 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -497,7 +497,7 @@ static void __init sun4c_probe_mmu(void)
patch_kernel_fault_handler();
}
-volatile unsigned long *sun4c_memerr_reg = NULL;
+volatile unsigned long __iomem *sun4c_memerr_reg = NULL;
void __init sun4c_probe_memerr_reg(void)
{
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 830feb272eca..2b760d0d9ce2 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -217,8 +217,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
if (!tsk_used_math(tsk))
return 0;
if (!regs)
- regs = (struct pt_regs *)tsk->thread.rsp0;
- --regs;
+ regs = ((struct pt_regs *)tsk->thread.rsp0) - 1;
if (tsk == current)
unlazy_fpu(tsk);
set_fs(KERNEL_DS);
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 683c33f7b967..ecbd7b83acc1 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -1181,7 +1181,7 @@ int __cpu_disable(void)
if (cpu == 0)
return -EBUSY;
- disable_APIC_timer();
+ clear_local_APIC();
/*
* HACK:
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index fdaddc4e5284..74102796e5c0 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -59,7 +59,7 @@ static int notsc __initdata = 0;
unsigned int cpu_khz; /* TSC clocks / usec, not used here */
static unsigned long hpet_period; /* fsecs / HPET clock */
unsigned long hpet_tick; /* HPET clocks / interrupt */
-static int hpet_use_timer;
+static int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */
unsigned long vxtime_hz = PIT_TICK_RATE;
int report_lost_ticks; /* command line option */
unsigned long long monotonic_base;
@@ -908,12 +908,14 @@ void __init time_init(void)
if (!hpet_init())
vxtime_hz = (1000000000000000L + hpet_period / 2) /
hpet_period;
+ else
+ vxtime.hpet_address = 0;
if (hpet_use_timer) {
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
#ifdef CONFIG_X86_PM_TIMER
- } else if (pmtmr_ioport) {
+ } else if (pmtmr_ioport && !vxtime.hpet_address) {
vxtime_hz = PM_TIMER_FREQUENCY;
timename = "PM";
pit_init();
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index ecf7acb5db9b..ae207064201e 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -247,9 +247,15 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
return __ioremap(phys_addr, size, _PAGE_PCD);
}
+/**
+ * iounmap - Free a IO remapping
+ * @addr: virtual address from ioremap_*
+ *
+ * Caller must ensure there is only one unmapping for the same pointer.
+ */
void iounmap(volatile void __iomem *addr)
{
- struct vm_struct *p;
+ struct vm_struct *p, *o;
if (addr <= high_memory)
return;
@@ -257,12 +263,31 @@ void iounmap(volatile void __iomem *addr)
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- write_lock(&vmlist_lock);
- p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
- if (!p)
+ addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
+ /* Use the vm area unlocked, assuming the caller
+ ensures there isn't another iounmap for the same address
+ in parallel. Reuse of the virtual address is prevented by
+ leaving it in the global lists until we're done with it.
+ cpa takes care of the direct mappings. */
+ read_lock(&vmlist_lock);
+ for (p = vmlist; p; p = p->next) {
+ if (p->addr == addr)
+ break;
+ }
+ read_unlock(&vmlist_lock);
+
+ if (!p) {
printk("iounmap: bad address %p\n", addr);
- else if (p->flags >> 20)
+ dump_stack();
+ return;
+ }
+
+ /* Reset the direct mapping. Can block */
+ if (p->flags >> 20)
ioremap_change_attr(p->phys_addr, p->size, 0);
- write_unlock(&vmlist_lock);
+
+ /* Finally remove it */
+ o = remove_vm_area((void *)addr);
+ BUG_ON(p != o || o == NULL);
kfree(p);
}
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index a828a01739cc..15b67d2760cb 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -53,6 +53,8 @@ static int __init populate_memnodemap(
int res = -1;
unsigned long addr, end;
+ if (shift >= 64)
+ return -1;
memset(memnodemap, 0xff, sizeof(memnodemap));
for (i = 0; i < numnodes; i++) {
addr = nodes[i].start;
@@ -65,7 +67,7 @@ static int __init populate_memnodemap(
if (memnodemap[addr >> shift] != 0xff)
return -1;
memnodemap[addr >> shift] = i;
- addr += (1 << shift);
+ addr += (1UL << shift);
} while (addr < end);
res = 1;
}
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index a0838c4a94e4..f16c0d57c552 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -8,18 +8,21 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/bitmap.h>
#include "pci.h"
#define MMCONFIG_APER_SIZE (256*1024*1024)
+static DECLARE_BITMAP(fallback_slots, 32);
+
/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
struct acpi_table_mcfg_config *cfg;
- char *virt;
+ char __iomem *virt;
};
static struct mmcfg_virt *pci_mmcfg_virt;
-static char *get_virt(unsigned int seg, int bus)
+static char __iomem *get_virt(unsigned int seg, unsigned bus)
{
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;
@@ -27,10 +30,9 @@ static char *get_virt(unsigned int seg, int bus)
while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
- /* something bad is going on, no cfg table is found. */
- /* so we fall back to the old way we used to do this */
- /* and just rely on the first entry to be correct. */
- return pci_mmcfg_virt[0].virt;
+ /* Not found - fall back to type 1. This happens
+ e.g. on the internal devices of a K8 northbridge. */
+ return NULL;
}
cfg = pci_mmcfg_virt[cfg_num].cfg;
if (cfg->pci_segment_group_number != seg)
@@ -41,20 +43,30 @@ static char *get_virt(unsigned int seg, int bus)
}
}
-static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
+static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
-
- return get_virt(seg, bus) + ((bus << 20) | (devfn << 12));
+ char __iomem *addr;
+ if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
+ return NULL;
+ addr = get_virt(seg, bus);
+ if (!addr)
+ return NULL;
+ return addr + ((bus << 20) | (devfn << 12));
}
static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
- char *addr = pci_dev_base(seg, bus, devfn);
+ char __iomem *addr;
+ /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
return -EINVAL;
+ addr = pci_dev_base(seg, bus, devfn);
+ if (!addr)
+ return pci_conf1_read(seg,bus,devfn,reg,len,value);
+
switch (len) {
case 1:
*value = readb(addr + reg);
@@ -73,11 +85,16 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
- char *addr = pci_dev_base(seg, bus, devfn);
+ char __iomem *addr;
+ /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
return -EINVAL;
+ addr = pci_dev_base(seg, bus, devfn);
+ if (!addr)
+ return pci_conf1_write(seg,bus,devfn,reg,len,value);
+
switch (len) {
case 1:
writeb(value, addr + reg);
@@ -98,6 +115,30 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};
+/* K8 systems have some devices (typically in the builtin northbridge)
+ that are only accessible using type1
+ Normally this can be expressed in the MCFG by not listing them
+ and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+ Instead try to discover all devices on bus 0 that are unreachable using MM
+ and fallback for them.
+ We only do this for bus 0/seg 0 */
+static __init void unreachable_devices(void)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ char __iomem *addr;
+
+ pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+ addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
+ if (addr == NULL|| readl(addr) != val1) {
+ set_bit(i, &fallback_slots);
+ }
+ }
+}
+
static int __init pci_mmcfg_init(void)
{
int i;
@@ -128,6 +169,8 @@ static int __init pci_mmcfg_init(void)
printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
}
+ unreachable_devices();
+
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;