summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:11:43 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:11:43 -0800
commitdf0386374805089cbd09cc4a308e893be6738a93 (patch)
tree218ddf00b4d68ccbeab2a0cc8f1985d936369422
parent87f504e5c78b910b0c1d6ffb89bc95e492322c84 (diff)
v2.4.9.2 -> v2.4.9.3
- Johannes Erdfelt, Oliver Neukum: USB printer driver race fix - John Byrne: fix stupid i386-SMP irq stack layout bug - Andreas Bombe, me: yenta IO window fix - Neil Brown: raid1 buffer state fix - David Miller, Paul Mackerras: fix up sparc and ppc respectively for kmap/kbd_rate - Matija Nalis: umsdos fixes, and make it possible to boot up with umsdos - Francois Romieu: fix bugs in dscc4 driver - Andy Grover: new PCI config space access functions (eventually for ACPI) - Albert Cranford: fix incorrect e2fsprog data from ver_linux script - Dave Jones: re-sync x86 setup code, fix macsonic kmalloc use - Johannes Erdfelt: remove obsolete plusb USB driver - Andries Brouwer: fix USB compact flash version info, add blksize ioctls
-rw-r--r--Documentation/Configure.help13
-rw-r--r--Makefile2
-rw-r--r--arch/i386/defconfig2
-rw-r--r--arch/i386/kernel/bluesmoke.c34
-rw-r--r--arch/i386/kernel/mtrr.c58
-rw-r--r--arch/i386/kernel/pci-pc.c535
-rw-r--r--arch/i386/kernel/setup.c66
-rw-r--r--arch/mips64/kernel/ioctl32.c2
-rw-r--r--arch/ppc/kernel/chrp_setup.c4
-rw-r--r--arch/ppc/kernel/head_8xx.S4
-rw-r--r--arch/ppc/kernel/pmac_setup.c4
-rw-r--r--arch/ppc/kernel/prep_setup.c4
-rw-r--r--arch/sparc64/kernel/ioctl32.c2
-rw-r--r--drivers/acpi/include/platform/acgcc.h2
-rw-r--r--drivers/block/DAC960.c18
-rw-r--r--drivers/block/blkpg.c23
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/cpqarray.c2
-rw-r--r--drivers/block/loop.c5
-rw-r--r--drivers/block/ps2esdi.c2
-rw-r--r--drivers/ide/ide.c2
-rw-r--r--drivers/macintosh/Makefile2
-rw-r--r--drivers/macintosh/via-pmu.c407
-rw-r--r--drivers/md/md.c33
-rw-r--r--drivers/md/raid1.c2
-rw-r--r--drivers/net/macsonic.c5
-rw-r--r--drivers/net/wan/dscc4.c24
-rw-r--r--drivers/pci/pci.c9
-rw-r--r--drivers/pcmcia/yenta.c10
-rw-r--r--drivers/scsi/sd.c6
-rw-r--r--drivers/usb/Config.in1
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/plusb.c1060
-rw-r--r--drivers/usb/printer.c5
-rw-r--r--drivers/usb/storage/unusual_devs.h2
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--fs/Makefile2
-rw-r--r--fs/umsdos/README-WIP.txt49
-rw-r--r--fs/umsdos/dir.c4
-rw-r--r--fs/umsdos/emd.c43
-rw-r--r--fs/umsdos/inode.c65
-rw-r--r--fs/umsdos/namei.c36
-rw-r--r--fs/umsdos/rdir.c3
-rw-r--r--include/asm-i386/hw_irq.h4
-rw-r--r--include/asm-i386/msr.h84
-rw-r--r--include/asm-i386/system.h13
-rw-r--r--include/asm-i386/timex.h2
-rw-r--r--include/asm-ppc/keyboard.h3
-rw-r--r--include/asm-ppc/kmap_types.h4
-rw-r--r--include/asm-ppc/machdep.h15
-rw-r--r--include/asm-sparc/kmap_types.h2
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/pmu.h24
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--mm/vmscan.c9
-rw-r--r--scripts/ver_linux2
56 files changed, 1131 insertions, 1594 deletions
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 364ac608b6c0..9a457df6bfdc 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -11690,19 +11690,6 @@ CONFIG_USB_USBNET
The module will be called usbnet.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
-PLUSB driver
-CONFIG_USB_PLUSB
- A driver for the Prolific PL-2302 USB-to-USB network device. This
- 'USB cable' connects two hosts via a point-to-point network with
- bandwidth of 5 Mbit/s. Configure this driver after connecting the
- USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and
- vice versa on the other host).
-
- This code is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called plusb.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
-
USB Diamond Rio500 support
CONFIG_USB_RIO500
Say Y here if you want to connect a USB Rio500 mp3 player to your
diff --git a/Makefile b/Makefile
index a9754f318748..16857718ac8b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 10
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 1083b11aab48..6e5153049c94 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -742,7 +742,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_USBNET is not set
#
# USB port drivers
diff --git a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
index 5ae7f060efc4..7c6e59aa6e3c 100644
--- a/arch/i386/kernel/bluesmoke.c
+++ b/arch/i386/kernel/bluesmoke.c
@@ -19,7 +19,7 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
u32 mcgstl, mcgsth;
int i;
- rdmsr(0x17a, mcgstl, mcgsth);
+ rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if(mcgstl&(1<<0)) /* Recoverable ? */
recover=0;
@@ -27,7 +27,7 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
for(i=0;i<banks;i++)
{
- rdmsr(0x401+i*4,low, high);
+ rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
if(high&(1<<31))
{
if(high&(1<<29))
@@ -38,18 +38,18 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
high&=~(1<<31);
if(high&(1<<27))
{
- rdmsr(0x402+i*4, alow, ahigh);
+ rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk("[%08x%08x]", alow, ahigh);
}
if(high&(1<<26))
{
- rdmsr(0x402+i*4, alow, ahigh);
+ rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk(" at %08x%08x",
high, low);
}
printk("\n");
/* Clear it */
- wrmsr(0x401+i*4, 0UL, 0UL);
+ wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */
wmb();
}
@@ -61,7 +61,7 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
panic("Unable to continue");
printk(KERN_EMERG "Attempting to continue.\n");
mcgstl&=~(1<<2);
- wrmsr(0x17a,mcgstl, mcgsth);
+ wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
}
/*
@@ -71,8 +71,8 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
static void pentium_machine_check(struct pt_regs * regs, long error_code)
{
u32 loaddr, hi, lotype;
- rdmsr(0x0, loaddr, hi);
- rdmsr(0x1, lotype, hi);
+ rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+ rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
if(lotype&(1<<5))
printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
@@ -133,8 +133,8 @@ void __init intel_mcheck_init(struct cpuinfo_x86 *c)
machine_check_vector = pentium_machine_check;
wmb();
/* Read registers before enabling */
- rdmsr(0x0, l, h);
- rdmsr(0x1, l, h);
+ rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
+ rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
if(done==0)
printk(KERN_INFO "Intel old style machine check architecture supported.\n");
/* Enable MCE */
@@ -161,17 +161,17 @@ void __init intel_mcheck_init(struct cpuinfo_x86 *c)
if(done==0)
printk(KERN_INFO "Intel machine check architecture supported.\n");
- rdmsr(0x179, l, h);
+ rdmsr(MSR_IA32_MCG_CAP, l, h);
if(l&(1<<8))
- wrmsr(0x17b, 0xffffffff, 0xffffffff);
+ wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
banks = l&0xff;
for(i=1;i<banks;i++)
{
- wrmsr(0x400+4*i, 0xffffffff, 0xffffffff);
+ wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
}
for(i=0;i<banks;i++)
{
- wrmsr(0x401+4*i, 0x0, 0x0);
+ wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
}
set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
@@ -191,10 +191,10 @@ static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
/* Winchip C6 */
machine_check_vector = winchip_machine_check;
wmb();
- rdmsr(0x107, lo, hi);
+ rdmsr(MSR_IDT_FCR1, lo, hi);
lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
lo&= ~(1<<4); /* Enable MCE */
- wrmsr(0x107, lo, hi);
+ wrmsr(MSR_IDT_FCR1, lo, hi);
__asm__ __volatile__ (
"movl %%cr4, %%eax\n\t"
"orl $0x40, %%eax\n\t"
@@ -236,6 +236,6 @@ void __init mcheck_init(struct cpuinfo_x86 *c)
static int __init mcheck_disable(char *str)
{
mce_disabled = 1;
- return 1;
+ return 0;
}
__setup("nomce", mcheck_disable);
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index fa815a804220..afaa4b2db31a 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -389,21 +389,19 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
return;
/* Save value of CR4 and clear Page Global Enable (bit 7) */
- if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
- asm volatile ("movl %%cr4, %0\n\t"
- "movl %0, %1\n\t"
- "andb $0x7f, %b1\n\t"
- "movl %1, %%cr4\n\t"
- : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory");
+ if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) {
+ ctxt->cr4val = read_cr4();
+ write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7));
+ }
/* Disable and flush caches. Note that wbinvd flushes the TLBs as
a side-effect */
- asm volatile ("movl %%cr0, %0\n\t"
- "orl $0x40000000, %0\n\t"
- "wbinvd\n\t"
- "movl %0, %%cr0\n\t"
- "wbinvd\n\t"
- : "=r" (tmp) : : "memory");
+ {
+ unsigned int cr0 = read_cr0() | 0x40000000;
+ wbinvd();
+ write_cr0( cr0 );
+ wbinvd();
+ }
if ( mtrr_if == MTRR_IF_INTEL ) {
/* Disable MTRRs, and set the default type to uncached */
@@ -420,15 +418,13 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
/* Restore the processor after a set_mtrr_prepare */
static void set_mtrr_done (struct set_mtrr_context *ctxt)
{
- unsigned long tmp;
-
if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) {
__restore_flags (ctxt->flags);
return;
}
/* Flush caches and TLBs */
- asm volatile ("wbinvd" : : : "memory" );
+ wbinvd();
/* Restore MTRRdefType */
if ( mtrr_if == MTRR_IF_INTEL ) {
@@ -440,15 +436,11 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
}
/* Enable caches */
- asm volatile ("movl %%cr0, %0\n\t"
- "andl $0xbfffffff, %0\n\t"
- "movl %0, %%cr0\n\t"
- : "=r" (tmp) : : "memory");
+ write_cr0( read_cr0() & 0xbfffffff );
/* Restore value of CR4 */
if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
- asm volatile ("movl %0, %%cr4"
- : : "r" (ctxt->cr4val) : "memory");
+ write_cr4(ctxt->cr4val);
/* Re-enable interrupts locally (if enabled previously) */
__restore_flags (ctxt->flags);
@@ -607,7 +599,7 @@ static void amd_get_mtrr (unsigned int reg, unsigned long *base,
{
unsigned long low, high;
- rdmsr (0xC0000085, low, high);
+ rdmsr (MSR_K6_UWCCR, low, high);
/* Upper dword is region 1, lower is region 0 */
if (reg == 1) low = high;
/* The base masks off on the right alignment */
@@ -771,7 +763,7 @@ static void amd_set_mtrr_up (unsigned int reg, unsigned long base,
/*
* Low is MTRR0 , High MTRR 1
*/
- rdmsr (0xC0000085, regs[0], regs[1]);
+ rdmsr (MSR_K6_UWCCR, regs[0], regs[1]);
/*
* Blank to disable
*/
@@ -792,8 +784,8 @@ static void amd_set_mtrr_up (unsigned int reg, unsigned long base,
* The writeback rule is quite specific. See the manual. Its
* disable local interrupts, write back the cache, set the mtrr
*/
- __asm__ __volatile__ ("wbinvd" : : : "memory");
- wrmsr (0xC0000085, regs[0], regs[1]);
+ wbinvd();
+ wrmsr (MSR_K6_UWCCR, regs[0], regs[1]);
if (do_safe) set_mtrr_done (&ctxt);
} /* End Function amd_set_mtrr_up */
@@ -826,7 +818,7 @@ static void centaur_set_mcr_up (unsigned int reg, unsigned long base,
}
centaur_mcr[reg].high = high;
centaur_mcr[reg].low = low;
- wrmsr (0x110 + reg, low, high);
+ wrmsr (MSR_IDT_MCR0 + reg, low, high);
if (do_safe) set_mtrr_done( &ctxt );
} /* End Function centaur_set_mtrr_up */
@@ -2012,12 +2004,12 @@ static void __init centaur_mcr1_init(void)
* find out what the bios might have done.
*/
- rdmsr(0x120, lo, hi);
+ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
if(((lo>>17)&7)==1) /* Type 1 Winchip2 MCR */
{
lo&= ~0x1C0; /* clear key */
lo|= 0x040; /* set key to 1 */
- wrmsr(0x120, lo, hi); /* unlock MCR */
+ wrmsr(MSR_IDT_MCR_CTRL, lo, hi); /* unlock MCR */
}
centaur_mcr_type = 1;
@@ -2031,7 +2023,7 @@ static void __init centaur_mcr1_init(void)
if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
{
if(!(lo & (1<<(9+i))))
- wrmsr (0x110 + i , 0, 0);
+ wrmsr (MSR_IDT_MCR0 + i , 0, 0);
else
/*
* If the BIOS set up an MCR we cannot see it
@@ -2047,7 +2039,7 @@ static void __init centaur_mcr1_init(void)
*/
lo |= 15; /* Write combine enables */
- wrmsr(0x120, lo, hi);
+ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
} /* End Function centaur_mcr1_init */
/*
@@ -2071,10 +2063,10 @@ static void __init centaur_mcr0_init(void)
for (i = 0; i < 8; ++i)
{
if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
- wrmsr (0x110 + i , 0, 0);
+ wrmsr (MSR_IDT_MCR0 + i , 0, 0);
}
- wrmsr(0x120, 0x01F0001F, 0); /* Write only */
+ wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); /* Write only */
} /* End Function centaur_mcr0_init */
/*
@@ -2231,6 +2223,8 @@ void __init mtrr_init_secondary_cpu(void)
*/
cyrix_arr_init_secondary ();
break;
+ case MTRR_IF_NONE:
+ break;
default:
/* I see no MTRRs I can support in SMP mode... */
printk ("mtrr: SMP support incomplete for this vendor\n");
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index ef3c7c35af01..a0aa4f46b887 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -20,65 +20,145 @@
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus;
-struct pci_ops *pci_root_ops;
+struct pci_bus *pci_root_bus = NULL;
+struct pci_ops *pci_root_ops = NULL;
+
+int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
+int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
/*
- * Direct access to PCI hardware...
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
*/
+spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
-#ifdef CONFIG_PCI_DIRECT
/*
* Functions for accessing PCI configuration space with type 1 accesses
*/
-#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
+#ifdef CONFIG_PCI_DIRECT
+
+#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
+ (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+ unsigned long flags;
+
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+ switch (len) {
+ case 1:
+ *value = inb(0xCFC + (reg & 3));
+ break;
+ case 2:
+ *value = inw(0xCFC + (reg & 2));
+ break;
+ case 4:
+ *value = inl(0xCFC);
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+ unsigned long flags;
+
+ if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+
+ switch (len) {
+ case 1:
+ outb((u8)value, 0xCFC + (reg & 3));
+ break;
+ case 2:
+ outw((u16)value, 0xCFC + (reg & 2));
+ break;
+ case 4:
+ outl((u32)value, 0xCFC);
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+#undef PCI_CONF1_ADDRESS
static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- *value = inb(0xCFC + (where&3));
- return PCIBIOS_SUCCESSFUL;
+ int result;
+ u32 data;
+
+ if (!value)
+ return -EINVAL;
+
+ result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, &data);
+
+ *value = (u8)data;
+
+ return result;
}
static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- *value = inw(0xCFC + (where&2));
- return PCIBIOS_SUCCESSFUL;
+ int result;
+ u32 data;
+
+ if (!value)
+ return -EINVAL;
+
+ result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, &data);
+
+ *value = (u16)data;
+
+ return result;
}
static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- *value = inl(0xCFC);
- return PCIBIOS_SUCCESSFUL;
+ if (!value)
+ return -EINVAL;
+
+ return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, value);
}
static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- outb(value, 0xCFC + (where&3));
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, value);
}
static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- outw(value, 0xCFC + (where&2));
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, value);
}
static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- outl(CONFIG_CMD(dev,where), 0xCF8);
- outl(value, 0xCFC);
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, value);
}
-#undef CONFIG_CMD
-
static struct pci_ops pci_direct_conf1 = {
pci_conf1_read_config_byte,
pci_conf1_read_config_word,
@@ -88,68 +168,131 @@ static struct pci_ops pci_direct_conf1 = {
pci_conf1_write_config_dword
};
+
/*
* Functions for accessing PCI configuration space with type 2 accesses
*/
-#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)
-#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
-#define SET(dev) if (dev->devfn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND; \
- outb(FUNC(dev->devfn), 0xCF8); \
- outb(dev->bus->number, 0xCFA);
+#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg)
-static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+static int pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
{
- SET(dev);
- *value = inb(IOADDR(dev->devfn,where));
+ unsigned long flags;
+
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ if (dev & 0x10)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+ outb((u8)bus, 0xCFA);
+
+ switch (len) {
+ case 1:
+ *value = inb(PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ case 2:
+ *value = inw(PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ case 4:
+ *value = inl(PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ }
+
outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+static int pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+ unsigned long flags;
+
+ if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ if (dev & 0x10)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outb((u8)(0xF0 | (fn << 1)), 0xCF8);
+ outb((u8)bus, 0xCFA);
+
+ switch (len) {
+ case 1:
+ outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ case 2:
+ outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ case 4:
+ outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg));
+ break;
+ }
+
+ outb (0, 0xCF8);
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+#undef PCI_CONF2_ADDRESS
+
+static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ int result;
+ u32 data;
+ result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, &data);
+ *value = (u8)data;
+ return result;
}
static int pci_conf2_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- SET(dev);
- *value = inw(IOADDR(dev->devfn,where));
- outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+ int result;
+ u32 data;
+ result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, &data);
+ *value = (u8)data;
+ return result;
}
static int pci_conf2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- SET(dev);
- *value = inl (IOADDR(dev->devfn,where));
- outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+ int result;
+ u32 data;
+ result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, &data);
+ *value = (u8)data;
+ return result;
}
static int pci_conf2_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- SET(dev);
- outb (value, IOADDR(dev->devfn,where));
- outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, value);
}
static int pci_conf2_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- SET(dev);
- outw (value, IOADDR(dev->devfn,where));
- outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, value);
}
static int pci_conf2_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- SET(dev);
- outl (value, IOADDR(dev->devfn,where));
- outb (0, 0xCF8);
- return PCIBIOS_SUCCESSFUL;
+ return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, value);
}
-#undef SET
-#undef IOADDR
-#undef FUNC
-
static struct pci_ops pci_direct_conf2 = {
pci_conf2_read_config_byte,
pci_conf2_read_config_word,
@@ -159,6 +302,7 @@ static struct pci_ops pci_direct_conf2 = {
pci_conf2_write_config_dword
};
+
/*
* Before we decide to use direct hardware access mechanisms, we try to do some
* trivial checks to ensure it at least _seems_ to be working -- we just test
@@ -420,114 +564,176 @@ static int __init pci_bios_find_device (unsigned short vendor, unsigned short de
return (int) (ret & 0xff00) >> 8;
}
+static int pci_bios_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+ unsigned long result = 0;
+ unsigned long flags;
+ unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ switch (len) {
+ case 1:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (result)
+ : "1" (PCIBIOS_READ_CONFIG_BYTE),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ case 2:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (result)
+ : "1" (PCIBIOS_READ_CONFIG_WORD),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ case 4:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (result)
+ : "1" (PCIBIOS_READ_CONFIG_DWORD),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return (int)((result & 0xff00) >> 8);
+}
+
+static int pci_bios_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+ unsigned long result = 0;
+ unsigned long flags;
+ unsigned long bx = ((bus << 8) | (dev << 3) | fn);
+
+ if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ switch (len) {
+ case 1:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=a" (result)
+ : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ case 2:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=a" (result)
+ : "0" (PCIBIOS_WRITE_CONFIG_WORD),
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ case 4:
+ __asm__("lcall (%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+ : "=a" (result)
+ : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+ "S" (&pci_indirect));
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return (int)((result & 0xff00) >> 8);
+}
+
static int pci_bios_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+ int result;
+ u32 data;
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_BYTE),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ if (!value)
+ return -EINVAL;
+
+ result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, &data);
+
+ *value = (u8)data;
+
+ return result;
}
static int pci_bios_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
+ int result;
+ u32 data;
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_WORD),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ if (!value)
+ return -EINVAL;
+
+ result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, &data);
+
+ *value = (u16)data;
+
+ return result;
}
static int pci_bios_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_DWORD),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ if (!value)
+ return -EINVAL;
+
+ return pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, value);
}
static int pci_bios_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
- "c" (value),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 1, value);
}
static int pci_bios_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_WORD),
- "c" (value),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 2, value);
}
static int pci_bios_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- unsigned long ret;
- unsigned long bx = (dev->bus->number << 8) | dev->devfn;
-
- __asm__("lcall (%%esi); cld\n\t"
- "jc 1f\n\t"
- "xor %%ah, %%ah\n"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
- "c" (value),
- "b" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- return (int) (ret & 0xff00) >> 8;
+ return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), where, 4, value);
}
+
/*
* Function table for BIOS32 access
*/
@@ -981,34 +1187,47 @@ void __init pcibios_fixup_bus(struct pci_bus *b)
pci_read_bridge_bases(b);
}
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space, but we still keep BIOS order of cards to be
- * compatible with 2.0.X. This should go away some day.
- */
-void __init pcibios_init(void)
+void __init pcibios_config_init(void)
{
- struct pci_ops *bios = NULL;
- struct pci_ops *dir = NULL;
+ /*
+ * Try all known PCI access methods. Note that we support using
+ * both PCI BIOS and direct access, with a preference for direct.
+ */
#ifdef CONFIG_PCI_BIOS
- if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
+ if ((pci_probe & PCI_PROBE_BIOS)
+ && ((pci_root_ops = pci_find_bios()))) {
pci_probe |= PCI_BIOS_SORT;
pci_bios_present = 1;
+ pci_config_read = pci_bios_read;
+ pci_config_write = pci_bios_write;
}
#endif
+
#ifdef CONFIG_PCI_DIRECT
- if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
- dir = pci_check_direct();
+ if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
+ && (pci_root_ops = pci_check_direct())) {
+ if (pci_root_ops == &pci_direct_conf1) {
+ pci_config_read = pci_conf1_read;
+ pci_config_write = pci_conf1_write;
+ }
+ else {
+ pci_config_read = pci_conf2_read;
+ pci_config_write = pci_conf2_write;
+ }
+ }
#endif
- if (dir)
- pci_root_ops = dir;
- else if (bios)
- pci_root_ops = bios;
- else {
- printk("PCI: No PCI bus detected\n");
+
+ return;
+}
+
+void __init pcibios_init(void)
+{
+ if (!pci_root_ops)
+ pcibios_config_init();
+ if (!pci_root_ops) {
+ printk("PCI: System does not support PCI\n");
return;
}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 4cbe6e15b4fb..3ab1b3a931cf 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -64,6 +64,9 @@
*
* VIA C3 Support.
* Dave Jones <davej@suse.de>, March 2001
+ *
+ * AMD Athlon/Duron/Thunderbird bluesmoke support.
+ * Dave Jones <davej@suse.de>, April 2001.
*/
/*
@@ -93,6 +96,7 @@
#include <linux/bootmem.h>
#include <asm/processor.h>
#include <linux/console.h>
+#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -145,9 +149,9 @@ struct e820map e820;
unsigned char aux_device_present;
+extern void mcheck_init(struct cpuinfo_x86 *c);
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
-extern unsigned long cpu_khz;
static int disable_x86_serial_nr __initdata = 1;
static int disable_x86_fxsr __initdata = 0;
@@ -1088,11 +1092,18 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
l2size = ecx >> 16;
/* AMD errata T13 (order #21922) */
- if (c->x86_vendor == X86_VENDOR_AMD &&
- c->x86 == 6 &&
- c->x86_model == 3 &&
- c->x86_mask == 0) {
- l2size = 64;
+ if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+ if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */
+ l2size = 64;
+ if (c->x86_model == 4 &&
+ (c->x86_mask==0 || c->x86_mask==1)) /* Tbird rev A1/A2 */
+ l2size = 256;
+ }
+
+ /* VIA C3 CPUs (670-68F) need further shifting. */
+ if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) &&
+ ((c->x86_model == 7) || (c->x86_model == 8))) {
+ l2size = l2size >> 8;
}
if ( l2size == 0 )
@@ -1109,7 +1120,7 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
* misexecution of code under Linux. Owners of such processors should
* contact AMD for precise details and a CPU swap.
*
- * See http://www.mygale.com/~poulot/k6bug.html
+ * See http://www.multimania.com/poulot/k6bug.html
* http://www.amd.com/K6/k6docs/revgd.html
*
* The following test is erm.. interesting. AMD neglected to up
@@ -1126,6 +1137,12 @@ static int __init init_amd(struct cpuinfo_x86 *c)
int mbytes = max_mapnr >> (20-PAGE_SHIFT);
int r;
+ /*
+ * FIXME: We should handle the K5 here. Set up the write
+ * range and also turn on MSR 83 bits 4 and 31 (write alloc,
+ * no bus pipeline)
+ */
+
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
@@ -1185,13 +1202,13 @@ static int __init init_amd(struct cpuinfo_x86 *c)
if(mbytes>508)
mbytes=508;
- rdmsr(0xC0000082, l, h);
+ rdmsr(MSR_K6_WHCR, l, h);
if ((l&0x0000FFFF)==0) {
unsigned long flags;
l=(1<<0)|((mbytes/4)<<1);
local_irq_save(flags);
- __asm__ __volatile__ ("wbinvd": : :"memory");
- wrmsr(0xC0000082, l, h);
+ wbinvd();
+ wrmsr(MSR_K6_WHCR, l, h);
local_irq_restore(flags);
printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
mbytes);
@@ -1206,13 +1223,13 @@ static int __init init_amd(struct cpuinfo_x86 *c)
if(mbytes>4092)
mbytes=4092;
- rdmsr(0xC0000082, l, h);
+ rdmsr(MSR_K6_WHCR, l, h);
if ((l&0xFFFF0000)==0) {
unsigned long flags;
l=((mbytes>>2)<<22)|(1<<16);
local_irq_save(flags);
- __asm__ __volatile__ ("wbinvd": : :"memory");
- wrmsr(0xC0000082, l, h);
+ wbinvd();
+ wrmsr(MSR_K6_WHCR, l, h);
local_irq_restore(flags);
printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
mbytes);
@@ -1226,10 +1243,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
break;
}
-
break;
case 6: /* An Athlon/Duron. We can trust the BIOS probably */
+ mcheck_init(c);
break;
}
@@ -1312,9 +1329,10 @@ extern void calibrate_delay(void) __init;
static void __init check_cx686_slop(struct cpuinfo_x86 *c)
{
+ unsigned long flags;
+
if (Cx86_dir0_msb == 3) {
unsigned char ccr3, ccr5;
- unsigned long flags;
local_irq_save(flags);
ccr3 = getCx86(CX86_CCR3);
@@ -1551,14 +1569,12 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
name="??";
}
- /* get FCR */
- rdmsr(0x107, lo, hi);
-
+ rdmsr(MSR_IDT_FCR1, lo, hi);
newlo=(lo|fcr_set) & (~fcr_clr);
if (newlo!=lo) {
printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
- wrmsr(0x107, newlo, hi );
+ wrmsr(MSR_IDT_FCR1, newlo, hi );
} else {
printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
}
@@ -1577,14 +1593,15 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
c->x86_cache_size = (cc>>24)+(dd>>24);
}
sprintf( c->x86_model_id, "WinChip %s", name );
+ mcheck_init(c);
break;
case 6:
switch (c->x86_model) {
case 6 ... 7: /* Cyrix III or C3 */
- rdmsr (0x1107, lo, hi);
+ rdmsr (MSR_VIA_FCR, lo, hi);
lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */
- wrmsr (0x1107, lo, hi);
+ wrmsr (MSR_VIA_FCR, lo, hi);
set_bit(X86_FEATURE_CX8, &c->x86_capability);
set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
@@ -1595,7 +1612,6 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
}
break;
}
-
}
@@ -1668,7 +1684,6 @@ static void __init init_rise(struct cpuinfo_x86 *c)
if (c->x86_model > 2)
printk(" II");
printk("\n");
- printk("If you have one of these please email davej@suse.de\n");
/* Unhide possibly hidden capability flags
The mp6 iDragon family don't have MSRs.
@@ -1694,7 +1709,6 @@ static void __init init_intel(struct cpuinfo_x86 *c)
#ifndef CONFIG_M686
static int f00f_workaround_enabled = 0;
#endif
- extern void mcheck_init(struct cpuinfo_x86 *c);
char *p = NULL;
unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
@@ -1989,9 +2003,9 @@ static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
disable_x86_serial_nr ) {
/* Disable processor serial number */
unsigned long lo,hi;
- rdmsr(0x119,lo,hi);
+ rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
lo |= 0x200000;
- wrmsr(0x119,lo,hi);
+ wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
printk(KERN_NOTICE "CPU serial number disabled.\n");
clear_bit(X86_FEATURE_PN, &c->x86_capability);
diff --git a/arch/mips64/kernel/ioctl32.c b/arch/mips64/kernel/ioctl32.c
index 9402aaaff8b0..3490c0c54cda 100644
--- a/arch/mips64/kernel/ioctl32.c
+++ b/arch/mips64/kernel/ioctl32.c
@@ -770,6 +770,8 @@ static struct ioctl32_list ioctl32_handler_table[] = {
IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans),
IOCTL32_DEFAULT(BLKELVGET),
IOCTL32_DEFAULT(BLKELVSET),
+ IOCTL32_DEFAULT(BLKBSZGET),
+ IOCTL32_DEFAULT(BLKBSZSET),
#ifdef CONFIG_MD
/* status */
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 0f47bd29c6ea..1d3702d21fe3 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.chrp_setup.c 1.32 08/20/01 22:58:32 paulus
+ * BK Id: SCCS/s.chrp_setup.c 1.34 08/29/01 10:07:29 paulus
*/
/*
* linux/arch/ppc/kernel/setup.c
@@ -78,7 +78,6 @@ extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
extern void select_adb_keyboard(void);
@@ -546,7 +545,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.kbd_translate = pckbd_translate;
ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
ppc_md.kbd_leds = pckbd_leds;
- ppc_md.kbd_rate_fn = pckbd_rate;
ppc_md.kbd_init_hw = pckbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index e038a6f21029..dfdcd728d232 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.head_8xx.S 1.19 08/16/01 23:00:17 paulus
+ * BK Id: SCCS/s.head_8xx.S 1.21 08/28/01 16:27:27 trini
*/
/*
* arch/ppc/kernel/except_8xx.S
@@ -823,8 +823,8 @@ initial_mmu:
mtspr DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr DC_CST, r8
- blr
#endif
+ blr
/*
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 0d72073c58e5..cd2a265d4b4e 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.pmac_setup.c 1.35 08/20/01 22:37:37 paulus
+ * BK Id: SCCS/s.pmac_setup.c 1.37 08/29/01 10:07:29 paulus
*/
/*
* linux/arch/ppc/kernel/setup.c
@@ -728,7 +728,6 @@ select_adb_keyboard(void)
ppc_md.kbd_setkeycode = 0;
ppc_md.kbd_getkeycode = 0;
ppc_md.kbd_leds = 0;
- ppc_md.kbd_rate_fn = 0;
#ifdef CONFIG_MAGIC_SYSRQ
#ifdef CONFIG_MAC_ADBKEYCODES
if (!keyboard_sends_linux_keycodes) {
@@ -747,7 +746,6 @@ select_adb_keyboard(void)
ppc_md.kbd_translate = mackbd_translate;
ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
ppc_md.kbd_leds = mackbd_leds;
- ppc_md.kbd_rate_fn = NULL;
ppc_md.kbd_init_hw = mackbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 9ee811f21f9a..feb7db27386f 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.prep_setup.c 1.32 08/20/01 15:06:15 paulus
+ * BK Id: SCCS/s.prep_setup.c 1.34 08/29/01 10:07:29 paulus
*/
/*
* linux/arch/ppc/kernel/setup.c
@@ -89,7 +89,6 @@ extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
@@ -955,7 +954,6 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.kbd_translate = pckbd_translate;
ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
ppc_md.kbd_leds = pckbd_leds;
- ppc_md.kbd_rate_fn = pckbd_rate;
ppc_md.kbd_init_hw = pckbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 85548b4d41df..21e02899a5fa 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -3691,6 +3691,8 @@ COMPATIBLE_IOCTL(BLKRASET)
COMPATIBLE_IOCTL(BLKFRASET)
COMPATIBLE_IOCTL(BLKSECTSET)
COMPATIBLE_IOCTL(BLKSSZGET)
+COMPATIBLE_IOCTL(BLKBSZGET)
+COMPATIBLE_IOCTL(BLKBSZSET)
/* RAID */
COMPATIBLE_IOCTL(RAID_VERSION)
diff --git a/drivers/acpi/include/platform/acgcc.h b/drivers/acpi/include/platform/acgcc.h
index 4d8d34811047..8c62e903addf 100644
--- a/drivers/acpi/include/platform/acgcc.h
+++ b/drivers/acpi/include/platform/acgcc.h
@@ -39,7 +39,6 @@
#define BREAKPOINT3
#define disable() __cli()
#define enable() __sti()
-#define wbinvd()
/*! [Begin] no source code translation */
@@ -101,7 +100,6 @@
#define disable() __cli()
#define enable() __sti()
#define halt() __asm__ __volatile__ ("sti; hlt":::"memory")
-#define wbinvd()
/*! [Begin] no source code translation
*
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index fb39eb06a454..f510b00e2c26 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -31,6 +31,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
+#include <linux/blkpg.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/locks.h>
@@ -5094,21 +5095,12 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
.nr_sects,
(long *) Argument);
case BLKRAGET:
- /* Get Read-Ahead. */
- if ((long *) Argument == NULL) return -EINVAL;
- return put_user(read_ahead[MAJOR(Inode->i_rdev)], (long *) Argument);
case BLKRASET:
- /* Set Read-Ahead. */
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (Argument > 256) return -EINVAL;
- read_ahead[MAJOR(Inode->i_rdev)] = Argument;
- return 0;
case BLKFLSBUF:
- /* Flush Buffers. */
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- fsync_dev(Inode->i_rdev);
- invalidate_buffers(Inode->i_rdev);
- return 0;
+ case BLKBSZGET:
+ case BLKBSZSET:
+ return blk_ioctl (Inode->i_rdev, Request, Argument);
+
case BLKRRPART:
/* Re-Read Partition Table. */
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
index 68240f8731e5..43f42cb65917 100644
--- a/drivers/block/blkpg.c
+++ b/drivers/block/blkpg.c
@@ -274,6 +274,29 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
return blkelvset_ioctl(&blk_get_queue(dev)->elevator,
(blkelv_ioctl_arg_t *) arg);
+ case BLKBSZGET:
+ /* get the logical block size (cf. BLKSSZGET) */
+ intval = BLOCK_SIZE;
+ if (blksize_size[MAJOR(dev)])
+ intval = blksize_size[MAJOR(dev)][MINOR(dev)];
+ return put_user (intval, (int *) arg);
+
+ case BLKBSZSET:
+ /* set the logical block size */
+ if (!capable (CAP_SYS_ADMIN))
+ return -EACCES;
+ if (!dev || !arg)
+ return -EINVAL;
+ if (get_user (intval, (int *) arg))
+ return -EFAULT;
+ if (intval > PAGE_SIZE || intval < 512 ||
+ (intval & (intval - 1)))
+ return -EINVAL;
+ if (is_mounted (dev) || is_swap_partition (dev))
+ return -EBUSY;
+ set_blocksize (dev, intval);
+ return 0;
+
default:
return -EINVAL;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 800debe3b416..0c1a044f4172 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -406,6 +406,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case BLKRRPART:
return revalidate_logvol(inode->i_rdev, 1);
case BLKFLSBUF:
+ case BLKBSZSET:
+ case BLKBSZGET:
case BLKROSET:
case BLKROGET:
case BLKRASET:
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 340dc7e65ee6..dc2287324a7e 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1266,6 +1266,8 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
}
case BLKFLSBUF:
+ case BLKBSZSET:
+ case BLKBSZGET:
case BLKROSET:
case BLKROGET:
case BLKRASET:
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 26d06cd8177a..8b4d168a5dec 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -62,6 +62,7 @@
#include <linux/major.h>
#include <linux/wait.h>
#include <linux/blk.h>
+#include <linux/blkpg.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
@@ -854,6 +855,10 @@ static int lo_ioctl(struct inode * inode, struct file * file,
}
err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg);
break;
+ case BLKBSZGET:
+ case BLKBSZSET:
+ err = blk_ioctl(inode->i_rdev, cmd, arg);
+ break;
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 0fdeccda1526..3050ba13cd7a 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -1127,6 +1127,8 @@ static int ps2esdi_ioctl(struct inode *inode,
case BLKRASET:
case BLKRAGET:
case BLKFLSBUF:
+ case BLKBSZGET:
+ case BLKBSZSET:
case BLKPG:
return blk_ioctl(inode->i_rdev, cmd, arg);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index aaf5fd51d804..4a1b3fce70a2 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -2788,6 +2788,8 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case BLKPG:
case BLKELVGET:
case BLKELVSET:
+ case BLKBSZGET:
+ case BLKBSZSET:
return blk_ioctl(inode->i_rdev, cmd, arg);
case HDIO_GET_BUSSTATE:
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6451d2ed6316..55465e4b7f89 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -15,7 +15,7 @@ O_TARGET := macintosh.o
# Objects that export symbols.
-export-objs := adb.o rtc.o mac_hid.o
+export-objs := adb.o rtc.o mac_hid.o via-pmu.o
# Object file lists.
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 6e7cff42614d..504167fe5166 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -32,24 +32,29 @@
#include <linux/pmu.h>
#include <linux/cuda.h>
#include <linux/smp_lock.h>
+#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/init.h>
#include <asm/irq.h>
#include <asm/hardirq.h>
#include <asm/feature.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
+#include <asm/cputable.h>
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
/* Some compile options */
#undef SUSPEND_USES_PMU
+#define DEBUG_SLEEP
/* Misc minor number allocated for /dev/pmu */
#define PMU_MINOR 154
@@ -102,13 +107,11 @@ static volatile enum pmu_state {
static struct adb_request *current_req;
static struct adb_request *last_req;
static struct adb_request *req_awaiting_reply;
-static unsigned char interrupt_data[256]; /* Made bigger: I've been told that might happen */
+static unsigned char interrupt_data[32];
static unsigned char *reply_ptr;
static int data_index;
static int data_len;
static volatile int adb_int_pending;
-static int pmu_adb_flags;
-static int adb_dev_map = 0;
static struct adb_request bright_req_1, bright_req_2, bright_req_3;
static struct device_node *vias;
static int pmu_kind = PMU_UNKNOWN;
@@ -118,11 +121,20 @@ static unsigned char *gpio_reg = NULL;
static int gpio_irq = -1;
static volatile int pmu_suspended = 0;
static spinlock_t pmu_lock;
+static u8 pmu_intr_mask;
+static int pmu_version;
+static int drop_interrupts;
+#ifdef CONFIG_PMAC_PBOOK
+static int sleep_in_progress;
+#endif /* CONFIG_PMAC_PBOOK */
int asleep;
struct notifier_block *sleep_notifier_list;
#ifdef CONFIG_ADB
+static int adb_dev_map = 0;
+static int pmu_adb_flags;
+
static int pmu_probe(void);
static int pmu_init(void);
static int pmu_send_request(struct adb_request *req, int sync);
@@ -163,8 +175,25 @@ struct adb_driver via_pmu_driver = {
#endif /* CONFIG_ADB */
extern void low_sleep_handler(void);
-extern void sleep_save_intrs(int);
-extern void sleep_restore_intrs(void);
+extern void pmac_sleep_save_intrs(int);
+extern void pmac_sleep_restore_intrs(void);
+extern void openpic_sleep_save_intrs(void);
+extern void openpic_sleep_restore_intrs(void);
+extern void enable_kernel_altivec(void);
+extern void enable_kernel_fp(void);
+
+#ifdef DEBUG_SLEEP
+int pmu_polled_request(struct adb_request *req);
+int pmu_wink(struct adb_request *req);
+#endif
+
+#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM)
+static int generic_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier generic_sleep_notifier = {
+ generic_notify_sleep,
+ SLEEP_LEVEL_MISC,
+};
+#endif /* defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM) */
/*
* This table indicates for each PMU opcode:
@@ -246,6 +275,11 @@ find_via_pmu()
pmu_has_adb = 1;
+ pmu_intr_mask = PMU_INT_PCEJECT |
+ PMU_INT_SNDBRT |
+ PMU_INT_ADB |
+ PMU_INT_TICK;
+
if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
|| device_is_compatible(vias->parent, "ohare")))
pmu_kind = PMU_OHARE_BASED;
@@ -258,7 +292,12 @@ find_via_pmu()
pmu_kind = PMU_KEYLARGO_BASED;
pmu_has_adb = (find_type_devices("adb") != NULL);
-
+ pmu_intr_mask = PMU_INT_PCEJECT |
+ PMU_INT_SNDBRT |
+ PMU_INT_ADB |
+ PMU_INT_TICK |
+ PMU_INT_ENVIRONMENT;
+
gpiop = find_devices("gpio");
if (gpiop && gpiop->n_addrs) {
gpio_reg = ioremap(gpiop->addrs->address, 0x10);
@@ -281,11 +320,16 @@ find_via_pmu()
return 0;
}
- printk(KERN_INFO "PMU driver initialized for %s\n",
- pbook_type[pmu_kind]);
+ printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n",
+ PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
sys_ctrler = SYS_CTRLER_PMU;
+#if defined(CONFIG_PMAC_PBOOK) && defined(CONFIG_PM)
+ pmu_register_sleep_notifier(&generic_sleep_notifier);
+ pm_active = 1;
+#endif
+
return 1;
}
@@ -367,7 +411,7 @@ init_pmu()
out_8(&via[B], via[B] | TREQ); /* negate TREQ */
out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK); /* TACK in, TREQ out */
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
timeout = 100000;
while (!req.complete) {
if (--timeout < 0) {
@@ -392,13 +436,20 @@ init_pmu()
udelay(10);
}
- /* Tell PMU we are ready. Which PMU support this ? */
+ /* Tell PMU we are ready. */
if (pmu_kind == PMU_KEYLARGO_BASED) {
pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
while (!req.complete)
pmu_poll();
}
-
+
+ /* Read PMU version */
+ pmu_request(&req, NULL, 1, PMU_GET_VERSION);
+ while (!req.complete)
+ pmu_poll();
+ if (req.reply_len > 1)
+ pmu_version = req.reply[1];
+
return 1;
}
@@ -529,7 +580,7 @@ pmu_adb_reset_bus(void)
req.done = NULL;
req.data[0] = PMU_ADB_CMD;
req.data[1] = 0;
- req.data[2] = ADB_BUSRESET; /* 3 ??? */
+ req.data[2] = ADB_BUSRESET;
req.data[3] = 0;
req.data[4] = 0;
req.reply_len = 0;
@@ -759,7 +810,7 @@ pmu_resume(void)
}
adb_int_pending = 1;
#ifdef SUSPEND_USES_PMU
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
spin_unlock_irqrestore(&pmu_lock, flags);
while(!req.complete)
pmu_poll();
@@ -789,16 +840,11 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
"intr=%x pmu_state=%d\n", intr, pmu_state);
break;
}
+ out_8(&via[IFR], intr);
if (intr & SR_INT)
pmu_sr_intr(regs);
- else if (intr & CB1_INT) {
+ else if (intr & CB1_INT)
adb_int_pending = 1;
- out_8(&via[IFR], CB1_INT);
- }
- intr &= ~(SR_INT | CB1_INT);
- if (intr != 0) {
- out_8(&via[IFR], intr);
- }
}
/* This is not necessary except if synchronous ADB requests are done
* with interrupts off, which should not happen. Since I'm not sure
@@ -846,23 +892,17 @@ pmu_sr_intr(struct pt_regs *regs)
out_8(&via[IFR], SR_INT);
return;
}
- /* This one seems to appear with PMU99. According to OF methods,
- * the protocol didn't change...
- */
- if (via[B] & TACK) {
- while ((in_8(&via[B]) & TACK) != 0)
+ /* The ack may not yet be low when we get the interrupt */
+ while ((in_8(&via[B]) & TACK) != 0)
;
- }
-
- /* reset TREQ and wait for TACK to go high */
- out_8(&via[B], in_8(&via[B]) | TREQ);
- wait_for_ack();
/* if reading grab the byte, and reset the interrupt */
if (pmu_state == reading || pmu_state == reading_intr)
bite = in_8(&via[SR]);
- out_8(&via[IFR], SR_INT);
+ /* reset TREQ and wait for TACK to go high */
+ out_8(&via[B], in_8(&via[B]) | TREQ);
+ wait_for_ack();
switch (pmu_state) {
case sending:
@@ -909,9 +949,8 @@ pmu_sr_intr(struct pt_regs *regs)
if (data_len == -1) {
data_len = bite;
if (bite > 32)
- printk(KERN_ERR "PMU: bad reply len %d\n",
- bite);
- } else {
+ printk(KERN_ERR "PMU: bad reply len %d\n", bite);
+ } else if (data_index < 32) {
reply_ptr[data_index++] = bite;
}
if (data_index < data_len) {
@@ -954,11 +993,14 @@ static void __openfirmware
pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
{
asleep = 0;
- if (len < 1) {
-// xmon_printk("empty ADB\n");
+ if (drop_interrupts || len < 1) {
adb_int_pending = 0;
return;
}
+ /* Note: for some reason, we get an interrupt with len=1,
+ * data[0]==0 after each normal ADB interrupt, at least
+ * on the Pismo. Still investigating... --BenH
+ */
if (data[0] & PMU_INT_ADB) {
if ((data[0] & PMU_INT_ADB_AUTO) == 0) {
struct adb_request *req = req_awaiting_reply;
@@ -1085,10 +1127,14 @@ pmu_restart(void)
cli();
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
- PMU_INT_TICK );
- while(!req.complete)
- pmu_poll();
+ drop_interrupts = 1;
+
+ if (pmu_kind != PMU_KEYLARGO_BASED) {
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+ PMU_INT_TICK );
+ while(!req.complete)
+ pmu_poll();
+ }
pmu_request(&req, NULL, 1, PMU_RESET);
while(!req.complete || (pmu_state != idle))
@@ -1104,10 +1150,14 @@ pmu_shutdown(void)
cli();
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
- PMU_INT_TICK );
- while(!req.complete)
- pmu_poll();
+ drop_interrupts = 1;
+
+ if (pmu_kind != PMU_KEYLARGO_BASED) {
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+ PMU_INT_TICK );
+ while(!req.complete)
+ pmu_poll();
+ }
pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
'M', 'A', 'T', 'T');
@@ -1127,6 +1177,22 @@ pmu_present(void)
static LIST_HEAD(sleep_notifiers);
+#ifdef CONFIG_PM
+static int
+generic_notify_sleep(struct pmu_sleep_notifier *self, int when)
+{
+ switch (when) {
+ case PBOOK_SLEEP_NOW:
+ if (pm_send_all(PM_SUSPEND, (void *)3))
+ return PBOOK_SLEEP_REJECT;
+ break;
+ case PBOOK_WAKE:
+ (void) pm_send_all(PM_RESUME, (void *)0);
+ }
+ return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PM */
+
int
pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
{
@@ -1268,23 +1334,42 @@ pbook_pci_restore(void)
}
}
-#if 0
+#ifdef DEBUG_SLEEP
/* N.B. This doesn't work on the 3400 */
-void pmu_blink(int n)
+void
+pmu_blink(int n)
{
struct adb_request req;
+ memset(&req, 0, sizeof(req));
+
for (; n > 0; --n) {
- pmu_request(&req, NULL, 4, 0xee, 4, 0, 1);
- while (!req.complete) pmu_poll();
- udelay(50000);
- pmu_request(&req, NULL, 4, 0xee, 4, 0, 0);
- while (!req.complete) pmu_poll();
- udelay(50000);
+ req.nbytes = 4;
+ req.done = NULL;
+ req.data[0] = 0xee;
+ req.data[1] = 4;
+ req.data[2] = 0;
+ req.data[3] = 1;
+ req.reply[0] = ADB_RET_OK;
+ req.reply_len = 1;
+ req.reply_expected = 0;
+ pmu_polled_request(&req);
+ mdelay(50);
+ req.nbytes = 4;
+ req.done = NULL;
+ req.data[0] = 0xee;
+ req.data[1] = 4;
+ req.data[2] = 0;
+ req.data[3] = 0;
+ req.reply[0] = ADB_RET_OK;
+ req.reply_len = 1;
+ req.reply_expected = 0;
+ pmu_polled_request(&req);
+ mdelay(50);
}
- udelay(150000);
+ mdelay(50);
}
-#endif
+#endif /* DEBUG_SLEEP */
/*
* Put the powerbook to sleep.
@@ -1317,7 +1402,6 @@ static void restore_via_state(void)
out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
}
-#define FEATURE_CTRL(base) ((unsigned int *)(base + 0x38))
#define GRACKLE_PM (1<<7)
#define GRACKLE_DOZE (1<<5)
#define GRACKLE_NAP (1<<4)
@@ -1363,7 +1447,8 @@ int __openfirmware powerbook_sleep_G3(void)
mb();
/* Wait for completion of async backlight requests */
- while (!bright_req_1.complete || !bright_req_2.complete || !bright_req_3.complete)
+ while (!bright_req_1.complete || !bright_req_2.complete ||
+ !bright_req_3.complete)
pmu_poll();
/* Turn off various things. Darwin does some retry tests here... */
@@ -1375,8 +1460,8 @@ int __openfirmware powerbook_sleep_G3(void)
while (!req.complete)
pmu_poll();
- /* Disable all interrupts except pmu */
- sleep_save_intrs(vias->intrs[0].line);
+ /* Disable all interrupts */
+ pmac_sleep_save_intrs(-1);
/* Make sure the PMU is idle */
while (pmu_state != idle)
@@ -1393,6 +1478,9 @@ int __openfirmware powerbook_sleep_G3(void)
if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
giveup_fpu(current);
+ /* We can now disable MSR_EE */
+ cli();
+
/* For 750, save backside cache setting and disable it */
save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */
if (save_l2cr)
@@ -1431,7 +1519,7 @@ int __openfirmware powerbook_sleep_G3(void)
_set_L2CR(save_l2cr);
/* Restore userland MMU context */
- set_context(current->mm->context);
+ set_context(current->active_mm->context, current->active_mm->pgd);
/* Re-enable DEC interrupts and kick DEC */
asm volatile("mtdec %0" : : "r" (0x7fffffff));
@@ -1464,26 +1552,29 @@ int __openfirmware powerbook_sleep_G3(void)
}
/* reenable interrupt controller */
- sleep_restore_intrs();
+ pmac_sleep_restore_intrs();
/* Leave some time for HW to settle down */
mdelay(100);
/* Notify drivers */
- mdelay(10);
broadcast_wake();
return 0;
}
-/* Not finished yet */
int __openfirmware powerbook_sleep_Core99(void)
{
- int ret;
unsigned long save_l2cr;
unsigned long wait;
struct adb_request req;
-
+ int ret, timeout;
+
+ if (!feature_can_sleep()) {
+ printk(KERN_ERR "Sleep mode not supported on this machine\n");
+ return -ENOSYS;
+ }
+
/* Notify device drivers */
ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
if (ret != PBOOK_SLEEP_OK) {
@@ -1507,81 +1598,140 @@ int __openfirmware powerbook_sleep_Core99(void)
}
/* Give the disks a little time to actually finish writing */
- for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+ for (wait = jiffies + HZ; time_before(jiffies, wait); )
mb();
+ /* Wait for completion of async backlight requests */
+ while (!bright_req_1.complete || !bright_req_2.complete ||
+ !bright_req_3.complete)
+ pmu_poll();
+
/* Tell PMU what events will wake us up */
pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
0xff, 0xff);
while (!req.complete)
pmu_poll();
+
pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
0, PMU_PWR_WAKEUP_KEY | PMU_PWR_WAKEUP_LID_OPEN);
while (!req.complete)
pmu_poll();
- /* Disable all interrupts except pmu */
- sleep_save_intrs(vias->intrs[0].line);
+ /* Save & disable all interrupts */
+ openpic_sleep_save_intrs();
+
+ /* Make sure the PMU is idle */
+ while (pmu_state != idle)
+ pmu_poll();
/* Make sure the decrementer won't interrupt us */
asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ /* Make sure any pending DEC interrupt occuring while we did
+ * the above didn't re-enable the DEC */
+ mb();
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
- /* Save the state of PCI config space for some slots */
- pbook_pci_save();
+ /* Giveup the FPU & vec */
+ enable_kernel_fp();
- feature_prepare_for_sleep();
+#ifdef CONFIG_ALTIVEC
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+ enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+ /* We can now disable MSR_EE */
+ cli();
/* For 750, save backside cache setting and disable it */
save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */
if (save_l2cr)
- _set_L2CR(0);
+ _set_L2CR(save_l2cr & 0x7fffffff);
- if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
- giveup_fpu(current);
+ /* Save the state of PCI config space for some slots */
+ //pbook_pci_save();
/* Ask the PMU to put us to sleep */
pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
- while (!req.complete)
- mb();
-
- cli();
- while (pmu_state != idle)
+ while (!req.complete && pmu_state != idle)
pmu_poll();
- /* Call low-level ASM sleep handler */
- low_sleep_handler();
+ out_8(&via[B], in_8(&via[B]) | TREQ);
+ wait_for_ack();
- /* Make sure the PMU is idle */
- while (pmu_state != idle)
- pmu_poll();
+ /* The VIA is supposed not to be restored correctly*/
+ save_via_state();
- sti();
+ /* Shut down various ASICs. There's a chance that we can no longer
+ * talk to the PMU after this, so I moved it to _after_ sending the
+ * sleep command to it. Still need to be checked.
+ */
+ feature_prepare_for_sleep();
+ /* Call low-level ASM sleep handler */
+ low_sleep_handler();
+
+ /* Restore Apple core ASICs state */
feature_wake_up();
- pbook_pci_restore();
- set_context(current->mm->context);
+ /* Restore VIA */
+ restore_via_state();
+
+ /* Restore PCI config space. This should be overridable by PCI device
+ * drivers as some of them may need special restore code. That's yet
+ * another issue that should be handled by the common code properly,
+ * maybe one day ?
+ */
+ /* Don't restore PCI for now, it crashes. Maybe unnecessary on pbook */
+ //pbook_pci_restore();
+ pmu_blink(2);
+
/* Restore L2 cache */
if (save_l2cr)
- _set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+ _set_L2CR(save_l2cr);
+
+ /* Restore userland MMU context */
+ set_context(current->active_mm->context, current->active_mm->pgd);
- /* reenable interrupts */
- sleep_restore_intrs();
+ /* Re-enable DEC interrupts and kick DEC */
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ sti();
+ asm volatile("mtdec %0" : : "r" (0x10000000));
/* Tell PMU we are ready */
pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
while (!req.complete)
pmu_poll();
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+ while (!req.complete)
+ pmu_poll();
+ /* ack all pending interrupts */
+ timeout = 100000;
+ interrupt_data[0] = 1;
+ while (interrupt_data[0] || pmu_state != idle) {
+ if (--timeout < 0)
+ break;
+ if (pmu_state == idle)
+ adb_int_pending = 1;
+ via_pmu_interrupt(0, 0, 0);
+ udelay(10);
+ }
+
+ /* reenable interrupt controller */
+ openpic_sleep_restore_intrs();
+
+ /* Leave some time for HW to settle down */
+ mdelay(100);
+
/* Notify drivers */
- mdelay(10);
broadcast_wake();
return 0;
}
-#define PB3400_MEM_CTRL ((unsigned int *)0xf8000070)
+#define PB3400_MEM_CTRL 0xf8000000
+#define PB3400_MEM_CTRL_SLEEP 0x70
int __openfirmware powerbook_sleep_3400(void)
{
@@ -1590,6 +1740,16 @@ int __openfirmware powerbook_sleep_3400(void)
unsigned int hid0;
unsigned long p, wait;
struct adb_request sleep_req;
+ char *mem_ctrl;
+ unsigned int *mem_ctrl_sleep;
+
+ /* first map in the memory controller registers */
+ mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+ if (mem_ctrl == NULL) {
+ printk("powerbook_sleep_3400: ioremap failed\n");
+ return -ENOMEM;
+ }
+ mem_ctrl_sleep = (unsigned int *) (mem_ctrl + PB3400_MEM_CTRL_SLEEP);
/* Notify device drivers */
ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
@@ -1617,11 +1777,20 @@ int __openfirmware powerbook_sleep_3400(void)
for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
mb();
+ /* Wait for completion of async backlight requests */
+ while (!bright_req_1.complete || !bright_req_2.complete ||
+ !bright_req_3.complete)
+ pmu_poll();
+
/* Disable all interrupts except pmu */
- sleep_save_intrs(vias->intrs[0].line);
+ pmac_sleep_save_intrs(vias->intrs[0].line);
/* Make sure the decrementer won't interrupt us */
asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ /* Make sure any pending DEC interrupt occuring while we did
+ * the above didn't re-enable the DEC */
+ mb();
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
/* Save the state of PCI config space for some slots */
pbook_pci_save();
@@ -1629,9 +1798,9 @@ int __openfirmware powerbook_sleep_3400(void)
/* Set the memory controller to keep the memory refreshed
while we're asleep */
for (i = 0x403f; i >= 0x4000; --i) {
- out_be32(PB3400_MEM_CTRL, i);
+ out_be32(mem_ctrl_sleep, i);
do {
- x = (in_be32(PB3400_MEM_CTRL) >> 16) & 0x3ff;
+ x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
} while (x == 0);
if (x >= 0x100)
break;
@@ -1651,32 +1820,36 @@ int __openfirmware powerbook_sleep_3400(void)
asm volatile("mfspr %0,1008" : "=r" (hid0) :);
hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
asm volatile("mtspr 1008,%0" : : "r" (hid0));
- save_flags(msr);
- msr |= MSR_POW | MSR_EE;
- restore_flags(msr);
+ _nmask_and_or_msr(0, MSR_POW | MSR_EE);
udelay(10);
/* OK, we're awake again, start restoring things */
- out_be32(PB3400_MEM_CTRL, 0x3f);
+ out_be32(mem_ctrl_sleep, 0x3f);
pbook_pci_restore();
/* wait for the PMU interrupt sequence to complete */
while (asleep)
mb();
+ /* Re-enable DEC interrupts and kick DEC */
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ sti();
+ asm volatile("mtdec %0" : : "r" (0x10000000));
+
/* reenable interrupts */
- sleep_restore_intrs();
+ pmac_sleep_restore_intrs();
/* Notify drivers */
broadcast_wake();
+ iounmap(mem_ctrl);
return 0;
}
/*
* Support for /dev/pmu device
*/
-#define RB_SIZE 10
+#define RB_SIZE 0x10
struct pmu_private {
struct list_head list;
int rb_get;
@@ -1830,6 +2003,11 @@ static int pmu_ioctl(struct inode * inode, struct file *filp,
switch (cmd) {
case PMU_IOC_SLEEP:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (sleep_in_progress)
+ return -EBUSY;
+ sleep_in_progress = 1;
switch (pmu_kind) {
case PMU_OHARE_BASED:
error = powerbook_sleep_3400();
@@ -1838,20 +2016,24 @@ static int pmu_ioctl(struct inode * inode, struct file *filp,
case PMU_PADDINGTON_BASED:
error = powerbook_sleep_G3();
break;
-#if 0 /* Not ready yet */
case PMU_KEYLARGO_BASED:
error = powerbook_sleep_Core99();
break;
-#endif
default:
error = -ENOSYS;
}
+ sleep_in_progress = 0;
return error;
+ case PMU_IOC_CAN_SLEEP:
+ return put_user(feature_can_sleep(), (__u32 *)arg);
+
#ifdef CONFIG_PMAC_BACKLIGHT
/* Backlight should have its own device or go via
* the fbdev
*/
case PMU_IOC_GET_BACKLIGHT:
+ if (sleep_in_progress)
+ return -EBUSY;
error = get_backlight_level();
if (error < 0)
return error;
@@ -1859,6 +2041,8 @@ static int pmu_ioctl(struct inode * inode, struct file *filp,
case PMU_IOC_SET_BACKLIGHT:
{
__u32 value;
+ if (sleep_in_progress)
+ return -EBUSY;
error = get_user(value, (__u32 *)arg);
if (!error)
error = set_backlight_level(value);
@@ -1893,7 +2077,7 @@ void pmu_device_init(void)
}
#endif /* CONFIG_PMAC_PBOOK */
-#if 0
+#ifdef DEBUG_SLEEP
static inline void polled_handshake(volatile unsigned char *via)
{
via[B] &= ~TREQ; eieio();
@@ -1939,6 +2123,8 @@ pmu_polled_request(struct adb_request *req)
while (pmu_state != idle)
pmu_poll();
+ while ((via[B] & TACK) == 0)
+ ;
polled_send_byte(v, c);
if (l < 0) {
l = req->nbytes - 1;
@@ -1959,4 +2145,15 @@ pmu_polled_request(struct adb_request *req)
restore_flags(flags);
return 0;
}
-#endif /* 0 */
+#endif /* DEBUG_SLEEP */
+
+EXPORT_SYMBOL(pmu_request);
+EXPORT_SYMBOL(pmu_poll);
+EXPORT_SYMBOL(pmu_suspend);
+EXPORT_SYMBOL(pmu_resume);
+#ifdef CONFIG_PMAC_PBOOK
+EXPORT_SYMBOL(pmu_register_sleep_notifier);
+EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
+EXPORT_SYMBOL(pmu_enable_irled);
+#endif /* CONFIG_PMAC_PBOOK */
+
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3a4daf75543d..5b97e8c61911 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -921,17 +921,19 @@ static int write_disk_sb(mdk_rdev_t * rdev)
dev = rdev->dev;
sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
if (rdev->sb_offset != sb_offset) {
- printk("%s's sb offset has changed from %ld to %ld, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset);
+ printk("%s's sb offset has changed from %ld to %ld, skipping\n",
+ partition_name(dev), rdev->sb_offset, sb_offset);
goto skip;
}
/*
* If the disk went offline meanwhile and it's just a spare, then
- * it's size has changed to zero silently, and the MD code does
+ * its size has changed to zero silently, and the MD code does
* not yet know that it's faulty.
*/
size = calc_dev_size(dev, rdev->mddev, 1);
if (size != rdev->size) {
- printk("%s's size has changed from %ld to %ld since import, skipping\n", partition_name(dev), rdev->size, size);
+ printk("%s's size has changed from %ld to %ld since import, skipping\n",
+ partition_name(dev), rdev->size, size);
goto skip;
}
@@ -2488,27 +2490,14 @@ static int md_ioctl (struct inode *inode, struct file *file,
(long *) arg);
goto done;
- case BLKFLSBUF:
- fsync_dev(dev);
- invalidate_buffers(dev);
- goto done;
-
+ case BLKRAGET:
case BLKRASET:
- if (arg > 0xff) {
- err = -EINVAL;
- goto abort;
- }
- read_ahead[MAJOR(dev)] = arg;
- goto done;
+ case BLKFLSBUF:
+ case BLKBSZGET:
+ case BLKBSZSET:
+ err = blk_ioctl (dev, cmd, arg);
+ goto abort;
- case BLKRAGET:
- if (!arg) {
- err = -EINVAL;
- goto abort;
- }
- err = md_put_user (read_ahead[
- MAJOR(dev)], (long *) arg);
- goto done;
default:;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index bceacf91017c..41fb53ca07c2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -162,7 +162,7 @@ static struct raid1_bh *raid1_alloc_r1bh(raid1_conf_t *conf)
conf->freer1 = r1_bh->next_r1;
conf->freer1_cnt--;
r1_bh->next_r1 = NULL;
- r1_bh->state = 0;
+ r1_bh->state = (1 << R1BH_PreAlloc);
r1_bh->bh_req.b_state = 0;
}
md_spin_unlock_irq(&conf->device_lock);
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index b37fa410cfeb..dea26603a471 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -135,8 +135,9 @@ int __init macsonic_init(struct net_device* dev)
unsigned long desc_base, desc_top;
if ((lp->sonic_desc =
kmalloc(SIZEOF_SONIC_DESC
- * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_DMA)) == NULL) {
+ * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_KERNEL | GFP_DMA)) == NULL) {
printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
+ return -ENOMEM;
}
desc_base = (unsigned long) lp->sonic_desc;
desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode);
@@ -165,7 +166,7 @@ int __init macsonic_init(struct net_device* dev)
/* FIXME, maybe we should use skbs */
if ((lp->rba = (char *)
- kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_DMA)) == NULL) {
+ kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
return -ENOMEM;
}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index bd559edd7982..60bd3f33695f 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -348,7 +348,7 @@ void inline try_get_rx_skb(struct dscc4_dev_priv *priv, int cur, struct net_devi
{
struct sk_buff *skb;
- skb = dev_alloc_skb(RX_MAX(dev->mtu+2));
+ skb = dev_alloc_skb(RX_MAX(HDLC_MAX_MRU+2));
priv->rx_skbuff[cur] = skb;
if (!skb) {
priv->rx_fd[cur--].data = (u32) NULL;
@@ -428,9 +428,9 @@ static __inline__ void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, int cur,
int pkt_len;
skb = dpriv->rx_skbuff[cur];
- pkt_len = TO_SIZE(rx_fd->state2);
- pci_dma_sync_single(pdev, rx_fd->data, pkt_len, PCI_DMA_FROMDEVICE);
- if((skb->data[pkt_len - 1] & FrameOk) == FrameOk) {
+ pkt_len = TO_SIZE(rx_fd->state2) - 1;
+ pci_dma_sync_single(pdev, rx_fd->data, pkt_len + 1, PCI_DMA_FROMDEVICE);
+ if((skb->data[pkt_len] & FrameOk) == FrameOk) {
pci_unmap_single(pdev, rx_fd->data, skb->len, PCI_DMA_FROMDEVICE);
dpriv->stats.rx_packets++;
dpriv->stats.rx_bytes += pkt_len;
@@ -442,11 +442,11 @@ static __inline__ void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, int cur,
netif_rx(skb);
try_get_rx_skb(dpriv, cur, dev);
} else {
- if(skb->data[pkt_len - 1] & FrameRdo)
+ if(skb->data[pkt_len] & FrameRdo)
dpriv->stats.rx_fifo_errors++;
- else if(!(skb->data[pkt_len - 1] | ~FrameCrc))
+ else if(!(skb->data[pkt_len] | ~FrameCrc))
dpriv->stats.rx_crc_errors++;
- else if(!(skb->data[pkt_len - 1] | ~FrameVfr))
+ else if(!(skb->data[pkt_len] | ~FrameVfr))
dpriv->stats.rx_length_errors++;
else
dpriv->stats.rx_errors++;
@@ -760,7 +760,7 @@ static int dscc4_open(struct net_device *dev)
/* FIXME: VIS */
writel(readl(ioaddr + CCR0) | 0x80001000, ioaddr + CCR0);
- writel(LengthCheck | (dev->mtu >> 5), ioaddr + RLCR);
+ writel(LengthCheck | (HDLC_MAX_MRU >> 5), ioaddr + RLCR);
/* no address recognition/crc-CCITT/cts enabled */
writel(readl(ioaddr + CCR1) | 0x021c8000, ioaddr + CCR1);
@@ -1224,7 +1224,7 @@ try:
dev->name, SOURCE_ID(state), state );
return;
}
- if (state & 0x0df80c01) {
+ if (state & 0x0df80c00) {
printk(KERN_DEBUG "%s (Tx): state=%08x (UFO alert)\n",
dev->name, state);
return;
@@ -1377,7 +1377,7 @@ try:
dev->name, SOURCE_ID(state), state);
goto try;
}
- if (state & 0x0df80c01) {
+ if (state & 0x0df80c00) {
printk(KERN_DEBUG "%s (Rx): state=%08x (UFO alert)\n",
dev->name, state);
goto try;
@@ -1609,7 +1609,7 @@ static int dscc4_init_ring(struct net_device *dev)
rx_fd->state1 = HiDesc; /* Hi, no Hold */
rx_fd->state2 = 0x00000000;
rx_fd->end = 0xbabeface;
- rx_fd->state1 |= ((u32)(dev->mtu & RxSizeMax)) << 16;
+ rx_fd->state1 |= ((u32)(HDLC_MAX_MRU & RxSizeMax)) << 16;
try_get_rx_skb(dpriv, i, dev);
i++;
rx_fd->next = (u32)(dpriv->rx_fd_dma + i*sizeof(struct RxFD));
@@ -1720,7 +1720,7 @@ static int dscc4_attach_hdlc_device(struct net_device *dev)
hdlc = &dpriv->hdlc;
/* XXX: Don't look at the next line */
hdlc->netdev.base_addr = (unsigned long)dev;
- // FIXME: set hdlc->set_mode ?
+ hdlc->set_mode = NULL;
hdlc->open = dscc4_hdlc_open;
hdlc->close = dscc4_hdlc_close;
hdlc->ioctl = dscc4_hdlc_ioctl;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a8b1377f5160..f8fcbe5b5a03 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -307,8 +307,8 @@ pci_set_power_state(struct pci_dev *dev, int state)
/**
* pci_save_state - save the PCI configuration space of a device before suspending
- * @dev - PCI device that we're dealing with
- * @buffer - buffer to hold config space context
+ * @dev: - PCI device that we're dealing with
+ * @buffer: - buffer to hold config space context
*
* @buffer must be large enough to hold the entire PCI 2.2 config space
* (>= 64 bytes).
@@ -327,8 +327,8 @@ pci_save_state(struct pci_dev *dev, u32 *buffer)
/**
* pci_restore_state - Restore the saved state of a PCI device
- * @dev - PCI device that we're dealing with
- * @buffer - saved PCI config space
+ * @dev: - PCI device that we're dealing with
+ * @buffer: - saved PCI config space
*
*/
int
@@ -489,6 +489,7 @@ void pci_release_regions(struct pci_dev *pdev)
/**
* pci_request_regions - Reserved PCI I/O and memory resources
* @pdev: PCI device whose resources are to be reserved
+ * @res_name: Name to be associated with resource.
*
* Mark all PCI regions associated with PCI device @pdev as
* being reserved by owner @res_name. Do not access any
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
index 6303192b2b81..c72c4ca43b0f 100644
--- a/drivers/pcmcia/yenta.c
+++ b/drivers/pcmcia/yenta.c
@@ -702,6 +702,12 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
u32 start, end;
u32 align, size, min, max;
unsigned offset;
+ unsigned mask;
+
+ /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
+ mask = ~0xfff;
+ if (type & IORESOURCE_IO)
+ mask = ~3;
offset = 0x1c + 8*nr;
bus = socket->dev->subordinate;
@@ -715,8 +721,8 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
if (!root)
return;
- start = config_readl(socket, offset);
- end = config_readl(socket, offset+4) | 0xfff;
+ start = config_readl(socket, offset) & mask;
+ end = config_readl(socket, offset+4) | ~mask;
if (start && end > start) {
res->start = start;
res->end = end;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 57f1817c1443..0e1e0ab1f8d6 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -238,8 +238,10 @@ static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd,
case BLKFLSBUF:
case BLKSSZGET:
case BLKPG:
- case BLKELVGET:
- case BLKELVSET:
+ case BLKELVGET:
+ case BLKELVSET:
+ case BLKBSZGET:
+ case BLKBSZSET:
return blk_ioctl(inode->i_rdev, cmd, arg);
case BLKRRPART: /* Re-read partition tables */
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index e085396c7fc9..d2c623a50e9d 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -64,7 +64,6 @@ comment 'USB Controllers'
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
comment 'USB Network adaptors'
- dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
dep_tristate ' USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3789e22a08ba..ddb549b0c346 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -60,7 +60,6 @@ obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
-obj-$(CONFIG_USB_PLUSB) += plusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
diff --git a/drivers/usb/plusb.c b/drivers/usb/plusb.c
deleted file mode 100644
index 6d92d5dddc5d..000000000000
--- a/drivers/usb/plusb.c
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*****************************************************************************/
-
-/*
- * plusb.c -- prolific pl-2301/pl-2302 driver.
- *
- * Copyright (C) 2000 Deti Fliegl (deti@fliegl.de)
- * Copyright (C) 2000 Pavel Machek (pavel@suse.cz)
- * Copyright (C) 2000 Eric Z. Ayers (eric@compgen.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * This driver creates a network interface (plusb0, plusb1, ...) that will
- * send messages over a USB host-host cable based on the Prolific ASIC.
- * It works a lot like plip or PP over an RS-232C null modem cable.
- *
- * Expect speeds of around 330Kbytes/second over a UHCI host controller.
- * OHCI should be faster. Increase the MTU for faster transfers of large
- * files (up-to 800Kbytes/second). (16384 is a good size)
- *
- * $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $
- *
- * Changelog:
- *
- * v0.1 deti
- * Original Version of driver.
- * v0.2 15 Sep 2000 pavel
- * Patches to decrease latency by rescheduling the bottom half of
- * interrupt code.
- * v0.3 10 Oct 2000 eric
- * Patches to work in v2.2 backport (v2.4 changes the way net_dev.name
- * is allocated)
- * v0.4 19 Oct 2000 eric
- * Some more performance fixes. Lock re-submitting urbs.
- * Lower the number of sk_buff's to queue.
- * v0.5 25 Oct 2000 eric
- * Removed use of usb_bulk_msg() all together. This caused
- * the driver to block in an interrupt context.
- * Consolidate read urb submission into read_urb_submit().
- * Performance is the same as v0.4.
- * v0.5.1 27 Oct 2000 eric
- * Extra debugging messages to help diagnose problem with uchi.o stack.
- * v0.5.2 27 Oct 2000 eric
- * Set the 'start' flag for the network device in plusb_net_start()
- * and plusb_net_stop() (doesn't help)
- * v0.5.3 27 Oct 2000 pavel
- * Commented out handlers when -EPIPE is received,
- * (remove calls to usb_clear_halt()) Since the callback is in
- * an interrupt context, it doesn't help, it just panics
- * the kernel. (what do we do?)
- * Under high load, dev_alloc_skb() fails, the read URB must
- * be re-submitted.
- * Added plusb_change_mtu() and increased the size of _BULK_DATA_LEN
- * v0.5.4 31 Oct 2000 eric
- * Fix race between plusb_net_xmit() and plusb_bulk_write_complete()
- * v0.5.5 1 Nov 2000 eric
- * Remove dev->start field, otherwise, it won't compile in 2.4
- * Use dev_kfree_skb_any(). (important in 2.4 kernel)
- * v0.5.6 2 Nov 2000 pavel,eric
- * Add calls to netif_stop_queue() and netif_start_queue()
- * Drop packets that come in while the free list is empty.
- * (This version is being submitted after the release of 2.4-test10)
- * v0.5.7 6 Nov 2000
- * Fix to not re-submit the urb on error to help when cables
- * are yanked (not tested)
- *
- *
- * KNOWN PROBLEMS: (Any suggestions greatfully accepted!)
- *
- * 2 Nov 2000
- * - The shutdown for this may not be entirely clean. Sometimes, the
- * kernel will Oops when the cable is unplugged, or
- * if the plusb module is removed.
- * - If you ifdown a device and then ifup it again, the link will not
- * always work. You have to 'rmmod plusb ; modprobe plusb' on
- * both machines to get it to work again. Something must be wrong with
- * plusb_net_open() and plusb_net_start() ? Maybe
- * the 'suspend' and 'resume' entry points need to be
- * implemented?
- * - Needs to handle -EPIPE correctly in bulk complete handlers.
- * (replace usb_clear_halt() function with async urbs?)
- * - I think this code relies too much on one spinlock and does
- * too much in the interrupt handler. The net1080 code is
- * much more elegant, and should work for this chip. Its
- * only drawback is that it is going to be tough to backport
- * it to v2.2.
- * - Occasionally the device will hang under the 'uhci.o'
- * driver. The workaround is to ifdown the device and
- * remove the modules, then re-insert them. You may have
- * better luck with the 'usb-uhci.o' driver.
- * - After using ifconfig down ; ifconfig up, sometimes packets
- * continue to be received, but there is a framing problem.
- *
- * FUTURE DIRECTIONS:
- *
- * - Fix the known problems.
- * - There isn't much functional difference between the net1080
- * driver and this one. It would be neat if the same driver
- * could handle both types of chips. Or if both drivers
- * could handle both types of chips - this one is easier to
- * backport to the 2.2 kernel.
- * - Get rid of plusb_add_buf_tail and the single spinlock.
- * Use a separate spinlock for the 2 lists, and use atomic
- * operators for writeurb_submitted and readurb_submitted members.
- *
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-//#define DEBUG 1
-#include <linux/usb.h>
-
-#if (LINUX_VERSION_CODE < 0x020300)
-#define dev_kfree_skb_any dev_kfree_skb
-#endif
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.5.7"
-#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
-#define DRIVER_DESC "PL-2302 USB Interface Driver for Linux (c)2000"
-
-/* Definitions formerly in plusb.h relocated. No need to export them -EZA */
-
-#define _PLUSB_INTPIPE 0x1
-#define _PLUSB_BULKOUTPIPE 0x2
-#define _PLUSB_BULKINPIPE 0x3
-
-#define _SKB_NUM 32
-
-/* increase size of BULK_DATA_LEN so we can use bigger MTU's*/
-#define _BULK_DATA_LEN 32768
-
-
-typedef struct
-{
- int connected; /* indicates if this structure is active */
- struct usb_device *usbdev;
- /* keep track of USB structure */
- int status; /* Prolific status byte returned from interrupt */
- int in_bh; /* flag to indicate that we are in the bulk handler */
- int opened; /* flag to indicate that network dev is open */
-
- spinlock_t lock; /* Lock for the buffer list. re-used for
- locking around submitting the readurb member.
- */
- urb_t *inturb; /* Read buffer for the interrupt callback */
- unsigned char * interrupt_in_buffer;
- /* holds data for the inturb*/
- urb_t *readurb; /* Read buffer for the bulk data callback */
- unsigned char * bulk_in_buffer;
- /* kmalloc'ed data for the readurb */
- int readurb_submitted;
- /* Flag to indicate that readurb already sent */
- urb_t *writeurb; /* Write buffer for the bulk data callback */
- int writeurb_submitted;
- /* Flag to indicate that writeurb already sent */
-
- struct list_head tx_skb_list;
- /* sk_buff's read from net device */
- struct list_head free_skb_list;
- /* free sk_buff list */
- struct net_device net_dev;
- /* handle to linux network device */
- struct net_device_stats net_stats;
- /* stats to return for ifconfig output */
-} plusb_t,*pplusb_t;
-
-/*
- * skb_list - queue of packets from the network driver to be delivered to USB
- */
-typedef struct
-{
- struct list_head skb_list;
- struct sk_buff *skb;
- int state;
- plusb_t *s;
-} skb_list_t,*pskb_list_t;
-
-
-/* --------------------------------------------------------------------- */
-
-#define NRPLUSB 4
-
-/*
- * Interrupt endpoint status byte, from Prolific PL-2301 docs
- * Check the 'download' link at www.prolifictech.com
- */
-#define _PL_INT_RES1 0x80 /* reserved */
-#define _PL_INT_RES2 0x40 /* reserved */
-#define _PL_INT_RXD _PL_INT_RES2 /* Read data ready - Not documented by Prolific, but seems to work! */
-#define _PL_INT_TX_RDY 0x20 /* OK to transmit data */
-#define _PL_INT_RESET_O 0x10 /* reset output pipe */
-#define _PL_INT_RESET_I 0x08 /* reset input pipe */
-#define _PL_INT_TX_C 0x04 /* transmission complete */
-#define _PL_INT_TX_REQ 0x02 /* transmission received */
-#define _PL_INT_PEER_E 0x01 /* peer exists */
-
-/*-------------------------------------------------------------------*/
-
-static plusb_t plusb[NRPLUSB];
-
-static void plusb_write_bulk_complete(urb_t *purb);
-static void plusb_read_bulk_complete(urb_t *purb);
-static void plusb_int_complete(urb_t *purb);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_add_buf_tail - Take the head of the src list and append it to
- * the tail of the dest list
- */
-static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_head *src)
-{
- unsigned long flags = 0;
- struct list_head *tmp;
- int ret = 0;
-
- spin_lock_irqsave (&s->lock, flags);
-
- if (list_empty (src)) {
- // no elements in source buffer
- ret = -1;
- goto err;
- }
- tmp = src->next;
- list_del (tmp);
- list_add_tail (tmp, dst);
-
- err: spin_unlock_irqrestore (&s->lock, flags);
- return ret;
-}
-/*-------------------------------------------------------------------*/
-
-/*
- * dequeue_next_skb - submit the first thing on the tx_skb_list to the
- * USB stack. This function should be called each time we get a new
- * message to send to the other host, or each time a message is successfully
- * sent.
- */
-static void dequeue_next_skb(char * func, plusb_t * s)
-{
- skb_list_t * skb_list;
- unsigned long flags = 0;
-
- if (!s->connected)
- return;
-
- spin_lock_irqsave (&s->lock, flags);
-
- if (!list_empty (&s->tx_skb_list) && !s->writeurb_submitted) {
- int submit_ret;
- skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list);
-
- if (skb_list->skb) {
- s->writeurb_submitted = 1;
-
- /* Use the buffer inside the sk_buff directly. why copy? */
- FILL_BULK_URB_TO(s->writeurb, s->usbdev,
- usb_sndbulkpipe(s->usbdev, _PLUSB_BULKOUTPIPE),
- skb_list->skb->data, skb_list->skb->len,
- plusb_write_bulk_complete, skb_list, 500);
-
- dbg ("%s: %s: submitting urb. skb_list %p", s->net_dev.name, func, skb_list);
-
- submit_ret = usb_submit_urb(s->writeurb);
- if (submit_ret) {
- s->writeurb_submitted = 0;
- printk (KERN_CRIT "%s: %s: can't submit writeurb: %d\n",
- s->net_dev.name, func, submit_ret);
- }
- } /* end if the skb value has been filled in */
- }
-
- spin_unlock_irqrestore (&s->lock, flags);
-}
-
-/*
- * submit_read_urb - re-submit the read URB to the stack
- */
-void submit_read_urb(char * func, plusb_t * s)
-{
- unsigned long flags=0;
-
- if (!s->connected)
- return;
-
- spin_lock_irqsave (&s->lock, flags);
-
- if (!s->readurb_submitted) {
- int ret;
- s->readurb_submitted=1;
- s->readurb->dev=s->usbdev;
- ret = usb_submit_urb(s->readurb);
- if (ret) {
- printk (KERN_CRIT "%s: %s: error %d submitting read URB\n",
- s->net_dev.name, func, ret);
- s->readurb_submitted=0;
- }
- }
-
- spin_unlock_irqrestore (&s->lock, flags);
-
-}
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_net_xmit - callback from the network device driver for outgoing data
- *
- * Data has arrived to the network device from the local machine and needs
- * to be sent over the USB cable. This is in an interrupt, so we don't
- * want to spend too much time in this function.
- *
- */
-static int plusb_net_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- plusb_t *s=dev->priv;
- skb_list_t *skb_list;
- unsigned int flags;
-
- dbg("plusb_net_xmit: len:%d i:%d",skb->len,in_interrupt());
-
- if(!s->connected || !s->opened) {
- /*
- NOTE: If we get to this point, you'll return the error
- kernel: virtual device plusb0 asks to queue packet
-
- Other things we could do:
- 1) just drop this packet
- 2) drop other packets in the queue
- */
- return 1;
- }
-
- spin_lock_irqsave (&s->lock, flags);
-
- if (list_empty(&s->free_skb_list)
- || plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list)) {
- /* The buffers on this side are full. DROP the packet
- I think that this shouldn't happen with the correct
- use of the netif_XXX functions -EZA
- */
- dbg ("plusb: Free list is empty.");
- kfree_skb(skb);
- s->net_stats.tx_dropped++;
- spin_unlock_irqrestore (&s->lock, flags);
- return 0;
- }
-
- skb_list = list_entry (s->tx_skb_list.prev, skb_list_t, skb_list);
- skb_list->skb=skb;
- skb_list->state=1;
- skb_list->s=s;
-
- if (list_empty(&s->free_skb_list)) {
- /* apply "backpressure". Tell the net layer to stop sending
- the driver packets.
- */
- netif_stop_queue(dev);
- }
-
- spin_unlock_irqrestore (&s->lock, flags);
-
- /* If there is no write urb outstanding, pull the first thing
- off of the list and submit it to the USB stack
- */
- dequeue_next_skb("plusb_net_xmit", s);
-
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * plusb_write_bulk_complete () - callback after the data has been
- * sent to the USB device, or a timeout occurred.
- */
-static void plusb_write_bulk_complete(urb_t *purb)
-{
- skb_list_t * skb_list=purb->context;
- plusb_t *s=skb_list->s;
-
- dbg ("%s: plusb_write_bulk_complete: status:%d skb_list:%p\n",
- s->net_dev.name, purb->status, skb_list);
-
- skb_list->state=0;
-
- if( purb->status == -EPIPE )
- printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n",
- s->net_dev.name);
-
- if(!purb->status) {
- s->net_stats.tx_packets++;
- s->net_stats.tx_bytes+=skb_list->skb->len;
- }
- else {
- err ("%s: plusb_write_bulk_complete: returned ERROR status:%d\n",
- s->net_dev.name, purb->status);
-
- s->net_stats.tx_errors++;
- s->net_stats.tx_aborted_errors++;
- }
-
- dbg("plusb_bh: dev_kfree_skb");
-
- /* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ:
- Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a
- */
- dev_kfree_skb_any(skb_list->skb);
-
- skb_list->skb = NULL;
- if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) {
- err ("plusb: tx list empty. This shouldn't happen.");
- }
-
- purb->status = 0;
- s->writeurb_submitted = 0;
-
- netif_wake_queue((&s->net_dev));
-
- dequeue_next_skb("plusb_write_bulk_complete", s);
-
-
-}
-
-/*
- * plusb_read_bulk_complete - Callback for data arriving from the USB device
- *
- * This gets called back when a full 'urb' is received from the remote system.
- * This urb was allocated by this driver and is kept in the member: s->readurb
- *
- */
-static void plusb_read_bulk_complete(urb_t *purb)
-{
-
- plusb_t *s=purb->context;
-
- dbg("plusb_read_bulk_complete: status:%d length:%d", purb->status,purb->actual_length);
-
- if(!s->connected)
- return;
-
- if( purb->status == -EPIPE )
- printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n",
- s->net_dev.name);
- else if (!purb->status) {
- struct sk_buff *skb;
- unsigned char *dst;
- int len=purb->transfer_buffer_length;
- struct net_device_stats *stats=&s->net_stats;
-
- skb=dev_alloc_skb(len);
-
- if(!skb) {
- printk (KERN_CRIT "%s: plusb_read_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame\n", s->net_dev.name, len);
- stats->rx_dropped++;
- } else {
- dst=(char *)skb_put(skb, len);
- memcpy( dst, purb->transfer_buffer, len);
-
- skb->dev=&s->net_dev;
- skb->protocol=eth_type_trans(skb, skb->dev);
- stats->rx_packets++;
- stats->rx_bytes+=len;
- netif_rx(skb);
- }
-
- }
-
- s->readurb_submitted = 0;
-
- if (purb->status) {
- /* Give the system a chance to "catch its breath". Shortcut
- re-submitting the read URB> It will be re-submitted if
- another interrupt comes back. The problem scenario is that
- the plub is pulled and the read returns an error.
- You don't want to resumbit in this case.
- */
- err ("%s: plusb_read_bulk_complete: returned status %d\n",
- s->net_dev.name, purb->status);
- return;
- }
-
-
- purb->status=0;
-
- /* Keep it coming! resubmit the URB for reading.. Make sure
- we aren't in contention with the interrupt callback.
- */
- submit_read_urb("plusb_read_bulk_complete", s);
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * plusb_int_complete - USB driver callback for interrupt msg from the device
- *
- * Interrupts are scheduled to go off on a periodic basis (see FILL_INT_URB)
- * For the prolific device, this is basically just returning a register
- * filled with bits. See the macro definitions for _PL_INT_XXX above.
- * Most of these bits are for implementing a machine-machine protocol
- * and can be set with a special message (described as the "Quicklink"
- * feature in the prolific documentation.)
- *
- * I don't think we need any of that to work as a network device. If a
- * message is lost, big deal - that's what UNIX networking expects from
- * the physical layer.
- *
- */
-static void plusb_int_complete(urb_t *purb)
-{
- plusb_t *s=purb->context;
- s->status=((unsigned char*)purb->transfer_buffer)[0]&255;
-
-#if 0
- /* This isn't right because 0x20 is TX_RDY and
- sometimes will not be set
- */
- if((s->status&0x3f)!=0x20) {
- warn("invalid device status %02X", s->status);
- return;
- }
-#endif
- if(!s->connected)
- return;
-
- /* Don't turn this on unless you want to see the log flooded. */
-#if 0
- printk("plusb_int_complete: PEER_E:%d TX_REQ:%d TX_C:%d RESET_IN:%d RESET_O: %d TX_RDY:%d RES1:%d RES2:%d\n",
- s->status & _PL_INT_PEER_E ? 1 : 0,
- s->status & _PL_INT_TX_REQ ? 1 : 0,
- s->status & _PL_INT_TX_C ? 1 : 0,
- s->status & _PL_INT_RESET_I ? 1 : 0,
- s->status & _PL_INT_RESET_O ? 1 : 0,
- s->status & _PL_INT_TX_RDY ? 1 : 0,
- s->status & _PL_INT_RES1 ? 1 : 0,
- s->status & _PL_INT_RES2 ? 1 : 0);
-#endif
-
-#if 1
- /* At first glance, this logic appears to not really be needed, but
- it can help recover from intermittent problems where the
- usb_submit_urb() fails in the read callback. -EZA
- */
-
- /* Try to submit the read URB again. Make sure
- we aren't in contention with the bulk read callback
- */
- submit_read_urb ("plusb_int_complete", s);
-
- /* While we are at it, why not check to see if the
- write urb should be re-submitted?
- */
- dequeue_next_skb("plusb_int_complete", s);
-
-#endif
-
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * plusb_free_all - deallocate all memory kept for an instance of the device.
- */
-static void plusb_free_all(plusb_t *s)
-{
- struct list_head *skb;
- skb_list_t *skb_list;
-
- dbg("plusb_free_all");
-
- /* set a flag to tell all callbacks to cease and desist */
- s->connected = 0;
-
- /* If the interrupt handler is about to fire, let it finish up */
- run_task_queue(&tq_immediate);
-
- if(s->inturb) {
- dbg("unlink inturb");
- usb_unlink_urb(s->inturb);
- dbg("free_urb inturb");
- usb_free_urb(s->inturb);
- s->inturb=NULL;
- }
-
- if(s->interrupt_in_buffer) {
- dbg("kfree s->interrupt_in_buffer");
- kfree(s->interrupt_in_buffer);
- s->interrupt_in_buffer=NULL;
- }
-
- if(s->readurb) {
- dbg("unlink readurb");
- usb_unlink_urb(s->readurb);
- dbg("free_urb readurb:");
- usb_free_urb(s->readurb);
- s->readurb=NULL;
- }
-
- if(s->bulk_in_buffer) {
- dbg("kfree s->bulk_in_buffer");
- kfree(s->bulk_in_buffer);
- s->bulk_in_buffer=NULL;
- }
-
- s->readurb_submitted = 0;
-
- if(s->writeurb) {
- dbg("unlink writeurb");
- usb_unlink_urb(s->writeurb);
- dbg("free_urb writeurb:");
- usb_free_urb(s->writeurb);
- s->writeurb=NULL;
- }
-
- s->writeurb_submitted = 0;
-
- while(!list_empty(&s->free_skb_list)) {
- skb=s->free_skb_list.next;
- list_del(skb);
- skb_list = list_entry (skb, skb_list_t, skb_list);
- kfree(skb_list);
- }
-
- while(!list_empty(&s->tx_skb_list)) {
- skb=s->tx_skb_list.next;
- list_del(skb);
- skb_list = list_entry (skb, skb_list_t, skb_list);
- if (skb_list->skb) {
- dbg ("Freeing SKB in queue");
- dev_kfree_skb_any(skb_list->skb);
- skb_list->skb = NULL;
- }
- kfree(skb_list);
- }
-
- s->in_bh=0;
-
- dbg("plusb_free_all: finished");
-}
-
-/*-------------------------------------------------------------------*/
-/*
- * plusb_alloc - allocate memory associated with one instance of the device
- */
-static int plusb_alloc(plusb_t *s)
-{
- int i;
- skb_list_t *skb;
-
- dbg("plusb_alloc");
-
- for(i=0 ; i < _SKB_NUM ; i++) {
- skb=kmalloc(sizeof(skb_list_t), GFP_KERNEL);
- if(!skb) {
- err("kmalloc for skb_list failed");
- goto reject;
- }
- memset(skb, 0, sizeof(skb_list_t));
- list_add(&skb->skb_list, &s->free_skb_list);
- }
-
- dbg("inturb allocation:");
- s->inturb=usb_alloc_urb(0);
- if(!s->inturb) {
- err("alloc_urb failed");
- goto reject;
- }
-
- dbg("bulk read urb allocation:");
- s->readurb=usb_alloc_urb(0);
- if(!s->readurb) {
- err("alloc_urb failed");
- goto reject;
- }
-
- dbg("bulk write urb allocation:");
- s->writeurb=usb_alloc_urb(0);
- if(!s->writeurb) {
- err("alloc_urb for writeurb failed");
- goto reject;
- }
-
- dbg("readurb/inturb init:");
- s->interrupt_in_buffer=kmalloc(64, GFP_KERNEL);
- if(!s->interrupt_in_buffer) {
- err("kmalloc failed");
- goto reject;
- }
-
- /* The original value of '10' makes this interrupt fire off a LOT.
- It was set so low because the callback determined when to
- sumbit the buld read URB. I've lowered it to 100 - the driver
- doesn't depend on that logic anymore. -EZA
- */
- FILL_INT_URB(s->inturb, s->usbdev,
- usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE),
- s->interrupt_in_buffer, 1,
- plusb_int_complete, s, HZ);
-
- dbg("inturb submission:");
- if(usb_submit_urb(s->inturb)<0) {
- err("usb_submit_urb failed");
- goto reject;
- }
-
- dbg("readurb init:");
- s->bulk_in_buffer = kmalloc(_BULK_DATA_LEN, GFP_KERNEL);
- if (!s->bulk_in_buffer) {
- err("kmalloc %d bytes for bulk in buffer failed", _BULK_DATA_LEN);
- }
-
- FILL_BULK_URB(s->readurb, s->usbdev,
- usb_rcvbulkpipe(s->usbdev, _PLUSB_BULKINPIPE),
- s->bulk_in_buffer, _BULK_DATA_LEN,
- plusb_read_bulk_complete, s);
-
- /* The write urb will be initialized inside the network
- interrupt.
- */
-
- /* get the bulk read going */
- submit_read_urb("plusb_alloc", s);
-
- dbg ("plusb_alloc: finished. readurb=%p writeurb=%p inturb=%p",
- s->readurb, s->writeurb, s->inturb);
-
- return 0;
-
- reject:
- dbg("plusb_alloc: failed");
-
- plusb_free_all(s);
- return -ENOMEM;
-}
-
-/*-------------------------------------------------------------------*/
-
-static int plusb_net_open(struct net_device *dev)
-{
- plusb_t *s=dev->priv;
-
- dbg("plusb_net_open");
-
- if(plusb_alloc(s))
- return -ENOMEM;
-
- s->opened=1;
-
- MOD_INC_USE_COUNT;
-
- netif_start_queue(dev);
-
- dbg("plusb_net_open: success");
-
- return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-static int plusb_net_stop(struct net_device *dev)
-{
- plusb_t *s=dev->priv;
-
- netif_stop_queue(dev);
-
- dbg("plusb_net_stop");
-
- s->opened=0;
- plusb_free_all(s);
-
- MOD_DEC_USE_COUNT;
- dbg("plusb_net_stop:finished");
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static struct net_device_stats *plusb_net_get_stats(struct net_device *dev)
-{
- plusb_t *s=dev->priv;
-
- dbg("net_device_stats");
-
- return &s->net_stats;
-}
-
-/* --------------------------------------------------------------------- */
-
-static plusb_t *plusb_find_struct (void)
-{
- int u;
-
- for (u = 0; u < NRPLUSB; u++) {
- plusb_t *s = &plusb[u];
- if (!s->connected)
- return s;
- }
- return NULL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void plusb_disconnect (struct usb_device *usbdev, void *ptr)
-{
- plusb_t *s = ptr;
-
- dbg("plusb_disconnect");
-
- plusb_free_all(s);
-
- if(!s->opened && s->net_dev.name) {
- dbg("unregistering netdev: %s",s->net_dev.name);
- unregister_netdev(&s->net_dev);
- s->net_dev.name[0] = '\0';
-#if (LINUX_VERSION_CODE < 0x020300)
- dbg("plusb_disconnect: About to free name");
- kfree (s->net_dev.name);
- s->net_dev.name = NULL;
-#endif
- }
-
- dbg("plusb_disconnect: finished");
- MOD_DEC_USE_COUNT;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int plusb_change_mtu(struct net_device *dev, int new_mtu)
-{
- if ((new_mtu < 68) || (new_mtu > _BULK_DATA_LEN))
- return -EINVAL;
-
- printk("plusb: changing mtu to %d\n", new_mtu);
- dev->mtu = new_mtu;
-
- /* NOTE: Could we change the size of the READ URB here dynamically
- to save kernel memory?
- */
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-int plusb_net_init(struct net_device *dev)
-{
- dbg("plusb_net_init");
-
- dev->open=plusb_net_open;
- dev->stop=plusb_net_stop;
- dev->hard_start_xmit=plusb_net_xmit;
- dev->get_stats = plusb_net_get_stats;
- ether_setup(dev);
- dev->change_mtu = plusb_change_mtu;
- /* Setting the default MTU to 16K gives good performance for
- me, and keeps the ping latency low too. Setting it up
- to 32K made performance go down. -EZA
- Pavel says it would be best not to do this...
- */
- /*dev->mtu=16384; */
- dev->tx_queue_len = 0;
- dev->flags = IFF_POINTOPOINT|IFF_NOARP;
-
-
- dbg("plusb_net_init: finished");
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void *plusb_probe (struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id)
-{
- plusb_t *s;
-
- dbg("plusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-
- if (usbdev->descriptor.idVendor != 0x067b || usbdev->descriptor.idProduct > 0x1)
- return NULL;
-
- /* We don't handle multiple configurations */
- if (usbdev->descriptor.bNumConfigurations != 1)
- return NULL;
-
- s = plusb_find_struct ();
- if (!s)
- return NULL;
-
- s->usbdev = usbdev;
-
- if (usb_set_configuration (s->usbdev, usbdev->config[0].bConfigurationValue) < 0) {
- err("set_configuration failed");
- return NULL;
- }
-
- if (usb_set_interface (s->usbdev, 0, 0) < 0) {
- err("set_interface failed");
- return NULL;
- }
-
-#if (LINUX_VERSION_CODE < 0x020300)
- {
- int i;
-
- /* For Kernel version 2.2, the driver is responsible for
- allocating this memory. For version 2.4, the rules
- have apparently changed, but there is a nifty function
- 'init_netdev' that might make this easier... It's in
- ../net/net_init.c - but can we get there from here? (no)
- -EZA
- */
-
- /* Find the device number... we seem to have lost it... -EZA */
- for (i=0; i<NRPLUSB; i++) {
- if (&plusb[i] == s)
- break;
- }
-
- if(!s->net_dev.name) {
- s->net_dev.name = kmalloc(strlen("plusbXXXX"), GFP_KERNEL);
- sprintf (s->net_dev.name, "plusb%d", i);
- s->net_dev.init=plusb_net_init;
- s->net_dev.priv=s;
-
- printk ("plusb_probe: Registering Device\n");
- if(!register_netdev(&s->net_dev))
- info("registered: %s", s->net_dev.name);
- else {
- err("register_netdev failed");
- s->net_dev.name[0] = '\0';
- }
- dbg ("plusb_probe: Connected!");
- }
- }
-#else
- /* Kernel version 2.3+ works a little bit differently than 2.2 */
- if(!s->net_dev.name[0]) {
- strcpy(s->net_dev.name, "plusb%d");
- s->net_dev.init=plusb_net_init;
- s->net_dev.priv=s;
- if(!register_netdev(&s->net_dev))
- info("registered: %s", s->net_dev.name);
- else {
- err("register_netdev failed");
- s->net_dev.name[0] = '\0';
- }
- }
-#endif
-
- s->connected = 1;
-
- if(s->opened) {
- dbg("net device already allocated, restarting USB transfers");
- plusb_alloc(s);
- }
-
- info("bound to interface: %d dev: %p", ifnum, usbdev);
- MOD_INC_USE_COUNT;
- return s;
-}
-/* --------------------------------------------------------------------- */
-
-static struct usb_driver plusb_driver =
-{
- name: "plusb",
- probe: plusb_probe,
- disconnect: plusb_disconnect,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int __init plusb_init (void)
-{
- unsigned u;
- dbg("plusb_init");
-
- /* initialize struct */
- for (u = 0; u < NRPLUSB; u++) {
- plusb_t *s = &plusb[u];
- memset (s, 0, sizeof (plusb_t));
- INIT_LIST_HEAD (&s->tx_skb_list);
- INIT_LIST_HEAD (&s->free_skb_list);
- spin_lock_init (&s->lock);
- }
-
- /* register misc device */
- usb_register (&plusb_driver);
-
- dbg("plusb_init: driver registered");
-
- info(DRIVER_VERSION ":" DRIVER_DESC);
-
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void __exit plusb_cleanup (void)
-{
- unsigned u;
-
- dbg("plusb_cleanup");
- for (u = 0; u < NRPLUSB; u++) {
- plusb_t *s = &plusb[u];
-#if (LINUX_VERSION_CODE < 0x020300)
- if(s->net_dev.name) {
- dbg("unregistering netdev: %s",s->net_dev.name);
- unregister_netdev(&s->net_dev);
- s->net_dev.name[0] = '\0';
- kfree (s->net_dev.name);
- s->net_dev.name = NULL;
- }
-#else
- if(s->net_dev.name[0]) {
- dbg("unregistering netdev: %s",s->net_dev.name);
- unregister_netdev(&s->net_dev);
- s->net_dev.name[0] = '\0';
- }
-#endif
- }
- usb_deregister (&plusb_driver);
- dbg("plusb_cleanup: finished");
-}
-
-/* --------------------------------------------------------------------- */
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-
-
-module_init (plusb_init);
-module_exit (plusb_cleanup);
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index b8271eca56c9..b691bcd05956 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -269,6 +269,7 @@ static int usblp_release(struct inode *inode, struct file *file)
struct usblp *usblp = file->private_data;
down (&usblp->sem);
+ lock_kernel();
usblp->used = 0;
if (usblp->dev) {
if (usblp->bidir)
@@ -277,6 +278,7 @@ static int usblp_release(struct inode *inode, struct file *file)
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
+ unlock_kernel();
return 0;
}
@@ -685,11 +687,9 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
BUG ();
}
-
down (&usblp->sem);
lock_kernel();
usblp->dev = NULL;
- unlock_kernel();
usb_unlink_urb(&usblp->writeurb);
if (usblp->bidir)
@@ -699,6 +699,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
usblp_cleanup (usblp);
else /* cleanup later, on close */
up (&usblp->sem);
+ unlock_kernel();
}
static struct usb_device_id usblp_ids [] = {
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 9bacf95547fe..8a6a731cfab2 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -96,7 +96,7 @@ UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
#endif
/* This entry is from Andries.Brouwer@cwi.nl */
-UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0205,
+UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208,
"SCM Microsystems",
"eUSB SmartMedia / CompactFlash Adapter",
US_SC_SCSI, US_PR_DPCM_USB, NULL,
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index d388ac1a3a83..3e63e5d73056 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -33,7 +33,7 @@
#define dac_val (0x3c9)
#define VGA_FB_PHYS 0xA0000
-#define VGA_FB_PHYS_LEN 65535
+#define VGA_FB_PHYS_LEN 65536
/* --------------------------------------------------------------------- */
diff --git a/fs/Makefile b/fs/Makefile
index 41265f21614f..d70410913702 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -32,6 +32,7 @@ subdir-$(CONFIG_RAMFS) += ramfs
subdir-$(CONFIG_CODA_FS) += coda
subdir-$(CONFIG_MINIX_FS) += minix
subdir-$(CONFIG_FAT_FS) += fat
+subdir-$(CONFIG_UMSDOS_FS) += umsdos
subdir-$(CONFIG_MSDOS_FS) += msdos
subdir-$(CONFIG_VFAT_FS) += vfat
subdir-$(CONFIG_BFS_FS) += bfs
@@ -43,7 +44,6 @@ subdir-$(CONFIG_NFS_FS) += nfs
subdir-$(CONFIG_NFSD) += nfsd
subdir-$(CONFIG_LOCKD) += lockd
subdir-$(CONFIG_NLS) += nls
-subdir-$(CONFIG_UMSDOS_FS) += umsdos
subdir-$(CONFIG_SYSV_FS) += sysv
subdir-$(CONFIG_SMB_FS) += smbfs
subdir-$(CONFIG_NCP_FS) += ncpfs
diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt
index 9c09891de727..14643c738f6e 100644
--- a/fs/umsdos/README-WIP.txt
+++ b/fs/umsdos/README-WIP.txt
@@ -5,18 +5,11 @@ Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing
There is no warning any more.
Both read-only and read-write stuff is fixed, both in
msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-There are still few hardlink nuisances, but those are not fatal.
-
-I'd call it pre-release, and ask for as many people as possible to
-come and test it! See notes below for some more information, or if
-you are trying to use UMSDOS as root partition.
Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
-will compile and work on 2.2.x kernels and glibc based systems may be found
-at http://cvs.linux.hr/
-
-Also look at the quick-hack "homepage" for umsdos filesystem at
-http://www.voyager.hr/~mnalis/umsdos
+will compile and work on 2.2.x+ kernels and glibc based systems, as well as
+kernel patches and other umsdos related information may be found at
+http://linux.voyager.hr/umsdos/
Information below is getting outdated slowly -- I'll fix it one day when I
get enough time - there are more important things to fix right now.
@@ -24,7 +17,7 @@ get enough time - there are more important things to fix right now.
Legend: those lines marked with '+' on the beggining of line indicates it
passed all of my tests, and performed perfect in all of them.
-Current status (990202) - UMSDOS 0.85:
+Current status (010125) - UMSDOS 0.86j:
(1) pure MSDOS (no --linux-.--- EMD file):
@@ -35,7 +28,7 @@ READ:
WRITE:
+ creat file - works
-+ delete file - works
++ unlink file - works
+ write file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
@@ -66,21 +59,22 @@ READ:
WRITE:
+ create symlink - works
-- create hardlink - works
++ create hardlink - works
+ create file - works
+ create special file - works
+ write to file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
-- rename hardlink (same dir) -
-- rename hardlink (dif. dir) -
++ rename hardlink (same dir) - works
+- rename hardlink (dif. dir) - works, but see notes below.
+ rename symlink (same dir) - works
+ rename symlink (dif. dir) - works
+ rename dir (same dir) - works
+ rename dir (dif. dir) - works
-+ delete file - works
++ unlink file - works
+ notify_change (chown,perms) - works
-+ delete hardlink - works
++ notify_change for hardlinks - works
++ unlink hardlink - works
+ mkdir - works
+ rmdir - works
+ umssyncing (many ioctls) - works
@@ -99,24 +93,11 @@ in filesystems that might be externally modified like umsdos. There is
example is specs file about it. Specifically, moving directory which
contains hardlinks will break them.
-Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
-partition (with linux installed in c:\linux) it will boot, but there may be
-some problems. Volunteers ready to test pseudoroot are needed (preferably
-ones with working backups or unimportant data). For example, '/DOS' pseudo
-directory is only partially re-implemented and buggy. It works most of the
-time, though. Update: should work ok in 0.84, although it still does not
-work correctly in combination with initrd featere. Working on this!
-
Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
-
-Warning: (about hardlinks) - modifying hardlinks (esp. if they are in
-different directories) are currently somewhat broken, I'm working on it.
-Problem seems to be that code uses and updates EMD of directory where 'real
-hardlink' is stored, not EMD of directory where our pseudo-hardlink is
-located! I'm looking for ideas how to work around this in clean way, since
-without it modifying hardlinks in any but most simple ways is broken!
+See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade
+procedure if you used broken versions...
------------------------------------------------------------------------------
@@ -130,6 +111,4 @@ or panics which force you to reboot etc.)
I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do
check for messages having "UMSDOS" in the subject, and read them. I might
miss some in all that volume, though. I should reply to any direct e-mail
-in few days. If I don't, probably I never got your message. You can try
-mnalis-umsdos@voyager.hr; however mnalis@jagor.srce.hr is preferable.
-
+in few days. If I don't, probably I never got your message.
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c
index 50a9459b6268..b2a140ce0127 100644
--- a/fs/umsdos/dir.c
+++ b/fs/umsdos/dir.c
@@ -651,13 +651,13 @@ char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
old_root = dget(current->fs->root);
read_unlock(&current->fs->lock);
spin_lock(&dcache_lock);
- path = __d_path(dentry, NULL, dentry->d_sb->s_root, NULL, buffer, len);
+ path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */
spin_unlock(&dcache_lock);
if (*path == '/')
path++; /* skip leading '/' */
- if (old_root->d_inode == pseudo_root)
+ if (current->fs->root->d_inode == pseudo_root)
{
*(path-1) = '/';
path -= (UMSDOS_PSDROOT_LEN+1);
diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c
index c1bf4e1dd2ce..51d76ca24009 100644
--- a/fs/umsdos/emd.c
+++ b/fs/umsdos/emd.c
@@ -18,7 +18,21 @@
#include <linux/pagemap.h>
#include <linux/delay.h>
-static void copy_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
+void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q)
+{
+ p->name_len = q->name_len;
+ p->flags = q->flags;
+ p->nlink = cpu_to_le16(q->nlink);
+ p->uid = cpu_to_le16(q->uid);
+ p->gid = cpu_to_le16(q->gid);
+ p->atime = cpu_to_le32(q->atime);
+ p->mtime = cpu_to_le32(q->mtime);
+ p->ctime = cpu_to_le32(q->ctime);
+ p->rdev = cpu_to_le16(q->rdev);
+ p->mode = cpu_to_le16(q->mode);
+}
+
+static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
{
p->name_len = q->name_len;
p->name[p->name_len]='\0';
@@ -136,6 +150,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di
printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len);
p->name_len = 0;
ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */
+ /* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */
}
recsize = umsdos_evalrecsize(p->name_len);
@@ -163,7 +178,7 @@ int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_di
page_cache_release(page2);
} else
memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare);
- copy_entry(entry, p);
+ get_entry(entry, p);
kunmap(page);
page_cache_release(page);
*pos += recsize;
@@ -249,16 +264,7 @@ int umsdos_writeentry (struct dentry *parent, struct umsdos_info *info,
offs+info->recsize-PAGE_CACHE_SIZE);
if (ret)
goto out_unlock3;
- p->name_len = entry->name_len;
- p->flags = entry->flags;
- p->nlink = cpu_to_le16(entry->nlink);
- p->uid = cpu_to_le16(entry->uid);
- p->gid = cpu_to_le16(entry->gid);
- p->atime = cpu_to_le32(entry->atime);
- p->mtime = cpu_to_le32(entry->mtime);
- p->ctime = cpu_to_le32(entry->ctime);
- p->rdev = cpu_to_le16(entry->rdev);
- p->mode = cpu_to_le16(entry->mode);
+ put_entry (p, entry);
memcpy(p->spare,entry->spare,
(char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare);
memcpy(page_address(page2),
@@ -279,16 +285,7 @@ int umsdos_writeentry (struct dentry *parent, struct umsdos_info *info,
offs + info->recsize);
if (ret)
goto out_unlock;
- p->name_len = entry->name_len;
- p->flags = entry->flags;
- p->nlink = cpu_to_le16(entry->nlink);
- p->uid = cpu_to_le16(entry->uid);
- p->gid = cpu_to_le16(entry->gid);
- p->atime = cpu_to_le32(entry->atime);
- p->mtime = cpu_to_le32(entry->mtime);
- p->ctime = cpu_to_le32(entry->ctime);
- p->rdev = cpu_to_le16(entry->rdev);
- p->mode = cpu_to_le16(entry->mode);
+ put_entry (p, entry);
memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare);
ret = mapping->a_ops->commit_write(NULL,page,offs,
offs + info->recsize);
@@ -463,7 +460,7 @@ static int umsdos_find (struct dentry *demd, struct umsdos_info *info)
goto skip_it;
info->f_pos = pos;
- copy_entry(entry, rentry);
+ get_entry(entry, rentry);
ret = 0;
break;
skip_it:
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index ff765811c9f3..9a47f8cd388e 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -38,7 +38,7 @@ void UMSDOS_put_inode (struct inode *inode)
,atomic_read(&inode->i_count)));
if (inode == pseudo_root) {
- printk (KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count));
+ Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count)));
}
if (atomic_read(&inode->i_count) == 1)
@@ -49,7 +49,7 @@ void UMSDOS_put_inode (struct inode *inode)
void UMSDOS_put_super (struct super_block *sb)
{
Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
- if (saved_root) {
+ if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) {
shrink_dcache_parent(saved_root);
dput(saved_root);
saved_root = NULL;
@@ -153,16 +153,56 @@ dentry, f_pos));
}
-int umsdos_notify_change_locked(struct dentry *, struct iattr *);
/*
* lock the parent dir before starting ...
+ * also handles hardlink converting
*/
int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
{
- struct inode *dir = dentry->d_parent->d_inode;
- struct inode *inode = dentry->d_inode;
+ struct inode *dir, *inode;
+ struct umsdos_info info;
+ struct dentry *temp, *old_dentry = NULL;
int ret;
+ ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len,
+ &info);
+ if (ret)
+ goto out;
+ ret = umsdos_findentry (dentry->d_parent, &info, 0);
+ if (ret) {
+printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, ret);
+ goto out;
+ }
+
+ if (info.entry.flags & UMSDOS_HLINK) {
+ /*
+ * In order to get the correct (real) inode, we just drop
+ * the original dentry.
+ */
+ d_drop(dentry);
+Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname));
+
+ /* Do a real lookup to get the short name dentry */
+ temp = umsdos_covered(dentry->d_parent, info.fake.fname,
+ info.fake.len);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out;
+
+ /* now resolve the link ... */
+ temp = umsdos_solve_hlink(temp);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out;
+ old_dentry = dentry;
+ dentry = temp; /* so umsdos_notify_change_locked will operate on that */
+ }
+
+ dir = dentry->d_parent->d_inode;
+ inode = dentry->d_inode;
+
ret = inode_change_ok (inode, attr);
if (ret)
goto out;
@@ -173,9 +213,12 @@ int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
if (ret == 0)
inode_setattr (inode, attr);
out:
+ if (old_dentry)
+ dput (dentry); /* if we had to use fake dentry for hardlinks, dput() it now */
return ret;
}
+
/*
* Must be called with the parent lock held.
*/
@@ -316,16 +359,16 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
struct super_block *res;
struct dentry *new_root;
- MSDOS_SB(sb)->options.isvfat = 0;
/*
* Call msdos-fs to mount the disk.
* Note: this returns res == sb or NULL
*/
res = msdos_read_super (sb, data, silent);
+
if (!res)
goto out_fail;
- printk (KERN_INFO "UMSDOS 0.86i "
+ printk (KERN_INFO "UMSDOS 0.86k "
"(compatibility level %d.%d, fast msdos)\n",
UMSDOS_VERSION, UMSDOS_RELEASE);
@@ -334,6 +377,7 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
/* install our dentry operations ... */
sb->s_root->d_op = &umsdos_dentry_operations;
+
umsdos_patch_dentry_inode(sb->s_root, 0);
/* Check whether to change to the /linux root */
@@ -345,10 +389,9 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
printk("umsdos_read_super: pseudo-root wrong ops!\n");
pseudo_root = new_root->d_inode;
-
saved_root = sb->s_root;
- sb->s_root = new_root;
printk(KERN_INFO "UMSDOS: changed to alternate root\n");
+ dget (sb->s_root); sb->s_root = dget(new_root);
}
return sb;
@@ -381,10 +424,12 @@ static struct dentry *check_pseudo_root(struct super_block *sb)
root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN);
if (IS_ERR(root))
goto out_noroot;
+
if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode))
goto out_dput;
- printk(KERN_INFO "check_pseudo_root: found %s/%s\n", root->d_parent->d_name.name, root->d_name.name);
+printk(KERN_INFO "check_pseudo_root: found %s/%s\n",
+root->d_parent->d_name.name, root->d_name.name);
/* look for /sbin/init */
sbin = lookup_one_len("sbin", root, 4);
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
index e6f9c3f94807..9049610da7ac 100644
--- a/fs/umsdos/namei.c
+++ b/fs/umsdos/namei.c
@@ -405,8 +405,15 @@ static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry,
goto out_unlock;
/* make sure it's the same inode! */
ret = -ENOENT;
- if (old->d_inode != old_inode)
- goto out_dput;
+ /*
+ * note: for hardlinks they will be different!
+ * old_inode will contain inode of .LINKxxx file containing data, and
+ * old->d_inode will contain inode of file containing path to .LINKxxx file
+ */
+ if (!(old_info.entry.flags & UMSDOS_HLINK)) {
+ if (old->d_inode != old_inode)
+ goto out_dput;
+ }
new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname,
new_info.fake.len);
@@ -531,7 +538,7 @@ int UMSDOS_link (struct dentry *olddentry, struct inode *dir,
struct umsdos_info hid_info;
#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_link: new %s%s -> %s/%s\n",
+printk("umsdos_link: new %s/%s -> %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
olddentry->d_parent->d_name.name, olddentry->d_name.name);
#endif
@@ -698,17 +705,36 @@ out_unlock:
if (ret == 0) {
struct iattr newattrs;
+ /* Do a real lookup to get the short name dentry */
+ temp = umsdos_covered(olddentry->d_parent,
+ old_info.fake.fname,
+ old_info.fake.len);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out_unlock2;
+
+ /* now resolve the link ... */
+ temp = umsdos_solve_hlink(temp);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out_unlock2;
+
+
#ifdef UMSDOS_PARANOIA
if (!oldinode->u.umsdos_i.i_is_hlink)
printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
#endif
- oldinode->i_nlink++;
+ temp->d_inode->i_nlink++;
Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
olddentry->d_parent->d_name.name, olddentry->d_name.name,
oldinode->i_ino, oldinode->i_nlink));
newattrs.ia_valid = 0;
- ret = umsdos_notify_change_locked(olddentry, &newattrs);
+ ret = umsdos_notify_change_locked(temp, &newattrs);
+ if (ret == 0)
+ mark_inode_dirty(temp->d_inode);
+ dput(temp);
+out_unlock2:
if (ret == 0)
mark_inode_dirty(olddentry->d_inode);
}
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
index 192009aa56f5..9fbca3941934 100644
--- a/fs/umsdos/rdir.c
+++ b/fs/umsdos/rdir.c
@@ -111,6 +111,9 @@ struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int
*/
Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name));
+/* only patch if needed (because we get called even for lookup
+ (not only rlookup) stuff sometimes, like in umsdos_covered() */
+ if (dentry->d_inode->u.umsdos_i.i_patched == 0)
umsdos_patch_dentry_inode(dentry, 0);
}
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index c99045972cf3..cdedca57e80c 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -130,7 +130,7 @@ asmlinkage void call_##x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $"#v"\n\t" \
+ "pushl $"#v"-256\n\t" \
SAVE_ALL \
SYMBOL_NAME_STR(call_##x)":\n\t" \
"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
@@ -143,7 +143,7 @@ asmlinkage void call_##x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $"#v"\n\t" \
+ "pushl $"#v"-256\n\t" \
SAVE_ALL \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 72bf155e92ca..11bcb7f29e42 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -1,3 +1,6 @@
+#ifndef __ASM_MSR_H
+#define __ASM_MSR_H
+
/*
* Access to machine-specific registers (available on 586 and better only)
* Note: the rd* operations modify the parameters directly (without using
@@ -5,9 +8,9 @@
*/
#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
@@ -18,10 +21,10 @@
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define rdtscl(low) \
- __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
+ __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
#define rdtscll(val) \
- __asm__ __volatile__ ("rdtsc" : "=A" (val))
+ __asm__ __volatile__("rdtsc" : "=A" (val))
#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
@@ -31,6 +34,71 @@
: "c" (counter))
/* symbolic names for some interesting MSRs */
-#define MSR_IA32_PLATFORM_ID 0x17
-#define MSR_IA32_UCODE_WRITE 0x79
-#define MSR_IA32_UCODE_REV 0x8B
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR 0
+#define MSR_IA32_P5_MC_TYPE 1
+#define MSR_IA32_PLATFORM_ID 0x17
+#define MSR_IA32_EBL_CR_POWERON 0x2a
+
+#define MSR_IA32_APICBASE 0x1b
+#define MSR_IA32_APICBASE_BSP (1<<8)
+#define MSR_IA32_APICBASE_ENABLE (1<<11)
+#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
+
+#define MSR_IA32_UCODE_WRITE 0x79
+#define MSR_IA32_UCODE_REV 0x8b
+
+#define MSR_IA32_PERFCTR0 0xc1
+#define MSR_IA32_PERFCTR1 0xc2
+
+#define MSR_IA32_BBL_CR_CTL 0x119
+
+#define MSR_IA32_MCG_CAP 0x179
+#define MSR_IA32_MCG_STATUS 0x17a
+#define MSR_IA32_MCG_CTL 0x17b
+
+#define MSR_IA32_EVNTSEL0 0x186
+#define MSR_IA32_EVNTSEL1 0x187
+
+#define MSR_IA32_DEBUGCTLMSR 0x1d9
+#define MSR_IA32_LASTBRANCHFROMIP 0x1db
+#define MSR_IA32_LASTBRANCHTOIP 0x1dc
+#define MSR_IA32_LASTINTFROMIP 0x1dd
+#define MSR_IA32_LASTINTTOIP 0x1de
+
+#define MSR_IA32_MC0_CTL 0x400
+#define MSR_IA32_MC0_STATUS 0x401
+#define MSR_IA32_MC0_ADDR 0x402
+#define MSR_IA32_MC0_MISC 0x403
+
+/* AMD Defined MSRs */
+#define MSR_K6_EFER 0xC0000080
+#define MSR_K6_STAR 0xC0000081
+#define MSR_K6_WHCR 0xC0000082
+#define MSR_K6_UWCCR 0xC0000085
+#define MSR_K6_PSOR 0xC0000087
+#define MSR_K6_PFIR 0xC0000088
+
+#define MSR_K7_EVNTSEL0 0xC0010000
+#define MSR_K7_PERFCTR0 0xC0010004
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1 0x107
+#define MSR_IDT_FCR2 0x108
+#define MSR_IDT_FCR3 0x109
+#define MSR_IDT_FCR4 0x10a
+
+#define MSR_IDT_MCR0 0x110
+#define MSR_IDT_MCR1 0x111
+#define MSR_IDT_MCR2 0x112
+#define MSR_IDT_MCR3 0x113
+#define MSR_IDT_MCR4 0x114
+#define MSR_IDT_MCR5 0x115
+#define MSR_IDT_MCR6 0x116
+#define MSR_IDT_MCR7 0x117
+#define MSR_IDT_MCR_CTRL 0x120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR 0x1107
+
+#endif /* __ASM_MSR_H */
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 6f2f63a8e3d3..932aa29c5f49 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -110,10 +110,23 @@ static inline unsigned long _get_base(char * addr)
})
#define write_cr0(x) \
__asm__("movl %0,%%cr0": :"r" (x));
+
+#define read_cr4() ({ \
+ unsigned int __dummy; \
+ __asm__( \
+ "movl %%cr4,%0\n\t" \
+ :"=r" (__dummy)); \
+ __dummy; \
+})
+#define write_cr4(x) \
+ __asm__("movl %0,%%cr4": :"r" (x));
#define stts() write_cr0(8 | read_cr0())
#endif /* __KERNEL__ */
+#define wbinvd() \
+ __asm__ __volatile__ ("wbinvd": : :"memory");
+
static inline unsigned long get_limit(unsigned long segment)
{
unsigned long __limit;
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index 1cb3b96b471a..97099dd0d414 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -45,4 +45,6 @@ static inline cycles_t get_cycles (void)
#endif
}
+extern unsigned long cpu_khz;
+
#endif
diff --git a/include/asm-ppc/keyboard.h b/include/asm-ppc/keyboard.h
index 4cc11f04d47e..d8e414c84cb3 100644
--- a/include/asm-ppc/keyboard.h
+++ b/include/asm-ppc/keyboard.h
@@ -1,5 +1,5 @@
/*
- * BK Id: %F% %I% %G% %U% %#%
+ * BK Id: SCCS/s.keyboard.h 1.11 08/29/01 10:07:29 paulus
*/
/*
* linux/include/asm-ppc/keyboard.h
@@ -75,7 +75,6 @@ static inline void kbd_init_hw(void)
ppc_md.kbd_init_hw();
}
-#define kbd_rate (ppc_md.kbd_rate_fn)
#define kbd_sysrq_xlate (ppc_md.ppc_kbd_sysrq_xlate)
extern unsigned long SYSRQ_KEY;
diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h
index b5243504f2ca..af0439610908 100644
--- a/include/asm-ppc/kmap_types.h
+++ b/include/asm-ppc/kmap_types.h
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.kmap_types.h 1.6 05/17/01 18:14:24 cort
+ * BK Id: SCCS/s.kmap_types.h 1.9 08/29/01 14:03:05 paulus
*/
#ifdef __KERNEL__
#ifndef _ASM_KMAP_TYPES_H
@@ -10,6 +10,8 @@ enum km_type {
KM_BOUNCE_WRITE,
KM_SKB_DATA,
KM_SKB_DATA_SOFTIRQ,
+ KM_USER0,
+ KM_USER1,
KM_TYPE_NR
};
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index 2862d8c89c7b..5f3cb66dd81c 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.machdep.h 1.19 08/18/01 18:16:33 paulus
+ * BK Id: SCCS/s.machdep.h 1.21 08/29/01 10:07:29 paulus
*/
#ifdef __KERNEL__
#ifndef _PPC_MACHDEP_H
@@ -14,7 +14,6 @@
struct pt_regs;
struct pci_bus;
struct pci_dev;
-struct kbd_repeat;
struct machdep_calls {
void (*setup_arch)(void);
@@ -61,7 +60,6 @@ struct machdep_calls {
char raw_mode);
char (*kbd_unexpected_up)(unsigned char keycode);
void (*kbd_leds)(unsigned char leds);
- int (*kbd_rate_fn)(struct kbd_repeat *rep);
void (*kbd_init_hw)(void);
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char *ppc_kbd_sysrq_xlate;
@@ -74,6 +72,10 @@ struct machdep_calls {
/* Called after scanning the bus, before allocating resources */
void (*pcibios_fixup)(void);
+ /* Called after PPC generic resource fixup to perform
+ machine specific fixups */
+ void (*pcibios_fixup_resources)(struct pci_dev *);
+
/* Called for each PCI bus in the system when it's probed */
void (*pcibios_fixup_bus)(struct pci_bus *);
@@ -82,6 +84,13 @@ struct machdep_calls {
* Returns 0 to allow assignment/enabling of the device. */
int (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
+ /* For interrupt routing */
+ unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *);
+ int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char);
+
+ /* Called in indirect_* to avoid touching devices */
+ int (*pci_exclude_device)(unsigned char, unsigned char);
+
/* Called at then very end of pcibios_init() */
void (*pcibios_after_init)(void);
diff --git a/include/asm-sparc/kmap_types.h b/include/asm-sparc/kmap_types.h
index 3388fa5bcd3a..82af4b9e8379 100644
--- a/include/asm-sparc/kmap_types.h
+++ b/include/asm-sparc/kmap_types.h
@@ -6,6 +6,8 @@ enum km_type {
KM_BOUNCE_WRITE,
KM_SKB_DATA,
KM_SKB_DATA_SOFTIRQ,
+ KM_USER0,
+ KM_USER1,
KM_TYPE_NR
};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8d70498784f5..1a8efa4044ea 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -182,7 +182,9 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
/* This was here just to show that the number is taken -
probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
#endif
-
+/* A jump here: 108-111 have been used for various private purposes. */
+#define BLKBSZGET _IOR(0x12,112,sizeof(int))
+#define BLKBSZSET _IOW(0x12,113,sizeof(int))
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index cd1ac601af84..1186ebc301a8 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -7,6 +7,9 @@
*/
#include <linux/config.h>
+
+#define PMU_DRIVER_VERSION 2
+
/*
* PMU commands
*/
@@ -23,6 +26,7 @@
#define PMU_GET_VOLBUTTON 0x48 /* get volume up/down position */
#define PMU_PCEJECT 0x4c /* eject PC-card from slot */
#define PMU_BATTERY_STATE 0x6b /* report battery state etc. */
+#define PMU_SMART_BATTERY_STATE 0x6f /* report battery state (new way) */
#define PMU_SET_INTR_MASK 0x70 /* set PMU interrupt mask */
#define PMU_INT_ACK 0x78 /* read interrupt bits */
#define PMU_SHUTDOWN 0x7e /* turn power off */
@@ -32,6 +36,7 @@
#define PMU_GET_BRIGHTBUTTON 0xd9 /* report brightness up/down pos */
#define PMU_GET_COVER 0xdc /* report cover open/closed */
#define PMU_SYSTEM_READY 0xdf /* tell PMU we are awake */
+#define PMU_GET_VERSION 0xea /* read the PMU version */
/* Bits to use with the PMU_POWER_CTRL0 command */
#define PMU_POW0_ON 0x80 /* OR this to power ON the device */
@@ -46,16 +51,23 @@
#define PMU_POW_IRLED 0x04 /* IR led power (on wallstreet) */
#define PMU_POW_MEDIABAY 0x08 /* media bay power (wallstreet/lombard ?) */
-
/* Bits in PMU interrupt and interrupt mask bytes */
-#define PMU_INT_ADB_AUTO 0x04 /* ADB autopoll, when PMU_INT_ADB */
#define PMU_INT_PCEJECT 0x04 /* PC-card eject buttons */
#define PMU_INT_SNDBRT 0x08 /* sound/brightness up/down buttons */
#define PMU_INT_ADB 0x10 /* ADB autopoll or reply data */
-#define PMU_INT_BATTERY 0x20
-#define PMU_INT_WAKEUP 0x40
+#define PMU_INT_BATTERY 0x20 /* Battery state change */
+#define PMU_INT_ENVIRONMENT 0x40 /* Environment interrupts */
#define PMU_INT_TICK 0x80 /* 1-second tick interrupt */
+/* Other bits in PMU interrupt valid when PMU_INT_ADB is set */
+#define PMU_INT_ADB_AUTO 0x04 /* ADB autopoll, when PMU_INT_ADB */
+#define PMU_INT_WAITING_CHARGER 0x01 /* ??? */
+#define PMU_INT_AUTO_SRQ_POLL 0x02 /* ??? */
+
+/* Bits in the environement message (either obtained via PMU_GET_COVER,
+ * or via PMU_INT_ENVIRONMENT on core99 */
+#define PMU_ENV_LID_CLOSED 0x01 /* The lid is closed */
+
/* Kind of PMU (model) */
enum {
PMU_UNKNOWN,
@@ -99,6 +111,8 @@ enum {
#define PMU_IOC_GET_MODEL _IOR('B', 3, sizeof(__u32*))
/* out param: u32* has_adb: 0 or 1 */
#define PMU_IOC_HAS_ADB _IOR('B', 4, sizeof(__u32*))
+/* out param: u32* can_sleep: 0 or 1 */
+#define PMU_IOC_CAN_SLEEP _IOR('B', 5, sizeof(__u32*))
#ifdef __KERNEL__
@@ -160,7 +174,7 @@ struct pmu_sleep_notifier
#define SLEEP_LEVEL_NET 60 /* bmac */
#define SLEEP_LEVEL_ADB 50 /* ADB */
#define SLEEP_LEVEL_MISC 30 /* Anything */
-#define SLEEP_LEVEL_LAST 0 /* Anything */
+#define SLEEP_LEVEL_LAST 0 /* Reserved for apm_emu */
/* special register notifier functions */
int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 09eee390b5bc..b2fc5595c04b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1082,7 +1082,7 @@ skb_cow(struct sk_buff *skb, unsigned int headroom)
/**
* skb_linearize - convert paged skb to linear one
* @skb: buffer to linarize
- * @gfp_mask: allocation mode
+ * @gfp: allocation mode
*
* If there is no free memory -ENOMEM is returned, otherwise zero
* is returned and the old skb data released. */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 1dfb9d1b76a0..e6fed11b1e07 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -818,10 +818,12 @@ int inactive_shortage(void)
#define GENERAL_SHORTAGE 4
static int do_try_to_free_pages(unsigned int gfp_mask, int user)
{
- /* Always walk at least the active queue when called */
- int shortage = INACTIVE_SHORTAGE;
+ int shortage = 0;
int maxtry;
+ /* Always walk at least the active queue when called */
+ refill_inactive_scan(DEF_PRIORITY);
+
maxtry = 1 << DEF_PRIORITY;
do {
/*
@@ -872,7 +874,8 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
break;
} while (shortage);
- return !shortage;
+ /* Return success if we're not "totally short" */
+ return shortage != (FREE_SHORTAGE | INACTIVE_SHORTAGE | GENERAL_SHORTAGE);
}
DECLARE_WAIT_QUEUE_HEAD(kswapd_wait);
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 8bc8096dede1..a5a459f0b1d1 100644
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -26,7 +26,7 @@ mount --version | awk -F\- '{print "mount ", $NF}'
insmod -V 2>&1 | awk 'NR==1 {print "modutils ",$NF}'
-tune2fs 2>&1 | grep tune2fs | sed 's/,//' | awk \
+tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \
'NR==1 {print "e2fsprogs ", $2}'
reiserfsck 2>&1 | grep reiserfsprogs | awk \