diff options
| -rw-r--r-- | arch/i386/kernel/smpboot.c | 3 | ||||
| -rw-r--r-- | arch/i386/mm/ioremap.c | 37 | ||||
| -rw-r--r-- | arch/i386/pci/direct.c | 4 | ||||
| -rw-r--r-- | arch/i386/pci/mmconfig.c | 65 | ||||
| -rw-r--r-- | arch/i386/pci/pci.h | 7 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ia32_binfmt.c | 3 | ||||
| -rw-r--r-- | arch/x86_64/kernel/smpboot.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/kernel/time.c | 6 | ||||
| -rw-r--r-- | arch/x86_64/mm/ioremap.c | 37 | ||||
| -rw-r--r-- | arch/x86_64/mm/numa.c | 4 | ||||
| -rw-r--r-- | arch/x86_64/pci/mmconfig.c | 63 | ||||
| -rw-r--r-- | drivers/block/cciss.c | 4 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_cp.c | 2 | ||||
| -rw-r--r-- | drivers/net/skge.c | 10 | ||||
| -rw-r--r-- | drivers/video/cfbcopyarea.c | 8 | ||||
| -rw-r--r-- | drivers/video/cfbfillrect.c | 16 | ||||
| -rw-r--r-- | drivers/video/cfbimgblt.c | 35 | ||||
| -rw-r--r-- | drivers/video/console/fbcon.c | 42 | ||||
| -rw-r--r-- | drivers/video/fbmem.c | 26 | ||||
| -rw-r--r-- | include/linux/fb.h | 30 | ||||
| -rw-r--r-- | net/ieee80211/Kconfig | 2 |
21 files changed, 307 insertions, 99 deletions
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) | |||
| 1338 | if (cpu == 0) | 1338 | if (cpu == 0) |
| 1339 | return -EBUSY; | 1339 | return -EBUSY; |
| 1340 | 1340 | ||
| 1341 | /* We enable the timer again on the exit path of the death loop */ | 1341 | clear_local_APIC(); |
| 1342 | disable_APIC_timer(); | ||
| 1343 | /* Allow any queued timer interrupts to get serviced */ | 1342 | /* Allow any queued timer interrupts to get serviced */ |
| 1344 | local_irq_enable(); | 1343 | local_irq_enable(); |
| 1345 | mdelay(1); | 1344 | mdelay(1); |
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index 5d09de8d1c6b..8498b5ac3955 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) | |||
| 223 | } | 223 | } |
| 224 | EXPORT_SYMBOL(ioremap_nocache); | 224 | EXPORT_SYMBOL(ioremap_nocache); |
| 225 | 225 | ||
| 226 | /** | ||
| 227 | * iounmap - Free a IO remapping | ||
| 228 | * @addr: virtual address from ioremap_* | ||
| 229 | * | ||
| 230 | * Caller must ensure there is only one unmapping for the same pointer. | ||
| 231 | */ | ||
| 226 | void iounmap(volatile void __iomem *addr) | 232 | void iounmap(volatile void __iomem *addr) |
| 227 | { | 233 | { |
| 228 | struct vm_struct *p; | 234 | struct vm_struct *p, *o; |
| 229 | 235 | ||
| 230 | if ((void __force *)addr <= high_memory) | 236 | if ((void __force *)addr <= high_memory) |
| 231 | return; | 237 | return; |
| @@ -239,22 +245,37 @@ void iounmap(volatile void __iomem *addr) | |||
| 239 | addr < phys_to_virt(ISA_END_ADDRESS)) | 245 | addr < phys_to_virt(ISA_END_ADDRESS)) |
| 240 | return; | 246 | return; |
| 241 | 247 | ||
| 242 | write_lock(&vmlist_lock); | 248 | addr = (volatile void *)(PAGE_MASK & (unsigned long __force)addr); |
| 243 | p = __remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr)); | 249 | |
| 244 | if (!p) { | 250 | /* Use the vm area unlocked, assuming the caller |
| 245 | printk(KERN_WARNING "iounmap: bad address %p\n", addr); | 251 | ensures there isn't another iounmap for the same address |
| 252 | in parallel. Reuse of the virtual address is prevented by | ||
| 253 | leaving it in the global lists until we're done with it. | ||
| 254 | cpa takes care of the direct mappings. */ | ||
| 255 | read_lock(&vmlist_lock); | ||
| 256 | for (p = vmlist; p; p = p->next) { | ||
| 257 | if (p->addr == addr) | ||
| 258 | break; | ||
| 259 | } | ||
| 260 | read_unlock(&vmlist_lock); | ||
| 261 | |||
| 262 | if (!p) { | ||
| 263 | printk("iounmap: bad address %p\n", addr); | ||
| 246 | dump_stack(); | 264 | dump_stack(); |
| 247 | goto out_unlock; | 265 | return; |
| 248 | } | 266 | } |
| 249 | 267 | ||
| 268 | /* Reset the direct mapping. Can block */ | ||
| 250 | if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { | 269 | if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { |
| 251 | change_page_attr(virt_to_page(__va(p->phys_addr)), | 270 | change_page_attr(virt_to_page(__va(p->phys_addr)), |
| 252 | p->size >> PAGE_SHIFT, | 271 | p->size >> PAGE_SHIFT, |
| 253 | PAGE_KERNEL); | 272 | PAGE_KERNEL); |
| 254 | global_flush_tlb(); | 273 | global_flush_tlb(); |
| 255 | } | 274 | } |
| 256 | out_unlock: | 275 | |
| 257 | write_unlock(&vmlist_lock); | 276 | /* Finally remove it */ |
| 277 | o = remove_vm_area((void *)addr); | ||
| 278 | BUG_ON(p != o || o == NULL); | ||
| 258 | kfree(p); | 279 | kfree(p); |
| 259 | } | 280 | } |
| 260 | EXPORT_SYMBOL(iounmap); | 281 | 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 @@ | |||
| 13 | #define PCI_CONF1_ADDRESS(bus, devfn, reg) \ | 13 | #define PCI_CONF1_ADDRESS(bus, devfn, reg) \ |
| 14 | (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) | 14 | (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) |
| 15 | 15 | ||
| 16 | static int pci_conf1_read(unsigned int seg, unsigned int bus, | 16 | int pci_conf1_read(unsigned int seg, unsigned int bus, |
| 17 | unsigned int devfn, int reg, int len, u32 *value) | 17 | unsigned int devfn, int reg, int len, u32 *value) |
| 18 | { | 18 | { |
| 19 | unsigned long flags; | 19 | unsigned long flags; |
| @@ -42,7 +42,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus, | |||
| 42 | return 0; | 42 | return 0; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static int pci_conf1_write(unsigned int seg, unsigned int bus, | 45 | int pci_conf1_write(unsigned int seg, unsigned int bus, |
| 46 | unsigned int devfn, int reg, int len, u32 value) | 46 | unsigned int devfn, int reg, int len, u32 value) |
| 47 | { | 47 | { |
| 48 | unsigned long flags; | 48 | unsigned long flags; |
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index dfbf80cff834..08a084901212 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
| @@ -19,21 +19,25 @@ | |||
| 19 | /* The base address of the last MMCONFIG device accessed */ | 19 | /* The base address of the last MMCONFIG device accessed */ |
| 20 | static u32 mmcfg_last_accessed_device; | 20 | static u32 mmcfg_last_accessed_device; |
| 21 | 21 | ||
| 22 | static DECLARE_BITMAP(fallback_slots, 32); | ||
| 23 | |||
| 22 | /* | 24 | /* |
| 23 | * Functions for accessing PCI configuration space with MMCONFIG accesses | 25 | * Functions for accessing PCI configuration space with MMCONFIG accesses |
| 24 | */ | 26 | */ |
| 25 | static u32 get_base_addr(unsigned int seg, int bus) | 27 | static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) |
| 26 | { | 28 | { |
| 27 | int cfg_num = -1; | 29 | int cfg_num = -1; |
| 28 | struct acpi_table_mcfg_config *cfg; | 30 | struct acpi_table_mcfg_config *cfg; |
| 29 | 31 | ||
| 32 | if (seg == 0 && bus == 0 && | ||
| 33 | test_bit(PCI_SLOT(devfn), fallback_slots)) | ||
| 34 | return 0; | ||
| 35 | |||
| 30 | while (1) { | 36 | while (1) { |
| 31 | ++cfg_num; | 37 | ++cfg_num; |
| 32 | if (cfg_num >= pci_mmcfg_config_num) { | 38 | if (cfg_num >= pci_mmcfg_config_num) { |
| 33 | /* something bad is going on, no cfg table is found. */ | 39 | /* Not found - fallback to type 1 */ |
| 34 | /* so we fall back to the old way we used to do this */ | 40 | return 0; |
| 35 | /* and just rely on the first entry to be correct. */ | ||
| 36 | return pci_mmcfg_config[0].base_address; | ||
| 37 | } | 41 | } |
| 38 | cfg = &pci_mmcfg_config[cfg_num]; | 42 | cfg = &pci_mmcfg_config[cfg_num]; |
| 39 | if (cfg->pci_segment_group_number != seg) | 43 | if (cfg->pci_segment_group_number != seg) |
| @@ -44,9 +48,9 @@ static u32 get_base_addr(unsigned int seg, int bus) | |||
| 44 | } | 48 | } |
| 45 | } | 49 | } |
| 46 | 50 | ||
| 47 | static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn) | 51 | static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) |
| 48 | { | 52 | { |
| 49 | u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12); | 53 | u32 dev_base = base | (bus << 20) | (devfn << 12); |
| 50 | if (dev_base != mmcfg_last_accessed_device) { | 54 | if (dev_base != mmcfg_last_accessed_device) { |
| 51 | mmcfg_last_accessed_device = dev_base; | 55 | mmcfg_last_accessed_device = dev_base; |
| 52 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); | 56 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); |
| @@ -57,13 +61,18 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 57 | unsigned int devfn, int reg, int len, u32 *value) | 61 | unsigned int devfn, int reg, int len, u32 *value) |
| 58 | { | 62 | { |
| 59 | unsigned long flags; | 63 | unsigned long flags; |
| 64 | u32 base; | ||
| 60 | 65 | ||
| 61 | if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) | 66 | if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) |
| 62 | return -EINVAL; | 67 | return -EINVAL; |
| 63 | 68 | ||
| 69 | base = get_base_addr(seg, bus, devfn); | ||
| 70 | if (!base) | ||
| 71 | return pci_conf1_read(seg,bus,devfn,reg,len,value); | ||
| 72 | |||
| 64 | spin_lock_irqsave(&pci_config_lock, flags); | 73 | spin_lock_irqsave(&pci_config_lock, flags); |
| 65 | 74 | ||
| 66 | pci_exp_set_dev_base(seg, bus, devfn); | 75 | pci_exp_set_dev_base(base, bus, devfn); |
| 67 | 76 | ||
| 68 | switch (len) { | 77 | switch (len) { |
| 69 | case 1: | 78 | case 1: |
| @@ -86,13 +95,18 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | |||
| 86 | unsigned int devfn, int reg, int len, u32 value) | 95 | unsigned int devfn, int reg, int len, u32 value) |
| 87 | { | 96 | { |
| 88 | unsigned long flags; | 97 | unsigned long flags; |
| 98 | u32 base; | ||
| 89 | 99 | ||
| 90 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) | 100 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) |
| 91 | return -EINVAL; | 101 | return -EINVAL; |
| 92 | 102 | ||
| 103 | base = get_base_addr(seg, bus, devfn); | ||
| 104 | if (!base) | ||
| 105 | return pci_conf1_write(seg,bus,devfn,reg,len,value); | ||
| 106 | |||
| 93 | spin_lock_irqsave(&pci_config_lock, flags); | 107 | spin_lock_irqsave(&pci_config_lock, flags); |
| 94 | 108 | ||
| 95 | pci_exp_set_dev_base(seg, bus, devfn); | 109 | pci_exp_set_dev_base(base, bus, devfn); |
| 96 | 110 | ||
| 97 | switch (len) { | 111 | switch (len) { |
| 98 | case 1: | 112 | case 1: |
| @@ -116,6 +130,37 @@ static struct pci_raw_ops pci_mmcfg = { | |||
| 116 | .write = pci_mmcfg_write, | 130 | .write = pci_mmcfg_write, |
| 117 | }; | 131 | }; |
| 118 | 132 | ||
| 133 | /* K8 systems have some devices (typically in the builtin northbridge) | ||
| 134 | that are only accessible using type1 | ||
| 135 | Normally this can be expressed in the MCFG by not listing them | ||
| 136 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
| 137 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
| 138 | and fallback for them. | ||
| 139 | We only do this for bus 0/seg 0 */ | ||
| 140 | static __init void unreachable_devices(void) | ||
| 141 | { | ||
| 142 | int i; | ||
| 143 | unsigned long flags; | ||
| 144 | |||
| 145 | for (i = 0; i < 32; i++) { | ||
| 146 | u32 val1; | ||
| 147 | u32 addr; | ||
| 148 | |||
| 149 | pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1); | ||
| 150 | if (val1 == 0xffffffff) | ||
| 151 | continue; | ||
| 152 | |||
| 153 | /* Locking probably not needed, but safer */ | ||
| 154 | spin_lock_irqsave(&pci_config_lock, flags); | ||
| 155 | addr = get_base_addr(0, 0, PCI_DEVFN(i, 0)); | ||
| 156 | if (addr != 0) | ||
| 157 | pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0)); | ||
| 158 | if (addr == 0 || readl((u32 *)addr) != val1) | ||
| 159 | set_bit(i, fallback_slots); | ||
| 160 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 119 | static int __init pci_mmcfg_init(void) | 164 | static int __init pci_mmcfg_init(void) |
| 120 | { | 165 | { |
| 121 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 166 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
| @@ -131,6 +176,8 @@ static int __init pci_mmcfg_init(void) | |||
| 131 | raw_pci_ops = &pci_mmcfg; | 176 | raw_pci_ops = &pci_mmcfg; |
| 132 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 177 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
| 133 | 178 | ||
| 179 | unreachable_devices(); | ||
| 180 | |||
| 134 | out: | 181 | out: |
| 135 | return 0; | 182 | return 0; |
| 136 | } | 183 | } |
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; | |||
| 74 | 74 | ||
| 75 | extern int (*pcibios_enable_irq)(struct pci_dev *dev); | 75 | extern int (*pcibios_enable_irq)(struct pci_dev *dev); |
| 76 | extern void (*pcibios_disable_irq)(struct pci_dev *dev); | 76 | extern void (*pcibios_disable_irq)(struct pci_dev *dev); |
| 77 | |||
| 78 | extern int pci_conf1_write(unsigned int seg, unsigned int bus, | ||
| 79 | unsigned int devfn, int reg, int len, u32 value); | ||
| 80 | extern int pci_conf1_read(unsigned int seg, unsigned int bus, | ||
| 81 | unsigned int devfn, int reg, int len, u32 *value); | ||
| 82 | |||
| 83 | |||
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 | |||
| 217 | if (!tsk_used_math(tsk)) | 217 | if (!tsk_used_math(tsk)) |
| 218 | return 0; | 218 | return 0; |
| 219 | if (!regs) | 219 | if (!regs) |
| 220 | regs = (struct pt_regs *)tsk->thread.rsp0; | 220 | regs = ((struct pt_regs *)tsk->thread.rsp0) - 1; |
| 221 | --regs; | ||
| 222 | if (tsk == current) | 221 | if (tsk == current) |
| 223 | unlazy_fpu(tsk); | 222 | unlazy_fpu(tsk); |
| 224 | set_fs(KERNEL_DS); | 223 | 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) | |||
| 1181 | if (cpu == 0) | 1181 | if (cpu == 0) |
| 1182 | return -EBUSY; | 1182 | return -EBUSY; |
| 1183 | 1183 | ||
| 1184 | disable_APIC_timer(); | 1184 | clear_local_APIC(); |
| 1185 | 1185 | ||
| 1186 | /* | 1186 | /* |
| 1187 | * HACK: | 1187 | * 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; | |||
| 59 | unsigned int cpu_khz; /* TSC clocks / usec, not used here */ | 59 | unsigned int cpu_khz; /* TSC clocks / usec, not used here */ |
| 60 | static unsigned long hpet_period; /* fsecs / HPET clock */ | 60 | static unsigned long hpet_period; /* fsecs / HPET clock */ |
| 61 | unsigned long hpet_tick; /* HPET clocks / interrupt */ | 61 | unsigned long hpet_tick; /* HPET clocks / interrupt */ |
| 62 | static int hpet_use_timer; | 62 | static int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */ |
| 63 | unsigned long vxtime_hz = PIT_TICK_RATE; | 63 | unsigned long vxtime_hz = PIT_TICK_RATE; |
| 64 | int report_lost_ticks; /* command line option */ | 64 | int report_lost_ticks; /* command line option */ |
| 65 | unsigned long long monotonic_base; | 65 | unsigned long long monotonic_base; |
| @@ -908,12 +908,14 @@ void __init time_init(void) | |||
| 908 | if (!hpet_init()) | 908 | if (!hpet_init()) |
| 909 | vxtime_hz = (1000000000000000L + hpet_period / 2) / | 909 | vxtime_hz = (1000000000000000L + hpet_period / 2) / |
| 910 | hpet_period; | 910 | hpet_period; |
| 911 | else | ||
| 912 | vxtime.hpet_address = 0; | ||
| 911 | 913 | ||
| 912 | if (hpet_use_timer) { | 914 | if (hpet_use_timer) { |
| 913 | cpu_khz = hpet_calibrate_tsc(); | 915 | cpu_khz = hpet_calibrate_tsc(); |
| 914 | timename = "HPET"; | 916 | timename = "HPET"; |
| 915 | #ifdef CONFIG_X86_PM_TIMER | 917 | #ifdef CONFIG_X86_PM_TIMER |
| 916 | } else if (pmtmr_ioport) { | 918 | } else if (pmtmr_ioport && !vxtime.hpet_address) { |
| 917 | vxtime_hz = PM_TIMER_FREQUENCY; | 919 | vxtime_hz = PM_TIMER_FREQUENCY; |
| 918 | timename = "PM"; | 920 | timename = "PM"; |
| 919 | pit_init(); | 921 | pit_init(); |
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index ecf7acb5db9b..0d260e4492f7 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) | |||
| 247 | return __ioremap(phys_addr, size, _PAGE_PCD); | 247 | return __ioremap(phys_addr, size, _PAGE_PCD); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | /** | ||
| 251 | * iounmap - Free a IO remapping | ||
| 252 | * @addr: virtual address from ioremap_* | ||
| 253 | * | ||
| 254 | * Caller must ensure there is only one unmapping for the same pointer. | ||
| 255 | */ | ||
| 250 | void iounmap(volatile void __iomem *addr) | 256 | void iounmap(volatile void __iomem *addr) |
| 251 | { | 257 | { |
| 252 | struct vm_struct *p; | 258 | struct vm_struct *p, *o; |
| 253 | 259 | ||
| 254 | if (addr <= high_memory) | 260 | if (addr <= high_memory) |
| 255 | return; | 261 | return; |
| @@ -257,12 +263,31 @@ void iounmap(volatile void __iomem *addr) | |||
| 257 | addr < phys_to_virt(ISA_END_ADDRESS)) | 263 | addr < phys_to_virt(ISA_END_ADDRESS)) |
| 258 | return; | 264 | return; |
| 259 | 265 | ||
| 260 | write_lock(&vmlist_lock); | 266 | addr = (volatile void *)(PAGE_MASK & (unsigned long __force)addr); |
| 261 | p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK)); | 267 | /* Use the vm area unlocked, assuming the caller |
| 262 | if (!p) | 268 | ensures there isn't another iounmap for the same address |
| 269 | in parallel. Reuse of the virtual address is prevented by | ||
| 270 | leaving it in the global lists until we're done with it. | ||
| 271 | cpa takes care of the direct mappings. */ | ||
| 272 | read_lock(&vmlist_lock); | ||
| 273 | for (p = vmlist; p; p = p->next) { | ||
| 274 | if (p->addr == addr) | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | read_unlock(&vmlist_lock); | ||
| 278 | |||
| 279 | if (!p) { | ||
| 263 | printk("iounmap: bad address %p\n", addr); | 280 | printk("iounmap: bad address %p\n", addr); |
| 264 | else if (p->flags >> 20) | 281 | dump_stack(); |
| 282 | return; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* Reset the direct mapping. Can block */ | ||
| 286 | if (p->flags >> 20) | ||
| 265 | ioremap_change_attr(p->phys_addr, p->size, 0); | 287 | ioremap_change_attr(p->phys_addr, p->size, 0); |
| 266 | write_unlock(&vmlist_lock); | 288 | |
| 289 | /* Finally remove it */ | ||
| 290 | o = remove_vm_area((void *)addr); | ||
| 291 | BUG_ON(p != o || o == NULL); | ||
| 267 | kfree(p); | 292 | kfree(p); |
| 268 | } | 293 | } |
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( | |||
| 53 | int res = -1; | 53 | int res = -1; |
| 54 | unsigned long addr, end; | 54 | unsigned long addr, end; |
| 55 | 55 | ||
| 56 | if (shift >= 64) | ||
| 57 | return -1; | ||
| 56 | memset(memnodemap, 0xff, sizeof(memnodemap)); | 58 | memset(memnodemap, 0xff, sizeof(memnodemap)); |
| 57 | for (i = 0; i < numnodes; i++) { | 59 | for (i = 0; i < numnodes; i++) { |
| 58 | addr = nodes[i].start; | 60 | addr = nodes[i].start; |
| @@ -65,7 +67,7 @@ static int __init populate_memnodemap( | |||
| 65 | if (memnodemap[addr >> shift] != 0xff) | 67 | if (memnodemap[addr >> shift] != 0xff) |
| 66 | return -1; | 68 | return -1; |
| 67 | memnodemap[addr >> shift] = i; | 69 | memnodemap[addr >> shift] = i; |
| 68 | addr += (1 << shift); | 70 | addr += (1UL << shift); |
| 69 | } while (addr < end); | 71 | } while (addr < end); |
| 70 | res = 1; | 72 | res = 1; |
| 71 | } | 73 | } |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index a0838c4a94e4..9c4f907e301c 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
| @@ -8,10 +8,13 @@ | |||
| 8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/acpi.h> | 10 | #include <linux/acpi.h> |
| 11 | #include <linux/bitmap.h> | ||
| 11 | #include "pci.h" | 12 | #include "pci.h" |
| 12 | 13 | ||
| 13 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 14 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
| 14 | 15 | ||
| 16 | static DECLARE_BITMAP(fallback_slots, 32); | ||
| 17 | |||
| 15 | /* Static virtual mapping of the MMCONFIG aperture */ | 18 | /* Static virtual mapping of the MMCONFIG aperture */ |
| 16 | struct mmcfg_virt { | 19 | struct mmcfg_virt { |
| 17 | struct acpi_table_mcfg_config *cfg; | 20 | struct acpi_table_mcfg_config *cfg; |
| @@ -19,7 +22,7 @@ struct mmcfg_virt { | |||
| 19 | }; | 22 | }; |
| 20 | static struct mmcfg_virt *pci_mmcfg_virt; | 23 | static struct mmcfg_virt *pci_mmcfg_virt; |
| 21 | 24 | ||
| 22 | static char *get_virt(unsigned int seg, int bus) | 25 | static char *get_virt(unsigned int seg, unsigned bus) |
| 23 | { | 26 | { |
| 24 | int cfg_num = -1; | 27 | int cfg_num = -1; |
| 25 | struct acpi_table_mcfg_config *cfg; | 28 | struct acpi_table_mcfg_config *cfg; |
| @@ -27,10 +30,9 @@ static char *get_virt(unsigned int seg, int bus) | |||
| 27 | while (1) { | 30 | while (1) { |
| 28 | ++cfg_num; | 31 | ++cfg_num; |
| 29 | if (cfg_num >= pci_mmcfg_config_num) { | 32 | if (cfg_num >= pci_mmcfg_config_num) { |
| 30 | /* something bad is going on, no cfg table is found. */ | 33 | /* Not found - fall back to type 1. This happens |
| 31 | /* so we fall back to the old way we used to do this */ | 34 | e.g. on the internal devices of a K8 northbridge. */ |
| 32 | /* and just rely on the first entry to be correct. */ | 35 | return NULL; |
| 33 | return pci_mmcfg_virt[0].virt; | ||
| 34 | } | 36 | } |
| 35 | cfg = pci_mmcfg_virt[cfg_num].cfg; | 37 | cfg = pci_mmcfg_virt[cfg_num].cfg; |
| 36 | if (cfg->pci_segment_group_number != seg) | 38 | if (cfg->pci_segment_group_number != seg) |
| @@ -41,20 +43,30 @@ static char *get_virt(unsigned int seg, int bus) | |||
| 41 | } | 43 | } |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | 46 | static char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) |
| 45 | { | 47 | { |
| 46 | 48 | char *addr; | |
| 47 | return get_virt(seg, bus) + ((bus << 20) | (devfn << 12)); | 49 | if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots)) |
| 50 | return NULL; | ||
| 51 | addr = get_virt(seg, bus); | ||
| 52 | if (!addr) | ||
| 53 | return NULL; | ||
| 54 | return addr + ((bus << 20) | (devfn << 12)); | ||
| 48 | } | 55 | } |
| 49 | 56 | ||
| 50 | static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | 57 | static int pci_mmcfg_read(unsigned int seg, unsigned int bus, |
| 51 | unsigned int devfn, int reg, int len, u32 *value) | 58 | unsigned int devfn, int reg, int len, u32 *value) |
| 52 | { | 59 | { |
| 53 | char *addr = pci_dev_base(seg, bus, devfn); | 60 | char *addr; |
| 54 | 61 | ||
| 62 | /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ | ||
| 55 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) | 63 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) |
| 56 | return -EINVAL; | 64 | return -EINVAL; |
| 57 | 65 | ||
| 66 | addr = pci_dev_base(seg, bus, devfn); | ||
| 67 | if (!addr) | ||
| 68 | return pci_conf1_read(seg,bus,devfn,reg,len,value); | ||
| 69 | |||
| 58 | switch (len) { | 70 | switch (len) { |
| 59 | case 1: | 71 | case 1: |
| 60 | *value = readb(addr + reg); | 72 | *value = readb(addr + reg); |
| @@ -73,11 +85,16 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 73 | static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | 85 | static int pci_mmcfg_write(unsigned int seg, unsigned int bus, |
| 74 | unsigned int devfn, int reg, int len, u32 value) | 86 | unsigned int devfn, int reg, int len, u32 value) |
| 75 | { | 87 | { |
| 76 | char *addr = pci_dev_base(seg, bus, devfn); | 88 | char *addr; |
| 77 | 89 | ||
| 90 | /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ | ||
| 78 | if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) | 91 | if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) |
| 79 | return -EINVAL; | 92 | return -EINVAL; |
| 80 | 93 | ||
| 94 | addr = pci_dev_base(seg, bus, devfn); | ||
| 95 | if (!addr) | ||
| 96 | return pci_conf1_write(seg,bus,devfn,reg,len,value); | ||
| 97 | |||
| 81 | switch (len) { | 98 | switch (len) { |
| 82 | case 1: | 99 | case 1: |
| 83 | writeb(value, addr + reg); | 100 | writeb(value, addr + reg); |
| @@ -98,6 +115,30 @@ static struct pci_raw_ops pci_mmcfg = { | |||
| 98 | .write = pci_mmcfg_write, | 115 | .write = pci_mmcfg_write, |
| 99 | }; | 116 | }; |
| 100 | 117 | ||
| 118 | /* K8 systems have some devices (typically in the builtin northbridge) | ||
| 119 | that are only accessible using type1 | ||
| 120 | Normally this can be expressed in the MCFG by not listing them | ||
| 121 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
| 122 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
| 123 | and fallback for them. | ||
| 124 | We only do this for bus 0/seg 0 */ | ||
| 125 | static __init void unreachable_devices(void) | ||
| 126 | { | ||
| 127 | int i; | ||
| 128 | for (i = 0; i < 32; i++) { | ||
| 129 | u32 val1; | ||
| 130 | char *addr; | ||
| 131 | |||
| 132 | pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); | ||
| 133 | if (val1 == 0xffffffff) | ||
| 134 | continue; | ||
| 135 | addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); | ||
| 136 | if (addr == NULL|| readl(addr) != val1) { | ||
| 137 | set_bit(i, &fallback_slots); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 101 | static int __init pci_mmcfg_init(void) | 142 | static int __init pci_mmcfg_init(void) |
| 102 | { | 143 | { |
| 103 | int i; | 144 | int i; |
| @@ -128,6 +169,8 @@ static int __init pci_mmcfg_init(void) | |||
| 128 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address); | 169 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address); |
| 129 | } | 170 | } |
| 130 | 171 | ||
| 172 | unreachable_devices(); | ||
| 173 | |||
| 131 | raw_pci_ops = &pci_mmcfg; | 174 | raw_pci_ops = &pci_mmcfg; |
| 132 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 175 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
| 133 | 176 | ||
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e34104d32637..c3441b3f086e 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -1464,8 +1464,10 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
| 1464 | request_queue_t *q = disk->queue; | 1464 | request_queue_t *q = disk->queue; |
| 1465 | if (disk->flags & GENHD_FL_UP) | 1465 | if (disk->flags & GENHD_FL_UP) |
| 1466 | del_gendisk(disk); | 1466 | del_gendisk(disk); |
| 1467 | if (q) | 1467 | if (q) { |
| 1468 | blk_cleanup_queue(q); | 1468 | blk_cleanup_queue(q); |
| 1469 | drv->queue = NULL; | ||
| 1470 | } | ||
| 1469 | } | 1471 | } |
| 1470 | } | 1472 | } |
| 1471 | 1473 | ||
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 03839ea31092..9f2b4efd0c7a 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
| @@ -1522,7 +1522,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1522 | 1522 | ||
| 1523 | dev_priv->gart_size = init->gart_size; | 1523 | dev_priv->gart_size = init->gart_size; |
| 1524 | dev_priv->gart_vm_start = dev_priv->fb_location | 1524 | dev_priv->gart_vm_start = dev_priv->fb_location |
| 1525 | + RADEON_READ(RADEON_CONFIG_APER_SIZE); | 1525 | + RADEON_READ(RADEON_CONFIG_APER_SIZE) * 2; |
| 1526 | 1526 | ||
| 1527 | #if __OS_HAS_AGP | 1527 | #if __OS_HAS_AGP |
| 1528 | if (!dev_priv->is_pci) | 1528 | if (!dev_priv->is_pci) |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 716467879b9c..8b6e2a11e28d 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
| @@ -2280,11 +2280,13 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 2280 | } | 2280 | } |
| 2281 | 2281 | ||
| 2282 | if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { | 2282 | if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { |
| 2283 | netif_stop_queue(dev); | 2283 | if (!netif_stopped(dev)) { |
| 2284 | spin_unlock_irqrestore(&skge->tx_lock, flags); | 2284 | netif_stop_queue(dev); |
| 2285 | 2285 | ||
| 2286 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", | 2286 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", |
| 2287 | dev->name); | 2287 | dev->name); |
| 2288 | } | ||
| 2289 | spin_unlock_irqrestore(&skge->tx_lock, flags); | ||
| 2288 | return NETDEV_TX_BUSY; | 2290 | return NETDEV_TX_BUSY; |
| 2289 | } | 2291 | } |
| 2290 | 2292 | ||
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index cdc71572cf35..74415325b016 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c | |||
| @@ -64,8 +64,8 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src | |||
| 64 | int const shift = dst_idx-src_idx; | 64 | int const shift = dst_idx-src_idx; |
| 65 | int left, right; | 65 | int left, right; |
| 66 | 66 | ||
| 67 | first = ~0UL >> dst_idx; | 67 | first = FB_SHIFT_HIGH(~0UL, dst_idx); |
| 68 | last = ~(~0UL >> ((dst_idx+n) % bits)); | 68 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); |
| 69 | 69 | ||
| 70 | if (!shift) { | 70 | if (!shift) { |
| 71 | // Same alignment for source and dest | 71 | // Same alignment for source and dest |
| @@ -216,8 +216,8 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem | |||
| 216 | 216 | ||
| 217 | shift = dst_idx-src_idx; | 217 | shift = dst_idx-src_idx; |
| 218 | 218 | ||
| 219 | first = ~0UL << (bits - 1 - dst_idx); | 219 | first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx); |
| 220 | last = ~(~0UL << (bits - 1 - ((dst_idx-n) % bits))); | 220 | last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits))); |
| 221 | 221 | ||
| 222 | if (!shift) { | 222 | if (!shift) { |
| 223 | // Same alignment for source and dest | 223 | // Same alignment for source and dest |
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index 167d9314e6eb..e5ff62e9cfb8 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c | |||
| @@ -110,8 +110,8 @@ bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsi | |||
| 110 | if (!n) | 110 | if (!n) |
| 111 | return; | 111 | return; |
| 112 | 112 | ||
| 113 | first = ~0UL >> dst_idx; | 113 | first = FB_SHIFT_HIGH(~0UL, dst_idx); |
| 114 | last = ~(~0UL >> ((dst_idx+n) % bits)); | 114 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); |
| 115 | 115 | ||
| 116 | if (dst_idx+n <= bits) { | 116 | if (dst_idx+n <= bits) { |
| 117 | // Single word | 117 | // Single word |
| @@ -167,8 +167,8 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
| 167 | if (!n) | 167 | if (!n) |
| 168 | return; | 168 | return; |
| 169 | 169 | ||
| 170 | first = ~0UL >> dst_idx; | 170 | first = FB_SHIFT_HIGH(~0UL, dst_idx); |
| 171 | last = ~(~0UL >> ((dst_idx+n) % bits)); | 171 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); |
| 172 | 172 | ||
| 173 | if (dst_idx+n <= bits) { | 173 | if (dst_idx+n <= bits) { |
| 174 | // Single word | 174 | // Single word |
| @@ -221,8 +221,8 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
| 221 | if (!n) | 221 | if (!n) |
| 222 | return; | 222 | return; |
| 223 | 223 | ||
| 224 | first = ~0UL >> dst_idx; | 224 | first = FB_SHIFT_HIGH(~0UL, dst_idx); |
| 225 | last = ~(~0UL >> ((dst_idx+n) % bits)); | 225 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); |
| 226 | 226 | ||
| 227 | if (dst_idx+n <= bits) { | 227 | if (dst_idx+n <= bits) { |
| 228 | // Single word | 228 | // Single word |
| @@ -290,8 +290,8 @@ bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat | |||
| 290 | if (!n) | 290 | if (!n) |
| 291 | return; | 291 | return; |
| 292 | 292 | ||
| 293 | first = ~0UL >> dst_idx; | 293 | first = FB_SHIFT_HIGH(~0UL, dst_idx); |
| 294 | last = ~(~0UL >> ((dst_idx+n) % bits)); | 294 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); |
| 295 | 295 | ||
| 296 | if (dst_idx+n <= bits) { | 296 | if (dst_idx+n <= bits) { |
| 297 | // Single word | 297 | // Single word |
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index a7770c4f17d0..910e2338a27e 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c | |||
| @@ -76,18 +76,6 @@ static u32 cfb_tab32[] = { | |||
| 76 | #define FB_WRITEL fb_writel | 76 | #define FB_WRITEL fb_writel |
| 77 | #define FB_READL fb_readl | 77 | #define FB_READL fb_readl |
| 78 | 78 | ||
| 79 | #if defined (__BIG_ENDIAN) | ||
| 80 | #define LEFT_POS(bpp) (32 - bpp) | ||
| 81 | #define SHIFT_HIGH(val, bits) ((val) >> (bits)) | ||
| 82 | #define SHIFT_LOW(val, bits) ((val) << (bits)) | ||
| 83 | #define BIT_NR(b) (7 - (b)) | ||
| 84 | #else | ||
| 85 | #define LEFT_POS(bpp) (0) | ||
| 86 | #define SHIFT_HIGH(val, bits) ((val) << (bits)) | ||
| 87 | #define SHIFT_LOW(val, bits) ((val) >> (bits)) | ||
| 88 | #define BIT_NR(b) (b) | ||
| 89 | #endif | ||
| 90 | |||
| 91 | static inline void color_imageblit(const struct fb_image *image, | 79 | static inline void color_imageblit(const struct fb_image *image, |
| 92 | struct fb_info *p, u8 __iomem *dst1, | 80 | struct fb_info *p, u8 __iomem *dst1, |
| 93 | u32 start_index, | 81 | u32 start_index, |
| @@ -109,7 +97,7 @@ static inline void color_imageblit(const struct fb_image *image, | |||
| 109 | val = 0; | 97 | val = 0; |
| 110 | 98 | ||
| 111 | if (start_index) { | 99 | if (start_index) { |
| 112 | u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); | 100 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index)); |
| 113 | val = FB_READL(dst) & start_mask; | 101 | val = FB_READL(dst) & start_mask; |
| 114 | shift = start_index; | 102 | shift = start_index; |
| 115 | } | 103 | } |
| @@ -119,20 +107,20 @@ static inline void color_imageblit(const struct fb_image *image, | |||
| 119 | color = palette[*src]; | 107 | color = palette[*src]; |
| 120 | else | 108 | else |
| 121 | color = *src; | 109 | color = *src; |
| 122 | color <<= LEFT_POS(bpp); | 110 | color <<= FB_LEFT_POS(bpp); |
| 123 | val |= SHIFT_HIGH(color, shift); | 111 | val |= FB_SHIFT_HIGH(color, shift); |
| 124 | if (shift >= null_bits) { | 112 | if (shift >= null_bits) { |
| 125 | FB_WRITEL(val, dst++); | 113 | FB_WRITEL(val, dst++); |
| 126 | 114 | ||
| 127 | val = (shift == null_bits) ? 0 : | 115 | val = (shift == null_bits) ? 0 : |
| 128 | SHIFT_LOW(color, 32 - shift); | 116 | FB_SHIFT_LOW(color, 32 - shift); |
| 129 | } | 117 | } |
| 130 | shift += bpp; | 118 | shift += bpp; |
| 131 | shift &= (32 - 1); | 119 | shift &= (32 - 1); |
| 132 | src++; | 120 | src++; |
| 133 | } | 121 | } |
| 134 | if (shift) { | 122 | if (shift) { |
| 135 | u32 end_mask = SHIFT_HIGH(~(u32)0, shift); | 123 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); |
| 136 | 124 | ||
| 137 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 125 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
| 138 | } | 126 | } |
| @@ -162,6 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
| 162 | u32 i, j, l; | 150 | u32 i, j, l; |
| 163 | 151 | ||
| 164 | dst2 = (u32 __iomem *) dst1; | 152 | dst2 = (u32 __iomem *) dst1; |
| 153 | fgcolor <<= FB_LEFT_POS(bpp); | ||
| 154 | bgcolor <<= FB_LEFT_POS(bpp); | ||
| 165 | 155 | ||
| 166 | for (i = image->height; i--; ) { | 156 | for (i = image->height; i--; ) { |
| 167 | shift = val = 0; | 157 | shift = val = 0; |
| @@ -172,22 +162,21 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
| 172 | 162 | ||
| 173 | /* write leading bits */ | 163 | /* write leading bits */ |
| 174 | if (start_index) { | 164 | if (start_index) { |
| 175 | u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); | 165 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); |
| 176 | val = FB_READL(dst) & start_mask; | 166 | val = FB_READL(dst) & start_mask; |
| 177 | shift = start_index; | 167 | shift = start_index; |
| 178 | } | 168 | } |
| 179 | 169 | ||
| 180 | while (j--) { | 170 | while (j--) { |
| 181 | l--; | 171 | l--; |
| 182 | color = (*s & 1 << (BIT_NR(l))) ? fgcolor : bgcolor; | 172 | color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor; |
| 183 | color <<= LEFT_POS(bpp); | 173 | val |= FB_SHIFT_HIGH(color, shift); |
| 184 | val |= SHIFT_HIGH(color, shift); | ||
| 185 | 174 | ||
| 186 | /* Did the bitshift spill bits to the next long? */ | 175 | /* Did the bitshift spill bits to the next long? */ |
| 187 | if (shift >= null_bits) { | 176 | if (shift >= null_bits) { |
| 188 | FB_WRITEL(val, dst++); | 177 | FB_WRITEL(val, dst++); |
| 189 | val = (shift == null_bits) ? 0 : | 178 | val = (shift == null_bits) ? 0 : |
| 190 | SHIFT_LOW(color,32 - shift); | 179 | FB_SHIFT_LOW(color,32 - shift); |
| 191 | } | 180 | } |
| 192 | shift += bpp; | 181 | shift += bpp; |
| 193 | shift &= (32 - 1); | 182 | shift &= (32 - 1); |
| @@ -196,7 +185,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
| 196 | 185 | ||
| 197 | /* write trailing bits */ | 186 | /* write trailing bits */ |
| 198 | if (shift) { | 187 | if (shift) { |
| 199 | u32 end_mask = SHIFT_HIGH(~(u32)0, shift); | 188 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); |
| 200 | 189 | ||
| 201 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 190 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
| 202 | } | 191 | } |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index bcea87c3cc06..3660e51b2612 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
| @@ -2048,7 +2048,7 @@ static int fbcon_switch(struct vc_data *vc) | |||
| 2048 | struct fbcon_ops *ops; | 2048 | struct fbcon_ops *ops; |
| 2049 | struct display *p = &fb_display[vc->vc_num]; | 2049 | struct display *p = &fb_display[vc->vc_num]; |
| 2050 | struct fb_var_screeninfo var; | 2050 | struct fb_var_screeninfo var; |
| 2051 | int i, prev_console; | 2051 | int i, prev_console, charcnt = 256; |
| 2052 | 2052 | ||
| 2053 | info = registered_fb[con2fb_map[vc->vc_num]]; | 2053 | info = registered_fb[con2fb_map[vc->vc_num]]; |
| 2054 | ops = info->fbcon_par; | 2054 | ops = info->fbcon_par; |
| @@ -2103,7 +2103,8 @@ static int fbcon_switch(struct vc_data *vc) | |||
| 2103 | fb_set_var(info, &var); | 2103 | fb_set_var(info, &var); |
| 2104 | ops->var = info->var; | 2104 | ops->var = info->var; |
| 2105 | 2105 | ||
| 2106 | if (old_info != NULL && old_info != info) { | 2106 | if (old_info != NULL && (old_info != info || |
| 2107 | info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { | ||
| 2107 | if (info->fbops->fb_set_par) | 2108 | if (info->fbops->fb_set_par) |
| 2108 | info->fbops->fb_set_par(info); | 2109 | info->fbops->fb_set_par(info); |
| 2109 | fbcon_del_cursor_timer(old_info); | 2110 | fbcon_del_cursor_timer(old_info); |
| @@ -2120,6 +2121,13 @@ static int fbcon_switch(struct vc_data *vc) | |||
| 2120 | 2121 | ||
| 2121 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); | 2122 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); |
| 2122 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 2123 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
| 2124 | |||
| 2125 | if (p->userfont) | ||
| 2126 | charcnt = FNTCHARCNT(vc->vc_font.data); | ||
| 2127 | |||
| 2128 | if (charcnt > 256) | ||
| 2129 | vc->vc_complement_mask <<= 1; | ||
| 2130 | |||
| 2123 | updatescrollmode(p, info, vc); | 2131 | updatescrollmode(p, info, vc); |
| 2124 | 2132 | ||
| 2125 | switch (p->scrollmode) { | 2133 | switch (p->scrollmode) { |
| @@ -2139,8 +2147,12 @@ static int fbcon_switch(struct vc_data *vc) | |||
| 2139 | 2147 | ||
| 2140 | scrollback_max = 0; | 2148 | scrollback_max = 0; |
| 2141 | scrollback_current = 0; | 2149 | scrollback_current = 0; |
| 2142 | ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; | 2150 | |
| 2143 | ops->update_start(info); | 2151 | if (!fbcon_is_inactive(vc, info)) { |
| 2152 | ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; | ||
| 2153 | ops->update_start(info); | ||
| 2154 | } | ||
| 2155 | |||
| 2144 | fbcon_set_palette(vc, color_table); | 2156 | fbcon_set_palette(vc, color_table); |
| 2145 | fbcon_clear_margins(vc, 0); | 2157 | fbcon_clear_margins(vc, 0); |
| 2146 | 2158 | ||
| @@ -2184,11 +2196,14 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) | |||
| 2184 | ops->graphics = 1; | 2196 | ops->graphics = 1; |
| 2185 | 2197 | ||
| 2186 | if (!blank) { | 2198 | if (!blank) { |
| 2199 | if (info->fbops->fb_save_state) | ||
| 2200 | info->fbops->fb_save_state(info); | ||
| 2187 | var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; | 2201 | var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; |
| 2188 | fb_set_var(info, &var); | 2202 | fb_set_var(info, &var); |
| 2189 | ops->graphics = 0; | 2203 | ops->graphics = 0; |
| 2190 | ops->var = info->var; | 2204 | ops->var = info->var; |
| 2191 | } | 2205 | } else if (info->fbops->fb_restore_state) |
| 2206 | info->fbops->fb_restore_state(info); | ||
| 2192 | } | 2207 | } |
| 2193 | 2208 | ||
| 2194 | if (!fbcon_is_inactive(vc, info)) { | 2209 | if (!fbcon_is_inactive(vc, info)) { |
| @@ -2736,8 +2751,12 @@ static void fbcon_modechanged(struct fb_info *info) | |||
| 2736 | updatescrollmode(p, info, vc); | 2751 | updatescrollmode(p, info, vc); |
| 2737 | scrollback_max = 0; | 2752 | scrollback_max = 0; |
| 2738 | scrollback_current = 0; | 2753 | scrollback_current = 0; |
| 2739 | ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; | 2754 | |
| 2740 | ops->update_start(info); | 2755 | if (!fbcon_is_inactive(vc, info)) { |
| 2756 | ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; | ||
| 2757 | ops->update_start(info); | ||
| 2758 | } | ||
| 2759 | |||
| 2741 | fbcon_set_palette(vc, color_table); | 2760 | fbcon_set_palette(vc, color_table); |
| 2742 | update_screen(vc); | 2761 | update_screen(vc); |
| 2743 | if (softback_buf) | 2762 | if (softback_buf) |
| @@ -2774,8 +2793,13 @@ static void fbcon_set_all_vcs(struct fb_info *info) | |||
| 2774 | updatescrollmode(p, info, vc); | 2793 | updatescrollmode(p, info, vc); |
| 2775 | scrollback_max = 0; | 2794 | scrollback_max = 0; |
| 2776 | scrollback_current = 0; | 2795 | scrollback_current = 0; |
| 2777 | ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; | 2796 | |
| 2778 | ops->update_start(info); | 2797 | if (!fbcon_is_inactive(vc, info)) { |
| 2798 | ops->var.xoffset = ops->var.yoffset = | ||
| 2799 | p->yscroll = 0; | ||
| 2800 | ops->update_start(info); | ||
| 2801 | } | ||
| 2802 | |||
| 2779 | fbcon_set_palette(vc, color_table); | 2803 | fbcon_set_palette(vc, color_table); |
| 2780 | update_screen(vc); | 2804 | update_screen(vc); |
| 2781 | if (softback_buf) | 2805 | if (softback_buf) |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6240aedb4154..10dfdf035264 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -722,14 +722,30 @@ static void try_to_load(int fb) | |||
| 722 | int | 722 | int |
| 723 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | 723 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) |
| 724 | { | 724 | { |
| 725 | struct fb_fix_screeninfo *fix = &info->fix; | ||
| 725 | int xoffset = var->xoffset; | 726 | int xoffset = var->xoffset; |
| 726 | int yoffset = var->yoffset; | 727 | int yoffset = var->yoffset; |
| 727 | int err; | 728 | int err = 0, yres = info->var.yres; |
| 729 | |||
| 730 | if (var->yoffset > 0) { | ||
| 731 | if (var->vmode & FB_VMODE_YWRAP) { | ||
| 732 | if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep)) | ||
| 733 | err = -EINVAL; | ||
| 734 | else | ||
| 735 | yres = 0; | ||
| 736 | } else if (!fix->ypanstep || (var->yoffset % fix->ypanstep)) | ||
| 737 | err = -EINVAL; | ||
| 738 | } | ||
| 739 | |||
| 740 | if (var->xoffset > 0 && (!fix->xpanstep || | ||
| 741 | (var->xoffset % fix->xpanstep))) | ||
| 742 | err = -EINVAL; | ||
| 743 | |||
| 744 | if (err || !info->fbops->fb_pan_display || xoffset < 0 || | ||
| 745 | yoffset < 0 || var->yoffset + yres > info->var.yres_virtual || | ||
| 746 | var->xoffset + info->var.xres > info->var.xres_virtual) | ||
| 747 | return -EINVAL; | ||
| 728 | 748 | ||
| 729 | if (xoffset < 0 || yoffset < 0 || !info->fbops->fb_pan_display || | ||
| 730 | xoffset + info->var.xres > info->var.xres_virtual || | ||
| 731 | yoffset + info->var.yres > info->var.yres_virtual) | ||
| 732 | return -EINVAL; | ||
| 733 | if ((err = info->fbops->fb_pan_display(var, info))) | 749 | if ((err = info->fbops->fb_pan_display(var, info))) |
| 734 | return err; | 750 | return err; |
| 735 | info->var.xoffset = var->xoffset; | 751 | info->var.xoffset = var->xoffset; |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 04a58f33ec53..a973be2cfe61 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
| @@ -617,6 +617,12 @@ struct fb_ops { | |||
| 617 | 617 | ||
| 618 | /* perform fb specific mmap */ | 618 | /* perform fb specific mmap */ |
| 619 | int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); | 619 | int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); |
| 620 | |||
| 621 | /* save current hardware state */ | ||
| 622 | void (*fb_save_state)(struct fb_info *info); | ||
| 623 | |||
| 624 | /* restore saved state */ | ||
| 625 | void (*fb_restore_state)(struct fb_info *info); | ||
| 620 | }; | 626 | }; |
| 621 | 627 | ||
| 622 | #ifdef CONFIG_FB_TILEBLITTING | 628 | #ifdef CONFIG_FB_TILEBLITTING |
| @@ -726,6 +732,18 @@ struct fb_tile_ops { | |||
| 726 | from userspace */ | 732 | from userspace */ |
| 727 | #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ | 733 | #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ |
| 728 | 734 | ||
| 735 | /* A driver may set this flag to indicate that it does want a set_par to be | ||
| 736 | * called every time when fbcon_switch is executed. The advantage is that with | ||
| 737 | * this flag set you can really be shure that set_par is always called before | ||
| 738 | * any of the functions dependant on the correct hardware state or altering | ||
| 739 | * that state, even if you are using some broken X releases. The disadvantage | ||
| 740 | * is that it introduces unwanted delays to every console switch if set_par | ||
| 741 | * is slow. It is a good idea to try this flag in the drivers initialization | ||
| 742 | * code whenever there is a bug report related to switching between X and the | ||
| 743 | * framebuffer console. | ||
| 744 | */ | ||
| 745 | #define FBINFO_MISC_ALWAYS_SETPAR 0x40000 | ||
| 746 | |||
| 729 | struct fb_info { | 747 | struct fb_info { |
| 730 | int node; | 748 | int node; |
| 731 | int flags; | 749 | int flags; |
| @@ -817,6 +835,18 @@ struct fb_info { | |||
| 817 | 835 | ||
| 818 | #endif | 836 | #endif |
| 819 | 837 | ||
| 838 | #if defined (__BIG_ENDIAN) | ||
| 839 | #define FB_LEFT_POS(bpp) (32 - bpp) | ||
| 840 | #define FB_SHIFT_HIGH(val, bits) ((val) >> (bits)) | ||
| 841 | #define FB_SHIFT_LOW(val, bits) ((val) << (bits)) | ||
| 842 | #define FB_BIT_NR(b) (7 - (b)) | ||
| 843 | #else | ||
| 844 | #define FB_LEFT_POS(bpp) (0) | ||
| 845 | #define FB_SHIFT_HIGH(val, bits) ((val) << (bits)) | ||
| 846 | #define FB_SHIFT_LOW(val, bits) ((val) >> (bits)) | ||
| 847 | #define FB_BIT_NR(b) (b) | ||
| 848 | #endif | ||
| 849 | |||
| 820 | /* | 850 | /* |
| 821 | * `Generic' versions of the frame buffer device operations | 851 | * `Generic' versions of the frame buffer device operations |
| 822 | */ | 852 | */ |
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index 91b16fbf91f0..d18ccba3ea9e 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig | |||
| @@ -55,7 +55,7 @@ config IEEE80211_CRYPT_CCMP | |||
| 55 | 55 | ||
| 56 | config IEEE80211_CRYPT_TKIP | 56 | config IEEE80211_CRYPT_TKIP |
| 57 | tristate "IEEE 802.11i TKIP encryption" | 57 | tristate "IEEE 802.11i TKIP encryption" |
| 58 | depends on IEEE80211 | 58 | depends on IEEE80211 && NET_RADIO |
| 59 | select CRYPTO | 59 | select CRYPTO |
| 60 | select CRYPTO_MICHAEL_MIC | 60 | select CRYPTO_MICHAEL_MIC |
| 61 | ---help--- | 61 | ---help--- |
