aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-12-13 11:36:18 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-12-13 11:36:18 -0500
commitd22a8ccff761c81f2930bd90fa5712e51a0e9a62 (patch)
tree52a92cf1b9a65e4440276706c4b4e879d4008a87
parent783e3385a134305d49d7b431df6e591265e7ec14 (diff)
parent98684a9d91bceff829b6dc7adf0f662d59cfa6e3 (diff)
Merge branch 'upstream-fixes'
-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/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.c63
-rw-r--r--drivers/block/cciss.c4
-rw-r--r--drivers/char/drm/radeon_cp.c2
-rw-r--r--drivers/net/skge.c2
-rw-r--r--drivers/scsi/libata-core.c4
-rw-r--r--drivers/video/cfbcopyarea.c8
-rw-r--r--drivers/video/cfbfillrect.c16
-rw-r--r--drivers/video/cfbimgblt.c35
-rw-r--r--drivers/video/console/fbcon.c42
-rw-r--r--drivers/video/fbmem.c26
-rw-r--r--include/linux/fb.h30
21 files changed, 303 insertions, 97 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}
224EXPORT_SYMBOL(ioremap_nocache); 224EXPORT_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 */
226void iounmap(volatile void __iomem *addr) 232void 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 }
256out_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}
260EXPORT_SYMBOL(iounmap); 281EXPORT_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
16static int pci_conf1_read(unsigned int seg, unsigned int bus, 16int 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
45static int pci_conf1_write(unsigned int seg, unsigned int bus, 45int 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 */
20static u32 mmcfg_last_accessed_device; 20static u32 mmcfg_last_accessed_device;
21 21
22static 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 */
25static u32 get_base_addr(unsigned int seg, int bus) 27static 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
47static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn) 51static 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 */
140static __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
119static int __init pci_mmcfg_init(void) 164static 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
75extern int (*pcibios_enable_irq)(struct pci_dev *dev); 75extern int (*pcibios_enable_irq)(struct pci_dev *dev);
76extern void (*pcibios_disable_irq)(struct pci_dev *dev); 76extern void (*pcibios_disable_irq)(struct pci_dev *dev);
77
78extern int pci_conf1_write(unsigned int seg, unsigned int bus,
79 unsigned int devfn, int reg, int len, u32 value);
80extern 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;
59unsigned int cpu_khz; /* TSC clocks / usec, not used here */ 59unsigned int cpu_khz; /* TSC clocks / usec, not used here */
60static unsigned long hpet_period; /* fsecs / HPET clock */ 60static unsigned long hpet_period; /* fsecs / HPET clock */
61unsigned long hpet_tick; /* HPET clocks / interrupt */ 61unsigned long hpet_tick; /* HPET clocks / interrupt */
62static int hpet_use_timer; 62static int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */
63unsigned long vxtime_hz = PIT_TICK_RATE; 63unsigned long vxtime_hz = PIT_TICK_RATE;
64int report_lost_ticks; /* command line option */ 64int report_lost_ticks; /* command line option */
65unsigned long long monotonic_base; 65unsigned 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 */
250void iounmap(volatile void __iomem *addr) 256void 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
16static DECLARE_BITMAP(fallback_slots, 32);
17
15/* Static virtual mapping of the MMCONFIG aperture */ 18/* Static virtual mapping of the MMCONFIG aperture */
16struct mmcfg_virt { 19struct 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};
20static struct mmcfg_virt *pci_mmcfg_virt; 23static struct mmcfg_virt *pci_mmcfg_virt;
21 24
22static char *get_virt(unsigned int seg, int bus) 25static 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
44static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) 46static 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
50static int pci_mmcfg_read(unsigned int seg, unsigned int bus, 57static 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,
73static int pci_mmcfg_write(unsigned int seg, unsigned int bus, 85static 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 */
125static __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
101static int __init pci_mmcfg_init(void) 142static 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 8b6e2a11e28d..00d683063c01 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -2280,7 +2280,7 @@ 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 if (!netif_stopped(dev)) { 2283 if (!netif_queue_stopped(dev)) {
2284 netif_stop_queue(dev); 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",
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 665ae79e1fd6..d0a0fdbd0fc4 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2443,7 +2443,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
2443 struct scatterlist *psg = &qc->pad_sgent; 2443 struct scatterlist *psg = &qc->pad_sgent;
2444 void *addr = kmap_atomic(psg->page, KM_IRQ0); 2444 void *addr = kmap_atomic(psg->page, KM_IRQ0);
2445 memcpy(addr + psg->offset, pad_buf, qc->pad_len); 2445 memcpy(addr + psg->offset, pad_buf, qc->pad_len);
2446 kunmap_atomic(psg->page, KM_IRQ0); 2446 kunmap_atomic(addr, KM_IRQ0);
2447 } 2447 }
2448 } else { 2448 } else {
2449 if (sg_dma_len(&sg[0]) > 0) 2449 if (sg_dma_len(&sg[0]) > 0)
@@ -2717,7 +2717,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
2717 if (qc->tf.flags & ATA_TFLAG_WRITE) { 2717 if (qc->tf.flags & ATA_TFLAG_WRITE) {
2718 void *addr = kmap_atomic(psg->page, KM_IRQ0); 2718 void *addr = kmap_atomic(psg->page, KM_IRQ0);
2719 memcpy(pad_buf, addr + psg->offset, qc->pad_len); 2719 memcpy(pad_buf, addr + psg->offset, qc->pad_len);
2720 kunmap_atomic(psg->page, KM_IRQ0); 2720 kunmap_atomic(addr, KM_IRQ0);
2721 } 2721 }
2722 2722
2723 sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); 2723 sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
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
91static inline void color_imageblit(const struct fb_image *image, 79static 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)
722int 722int
723fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) 723fb_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
729struct fb_info { 747struct 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 */