Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2003-06-13 09:06:08 +1000
committerAnton Blanchard <anton@samba.org>2003-06-13 09:06:08 +1000
commitfca18b6a9efb4875c9fb97eb3a5db20b2e191dff (patch)
tree7a480779c0eb7ce7fc7485dce4a3655b4525ea9e
parent3f90ad0c97ee01b57ec64850be023b75335346b4 (diff)
parent97ef4805f9aa05671473d98fba8d1152b1cc7183 (diff)
Merge samba.org:/scratch/anton/linux-2.5
into samba.org:/scratch/anton/tmp3
-rw-r--r--MAINTAINERS36
-rw-r--r--arch/alpha/Kconfig2
-rw-r--r--arch/arm/Kconfig9
-rw-r--r--arch/arm/Makefile21
-rw-r--r--arch/arm/lib/div64.S31
-rw-r--r--arch/arm/mach-sa1100/irq.c93
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c8
-rw-r--r--arch/i386/kernel/io_apic.c7
-rw-r--r--arch/i386/mm/discontig.c10
-rw-r--r--drivers/acpi/acpi_ksyms.c4
-rw-r--r--drivers/acpi/osl.c12
-rw-r--r--drivers/acpi/pci_irq.c19
-rw-r--r--drivers/acpi/pci_root.c56
-rw-r--r--drivers/acpi/sleep/main.c9
-rw-r--r--drivers/acpi/tables.c2
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/base/class.c2
-rw-r--r--drivers/base/memblk.c9
-rw-r--r--drivers/base/node.c15
-rw-r--r--drivers/base/power.c20
-rw-r--r--drivers/base/sys.c45
-rw-r--r--drivers/block/cpqarray.c26
-rw-r--r--drivers/char/agp/amd-k8-agp.c3
-rw-r--r--drivers/char/agp/frontend.c1
-rw-r--r--drivers/char/agp/intel-agp.c6
-rw-r--r--drivers/char/agp/sworks-agp.c15
-rw-r--r--drivers/char/mem.c122
-rw-r--r--drivers/char/rtc.c5
-rw-r--r--drivers/i2c/Kconfig4
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/chips/Kconfig19
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/lm85.c1223
-rw-r--r--drivers/i2c/i2c-core.c36
-rw-r--r--drivers/i2c/i2c-dev.c10
-rw-r--r--drivers/i2c/i2c-iop3xx.c536
-rw-r--r--drivers/i2c/i2c-iop3xx.h118
-rw-r--r--drivers/pcmcia/Kconfig11
-rw-r--r--drivers/pcmcia/Makefile6
-rw-r--r--drivers/pcmcia/bulkmem.c22
-rw-r--r--drivers/pcmcia/cardbus.c12
-rw-r--r--drivers/pcmcia/cistpl.c30
-rw-r--r--drivers/pcmcia/cs.c557
-rw-r--r--drivers/pcmcia/cs_internal.h105
-rw-r--r--drivers/pcmcia/ds.c129
-rw-r--r--drivers/pcmcia/i82092.c82
-rw-r--r--drivers/pcmcia/i82092aa.h20
-rw-r--r--drivers/pcmcia/i82365.c165
-rw-r--r--drivers/pcmcia/pci_socket.c250
-rw-r--r--drivers/pcmcia/pci_socket.h48
-rw-r--r--drivers/pcmcia/ricoh.h43
-rw-r--r--drivers/pcmcia/rsrc_mgr.c32
-rw-r--r--drivers/pcmcia/sa1100_generic.c21
-rw-r--r--drivers/pcmcia/sa11xx_core.c104
-rw-r--r--drivers/pcmcia/sa11xx_core.h2
-rw-r--r--drivers/pcmcia/tcic.c79
-rw-r--r--drivers/pcmcia/ti113x.h130
-rw-r--r--drivers/pcmcia/yenta.c289
-rw-r--r--drivers/pcmcia/yenta.h20
-rw-r--r--drivers/serial/core.c6
-rw-r--r--fs/devfs/base.c9
-rw-r--r--fs/jfs/inode.c12
-rw-r--r--fs/jfs/namei.c19
-rw-r--r--fs/jfs/super.c6
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/file.c8
-rw-r--r--include/asm-arm/arch-iop3xx/iop321.h124
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h4
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h2
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h4
-rw-r--r--include/asm-i386/pgtable.h7
-rw-r--r--include/asm-m68k/pgtable.h17
-rw-r--r--include/asm-ppc/pgtable.h5
-rw-r--r--include/asm-ppc64/pgtable.h5
-rw-r--r--include/asm-s390/pgtable.h33
-rw-r--r--include/asm-x86_64/pgtable.h5
-rw-r--r--include/linux/acpi.h9
-rw-r--r--include/linux/compat_ioctl.h21
-rw-r--r--include/linux/i2c-dev.h6
-rw-r--r--include/linux/i2c.h4
-rw-r--r--include/linux/node.h3
-rw-r--r--include/linux/page-flags.h11
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/reboot.h1
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/slab.h33
-rw-r--r--include/linux/sysdev.h1
-rw-r--r--include/pcmcia/cs.h4
-rw-r--r--include/pcmcia/ss.h129
-rw-r--r--kernel/ksyms.c3
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/sys.c6
-rw-r--r--lib/kobject.c13
-rw-r--r--mm/page-writeback.c14
-rw-r--r--mm/page_alloc.c9
-rw-r--r--mm/slab.c8
97 files changed, 3582 insertions, 1671 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 45fd35585af6..b03e000bbe61 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -207,6 +207,7 @@ S: Maintained
AGPGART DRIVER
P: Dave Jones
M: davej@codemonkey.org.uk
+W: http://www.codemonkey.org.uk/agp/
S: Maintained
AHA152X SCSI DRIVER
@@ -771,27 +772,24 @@ M: jes@trained-monkey.org
L: linux-hippi@sunsite.dk
S: Maintained
-HP (was COMPAQ) FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
-P: Stephen Cameron
-M: arrays@hp.com
-M: steve.cameron@hp.com
-L: cpqfc-discuss@lists.sourceforge.net
-S: Odd Fixes
-
-HP (was COMPAQ) SMART2 RAID DRIVER
-P: Stephen Cameron
-M: arrays@hp.com
-M: steve.cameron@hp.com
-L: cpqarray-discuss@lists.sourceforge.net
-S: Odd Fixes
-
-HP (was COMPAQ) SMART CISS RAID DRIVER
-P: Stephen Cameron
-M: arrays@hp.com
-M: steve.cameron@hp.com
-L: cciss-discuss@lists.sourceforge.net
+COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
+P: Chase Maupin
+M: Chase Maupin (support@compaq.com)
+L: compaqandlinux@cpqlin.van-dijk.net
S: Supported
+COMPAQ SMART2 RAID DRIVER
+P: Francis Wiran
+M: Francis Wiran <support@compaq.com>
+L: compaqandlinux@cpqlin.van-dijk.net
+S: Supported
+
+COMPAQ SMART CISS RAID DRIVER
+P: Mike Miller, Michael Ni
+M: Mike Miller, Michael Ni <support@compaq.com>
+L: compaqandlinux@cpqlin.van-dijk.net
+S: Supported
+
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
P: Jaroslav Kysela
M: perex@suse.cz
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 1ab1f6a4b9f7..59ae017cb89f 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -297,7 +297,7 @@ config PCI
config PCI_DOMAINS
bool
- default PCI
+ default y
config ALPHA_CORE_AGP
bool
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2bf30328f874..d65ff8475924 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -377,6 +377,15 @@ config ARM_THUMB
If you don't know what this all is, saying Y is a safe choice.
+config CPU_BIG_ENDIAN
+ bool "Build big-endian kernel"
+ depends on ARCH_SUPPORTS_BIG_ENDIAN
+ help
+ Say Y if you plan on running a kernel in big-endian mode.
+ Note that your board must be properly built and your board
+ port must properly enable and big-endian related features
+ of your chipset/board/processor.
+
config CPU_ICACHE_DISABLE
bool "Disable I-Cache"
depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 09cea076738e..a67c83382571 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -24,6 +24,12 @@ ifeq ($(CONFIG_DEBUG_INFO),y)
CFLAGS +=-g
endif
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+CFLAGS += -mbig-endian
+AS += -EB
+LD += -EB
+endif
+
# Select CPU dependent flags. Note that order of declaration is important;
# the options further down the list override previous items.
#
@@ -34,10 +40,7 @@ apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3
# Note that GCC does not numerically define an architecture version
# macro, but instead defines a whole series of macros which makes
# testing for a specific architecture or later rather impossible.
-#
-# Note - GCC does accept -march=armv5te, but someone messed up the assembler or the
-# gcc specs file - this needs fixing properly - ie in gcc and/or binutils.
-arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5t
+arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5te
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
@@ -50,13 +53,13 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm -Wa,-mxscale #-mtune=xscale
+tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale
# Force -mno-fpu to be passed to the assembler. Some versions of gcc don't
# do this with -msoft-float
CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
-AFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mno-fpu -msoft-float -Wa,-mno-fpu
+AFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu
#Default value
DATAADDR := .
@@ -76,7 +79,11 @@ endif
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR := armv
head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
-LDFLAGS_BLOB += --oformat elf32-littlearm
+ ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+ LDFLAGS_BLOB += --oformat elf32-bigarm
+ else
+ LDFLAGS_BLOB += --oformat elf32-littlearm
+ endif
textaddr-y := 0xC0008000
endif
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index 8abb07d45c62..b3f42097690d 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -1,27 +1,42 @@
#include <linux/linkage.h>
+#ifndef __ARMEB__
ql .req r0 @ quotient low
qh .req r1 @ quotient high
-dl .req r3 @ divisor low
-dh .req r2 @ divisor high
+onl .req r0 @ original dividend low
+onh .req r1 @ original dividend high
nl .req r4 @ dividend low
nh .req r5 @ dividend high
+res .req r4 @ result
+#else
+ql .req r1
+qh .req r0
+onl .req r1
+onh .req r0
+nl .req r5
+nh .req r4
+res .req r5
+#endif
+
+dl .req r3 @ divisor low
+dh .req r2 @ divsor high
+
ENTRY(do_div64)
stmfd sp!, {r4, r5, lr}
- mov nl, r0
- movs nh, r1 @ if high bits are zero
+ mov nl, onl
+ movs nh, onh @ if high bits are zero
movne lr, #33
moveq lr, #1 @ only divide low bits
- moveq nh, r0
+ moveq nh, onl
1: cmp nh, dh
bls 2f
add lr, lr, #1
- movs dh, dh, lsl #1 @ left justify divisor
+ movs dh, dh, lsl #1 @ left justify disor
bpl 1b
-2: movs nh, r1
+2: movs nh, onh
moveq dl, dh
moveq dh, #0
movne dl, #0
@@ -38,5 +53,5 @@ ENTRY(do_div64)
subs lr, lr, #1
bne 3b
- mov r2, nl
+ mov r2, res
ldmfd sp!, {r4, r5, pc}
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 0827af01742a..1a934f83133e 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/ptrace.h>
-#include <linux/device.h>
+#include <linux/sysdev.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -211,94 +211,73 @@ static struct resource irq_resource = {
.end = 0x9005ffff,
};
-struct sa1100irq_state {
+static struct {
unsigned int saved;
unsigned int icmr;
unsigned int iclr;
unsigned int iccr;
-};
+} sa1100irq_state;
static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
{
- struct sa1100irq_state *st;
-
- if (!dev->saved_state && level == SUSPEND_NOTIFY)
- dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
- GFP_KERNEL);
- if (!dev->saved_state)
- return -ENOMEM;
-
- if (level == SUSPEND_POWER_DOWN) {
- st = (struct sa1100irq_state *)dev->saved_state;
+ struct sa1100irq_state *st = &sa1100irq_state;
- st->saved = 1;
- st->icmr = ICMR;
- st->iclr = ICLR;
- st->iccr = ICCR;
+ st->saved = 1;
+ st->icmr = ICMR;
+ st->iclr = ICLR;
+ st->iccr = ICCR;
- /*
- * Disable all GPIO-based interrupts.
- */
- ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
- IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
- IC_GPIO1|IC_GPIO0);
+ /*
+ * Disable all GPIO-based interrupts.
+ */
+ ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
+ IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
+ IC_GPIO1|IC_GPIO0);
- /*
- * Set the appropriate edges for wakeup.
- */
- GRER = PWER & GPIO_IRQ_rising_edge;
- GFER = PWER & GPIO_IRQ_falling_edge;
+ /*
+ * Set the appropriate edges for wakeup.
+ */
+ GRER = PWER & GPIO_IRQ_rising_edge;
+ GFER = PWER & GPIO_IRQ_falling_edge;
+
+ /*
+ * Clear any pending GPIO interrupts.
+ */
+ GEDR = GEDR;
- /*
- * Clear any pending GPIO interrupts.
- */
- GEDR = GEDR;
- }
return 0;
}
-static int sa1100irq_resume(struct device *dev, u32 level)
+static int sa1100irq_resume(struct sys_device *dev)
{
- struct sa1100irq_state *st;
-
- if (level == RESUME_POWER_ON) {
- st = (struct sa1100irq_state *)dev->saved_state;
- dev->saved_state = NULL;
-
- if (st->saved) {
- ICCR = st->iccr;
- ICLR = st->iclr;
+ struct sa1100irq_state *st = &sa1100irq_state;
- GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
- GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+ if (st->saved) {
+ ICCR = st->iccr;
+ ICLR = st->iclr;
- ICMR = st->icmr;
- }
+ GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+ GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
- kfree(st);
+ ICMR = st->icmr;
}
return 0;
}
-static struct device_driver sa1100irq_driver = {
- .name = "sa11x0-irq",
- .bus = &system_bus_type,
+static struct sysdev_class sa1100irq_sysclass = {
+ set_kset_name("sa11x0-irq"),
.suspend = sa1100irq_suspend,
.resume = sa1100irq_resume,
};
static struct sys_device sa1100irq_device = {
- .name = "irq",
.id = 0,
- .dev = {
- .name = "Intel SA11x0 [Interrupt Controller]",
- .driver = &sa1100irq_driver,
- },
+ .cls = &sa1100irq_sysclass,
};
static int __init sa1100irq_init_devicefs(void)
{
- driver_register(&sa1100irq_driver);
+ sysdev_class_register(&sa1100irq_sysclass);
return sys_device_register(&sa1100irq_device);
}
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 5482dc9523c8..29f210384f0e 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -10,6 +10,7 @@
*
* Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
* - We cli/sti on stepping A0 CPUs around the FID/VID transition.
+ * (ADDENDUM: This seems to be needed on more systems, so we do it unconditionally now).
* Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
* - We disable half multipliers if ACPI is used on A0 stepping CPUs.
*/
@@ -259,8 +260,7 @@ static void change_speed (unsigned int index)
/* Now do the magic poking into the MSRs. */
- if (have_a0 == 1) /* A0 errata 5 */
- __asm__("\tcli\n");
+ __asm__("\tcli\n");
if (freqs.old > freqs.new) {
/* Going down, so change FID first */
@@ -272,9 +272,7 @@ static void change_speed (unsigned int index)
change_FID(vid);
}
-
- if (have_a0 == 1)
- __asm__("\tsti\n");
+ __asm__("\tsti\n");
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 6d22a16b1ad1..a55c5b2303d4 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1160,7 +1160,8 @@ void __init setup_IO_APIC_irqs(void)
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* enable IRQ */
- entry.dest.logical.logical_dest = TARGET_CPUS;
+ entry.dest.logical.logical_dest =
+ cpu_mask_to_apicid(TARGET_CPUS);
idx = find_irq_entry(apic,pin,mp_INT);
if (idx == -1) {
@@ -1239,7 +1240,7 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
*/
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* unmask IRQ now */
- entry.dest.logical.logical_dest = TARGET_CPUS;
+ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.delivery_mode = INT_DELIVERY_MODE;
entry.polarity = 0;
entry.trigger = 0;
@@ -2309,7 +2310,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq)
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
- entry.dest.logical.logical_dest = TARGET_CPUS;
+ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.mask = 1; /* Disabled (masked) */
entry.trigger = 1; /* Level sensitive */
entry.polarity = 1; /* Low active */
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 382efc980923..aadfcb53b6d0 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -114,10 +114,16 @@ void __init get_memcfg_numa_flat(void)
*/
static void __init find_max_pfn_node(int nid)
{
- if (node_start_pfn[nid] >= node_end_pfn[nid])
- BUG();
if (node_end_pfn[nid] > max_pfn)
node_end_pfn[nid] = max_pfn;
+ /*
+ * if a user has given mem=XXXX, then we need to make sure
+ * that the node _starts_ before that, too, not just ends
+ */
+ if (node_start_pfn[nid] > max_pfn)
+ node_start_pfn[nid] = max_pfn;
+ if (node_start_pfn[nid] > node_end_pfn[nid])
+ BUG();
}
/*
diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
index 935fc412d5dc..177d179b55f9 100644
--- a/drivers/acpi/acpi_ksyms.c
+++ b/drivers/acpi/acpi_ksyms.c
@@ -144,8 +144,8 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver);
#include <linux/pci.h>
extern int acpi_pci_irq_enable(struct pci_dev *dev);
EXPORT_SYMBOL(acpi_pci_irq_enable);
-extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin);
-EXPORT_SYMBOL(acpi_pci_irq_lookup);
+EXPORT_SYMBOL(acpi_pci_register_driver);
+EXPORT_SYMBOL(acpi_pci_unregister_driver);
#endif /*CONFIG_ACPI_PCI */
#ifdef CONFIG_ACPI_EC
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 997b6cb20cf0..10a02822ef56 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -38,6 +38,7 @@
#include <acpi/acpi.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
#ifdef CONFIG_ACPI_EFI
#include <linux/efi.h>
@@ -948,19 +949,22 @@ acpi_os_get_line(char *buffer)
return 0;
}
-/*
- * We just have to assume we're dealing with valid memory
- */
-
+/* Assumes no unreadable holes inbetween */
BOOLEAN
acpi_os_readable(void *ptr, u32 len)
{
+#if defined(__i386__) || defined(__x86_64__)
+ char tmp;
+ return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1);
+#endif
return 1;
}
BOOLEAN
acpi_os_writable(void *ptr, u32 len)
{
+ /* could do dummy write (racy) or a kernel page table lookup.
+ The later may be difficult at early boot when kmap doesn't work yet. */
return 1;
}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9b69fc6bbe72..c02559e3ddd4 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -229,22 +229,20 @@ acpi_pci_irq_add_prt (
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
-int
-acpi_pci_irq_lookup (
- int segment,
- int bus,
- int device,
- int pin)
+static int
+acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
{
struct acpi_prt_entry *entry = NULL;
+ int segment = pci_domain_nr(bus);
+ int bus_nr = bus->number;
ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Searching for PRT entry for %02x:%02x:%02x[%c]\n",
- segment, bus, device, ('A' + pin)));
+ segment, bus_nr, device, ('A' + pin)));
- entry = acpi_pci_irq_find_prt_entry(segment, bus, device, pin);
+ entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
if (!entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
return_VALUE(0);
@@ -288,7 +286,8 @@ acpi_pci_irq_derive (
while (!irq && bridge->bus->self) {
pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
bridge = bridge->bus->self;
- irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin);
+ irq = acpi_pci_irq_lookup(bridge->bus,
+ PCI_SLOT(bridge->devfn), pin);
}
if (!irq) {
@@ -331,7 +330,7 @@ acpi_pci_irq_enable (
* First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
* values override any BIOS-assigned IRQs set during boot.
*/
- irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 210ef7f6576c..20a1a9fecc72 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -59,17 +59,63 @@ static struct acpi_driver acpi_pci_root_driver = {
},
};
- struct acpi_pci_root {
+struct acpi_pci_root {
struct list_head node;
- acpi_handle handle;
- struct acpi_pci_id id;
- struct pci_bus *bus;
+ acpi_handle handle;
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
u64 mem_tra;
u64 io_tra;
- };
+};
struct list_head acpi_pci_roots;
+static struct acpi_pci_driver *sub_driver;
+
+int acpi_pci_register_driver(struct acpi_pci_driver *driver)
+{
+ int n = 0;
+ struct list_head *entry;
+
+ struct acpi_pci_driver **pptr = &sub_driver;
+ while (*pptr)
+ pptr = &(*pptr)->next;
+ *pptr = driver;
+
+ if (!driver->add)
+ return 0;
+
+ list_for_each(entry, &acpi_pci_roots) {
+ struct acpi_pci_root *root;
+ root = list_entry(entry, struct acpi_pci_root, node);
+ driver->add(root->handle);
+ n++;
+ }
+
+ return n;
+}
+
+void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
+{
+ struct list_head *entry;
+
+ struct acpi_pci_driver **pptr = &sub_driver;
+ while (*pptr) {
+ if (*pptr != driver)
+ continue;
+ *pptr = (*pptr)->next;
+ break;
+ }
+
+ if (!driver->remove)
+ return;
+
+ list_for_each(entry, &acpi_pci_roots) {
+ struct acpi_pci_root *root;
+ root = list_entry(entry, struct acpi_pci_root, node);
+ driver->remove(root->handle);
+ }
+}
void
acpi_pci_get_translations (
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 3be419abf318..7c555c819de2 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -214,6 +214,10 @@ acpi_suspend (
{
acpi_status status;
+ /* Suspend is hard to get right on SMP. */
+ if (num_online_cpus() != 1)
+ return AE_ERROR;
+
/* get out if state is invalid */
if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5)
return AE_ERROR;
@@ -226,7 +230,10 @@ acpi_suspend (
* TBD: S1 can be done without device_suspend. Make a CONFIG_XX
* to handle however when S1 failed without device_suspend.
*/
- freeze_processes(); /* device_suspend needs processes to be stopped */
+ if (freeze_processes()) {
+ thaw_processes();
+ return AE_ERROR; /* device_suspend needs processes to be stopped */
+ }
/* do we have a wakeup address for S2 and S3? */
/* Here, we support only S4BIOS, those we set the wakeup address */
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index b858adf8b82d..3919b450f86f 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -56,7 +56,7 @@ static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
[ACPI_SRAT] = "SRAT",
[ACPI_SSDT] = "SSDT",
[ACPI_SPMI] = "SPMI",
- [ACPI_HPET] = "HPET"
+ [ACPI_HPET] = "HPET",
};
/* System Description Table (RSDT/XSDT) */
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 1e98023d11fc..69a1dbae4c5f 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -430,7 +430,7 @@ acpi_thermal_call_usermode (
ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
if (!path)
- return_VALUE(-EINVAL);;
+ return_VALUE(-EINVAL);
argv[0] = path;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 3989b53ab42d..ea551b8dc28b 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -264,8 +264,6 @@ int class_device_add(struct class_device *class_dev)
return -EINVAL;
parent = class_get(class_dev->class);
- if (class_dev->dev)
- get_device(class_dev->dev);
pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id);
diff --git a/drivers/base/memblk.c b/drivers/base/memblk.c
index f3f3fdf7292c..e832cb15839f 100644
--- a/drivers/base/memblk.c
+++ b/drivers/base/memblk.c
@@ -13,13 +13,6 @@ static struct sysdev_class memblk_class = {
set_kset_name("memblk"),
};
-
-static struct device_driver memblk_driver = {
- .name = "memblk",
- .bus = &system_bus_type,
-};
-
-
/*
* register_memblk - Setup a driverfs device for a MemBlk
* @num - MemBlk number to use when creating the device.
@@ -37,7 +30,7 @@ int __init register_memblk(struct memblk *memblk, int num, struct node *root)
error = sys_device_register(&memblk->sysdev);
if (!error)
error = sysfs_create_link(&root->sysdev.kobj,
- &memblk->sysdev,kobj,
+ &memblk->sysdev.kobj,
memblk->sysdev.kobj.name);
return error;
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 08e7c52c68e6..76a11b3288fa 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -2,7 +2,7 @@
* drivers/base/node.c - basic Node class support
*/
-#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
@@ -14,18 +14,17 @@ static struct sysdev_class node_class = {
};
-static ssize_t node_read_cpumap(struct device * dev, char * buf)
+static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
{
- struct node *node_dev = to_node(to_root(dev));
+ struct node *node_dev = to_node(dev);
return sprintf(buf,"%lx\n",node_dev->cpumap);
}
static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL);
#define K(x) ((x) << (PAGE_SHIFT - 10))
-static ssize_t node_read_meminfo(struct device * dev, char * buf)
+static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
{
- struct sys_root *node = to_root(dev);
- int nid = node->id;
+ int nid = dev->id;
struct sysinfo i;
si_meminfo_node(&i, nid);
return sprintf(buf, "\n"
@@ -64,8 +63,8 @@ int __init register_node(struct node *node, int num, struct node *parent)
error = sys_device_register(&node->sysdev);
if (!error){
- sys_device_create_file(&node->sysroot.dev, &attr_cpumap);
- sys_device_create_file(&node->sysroot.dev, &attr_meminfo);
+ sysdev_create_file(&node->sysdev, &attr_cpumap);
+ sysdev_create_file(&node->sysdev, &attr_meminfo);
}
return error;
}
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 7f5a6abc4e00..78346491389a 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -10,7 +10,7 @@
*
*/
-#define DEBUG
+#undef DEBUG
#include <linux/device.h>
#include <linux/module.h>
@@ -49,19 +49,19 @@ extern int sysdev_restore(void);
*/
int device_suspend(u32 state, u32 level)
{
- struct list_head * node;
+ struct device * dev;
int error = 0;
printk(KERN_EMERG "Suspending devices\n");
down_write(&devices_subsys.rwsem);
- list_for_each(node,&devices_subsys.kset.list) {
- struct device * dev = to_dev(node);
+ list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
if (dev->driver && dev->driver->suspend) {
pr_debug("suspending device %s\n",dev->name);
error = dev->driver->suspend(dev,state,level);
if (error)
- printk(KERN_ERR "%s: suspend returned %d\n",dev->name,error);
+ printk(KERN_ERR "%s: suspend returned %d\n",
+ dev->name,error);
}
}
up_write(&devices_subsys.rwsem);
@@ -93,7 +93,7 @@ int device_suspend(u32 state, u32 level)
*/
void device_resume(u32 level)
{
- struct list_head * node;
+ struct device * dev;
switch (level) {
case RESUME_POWER_ON:
@@ -107,8 +107,7 @@ void device_resume(u32 level)
}
down_write(&devices_subsys.rwsem);
- list_for_each_prev(node,&devices_subsys.kset.list) {
- struct device * dev = to_dev(node);
+ list_for_each_entry(dev,&devices_subsys.kset.list,kobj.entry) {
if (dev->driver && dev->driver->resume) {
pr_debug("resuming device %s\n",dev->name);
dev->driver->resume(dev,level);
@@ -124,13 +123,12 @@ void device_resume(u32 level)
*/
void device_shutdown(void)
{
- struct list_head * entry;
+ struct device * dev;
printk(KERN_EMERG "Shutting down devices\n");
down_write(&devices_subsys.rwsem);
- list_for_each(entry,&devices_subsys.kset.list) {
- struct device * dev = to_dev(entry);
+ list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
pr_debug("shutting down %s: ",dev->name);
if (dev->driver && dev->driver->shutdown) {
pr_debug("Ok\n");
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 34001cb52fa1..e8a4daa442e8 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -12,7 +12,7 @@
* add themselves as children of the system bus.
*/
-#define DEBUG
+#undef DEBUG
#include <linux/sysdev.h>
#include <linux/err.h>
@@ -62,6 +62,19 @@ static struct kobj_type ktype_sysdev = {
.sysfs_ops = &sysfs_ops,
};
+
+int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a)
+{
+ return sysfs_create_file(&s->kobj,&a->attr);
+}
+
+
+void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a)
+{
+ sysfs_remove_file(&s->kobj,&a->attr);
+}
+
+
/*
* declare system_subsys
*/
@@ -104,9 +117,16 @@ int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down_write(&system_subsys.rwsem);
- if (cls && kset_get(&cls->kset))
+ if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry,&cls->drivers);
- else
+
+ /* If devices of this class already exist, tell the driver */
+ if (drv->add) {
+ struct sys_device *dev;
+ list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+ drv->add(dev);
+ }
+ } else
list_add_tail(&drv->entry,&global_drivers);
up_write(&system_subsys.rwsem);
return 0;
@@ -123,8 +143,14 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
{
down_write(&system_subsys.rwsem);
list_del_init(&drv->entry);
- if (cls)
+ if (cls) {
+ if (drv->remove) {
+ struct sys_device *dev;
+ list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+ drv->remove(dev);
+ }
kset_put(&cls->kset);
+ }
up_write(&system_subsys.rwsem);
}
@@ -157,7 +183,7 @@ int sys_device_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
- down_read(&system_subsys.rwsem);
+ down_write(&system_subsys.rwsem);
/* Generic notification is implicit, because it's that
* code that should have called us.
*/
@@ -173,7 +199,7 @@ int sys_device_register(struct sys_device * sysdev)
if (drv->add)
drv->add(sysdev);
}
- up_read(&system_subsys.rwsem);
+ up_write(&system_subsys.rwsem);
}
return error;
}
@@ -182,7 +208,7 @@ void sys_device_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
- down_read(&system_subsys.rwsem);
+ down_write(&system_subsys.rwsem);
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->remove)
drv->remove(sysdev);
@@ -192,7 +218,10 @@ void sys_device_unregister(struct sys_device * sysdev)
if (drv->remove)
drv->remove(sysdev);
}
- up_read(&system_subsys.rwsem);
+
+ list_del_init(&sysdev->entry);
+
+ up_write(&system_subsys.rwsem);
kobject_unregister(&sysdev->kobj);
}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d18ef9356fa6..ade17d7c0bca 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1028,7 +1028,7 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
int diskinfo[4];
struct hd_geometry *geo = (struct hd_geometry *)arg;
ida_ioctl_t *io = (ida_ioctl_t*)arg;
- ida_ioctl_t my_io;
+ ida_ioctl_t *my_io;
switch(cmd) {
case HDIO_GETGEO:
@@ -1051,12 +1051,24 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
return -EFAULT;
return 0;
case IDAPASSTHRU:
- if (!capable(CAP_SYS_RAWIO)) return -EPERM;
- if (copy_from_user(&my_io, io, sizeof(my_io)))
- return -EFAULT;
- error = ida_ctlr_ioctl(host, drv - host->drv, &my_io);
- if (error) return error;
- return copy_to_user(io, &my_io, sizeof(my_io)) ? -EFAULT : 0;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ my_io = kmalloc(sizeof(ida_ioctl_t), GFP_KERNEL);
+ if (!my_io)
+ return -ENOMEM;
+ error = -EFAULT;
+ if (copy_from_user(my_io, io, sizeof(*my_io)))
+ goto out_passthru;
+ error = ida_ctlr_ioctl(host, drv - host->drv, my_io);
+ if (error)
+ goto out_passthru;
+ error = -EFAULT;
+ if (copy_to_user(io, &my_io, sizeof(*my_io)))
+ goto out_passthru;
+ error = 0;
+out_passthru:
+ kfree(my_io);
+ return error;
case IDAGETCTLRSIG:
if (!arg) return -EINVAL;
put_user(host->ctlr_sig, (int*)arg);
diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c
index d4e369ef6d77..91492df0546b 100644
--- a/drivers/char/agp/amd-k8-agp.c
+++ b/drivers/char/agp/amd-k8-agp.c
@@ -278,12 +278,13 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
default: revstring="??";
break;
}
- printk ("Detected AMD 8151 AGP Bridge rev %s", revstring);
+ printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring);
/*
* Work around errata.
* Chips before B2 stepping incorrectly reporting v3.5
*/
if (rev_id < 0x13) {
+ printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
bridge->major_version = 3;
bridge->minor_version = 0;
}
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index c28bb5ec1650..7d688668a084 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -300,7 +300,6 @@ static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
struct agp_memory *memory;
memory = agp_allocate_memory(pg_count, type);
- printk(KERN_DEBUG "agp_allocate_memory: %p\n", memory);
if (memory == NULL)
return NULL;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index de446ebbefa4..ff034f558aae 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -447,7 +447,7 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
printk (KERN_DEBUG "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
pg_start,intel_i830_private.gtt_entries);
- printk ("Trying to insert into local/stolen memory\n");
+ printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
return (-EINVAL);
}
@@ -483,7 +483,7 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
global_cache_flush();
if (pg_start < intel_i830_private.gtt_entries) {
- printk ("Trying to disable local/stolen memory\n");
+ printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
return (-EINVAL);
}
@@ -645,7 +645,7 @@ static int intel_815_configure(void)
/* the Intel 815 chipset spec. says that bits 29-31 in the
* ATTBASE register are reserved -> try not to write them */
if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
- printk (KERN_EMERG "gatt bus addr too high");
+ printk (KERN_EMERG PFX "gatt bus addr too high");
return -EINVAL;
}
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 84981423e025..423c6594e46f 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -240,7 +240,7 @@ static void serverworks_tlbflush(struct agp_memory *temp)
while(INREG8(serverworks_private.registers,
SVWRKS_POSTFLUSH) == 0x01) {
if((signed)(end - jiffies) <= 0) {
- printk(KERN_ERR "Posted write buffer flush took more"
+ printk(KERN_ERR PFX "Posted write buffer flush took more"
"then 3 seconds\n");
}
}
@@ -249,7 +249,7 @@ static void serverworks_tlbflush(struct agp_memory *temp)
while(INREG32(serverworks_private.registers,
SVWRKS_DIRFLUSH) == 0x00000001) {
if((signed)(end - jiffies) <= 0) {
- printk(KERN_ERR "TLB flush took more"
+ printk(KERN_ERR PFX "TLB flush took more"
"then 3 seconds\n");
}
}
@@ -447,8 +447,7 @@ static int __init agp_serverworks_probe(struct pci_dev *pdev,
PCI_DEVFN(0, 1));
if (!bridge_dev) {
printk(KERN_INFO PFX "agpgart: Detected a Serverworks "
- "Chipset, but could not find the secondary "
- "device.\n");
+ "Chipset, but could not find the secondary device.\n");
return -ENODEV;
}
@@ -470,8 +469,8 @@ static int __init agp_serverworks_probe(struct pci_dev *pdev,
if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2);
if (temp2 != 0) {
- printk("Detected 64 bit aperture address, but top "
- "bits are not zero. Disabling agp\n");
+ printk(KERN_INFO PFX "Detected 64 bit aperture address, "
+ "but top bits are not zero. Disabling agp\n");
return -ENODEV;
}
serverworks_private.mm_addr_ofs = 0x18;
@@ -483,8 +482,8 @@ static int __init agp_serverworks_probe(struct pci_dev *pdev,
pci_read_config_dword(pdev,
serverworks_private.mm_addr_ofs + 4, &temp2);
if (temp2 != 0) {
- printk("Detected 64 bit MMIO address, but top "
- "bits are not zero. Disabling agp\n");
+ printk(KERN_INFO PFX "Detected 64 bit MMIO address, "
+ "but top bits are not zero. Disabling agp\n");
return -ENODEV;
}
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cdcb2dcea854..7f1464f3e6b8 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -29,13 +29,56 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
+#ifdef CONFIG_IA64
+# include <linux/efi.h>
+#endif
+
#ifdef CONFIG_FB
extern void fbmem_init(void);
#endif
#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
extern void tapechar_init(void);
#endif
-
+
+/*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+ *
+ */
+static inline int uncached_access(struct file *file, unsigned long addr)
+{
+#if defined(__i386__)
+ /*
+ * On the PPro and successors, the MTRRs are used to set
+ * memory types for physical addresses outside main memory,
+ * so blindly setting PCD or PWT on those pages is wrong.
+ * For Pentiums and earlier, the surround logic should disable
+ * caching for the high addresses through the KEN pin, but
+ * we maintain the tradition of paranoia in this code.
+ */
+ if (file->f_flags & O_SYNC)
+ return 1;
+ return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
+ && addr >= __pa(high_memory);
+#elif defined(CONFIG_IA64)
+ /*
+ * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
+ */
+ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#else
+ /*
+ * Accessing memory above the top the kernel knows about or through a file pointer
+ * that was marked O_SYNC will be done non-cached.
+ */
+ if (file->f_flags & O_SYNC)
+ return 1;
+ return addr >= __pa(high_memory);
+#endif
+}
+
static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
const char * buf, size_t count, loff_t *ppos)
{
@@ -72,7 +115,7 @@ static ssize_t read_mem(struct file * file, char * buf,
unsigned long p = *ppos;
unsigned long end_mem;
ssize_t read;
-
+
end_mem = __pa(high_memory);
if (p >= end_mem)
return 0;
@@ -116,77 +159,16 @@ static ssize_t write_mem(struct file * file, const char * buf,
return do_write_mem(file, __va(p), p, buf, count, ppos);
}
-#ifndef pgprot_noncached
-
-/*
- * This should probably be per-architecture in <asm/pgtable.h>
- */
-static inline pgprot_t pgprot_noncached(pgprot_t _prot)
-{
- unsigned long prot = pgprot_val(_prot);
-
-#if defined(__i386__) || defined(__x86_64__)
- /* On PPro and successors, PCD alone doesn't always mean
- uncached because of interactions with the MTRRs. PCD | PWT
- means definitely uncached. */
- if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD | _PAGE_PWT;
-#elif defined(__powerpc__)
- prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-#elif defined(__mc68000__) && defined(CONFIG_MMU)
-#ifdef SUN3_PAGE_NOCACHE
- if (MMU_IS_SUN3)
- prot |= SUN3_PAGE_NOCACHE;
- else
-#endif
- if (MMU_IS_851 || MMU_IS_030)
- prot |= _PAGE_NOCACHE030;
- /* Use no-cache mode, serialized */
- else if (MMU_IS_040 || MMU_IS_060)
- prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
-#endif
-
- return __pgprot(prot);
-}
-
-#endif /* !pgprot_noncached */
-
-/*
- * Architectures vary in how they handle caching for addresses
- * outside of main memory.
- */
-static inline int noncached_address(unsigned long addr)
-{
-#if defined(__i386__)
- /*
- * On the PPro and successors, the MTRRs are used to set
- * memory types for physical addresses outside main memory,
- * so blindly setting PCD or PWT on those pages is wrong.
- * For Pentiums and earlier, the surround logic should disable
- * caching for the high addresses through the KEN pin, but
- * we maintain the tradition of paranoia in this code.
- */
- return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
- test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
- test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
- test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
- && addr >= __pa(high_memory);
-#else
- return addr >= __pa(high_memory);
-#endif
-}
-
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ int uncached;
- /*
- * Accessing memory above the top the kernel knows about or
- * through a file pointer that was marked O_SYNC will be
- * done non-cached.
- */
- if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ uncached = uncached_access(file, offset);
+#ifdef pgprot_noncached
+ if (uncached)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
/* Don't try to swap out physical pages.. */
vma->vm_flags |= VM_RESERVED;
@@ -194,7 +176,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
/*
* Don't dump addresses that are not real memory to a core file.
*/
- if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
+ if (uncached)
vma->vm_flags |= VM_IO;
if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start,
@@ -713,4 +695,4 @@ static int __init chr_dev_init(void)
return 0;
}
-subsys_initcall(chr_dev_init);
+fs_initcall(chr_dev_init);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index dc5c7f7ebbe5..7838aee59b13 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -284,12 +284,13 @@ static ssize_t rtc_read(struct file *file, char *buf,
add_wait_queue(&rtc_wait, &wait);
- current->state = TASK_INTERRUPTIBLE;
-
do {
/* First make it right. Then make it fast. Putting this whole
* block within the parentheses of a while would be too
* confusing. And no, xchg() is not the answer. */
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+
spin_lock_irq (&rtc_lock);
data = rtc_irq_data;
rtc_irq_data = 0;
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 14ed63e87241..1d680780775f 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -193,6 +193,10 @@ config I2C_IBM_OCP_ADAP
tristate "IBM on-chip I2C Adapter"
depends on I2C_IBM_OCP_ALGO
+config I2C_IOP3XX
+ tristate "Intel XScale IOP3xx on-chip I2C interface"
+ depends on ARCH_IOP3XX && I2C
+
config I2C_CHARDEV
tristate "I2C device interface"
depends on I2C
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index cbcf2704c383..6beb307886cb 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
+obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-y += busses/ chips/
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 809c480f6ebc..fcd73271a1e0 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -47,6 +47,21 @@ config SENSORS_LM75
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+config SENSORS_LM85
+ tristate " National Semiconductors LM85 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for National Semiconductor LM85
+ sensor chips and clones: ADT7463 and ADM1027.
+ This can also be built as a module which can be inserted and
+ removed while the kernel is running.
+
+ The module will be called lm85.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
config SENSORS_VIA686A
tristate " VIA686A"
depends on I2C && EXPERIMENTAL
@@ -76,8 +91,8 @@ config SENSORS_W83781D
config I2C_SENSOR
tristate
- default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y
- default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m
+ default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y || SENSORS_LM85=y
+ default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m || SENSORS_LM85=m
default n
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 8a8c2b3afe84..3921d68eb524 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
+obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
new file mode 100644
index 000000000000..cffe8bb66b64
--- /dev/null
+++ b/drivers/i2c/chips/lm85.c
@@ -0,0 +1,1223 @@
+/*
+ lm85.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+ Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
+ Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
+
+ Chip details at <http://www.national.com/ds/LM/LM85.pdf>
+
+ 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.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+/*
+#include <asm/io.h>
+*/
+
+#undef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463);
+
+/* Enable debug if true */
+static int lm85debug = 0;
+
+/* The LM85 registers */
+
+#define LM85_REG_IN(nr) (0x20 + (nr))
+#define LM85_REG_IN_MIN(nr) (0x44 + (nr) * 2)
+#define LM85_REG_IN_MAX(nr) (0x45 + (nr) * 2)
+
+#define LM85_REG_TEMP(nr) (0x25 + (nr))
+#define LM85_REG_TEMP_MIN(nr) (0x4e + (nr) * 2)
+#define LM85_REG_TEMP_MAX(nr) (0x4f + (nr) * 2)
+
+/* Fan speeds are LSB, MSB (2 bytes) */
+#define LM85_REG_FAN(nr) (0x28 + (nr) *2)
+#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) *2)
+
+#define LM85_REG_PWM(nr) (0x30 + (nr))
+
+#define ADT7463_REG_OPPOINT(nr) (0x33 + (nr))
+
+#define ADT7463_REG_TMIN_CTL1 0x36
+#define ADT7463_REG_TMIN_CTL2 0x37
+
+#define LM85_REG_DEVICE 0x3d
+#define LM85_REG_COMPANY 0x3e
+#define LM85_REG_VERSTEP 0x3f
+/* These are the recognized values for the above regs */
+#define LM85_DEVICE_ADX 0x27
+#define LM85_COMPANY_NATIONAL 0x01
+#define LM85_COMPANY_ANALOG_DEV 0x41
+#define LM85_VERSTEP_GENERIC 0x60
+#define LM85_VERSTEP_LM85C 0x60
+#define LM85_VERSTEP_LM85B 0x62
+#define LM85_VERSTEP_ADM1027 0x60
+#define LM85_VERSTEP_ADT7463 0x62
+
+#define LM85_REG_CONFIG 0x40
+
+#define LM85_REG_ALARM1 0x41
+#define LM85_REG_ALARM2 0x42
+
+#define LM85_REG_VID 0x43
+
+/* Automated FAN control */
+#define LM85_REG_AFAN_CONFIG(nr) (0x5c + (nr))
+#define LM85_REG_AFAN_RANGE(nr) (0x5f + (nr))
+#define LM85_REG_AFAN_SPIKE1 0x62
+#define LM85_REG_AFAN_SPIKE2 0x63
+#define LM85_REG_AFAN_MINPWM(nr) (0x64 + (nr))
+#define LM85_REG_AFAN_LIMIT(nr) (0x67 + (nr))
+#define LM85_REG_AFAN_CRITICAL(nr) (0x6a + (nr))
+#define LM85_REG_AFAN_HYST1 0x6d
+#define LM85_REG_AFAN_HYST2 0x6e
+
+#define LM85_REG_TACH_MODE 0x74
+#define LM85_REG_SPINUP_CTL 0x75
+
+#define ADM1027_REG_TEMP_OFFSET(nr) (0x70 + (nr))
+#define ADM1027_REG_CONFIG2 0x73
+#define ADM1027_REG_INTMASK1 0x74
+#define ADM1027_REG_INTMASK2 0x75
+#define ADM1027_REG_EXTEND_ADC1 0x76
+#define ADM1027_REG_EXTEND_ADC2 0x77
+#define ADM1027_REG_CONFIG3 0x78
+#define ADM1027_REG_FAN_PPR 0x7b
+
+#define ADT7463_REG_THERM 0x79
+#define ADT7463_REG_THERM_LIMIT 0x7A
+
+#define LM85_ALARM_IN0 0x0001
+#define LM85_ALARM_IN1 0x0002
+#define LM85_ALARM_IN2 0x0004
+#define LM85_ALARM_IN3 0x0008
+#define LM85_ALARM_TEMP1 0x0010
+#define LM85_ALARM_TEMP2 0x0020
+#define LM85_ALARM_TEMP3 0x0040
+#define LM85_ALARM_ALARM2 0x0080
+#define LM85_ALARM_IN4 0x0100
+#define LM85_ALARM_RESERVED 0x0200
+#define LM85_ALARM_FAN1 0x0400
+#define LM85_ALARM_FAN2 0x0800
+#define LM85_ALARM_FAN3 0x1000
+#define LM85_ALARM_FAN4 0x2000
+#define LM85_ALARM_TEMP1_FAULT 0x4000
+#define LM85_ALARM_TEMP3_FAULT 0x8000
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ */
+
+/* IN are scaled 1.000 == 0xc0, mag = 3 */
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
+#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
+#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
+
+/* IN are scaled acording to built-in resistors */
+static int lm85_scaling[] = { /* .001 Volts */
+ 2500, 2250, 3300, 5000, 12000
+ };
+#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
+#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
+#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
+/*
+#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
+*/
+#define INS_FROM_REG(n,val) ( ( (val*4*lm85_scaling[n]) + (192*4/2) ) / (192*4) )
+
+/* FAN speed is measured using 90kHz clock */
+#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
+
+/* Temperature is reported in .01 degC increments */
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+50)/100,-127,127))
+#define TEMPEXT_FROM_REG(val,ext) ((val)*100 + (ext)*25)
+#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
+#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+
+#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
+#define PWM_FROM_REG(val) (val)
+
+#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* ZONEs have the following parameters:
+ * Limit (low) temp, 1. degC
+ * Hysteresis (below limit), 1. degC (0-15)
+ * Range of speed control, .1 degC (2-80)
+ * Critical (high) temp, 1. degC
+ *
+ * FAN PWMs have the following parameters:
+ * Reference Zone, 1, 2, 3, etc.
+ * Spinup time, .05 sec
+ * PWM value at limit/low temp, 1 count
+ * PWM Frequency, 1. Hz
+ * PWM is Min or OFF below limit, flag
+ * Invert PWM output, flag
+ *
+ * Some chips filter the temp, others the fan.
+ * Filter constant (or disabled) .1 seconds
+ */
+
+/* These are the zone temperature range encodings */
+static int lm85_range_map[] = { /* .1 degC */
+ 20, 25, 33, 40, 50, 66,
+ 80, 100, 133, 160, 200, 266,
+ 320, 400, 533, 800
+ };
+static int RANGE_TO_REG( int range )
+{
+ int i;
+
+ if( range >= lm85_range_map[15] ) { return 15 ; }
+ for( i = 0 ; i < 15 ; ++i )
+ if( range <= lm85_range_map[i] )
+ break ;
+ return( i & 0x0f );
+}
+#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
+
+/* These are the Acoustic Enhancement, or Temperature smoothing encodings
+ * NOTE: The enable/disable bit is INCLUDED in these encodings as the
+ * MSB (bit 3, value 8). If the enable bit is 0, the encoded value
+ * is ignored, or set to 0.
+ */
+static int lm85_smooth_map[] = { /* .1 sec */
+ 350, 176, 118, 70, 44, 30, 16, 8
+/* 35.4 * 1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48 */
+ };
+static int SMOOTH_TO_REG( int smooth )
+{
+ int i;
+
+ if( smooth <= 0 ) { return 0 ; } /* Disabled */
+ for( i = 0 ; i < 7 ; ++i )
+ if( smooth >= lm85_smooth_map[i] )
+ break ;
+ return( (i & 0x07) | 0x08 );
+}
+#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
+
+/* These are the fan spinup delay time encodings */
+static int lm85_spinup_map[] = { /* .1 sec */
+ 0, 1, 2, 4, 7, 10, 20, 40
+ };
+static int SPINUP_TO_REG( int spinup )
+{
+ int i;
+
+ if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( spinup <= lm85_spinup_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
+
+/* These are the PWM frequency encodings */
+static int lm85_freq_map[] = { /* .1 Hz */
+ 100, 150, 230, 300, 380, 470, 620, 980
+ };
+static int FREQ_TO_REG( int freq )
+{
+ int i;
+
+ if( freq >= lm85_freq_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( freq <= lm85_freq_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
+
+/* Since we can't use strings, I'm abusing these numbers
+ * to stand in for the following meanings:
+ * 1 -- PWM responds to Zone 1
+ * 2 -- PWM responds to Zone 2
+ * 3 -- PWM responds to Zone 3
+ * 23 -- PWM responds to the higher temp of Zone 2 or 3
+ * 123 -- PWM responds to highest of Zone 1, 2, or 3
+ * 0 -- PWM is always at 0% (ie, off)
+ * -1 -- PWM is always at 100%
+ * -2 -- PWM responds to manual control
+ */
+
+#endif /* Extended functionality */
+
+static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
+#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+static int ZONE_TO_REG( int zone )
+{
+ int i;
+
+ for( i = 0 ; i <= 7 ; ++i )
+ if( zone == lm85_zone_map[i] )
+ break ;
+ if( i > 7 ) /* Not found. */
+ i = 3; /* Always 100% */
+ return( (i & 0x07)<<5 );
+}
+
+#endif /* Extended functionality */
+
+#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
+#define HYST_FROM_REG(val) (-(val)*10)
+
+#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+#define OFFSET_FROM_REG(val) ((val)*25)
+
+#define PPR_MASK(fan) (0x03<<(fan *2))
+#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
+#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
+
+/* i2c-vid.h defines vid_from_reg() */
+#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
+
+#define ALARMS_FROM_REG(val) (val)
+
+/* Unlike some other drivers we DO NOT set initial limits. Use
+ * the config file to set limits. Some users have reported
+ * motherboards shutting down when we set limits in a previous
+ * version of the driver.
+ */
+
+/* Typically used with Pentium 4 systems v9.1 VRM spec */
+#define LM85_INIT_VRM 91
+
+/* Chip sampling rates
+ *
+ * Some sensors are not updated more frequently than once per second
+ * so it doesn't make sense to read them more often than that.
+ * We cache the results and return the saved data if the driver
+ * is called again before a second has elapsed.
+ *
+ * Also, there is significant configuration data for this chip
+ * given the automatic PWM fan control that is possible. There
+ * are about 47 bytes of config data to only 22 bytes of actual
+ * readings. So, we keep the config data up to date in the cache
+ * when it is written and only sample it once every 1 *minute*
+ */
+#define LM85_DATA_INTERVAL (HZ + HZ / 2)
+#define LM85_CONFIG_INTERVAL (1 * 60 * HZ)
+
+/* For each registered LM85, we need to keep some data in memory. That
+ data is pointed to by lm85_list[NR]->data. The structure itself is
+ dynamically allocated, at the same time when a new lm85 client is
+ allocated. */
+
+/* LM85 can automatically adjust fan speeds based on temperature
+ * This structure encapsulates an entire Zone config. There are
+ * three zones (one for each temperature input) on the lm85
+ */
+struct lm85_zone {
+ s8 limit; /* Low temp limit */
+ u8 hyst; /* Low limit hysteresis. (0-15) */
+ u8 range; /* Temp range, encoded */
+ s8 critical; /* "All fans ON" temp limit */
+};
+
+struct lm85_autofan {
+ u8 config; /* Register value */
+ u8 freq; /* PWM frequency, encoded */
+ u8 min_pwm; /* Minimum PWM value, encoded */
+ u8 min_off; /* Min PWM or OFF below "limit", flag */
+};
+
+struct lm85_data {
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ int valid; /* !=0 if following fields are valid */
+ unsigned long last_reading; /* In jiffies */
+ unsigned long last_config; /* In jiffies */
+
+ u8 in[5]; /* Register value */
+ u8 in_max[5]; /* Register value */
+ u8 in_min[5]; /* Register value */
+ s8 temp[3]; /* Register value */
+ s8 temp_min[3]; /* Register value */
+ s8 temp_max[3]; /* Register value */
+ s8 temp_offset[3]; /* Register value */
+ u16 fan[4]; /* Register value */
+ u16 fan_min[4]; /* Register value */
+ u8 pwm[3]; /* Register value */
+ u8 spinup_ctl; /* Register encoding, combined */
+ u8 tach_mode; /* Register encoding, combined */
+ u16 extend_adc; /* Register value */
+ u8 fan_ppr; /* Register value */
+ u8 smooth[3]; /* Register encoding */
+ u8 vid; /* Register value */
+ u8 vrm; /* VRM version */
+ u8 syncpwm3; /* Saved PWM3 for TACH 2,3,4 config */
+ u8 oppoint[3]; /* Register value */
+ u16 tmin_ctl; /* Register value */
+ u32 therm_total; /* Cummulative therm count */
+ u8 therm_limit; /* Register value */
+ u16 alarms; /* Register encoding, combined */
+ struct lm85_autofan autofan[3];
+ struct lm85_zone zone[3];
+};
+
+static int lm85_attach_adapter(struct i2c_adapter *adapter);
+static int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind);
+static int lm85_detach_client(struct i2c_client *client);
+
+static int lm85_read_value(struct i2c_client *client, u8 register);
+static int lm85_write_value(struct i2c_client *client, u8 register, int value);
+static void lm85_update_client(struct i2c_client *client);
+static void lm85_init_client(struct i2c_client *client);
+
+
+static struct i2c_driver lm85_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm85",
+ .id = I2C_DRIVERID_LM85,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = lm85_attach_adapter,
+ .detach_client = lm85_detach_client,
+};
+
+/* Unique ID assigned to each LM85 detected */
+static int lm85_id = 0;
+
+
+/* 4 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) );
+}
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) );
+}
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val);
+ lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
+ return count;
+}
+
+#define show_fan_offset(offset) \
+static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_fan_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_fan_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_fan_min(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
+ show_fan_##offset##_min, set_fan_##offset##_min)
+
+show_fan_offset(1);
+show_fan_offset(2);
+show_fan_offset(3);
+show_fan_offset(4);
+
+/* vid, vrm, alarms */
+
+static ssize_t show_vid_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+
+static ssize_t show_vrm_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->vrm = val;
+ return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+
+static ssize_t show_alarms_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+
+/* pwm */
+
+static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) );
+}
+static ssize_t set_pwm(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->pwm[nr] = PWM_TO_REG(val);
+ lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
+ return count;
+}
+static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int pwm_zone;
+
+ lm85_update_client(client);
+ pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
+ return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+}
+
+#define show_pwm_reg(offset) \
+static ssize_t show_pwm_##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_pwm_##offset (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_pwm(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm_enable(dev, buf, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm_##offset, set_pwm_##offset) \
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO, show_pwm_enable##offset, NULL)
+
+show_pwm_reg(1);
+show_pwm_reg(2);
+show_pwm_reg(3);
+
+/* Voltages */
+
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+}
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) );
+}
+static ssize_t set_in_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_min[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
+ return count;
+}
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) );
+}
+static ssize_t set_in_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_max[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
+ return count;
+}
+#define show_in_reg(offset) \
+static ssize_t show_in_##offset (struct device *dev, char *buf) \
+{ \
+ return show_in(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_in_min(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_in_max(dev, buf, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_min(dev, buf, count, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_max(dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in_##offset, NULL) \
+static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_min, set_in_##offset##_min) \
+static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_max, set_in_##offset##_max)
+
+show_in_reg(0);
+show_in_reg(1);
+show_in_reg(2);
+show_in_reg(3);
+show_in_reg(4);
+
+/* Temps */
+
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+}
+static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
+}
+static ssize_t set_temp_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_min[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
+ return count;
+}
+static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
+}
+static ssize_t set_temp_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_max[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
+ return count;
+}
+#define show_temp_reg(offset) \
+static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_temp_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_temp_max(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_min(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_max(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
+static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_min, set_temp_##offset##_min) \
+static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_max, set_temp_##offset##_max)
+
+show_temp_reg(1);
+show_temp_reg(2);
+show_temp_reg(3);
+
+
+int lm85_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, lm85_detect);
+}
+
+int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind)
+{
+ int company, verstep ;
+ struct i2c_client *new_client = NULL;
+ struct lm85_data *data;
+ int err = 0;
+ const char *type_name = "";
+
+ if (i2c_is_isa_adapter(adapter)) {
+ /* This chip has no ISA interface */
+ goto ERROR0 ;
+ };
+
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ /* We need to be able to do byte I/O */
+ goto ERROR0 ;
+ };
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access lm85_{read,write}_value. */
+
+ if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
+ sizeof(struct lm85_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ memset(new_client, 0, sizeof(struct i2c_client) +
+ sizeof(struct lm85_data));
+ data = (struct lm85_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &lm85_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ company = lm85_read_value(new_client, LM85_REG_COMPANY);
+ verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
+
+ if (lm85debug) {
+ printk("lm85: Detecting device at %d,0x%02x with"
+ " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+ i2c_adapter_id(new_client->adapter), new_client->addr,
+ company, verstep);
+ }
+
+ /* If auto-detecting, Determine the chip type. */
+ if (kind <= 0) {
+ if (lm85debug) {
+ printk("lm85: Autodetecting device at %d,0x%02x ...\n",
+ i2c_adapter_id(adapter), address );
+ }
+ if( company == LM85_COMPANY_NATIONAL
+ && verstep == LM85_VERSTEP_LM85C ) {
+ kind = lm85c ;
+ } else if( company == LM85_COMPANY_NATIONAL
+ && verstep == LM85_VERSTEP_LM85B ) {
+ kind = lm85b ;
+ } else if( company == LM85_COMPANY_NATIONAL
+ && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to LM85.\n", verstep );
+ kind = any_chip ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && verstep == LM85_VERSTEP_ADM1027 ) {
+ kind = adm1027 ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && verstep == LM85_VERSTEP_ADT7463 ) {
+ kind = adt7463 ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to ADM1027.\n", verstep );
+ kind = adm1027 ;
+ } else if( kind == 0 && (verstep & 0xf0) == 0x60) {
+ printk("lm85: Generic LM85 Version 6 detected\n");
+ /* Leave kind as "any_chip" */
+ } else {
+ if (lm85debug) {
+ printk("lm85: Autodetection failed\n");
+ }
+ /* Not an LM85 ... */
+ if( kind == 0 ) { /* User used force=x,y */
+ printk("lm85: Generic LM85 Version 6 not"
+ " found at %d,0x%02x. Try force_lm85c.\n",
+ i2c_adapter_id(adapter), address );
+ }
+ err = 0 ;
+ goto ERROR1;
+ }
+ }
+
+ /* Fill in the chip specific driver values */
+ if ( kind == any_chip ) {
+ type_name = "lm85";
+ strlcpy(new_client->dev.name, "Generic LM85", DEVICE_NAME_SIZE);
+ } else if ( kind == lm85b ) {
+ type_name = "lm85b";
+ strlcpy(new_client->dev.name, "National LM85-B", DEVICE_NAME_SIZE);
+ } else if ( kind == lm85c ) {
+ type_name = "lm85c";
+ strlcpy(new_client->dev.name, "National LM85-C", DEVICE_NAME_SIZE);
+ } else if ( kind == adm1027 ) {
+ type_name = "adm1027";
+ strlcpy(new_client->dev.name, "Analog Devices ADM1027", DEVICE_NAME_SIZE);
+ } else if ( kind == adt7463 ) {
+ type_name = "adt7463";
+ strlcpy(new_client->dev.name, "Analog Devices ADT7463", DEVICE_NAME_SIZE);
+ } else {
+ dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind);
+ err = -EFAULT ;
+ goto ERROR1;
+ }
+
+ /* Fill in the remaining client fields */
+ new_client->id = lm85_id++;
+ data->type = kind;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ if (lm85debug) {
+ printk("lm85: Assigning ID %d to %s at %d,0x%02x\n",
+ new_client->id, new_client->dev.name,
+ i2c_adapter_id(new_client->adapter),
+ new_client->addr);
+ }
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR1;
+
+ /* Set the VRM version */
+ data->vrm = LM85_INIT_VRM ;
+
+ device_create_file(&new_client->dev, &dev_attr_fan_input1);
+ device_create_file(&new_client->dev, &dev_attr_fan_input2);
+ device_create_file(&new_client->dev, &dev_attr_fan_input3);
+ device_create_file(&new_client->dev, &dev_attr_fan_input4);
+ device_create_file(&new_client->dev, &dev_attr_fan_min1);
+ device_create_file(&new_client->dev, &dev_attr_fan_min2);
+ device_create_file(&new_client->dev, &dev_attr_fan_min3);
+ device_create_file(&new_client->dev, &dev_attr_fan_min4);
+ device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable1);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable2);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable3);
+ device_create_file(&new_client->dev, &dev_attr_in_input0);
+ device_create_file(&new_client->dev, &dev_attr_in_input1);
+ device_create_file(&new_client->dev, &dev_attr_in_input2);
+ device_create_file(&new_client->dev, &dev_attr_in_input3);
+ device_create_file(&new_client->dev, &dev_attr_in_input4);
+ device_create_file(&new_client->dev, &dev_attr_in_min0);
+ device_create_file(&new_client->dev, &dev_attr_in_min1);
+ device_create_file(&new_client->dev, &dev_attr_in_min2);
+ device_create_file(&new_client->dev, &dev_attr_in_min3);
+ device_create_file(&new_client->dev, &dev_attr_in_min4);
+ device_create_file(&new_client->dev, &dev_attr_in_max0);
+ device_create_file(&new_client->dev, &dev_attr_in_max1);
+ device_create_file(&new_client->dev, &dev_attr_in_max2);
+ device_create_file(&new_client->dev, &dev_attr_in_max3);
+ device_create_file(&new_client->dev, &dev_attr_in_max4);
+ device_create_file(&new_client->dev, &dev_attr_temp_input1);
+ device_create_file(&new_client->dev, &dev_attr_temp_input2);
+ device_create_file(&new_client->dev, &dev_attr_temp_input3);
+ device_create_file(&new_client->dev, &dev_attr_temp_min1);
+ device_create_file(&new_client->dev, &dev_attr_temp_min2);
+ device_create_file(&new_client->dev, &dev_attr_temp_min3);
+ device_create_file(&new_client->dev, &dev_attr_temp_max1);
+ device_create_file(&new_client->dev, &dev_attr_temp_max2);
+ device_create_file(&new_client->dev, &dev_attr_temp_max3);
+ device_create_file(&new_client->dev, &dev_attr_vrm);
+ device_create_file(&new_client->dev, &dev_attr_vid);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+
+ /* Initialize the LM85 chip */
+ lm85_init_client(new_client);
+ return 0;
+
+ /* Error out and cleanup code */
+ ERROR1:
+ kfree(new_client);
+ ERROR0:
+ return err;
+}
+
+int lm85_detach_client(struct i2c_client *client)
+{
+ i2c_detach_client(client);
+ kfree(client);
+ return 0;
+}
+
+
+int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+ int res;
+
+ /* What size location is it? */
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Read WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ case LM85_REG_ALARM1 : /* Read both bytes at once */
+ case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */
+ res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Read WORD MSB, LSB */
+ res = i2c_smbus_read_byte_data(client, reg) << 8 ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) & 0xff ;
+ break ;
+ default: /* Read BYTE data */
+ res = i2c_smbus_read_byte_data(client, reg);
+ break ;
+ }
+
+ return res ;
+}
+
+int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+ int res ;
+
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Write WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ /* NOTE: ALARM is read only, so not included here */
+ res = i2c_smbus_write_byte_data(client, reg, value & 0xff) ;
+ res |= i2c_smbus_write_byte_data(client, reg+1, (value>>8) & 0xff) ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Write WORD MSB, LSB */
+ res = i2c_smbus_write_byte_data(client, reg, (value>>8) & 0xff);
+ res |= i2c_smbus_write_byte_data(client, reg+1, value & 0xff) ;
+ break ;
+ default: /* Write BYTE data */
+ res = i2c_smbus_write_byte_data(client, reg, value);
+ break ;
+ }
+
+ return res ;
+}
+
+void lm85_init_client(struct i2c_client *client)
+{
+ int value;
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ if (lm85debug) {
+ printk("lm85(%d): Initializing device\n", client->id);
+ }
+
+ /* Warn if part was not "READY" */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ if (lm85debug) {
+ printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
+ }
+ if( value & 0x02 ) {
+ printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( ! (value & 0x04) ) {
+ printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( value & 0x10
+ && ( data->type == adm1027
+ || data->type == adt7463 ) ) {
+ printk("lm85(%d): Client (%d,0x%02x) VxI mode is set. "
+ "Please report this to the lm85 maintainer.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+
+ /* WE INTENTIONALLY make no changes to the limits,
+ * offsets, pwms, fans and zones. If they were
+ * configured, we don't want to mess with them.
+ * If they weren't, the default is 100% PWM, no
+ * control and will suffice until 'sensors -s'
+ * can be run by the user.
+ */
+
+ /* Start monitoring */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ /* Try to clear LOCK, Set START, save everything else */
+ value = (value & ~ 0x02) | 0x01 ;
+ if (lm85debug) {
+ printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
+ }
+ lm85_write_value(client, LM85_REG_CONFIG, value);
+
+}
+
+void lm85_update_client(struct i2c_client *client)
+{
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if ( !data->valid ||
+ (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+ /* Things that change quickly */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading sensor values\n", client->id);
+ }
+ /* Have to read extended bits first to "freeze" the
+ * more significant bits that are read later.
+ */
+ if ( (data->type == adm1027) || (data->type == adt7463) ) {
+ data->extend_adc =
+ lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+ }
+
+ for (i = 0; i <= 4; ++i) {
+ data->in[i] =
+ lm85_read_value(client, LM85_REG_IN(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan[i] =
+ lm85_read_value(client, LM85_REG_FAN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp[i] =
+ lm85_read_value(client, LM85_REG_TEMP(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->pwm[i] =
+ lm85_read_value(client, LM85_REG_PWM(i));
+ }
+
+ if ( data->type == adt7463 ) {
+ if( data->therm_total < ULONG_MAX - 256 ) {
+ data->therm_total +=
+ lm85_read_value(client, ADT7463_REG_THERM );
+ }
+ }
+
+ data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+ data->last_reading = jiffies ;
+ }; /* last_reading */
+
+ if ( !data->valid ||
+ (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+ /* Things that don't change often */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading config values\n", client->id);
+ }
+ for (i = 0; i <= 4; ++i) {
+ data->in_min[i] =
+ lm85_read_value(client, LM85_REG_IN_MIN(i));
+ data->in_max[i] =
+ lm85_read_value(client, LM85_REG_IN_MAX(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan_min[i] =
+ lm85_read_value(client, LM85_REG_FAN_MIN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp_min[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+ data->temp_max[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+ }
+
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 2; ++i) {
+ int val ;
+ data->autofan[i].config =
+ lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+ val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+ data->autofan[i].freq = val & 0x07 ;
+ data->zone[i].range = (val >> 4) & 0x0f ;
+ data->autofan[i].min_pwm =
+ lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+ data->zone[i].limit =
+ lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+ data->zone[i].critical =
+ lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+ }
+
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+ data->smooth[0] = i & 0x0f ;
+ data->syncpwm3 = i & 0x10 ; /* Save PWM3 config */
+ data->autofan[0].min_off = (i & 0x20) != 0 ;
+ data->autofan[1].min_off = (i & 0x40) != 0 ;
+ data->autofan[2].min_off = (i & 0x80) != 0 ;
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE2);
+ data->smooth[1] = (i>>4) & 0x0f ;
+ data->smooth[2] = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+ data->zone[0].hyst = (i>>4) & 0x0f ;
+ data->zone[1].hyst = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+ data->zone[2].hyst = (i>>4) & 0x0f ;
+
+ if ( (data->type == lm85b) || (data->type == lm85c) ) {
+ data->tach_mode = lm85_read_value(client,
+ LM85_REG_TACH_MODE );
+ data->spinup_ctl = lm85_read_value(client,
+ LM85_REG_SPINUP_CTL );
+ } else if ( (data->type == adt7463) || (data->type == adm1027) ) {
+ if ( data->type == adt7463 ) {
+ for (i = 0; i <= 2; ++i) {
+ data->oppoint[i] = lm85_read_value(client,
+ ADT7463_REG_OPPOINT(i) );
+ }
+ data->tmin_ctl = lm85_read_value(client,
+ ADT7463_REG_TMIN_CTL1 );
+ data->therm_limit = lm85_read_value(client,
+ ADT7463_REG_THERM_LIMIT );
+ }
+ for (i = 0; i <= 2; ++i) {
+ data->temp_offset[i] = lm85_read_value(client,
+ ADM1027_REG_TEMP_OFFSET(i) );
+ }
+ data->tach_mode = lm85_read_value(client,
+ ADM1027_REG_CONFIG3 );
+ data->fan_ppr = lm85_read_value(client,
+ ADM1027_REG_FAN_PPR );
+ }
+
+ data->last_config = jiffies;
+ }; /* last_config */
+
+ data->valid = 1;
+
+ up(&data->update_lock);
+}
+
+
+static int __init sm_lm85_init(void)
+{
+ return i2c_add_driver(&lm85_driver);
+}
+
+static void __exit sm_lm85_exit(void)
+{
+ i2c_del_driver(&lm85_driver);
+}
+
+/* Thanks to Richard Barrington for adding the LM85 to sensors-detect.
+ * Thanks to Margit Schubert-While <margitsw@t-online.de> for help with
+ * post 2.7.0 CVS changes
+ */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, Margit Schubert-While <margitsw@t-online.de>");
+MODULE_DESCRIPTION("LM85-B, LM85-C driver");
+MODULE_PARM(lm85debug, "i");
+MODULE_PARM_DESC(lm85debug, "Enable debugging statements");
+
+module_init(sm_lm85_init);
+module_exit(sm_lm85_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f7e5545515e3..a200d525ccf7 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -510,7 +510,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.len = count;
- (const char *)msg.buf = buf;
+ msg.buf = (char *)buf;
DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
count));
@@ -861,13 +861,13 @@ int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
return 0;
}
-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
value,0,I2C_SMBUS_QUICK,NULL);
}
-extern s32 i2c_smbus_read_byte(struct i2c_client * client)
+s32 i2c_smbus_read_byte(struct i2c_client *client)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -877,14 +877,14 @@ extern s32 i2c_smbus_read_byte(struct i2c_client * client)
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{
union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
}
-extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -894,8 +894,7 @@ extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
- u8 value)
+s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
{
union i2c_smbus_data data;
data.byte = value;
@@ -904,7 +903,7 @@ extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
I2C_SMBUS_BYTE_DATA,&data);
}
-extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -914,8 +913,7 @@ extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
return 0x0FFFF & data.word;
}
-extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -924,8 +922,7 @@ extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
I2C_SMBUS_WORD_DATA,&data);
}
-extern s32 i2c_smbus_process_call(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -938,8 +935,7 @@ extern s32 i2c_smbus_process_call(struct i2c_client * client,
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -954,8 +950,7 @@ extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
}
}
-extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -970,8 +965,7 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -990,8 +984,7 @@ extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -1006,8 +999,7 @@ extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
}
}
-extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 7a0feb87ae4e..b5f8572e50c5 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -122,7 +122,7 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
+static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
char *tmp;
@@ -147,7 +147,7 @@ static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
return ret;
}
-static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
+static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
loff_t *offset)
{
int ret;
@@ -211,12 +211,12 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
- return (copy_to_user((unsigned long *)arg,&funcs,
+ return (copy_to_user((unsigned long __user *)arg, &funcs,
sizeof(unsigned long)))?-EFAULT:0;
case I2C_RDWR:
if (copy_from_user(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data *)arg,
+ (struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
@@ -284,7 +284,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
case I2C_SMBUS:
if (copy_from_user(&data_arg,
- (struct i2c_smbus_ioctl_data *) arg,
+ (struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
diff --git a/drivers/i2c/i2c-iop3xx.c b/drivers/i2c/i2c-iop3xx.c
new file mode 100644
index 000000000000..a1142284b1d8
--- /dev/null
+++ b/drivers/i2c/i2c-iop3xx.c
@@ -0,0 +1,536 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
+/* ------------------------------------------------------------------------- */
+/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ * <Peter dot Milne at D hyphen TACQ dot 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, version 2.
+
+
+ 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. */
+/* ------------------------------------------------------------------------- */
+/*
+ With acknowledgements to i2c-algo-ibm_ocp.c by
+ Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
+
+ And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
+
+ Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+
+ And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+
+ ---------------------------------------------------------------------------*/
+
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+
+
+#include <asm/arch-iop3xx/iop321.h>
+#include <asm/arch-iop3xx/iop321-irqs.h>
+#include "i2c-iop3xx.h"
+
+
+/* ----- global defines ----------------------------------------------- */
+#define PASSERT(x) do { if (!(x) ) \
+ printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
+ } while (0)
+
+
+/* ----- global variables --------------------------------------------- */
+
+
+static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
+{
+ unsigned char addr;
+
+ addr = (msg->addr << 1);
+
+ if (msg->flags & I2C_M_RD)
+ addr |= 1;
+
+ /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+
+ return addr;
+}
+
+
+static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ /* Follows devman 9.3 */
+ *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
+ *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
+ *iop3xx_adap->biu->CR = 0;
+}
+
+static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ *iop3xx_adap->biu->SAR = MYSAR;
+}
+
+static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+
+ /* NB SR bits not same position as CR IE bits :-( */
+ iop3xx_adap->biu->SR_enabled =
+ IOP321_ISR_ALD | IOP321_ISR_BERRD |
+ IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
+
+ cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
+
+ *iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+
+ cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
+ IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
+ *iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+
+ cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
+ iop3xx_adap->biu->SR_enabled = 0;
+ *iop3xx_adap->biu->CR = cr;
+}
+
+/*
+ * NB: the handler has to clear the source of the interrupt!
+ * Then it passes the SR flags of interest to BH via adap data
+ */
+static void iop3xx_i2c_handler(int this_irq,
+ void *dev_id,
+ struct pt_regs *regs)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+
+ u32 sr = *iop3xx_adap->biu->SR;
+
+ if ((sr &= iop3xx_adap->biu->SR_enabled)) {
+ *iop3xx_adap->biu->SR = sr;
+ iop3xx_adap->biu->SR_received |= sr;
+ wake_up_interruptible(&iop3xx_adap->waitq);
+ }
+}
+
+/* check all error conditions, clear them , report most important */
+static int iop3xx_adap_error(u32 sr)
+{
+ int rc = 0;
+
+ if ((sr&IOP321_ISR_BERRD)) {
+ if ( !rc ) rc = -I2C_ERR_BERR;
+ }
+ if ((sr&IOP321_ISR_ALD)) {
+ if ( !rc ) rc = -I2C_ERR_ALD;
+ }
+ return rc;
+}
+
+static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ unsigned long flags;
+ u32 sr;
+
+ spin_lock_irqsave(&iop3xx_adap->lock, flags);
+ sr = iop3xx_adap->biu->SR_received;
+ iop3xx_adap->biu->SR_received = 0;
+ spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
+
+ return sr;
+}
+
+/*
+ * sleep until interrupted, then recover and analyse the SR
+ * saved by handler
+ */
+typedef int (* compare_func)(unsigned test, unsigned mask);
+/* returns 1 on correct comparison */
+
+static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ unsigned flags, unsigned* status,
+ compare_func compare)
+{
+ unsigned sr = 0;
+ int interrupted;
+ int done;
+ int rc;
+
+ do {
+ interrupted = wait_event_interruptible_timeout (
+ iop3xx_adap->waitq,
+ (done = compare( sr = get_srstat(iop3xx_adap),flags )),
+ iop3xx_adap->timeout
+ );
+ if ((rc = iop3xx_adap_error(sr)) < 0) {
+ *status = sr;
+ return rc;
+ }else if (!interrupted) {
+ *status = sr;
+ return rc = -ETIMEDOUT;
+ }
+ } while(!done);
+
+ *status = sr;
+
+ return rc = 0;
+}
+
+/*
+ * Concrete compare_funcs
+ */
+static int all_bits_clear(unsigned test, unsigned mask)
+{
+ return (test & mask) == 0;
+}
+static int any_bits_set(unsigned test, unsigned mask)
+{
+ return (test & mask) != 0;
+}
+
+static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ status, any_bits_set);
+}
+
+static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ status, any_bits_set);
+}
+
+static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
+}
+
+/*
+ * Description: This performs the IOP3xx initialization sequence
+ * Valid for IOP321. Maybe valid for IOP310?.
+ */
+static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+ *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
+ IOP321_GPOD_I2C0:
+ IOP321_GPOD_I2C1);
+
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_set_slave_addr(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
+
+ return 0;
+}
+
+static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ struct i2c_msg* msg)
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
+
+ cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
+ cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
+
+ *iop3xx_adap->biu->CR = cr;
+ rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+ /* this assert fires every time, contrary to IOP manual
+ PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
+ */
+ PASSERT((status&IOP321_ISR_RXREAD)==0);
+
+ return rc;
+}
+
+static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = byte;
+ cr &= ~IOP321_ICR_MSTART;
+ if (stop) {
+ cr |= IOP321_ICR_MSTOP;
+ } else {
+ cr &= ~IOP321_ICR_MSTOP;
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+ rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+
+ return rc;
+}
+
+static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ char* byte, int stop)
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ cr &= ~IOP321_ICR_MSTART;
+
+ if (stop) {
+ cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+ } else {
+ cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+
+ rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
+
+ *byte = *iop3xx_adap->biu->DBR;
+
+ return rc;
+}
+
+static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap,
+ const char *buf, int count)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int ii;
+ int rc = 0;
+
+ for (ii = 0; rc == 0 && ii != count; ++ii) {
+ rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
+ }
+ return rc;
+}
+
+static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
+ char *buf, int count)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int ii;
+ int rc = 0;
+
+ for (ii = 0; rc == 0 && ii != count; ++ii) {
+ rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
+ }
+ return rc;
+}
+
+/*
+ * Description: This function implements combined transactions. Combined
+ * transactions consist of combinations of reading and writing blocks of data.
+ * FROM THE SAME ADDRESS
+ * Each transfer (i.e. a read or a write) is separated by a repeated start
+ * condition.
+ */
+static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int rc;
+
+ rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+ if (rc < 0) {
+ return rc;
+ }
+
+ if ((pmsg->flags&I2C_M_RD)) {
+ return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+ } else {
+ return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
+ }
+}
+
+/*
+ * master_xfer() - main read/write entry
+ */
+static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int im = 0;
+ int ret = 0;
+ int status;
+
+ iop3xx_adap_wait_idle(iop3xx_adap, &status);
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
+
+ for (im = 0; ret == 0 && im != num; ++im) {
+ ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
+ }
+
+ iop3xx_adap_transaction_cleanup(iop3xx_adap);
+
+ return ret;
+}
+
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+
+static u32 iic_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm iic_algo = {
+ .name = "IOP3xx I2C algorithm",
+ .id = I2C_ALGO_OCP_IOP3XX,
+ .master_xfer = iop3xx_master_xfer,
+ .algo_control = algo_control,
+ .functionality = iic_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ if (!request_region( REGION_START(iop3xx_adap),
+ REGION_LENGTH(iop3xx_adap),
+ iic_adap->name)) {
+ return -ENODEV;
+ }
+
+ init_waitqueue_head(&iop3xx_adap->waitq);
+ spin_lock_init(&iop3xx_adap->lock);
+
+ if (request_irq(
+ iop3xx_adap->biu->irq,
+ iop3xx_i2c_handler,
+ /* SA_SAMPLE_RANDOM */ 0,
+ iic_adap->name,
+ iop3xx_adap)) {
+ return -ENODEV;
+ }
+
+ /* register new iic_adapter to i2c module... */
+ iic_adap->id |= iic_algo.id;
+ iic_adap->algo = &iic_algo;
+
+ iic_adap->timeout = 100; /* default values, should */
+ iic_adap->retries = 3; /* be replaced by defines */
+
+ iop3xx_adap_init(iic_adap->algo_data);
+ i2c_add_adapter(iic_adap);
+ return 0;
+}
+
+static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ iop3xx_adap_final_cleanup(iop3xx_adap);
+ free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
+
+ release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+
+ return i2c_del_adapter(iic_adap);
+}
+
+#ifdef CONFIG_ARCH_IOP321
+
+static struct iop3xx_biu biu0 = {
+ .CR = IOP321_ICR0,
+ .SR = IOP321_ISR0,
+ .SAR = IOP321_ISAR0,
+ .DBR = IOP321_IDBR0,
+ .BMR = IOP321_IBMR0,
+ .irq = IRQ_IOP321_I2C_0,
+};
+
+static struct iop3xx_biu biu1 = {
+ .CR = IOP321_ICR1,
+ .SR = IOP321_ISR1,
+ .SAR = IOP321_ISAR1,
+ .DBR = IOP321_IDBR1,
+ .BMR = IOP321_IBMR1,
+ .irq = IRQ_IOP321_I2C_1,
+};
+
+#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
+#else
+#error Please define the BIU struct iop3xx_biu for your processor arch
+#endif
+
+static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
+ .channel = 0,
+ .biu = &biu0,
+ .timeout = 1*HZ,
+};
+static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
+ .channel = 1,
+ .biu = &biu1,
+ .timeout = 1*HZ,
+};
+
+static struct i2c_adapter iop3xx_ops0 = {
+ .owner = THIS_MODULE,
+ .name = ADAPTER_NAME_ROOT "0",
+ .id = I2C_HW_IOP321,
+ .algo_data = &algo_iop3xx_data0,
+};
+static struct i2c_adapter iop3xx_ops1 = {
+ .owner = THIS_MODULE,
+ .name = ADAPTER_NAME_ROOT "1",
+ .id = I2C_HW_IOP321,
+ .algo_data = &algo_iop3xx_data1,
+};
+
+static int __init i2c_iop3xx_init (void)
+{
+ return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
+ i2c_iop3xx_add_bus(&iop3xx_ops1);
+}
+
+static void __exit i2c_iop3xx_exit (void)
+{
+ i2c_iop3xx_del_bus(&iop3xx_ops0);
+ i2c_iop3xx_del_bus(&iop3xx_ops1);
+}
+
+module_init (i2c_iop3xx_init);
+module_exit (i2c_iop3xx_exit);
+
+MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(i2c_debug,"i");
+
+MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+
diff --git a/drivers/i2c/i2c-iop3xx.h b/drivers/i2c/i2c-iop3xx.h
new file mode 100644
index 000000000000..f375881842a1
--- /dev/null
+++ b/drivers/i2c/i2c-iop3xx.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */
+/* ------------------------------------------------------------------------- */
+/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ * <Peter dot Milne at D hyphen TACQ dot 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, version 2.
+
+ 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. */
+/* ------------------------------------------------------------------------- */
+
+
+#ifndef I2C_IOP3XX_H
+#define I2C_IOP3XX_H 1
+
+/*
+ * iop321 hardware bit definitions
+ */
+#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */
+#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */
+#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */
+#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */
+#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */
+#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */
+#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */
+#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */
+#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */
+/*
+ * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set
+ * when sending a master mode general call message from the I2C unit"
+ */
+#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */
+/*
+ * "NOTE: To avoid I2C bus integrity problems,
+ * the user needs to ensure that the GPIO Output Data Register -
+ * GPOD bits associated with an I2C port are cleared prior to setting
+ * the enable bit for that I2C serial port.
+ * The user prepares to enable I2C port 0 and
+ * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively.
+ */
+#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
+#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data
+ * NB TBYTE must be clear */
+#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */
+#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */
+#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */
+#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */
+
+
+#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */
+#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */
+#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */
+#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */
+#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */
+#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */
+#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */
+#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */
+#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */
+#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */
+#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */
+
+#define IOP321_ISR_CLEARBITS 0x07f0
+
+#define IOP321_ISAR_SAMASK 0x007f
+
+#define IOP321_IDBR_MASK 0x00ff
+
+#define IOP321_IBMR_SCL 0x0002
+#define IOP321_IBMR_SDA 0x0001
+
+#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
+#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
+
+#define MYSAR 0x02 /* SWAG a suitable slave address */
+
+#define I2C_ERR 321
+#define I2C_ERR_BERR (I2C_ERR+0)
+#define I2C_ERR_ALD (I2C_ERR+1)
+
+
+struct iop3xx_biu { /* Bus Interface Unit - the hardware */
+/* physical hardware defs - regs*/
+ u32 *CR;
+ u32 *SR;
+ u32 *SAR;
+ u32 *DBR;
+ u32 *BMR;
+/* irq bit vector */
+ u32 irq;
+/* stored flags */
+ u32 SR_enabled, SR_received;
+};
+
+struct i2c_algo_iop3xx_data {
+ int channel;
+
+ wait_queue_head_t waitq;
+ spinlock_t lock;
+ int timeout;
+ struct iop3xx_biu* biu;
+};
+
+#define REGION_START(adap) ((u32)((adap)->biu->CR))
+#define REGION_END(adap) ((u32)((adap)->biu->BMR+1))
+#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap))
+
+#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq)
+
+#endif /* I2C_IOP3XX_H */
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 301eecf29743..d06cfa73d893 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -29,8 +29,8 @@ config PCMCIA
and ds. If you want to compile it as a module, say M here and
read <file:Documentation/modules.txt>.
-config CARDBUS
- bool "CardBus support"
+config YENTA
+ tristate "CardBus yenta-compatible bridge support"
depends on PCMCIA && PCI
---help---
CardBus is a bus mastering architecture for PC-cards, which allows
@@ -48,6 +48,11 @@ config CARDBUS
If unsure, say Y.
+config CARDBUS
+ bool
+ depends on YENTA
+ default y if YENTA
+
config I82092
tristate "i82092 compatible bridge support"
depends on PCMCIA && PCI
@@ -58,7 +63,7 @@ config I82092
config I82365
tristate "i82365 compatible bridge support"
- depends on PCMCIA
+ depends on PCMCIA && ISA
help
Say Y here to include support for ISA-bus PCMCIA host bridges that
are register compatible with the Intel i82365. These are found on
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 32c8efc83192..6e83826cf74e 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -3,9 +3,7 @@
#
obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o
-ifeq ($(CONFIG_CARDBUS),y)
- obj-$(CONFIG_PCMCIA) += yenta_socket.o
-endif
+obj-$(CONFIG_YENTA) += yenta.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
@@ -14,8 +12,6 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
-yenta_socket-y += pci_socket.o yenta.o
-
pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
index 4419780fb6d6..01c843e44b0a 100644
--- a/drivers/pcmcia/bulkmem.c
+++ b/drivers/pcmcia/bulkmem.c
@@ -63,7 +63,7 @@ static int do_mtd_request(memory_handle_t handle, mtd_request_t *req,
{
int ret, tries;
client_t *mtd;
- socket_info_t *s;
+ struct pcmcia_socket *s;
mtd = handle->mtd;
if (mtd == NULL)
@@ -130,7 +130,7 @@ static void retry_erase(erase_busy_t *busy, u_int cause)
eraseq_entry_t *erase = busy->erase;
mtd_request_t req;
client_t *mtd;
- socket_info_t *s;
+ struct pcmcia_socket *s;
int ret;
DEBUG(2, "cs: trying erase request 0x%p...\n", busy);
@@ -259,27 +259,27 @@ static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req)
win->ctl.flags |= MAP_ATTRIB;
win->ctl.speed = req->AccessSpeed;
win->ctl.card_start = req->CardOffset;
- win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl);
+ win->sock->ss_entry->set_mem_map(win->sock, &win->ctl);
return CS_SUCCESS;
}
static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
if (req->Vpp1 != req->Vpp2)
return CS_BAD_VPP;
s = SOCKET(handle);
s->socket.Vpp = req->Vpp1;
- if (s->ss_entry->set_socket(s->sock, &s->socket))
+ if (s->ss_entry->set_socket(s, &s->socket))
return CS_BAD_VPP;
return CS_SUCCESS;
}
static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
s = SOCKET(handle);
@@ -287,7 +287,7 @@ static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
s->socket.csc_mask |= SS_READY;
else
s->socket.csc_mask &= ~SS_READY;
- if (s->ss_entry->set_socket(s->sock, &s->socket))
+ if (s->ss_entry->set_socket(s, &s->socket))
return CS_GENERAL_FAILURE;
return CS_SUCCESS;
}
@@ -417,7 +417,7 @@ static int match_region(client_handle_t handle, memory_handle_t list,
int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
{
- socket_info_t *s = SOCKET(handle);
+ struct pcmcia_socket *s = SOCKET(handle);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
@@ -450,7 +450,7 @@ int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn)
int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg)
{
memory_handle_t list;
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
@@ -533,12 +533,12 @@ int pcmcia_check_erase_queue(eraseq_handle_t eraseq)
int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
memory_handle_t region;
if ((handle == NULL) || CHECK_HANDLE(*handle))
return CS_BAD_HANDLE;
- s = SOCKET(*handle);
+ s = (*handle)->Socket;
if (open->Attributes & MEMORY_TYPE_AM)
region = s->a_region;
else
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index b10a31a7caa1..b512673bd2ac 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -119,11 +119,11 @@ static u_int xlate_rom_addr(u_char * b, u_int addr)
These are similar to setup_cis_mem and release_cis_mem for 16-bit
cards. The "result" that is used externally is the cb_cis_virt
- pointer in the socket_info_t structure.
+ pointer in the struct pcmcia_socket structure.
=====================================================================*/
-static void cb_release_cis_mem(socket_info_t * s)
+static void cb_release_cis_mem(struct pcmcia_socket * s)
{
if (s->cb_cis_virt) {
DEBUG(1, "cs: cb_release_cis_mem()\n");
@@ -133,7 +133,7 @@ static void cb_release_cis_mem(socket_info_t * s)
}
}
-static int cb_setup_cis_mem(socket_info_t * s, struct resource *res)
+static int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res)
{
unsigned int start, size;
@@ -162,7 +162,7 @@ static int cb_setup_cis_mem(socket_info_t * s, struct resource *res)
=====================================================================*/
-int read_cb_mem(socket_info_t * s, int space, u_int addr, u_int len, void *ptr)
+int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr)
{
struct pci_dev *dev;
struct resource *res;
@@ -237,7 +237,7 @@ static void cardbus_assign_irqs(struct pci_bus *bus, int irq)
}
}
-int cb_alloc(socket_info_t * s)
+int cb_alloc(struct pcmcia_socket * s)
{
struct pci_bus *bus = s->cap.cb_dev->subordinate;
struct pci_dev *dev;
@@ -266,7 +266,7 @@ int cb_alloc(socket_info_t * s)
return CS_SUCCESS;
}
-void cb_free(socket_info_t * s)
+void cb_free(struct pcmcia_socket * s)
{
struct pci_dev *bridge = s->cap.cb_dev;
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 303ee17d6825..5d27f616dee4 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -82,11 +82,11 @@ static const u_int exponent[] = {
INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
-void release_cis_mem(socket_info_t *s)
+void release_cis_mem(struct pcmcia_socket *s)
{
if (s->cis_mem.sys_start != 0) {
s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+ s->ss_entry->set_mem_map(s, &s->cis_mem);
if (!(s->cap.features & SS_CAP_STATIC_MAP))
release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
iounmap(s->cis_virt);
@@ -101,7 +101,7 @@ void release_cis_mem(socket_info_t *s)
* map the memory space.
*/
static unsigned char *
-set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags)
+set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
{
pccard_mem_map *mem = &s->cis_mem;
if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
@@ -119,7 +119,7 @@ set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags)
}
mem->card_start = card_offset;
mem->flags = flags;
- s->ss_entry->set_mem_map(s->sock, mem);
+ s->ss_entry->set_mem_map(s, mem);
if (s->cap.features & SS_CAP_STATIC_MAP) {
if (s->cis_virt)
iounmap(s->cis_virt);
@@ -139,7 +139,7 @@ set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags)
#define IS_ATTR 1
#define IS_INDIRECT 8
-int read_cis_mem(socket_info_t *s, int attr, u_int addr,
+int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
u_char *sys, *end, *buf = ptr;
@@ -202,7 +202,7 @@ int read_cis_mem(socket_info_t *s, int attr, u_int addr,
return 0;
}
-void write_cis_mem(socket_info_t *s, int attr, u_int addr,
+void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
u_char *sys, *end, *buf = ptr;
@@ -266,7 +266,7 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr,
======================================================================*/
-static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
+static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
struct cis_cache_entry *cis;
@@ -306,7 +306,7 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
}
static void
-remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len)
+remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
{
struct cis_cache_entry *cis;
@@ -318,7 +318,7 @@ remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len)
}
}
-void destroy_cis_cache(socket_info_t *s)
+void destroy_cis_cache(struct pcmcia_socket *s)
{
struct list_head *l, *n;
@@ -337,7 +337,7 @@ void destroy_cis_cache(socket_info_t *s)
======================================================================*/
-int verify_cis_cache(socket_info_t *s)
+int verify_cis_cache(struct pcmcia_socket *s)
{
struct cis_cache_entry *cis;
char buf[256];
@@ -369,7 +369,7 @@ int verify_cis_cache(socket_info_t *s)
int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
s = SOCKET(handle);
@@ -409,7 +409,7 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
s = SOCKET(handle);
@@ -445,7 +445,7 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
return pcmcia_get_next_tuple(handle, tuple);
}
-static int follow_link(socket_info_t *s, tuple_t *tuple)
+static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
{
u_char link[5];
u_int ofs;
@@ -487,7 +487,7 @@ static int follow_link(socket_info_t *s, tuple_t *tuple)
int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
u_char link[2], tmp;
int ofs, i, attr;
@@ -588,7 +588,7 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
u_int len;
if (CHECK_HANDLE(handle))
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index ba9a69e5c5e2..be950332b550 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -124,9 +124,11 @@ socket_state_t dead_socket = {
0, SS_DETECT, 0, 0, 0
};
-/* Table of sockets */
-socket_t sockets = 0;
-socket_info_t *socket_table[MAX_SOCK];
+
+/* List of all sockets, protected by a rwsem */
+LIST_HEAD(pcmcia_socket_list);
+DECLARE_RWSEM(pcmcia_socket_list_rwsem);
+
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_pccard = NULL;
@@ -235,48 +237,48 @@ static const lookup_t service_table[] = {
======================================================================*/
-static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info)
+static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
int error;
if (handler && !try_module_get(s->ss_entry->owner))
return -ENODEV;
- error = s->ss_entry->register_callback(s->sock, handler, info);
+ error = s->ss_entry->register_callback(s, handler, info);
if (!handler)
module_put(s->ss_entry->owner);
return error;
}
-static int get_socket_status(socket_info_t *s, int *val)
+static int get_socket_status(struct pcmcia_socket *s, int *val)
{
- return s->ss_entry->get_status(s->sock, val);
+ return s->ss_entry->get_status(s, val);
}
-static int set_socket(socket_info_t *s, socket_state_t *state)
+static int set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
- return s->ss_entry->set_socket(s->sock, state);
+ return s->ss_entry->set_socket(s, state);
}
-static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
+static int set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
{
- return s->ss_entry->set_io_map(s->sock, io);
+ return s->ss_entry->set_io_map(s, io);
}
-static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
+static int set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
{
- return s->ss_entry->set_mem_map(s->sock, mem);
+ return s->ss_entry->set_mem_map(s, mem);
}
-static int suspend_socket(socket_info_t *s)
+static int suspend_socket(struct pcmcia_socket *s)
{
s->socket = dead_socket;
- return s->ss_entry->suspend(s->sock);
+ return s->ss_entry->suspend(s);
}
-static int init_socket(socket_info_t *s)
+static int init_socket(struct pcmcia_socket *s)
{
s->socket = dead_socket;
- return s->ss_entry->init(s->sock);
+ return s->ss_entry->init(s);
}
/*====================================================================*/
@@ -285,7 +287,7 @@ static int init_socket(socket_info_t *s)
static int proc_read_clients(char *buf, char **start, off_t pos,
int count, int *eof, void *data)
{
- socket_info_t *s = data;
+ struct pcmcia_socket *s = data;
client_handle_t c;
char *p = buf;
@@ -303,145 +305,226 @@ static int proc_read_clients(char *buf, char **start, off_t pos,
======================================================================*/
-static int pccardd(void *__skt);
-void pcmcia_unregister_socket(struct class_device *dev);
+/**
+ * socket drivers are expected to use the following callbacks in their
+ * .drv struct:
+ * - pcmcia_socket_dev_suspend
+ * - pcmcia_socket_dev_resume
+ * These functions check for the appropriate struct pcmcia_soket arrays,
+ * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
+ */
+static int socket_resume(struct pcmcia_socket *skt);
+static int socket_suspend(struct pcmcia_socket *skt);
+
+int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct pcmcia_socket *socket;
+
+ if (level != SUSPEND_SAVE_STATE)
+ return 0;
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+ if (socket->dev.dev != dev)
+ continue;
+ down(&socket->skt_sem);
+ socket_suspend(socket);
+ up(&socket->skt_sem);
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
+
+int pcmcia_socket_dev_resume(struct device *dev, u32 level)
+{
+ struct pcmcia_socket *socket;
+ if (level != RESUME_RESTORE_STATE)
+ return 0;
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+ if (socket->dev.dev != dev)
+ continue;
+ down(&socket->skt_sem);
+ socket_resume(socket);
+ up(&socket->skt_sem);
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+
+
+static int pccardd(void *__skt);
#define to_class_data(dev) dev->class_data
-/**
- * pcmcia_register_socket - add a new pcmcia socket device
- */
-int pcmcia_register_socket(struct class_device *class_dev)
+static int pcmcia_add_socket(struct class_device *class_dev)
{
- struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
- socket_info_t *s_info;
- unsigned int i, j, ret;
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
+ int ret = 0;
- if (!cls_d)
- return -EINVAL;
+ /* base address = 0, map = 0 */
+ socket->cis_mem.flags = 0;
+ socket->cis_mem.speed = cis_speed;
+ socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
+ INIT_LIST_HEAD(&socket->cis_cache);
+ spin_lock_init(&socket->lock);
- DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops);
-
- s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL);
- if (!s_info)
- return -ENOMEM;
- memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
-
- cls_d->s_info = s_info;
- ret = 0;
-
- /* socket initialization */
- for (i = 0; i < cls_d->nsock; i++) {
- socket_info_t *s = &s_info[i];
-
- s->ss_entry = cls_d->ops;
- s->sock = i + cls_d->sock_offset;
-
- /* base address = 0, map = 0 */
- s->cis_mem.flags = 0;
- s->cis_mem.speed = cis_speed;
- s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
- INIT_LIST_HEAD(&s->cis_cache);
- spin_lock_init(&s->lock);
-
- /* TBD: remove usage of socket_table, use class_for_each_dev instead */
- for (j = 0; j < sockets; j++)
- if (socket_table[j] == NULL) break;
- socket_table[j] = s;
- if (j == sockets) sockets++;
-
- init_socket(s);
- s->ss_entry->inquire_socket(s->sock, &s->cap);
-
- init_completion(&s->thread_done);
- init_waitqueue_head(&s->thread_wait);
- init_MUTEX(&s->skt_sem);
- spin_lock_init(&s->thread_lock);
- ret = kernel_thread(pccardd, s, CLONE_KERNEL);
- if (ret < 0) {
- pcmcia_unregister_socket(class_dev);
- break;
- }
+ init_socket(socket);
+ socket->ss_entry->inquire_socket(socket, &socket->cap);
+
+ init_completion(&socket->thread_done);
+ init_waitqueue_head(&socket->thread_wait);
+ init_MUTEX(&socket->skt_sem);
+ spin_lock_init(&socket->thread_lock);
+ ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
+ if (ret < 0)
+ return ret;
- wait_for_completion(&s->thread_done);
- BUG_ON(!s->thread);
+ wait_for_completion(&socket->thread_done);
+ BUG_ON(!socket->thread);
#ifdef CONFIG_PROC_FS
- if (proc_pccard) {
- char name[3];
- sprintf(name, "%02d", j);
- s->proc = proc_mkdir(name, proc_pccard);
- if (s->proc)
- s->ss_entry->proc_setup(i, s->proc);
+ if (proc_pccard) {
+ char name[3];
+ sprintf(name, "%02d", socket->sock);
+ socket->proc = proc_mkdir(name, proc_pccard);
+ if (socket->proc)
+ socket->ss_entry->proc_setup(socket, socket->proc);
#ifdef PCMCIA_DEBUG
- if (s->proc)
- create_proc_read_entry("clients", 0, s->proc,
- proc_read_clients, s);
+ if (socket->proc)
+ create_proc_read_entry("clients", 0, socket->proc,
+ proc_read_clients, socket);
#endif
- }
+ }
+#endif
+ return 0;
+}
+
+static void pcmcia_remove_socket(struct class_device *class_dev)
+{
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
+ client_t *client;
+
+#ifdef CONFIG_PROC_FS
+ if (proc_pccard) {
+ char name[3];
+ sprintf(name, "%02d", socket->sock);
+#ifdef PCMCIA_DEBUG
+ remove_proc_entry("clients", socket->proc);
#endif
+ remove_proc_entry(name, proc_pccard);
}
- return ret;
+#endif
+ if (socket->thread) {
+ init_completion(&socket->thread_done);
+ socket->thread = NULL;
+ wake_up(&socket->thread_wait);
+ wait_for_completion(&socket->thread_done);
+ }
+ release_cis_mem(socket);
+ while (socket->clients) {
+ client = socket->clients;
+ socket->clients = socket->clients->next;
+ kfree(client);
+ }
+ socket->ss_entry = NULL;
+}
+
+
+/**
+ * pcmcia_register_socket - add a new pcmcia socket device
+ */
+int pcmcia_register_socket(struct pcmcia_socket *socket)
+{
+ if (!socket || !socket->ss_entry || !socket->dev.dev)
+ return -EINVAL;
+
+ DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ss_entry);
+
+ /* try to obtain a socket number [yes, it gets ugly if we
+ * register more than 2^sizeof(unsigned int) pcmcia
+ * sockets... but the socket number is deprecated
+ * anyways, so I don't care] */
+ down_write(&pcmcia_socket_list_rwsem);
+ if (list_empty(&pcmcia_socket_list))
+ socket->sock = 0;
+ else {
+ unsigned int found, i = 1;
+ struct pcmcia_socket *tmp;
+ do {
+ found = 1;
+ list_for_each_entry(tmp, &pcmcia_socket_list, socket_list) {
+ if (tmp->sock == i)
+ found = 0;
+ }
+ i++;
+ } while (!found);
+ socket->sock = i - 1;
+ }
+ list_add_tail(&socket->socket_list, &pcmcia_socket_list);
+ up_write(&pcmcia_socket_list_rwsem);
+
+
+ /* set proper values in socket->dev */
+ socket->dev.class_data = socket;
+ socket->dev.class = &pcmcia_socket_class;
+ snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u\n", socket->sock);
+
+ /* register with the device core */
+ if (class_device_register(&socket->dev)) {
+ down_write(&pcmcia_socket_list_rwsem);
+ list_del(&socket->socket_list);
+ up_write(&pcmcia_socket_list_rwsem);
+ return -EINVAL;
+ }
+
+ return 0;
} /* pcmcia_register_socket */
+EXPORT_SYMBOL(pcmcia_register_socket);
/**
* pcmcia_unregister_socket - remove a pcmcia socket device
*/
-void pcmcia_unregister_socket(struct class_device *class_dev)
+void pcmcia_unregister_socket(struct pcmcia_socket *socket)
{
- struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
- unsigned int i;
- int j, socket = -1;
- client_t *client;
- socket_info_t *s;
-
- if (!cls_d)
+ if (!socket)
return;
- s = (socket_info_t *) cls_d->s_info;
+ DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ss_entry);
- for (i = 0; i < cls_d->nsock; i++) {
- for (j = 0; j < MAX_SOCK; j++)
- if (socket_table [j] == s) {
- socket = j;
- break;
- }
- if (socket < 0)
- continue;
-
-#ifdef CONFIG_PROC_FS
- if (proc_pccard) {
- char name[3];
- sprintf(name, "%02d", socket);
-#ifdef PCMCIA_DEBUG
- remove_proc_entry("clients", s->proc);
-#endif
- remove_proc_entry(name, proc_pccard);
- }
-#endif
- if (s->thread) {
- init_completion(&s->thread_done);
- s->thread = NULL;
- wake_up(&s->thread_wait);
- wait_for_completion(&s->thread_done);
- }
- release_cis_mem(s);
- while (s->clients) {
- client = s->clients;
- s->clients = s->clients->next;
- kfree(client);
- }
- s->ss_entry = NULL;
- socket_table[socket] = NULL;
- for (j = socket; j < sockets-1; j++)
- socket_table[j] = socket_table[j+1];
- sockets--;
+ /* remove from the device core */
+ class_device_unregister(&socket->dev);
- s++;
- }
- kfree(cls_d->s_info);
+ /* remove from our own list */
+ down_write(&pcmcia_socket_list_rwsem);
+ list_del(&socket->socket_list);
+ up_write(&pcmcia_socket_list_rwsem);
} /* pcmcia_unregister_socket */
+EXPORT_SYMBOL(pcmcia_unregister_socket);
+
+
+struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
+{
+ struct pcmcia_socket *s;
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list)
+ if (s->sock == nr) {
+ up_read(&pcmcia_socket_list_rwsem);
+ return s;
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return NULL;
+
+}
+EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
/*======================================================================
@@ -465,9 +548,9 @@ static void free_regions(memory_handle_t *list)
}
}
-static int send_event(socket_info_t *s, event_t event, int priority);
+static int send_event(struct pcmcia_socket *s, event_t event, int priority);
-static void shutdown_socket(socket_info_t *s)
+static void shutdown_socket(struct pcmcia_socket *s)
{
client_t **c;
@@ -522,7 +605,7 @@ static void shutdown_socket(socket_info_t *s)
======================================================================*/
-static int send_event(socket_info_t *s, event_t event, int priority)
+static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
client_t *client = s->clients;
int ret;
@@ -543,7 +626,7 @@ static int send_event(socket_info_t *s, event_t event, int priority)
return ret;
} /* send_event */
-static void pcmcia_error(socket_info_t *skt, const char *fmt, ...)
+static void pcmcia_error(struct pcmcia_socket *skt, const char *fmt, ...)
{
static char buf[128];
va_list ap;
@@ -559,7 +642,7 @@ static void pcmcia_error(socket_info_t *skt, const char *fmt, ...)
#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
-static void socket_remove_drivers(socket_info_t *skt)
+static void socket_remove_drivers(struct pcmcia_socket *skt)
{
client_t *client;
@@ -570,7 +653,7 @@ static void socket_remove_drivers(socket_info_t *skt)
client->state |= CLIENT_STALE;
}
-static void socket_shutdown(socket_info_t *skt)
+static void socket_shutdown(struct pcmcia_socket *skt)
{
socket_remove_drivers(skt);
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -579,7 +662,7 @@ static void socket_shutdown(socket_info_t *skt)
shutdown_socket(skt);
}
-static int socket_reset(socket_info_t *skt)
+static int socket_reset(struct pcmcia_socket *skt)
{
int status, i;
@@ -609,7 +692,7 @@ static int socket_reset(socket_info_t *skt)
return CS_GENERAL_FAILURE;
}
-static int socket_setup(socket_info_t *skt, int initial_delay)
+static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
{
int status, i;
@@ -673,7 +756,7 @@ static int socket_setup(socket_info_t *skt, int initial_delay)
* Handle card insertion. Setup the socket, reset the card,
* and then tell the rest of PCMCIA that a card is present.
*/
-static int socket_insert(socket_info_t *skt)
+static int socket_insert(struct pcmcia_socket *skt)
{
int ret;
@@ -693,7 +776,7 @@ static int socket_insert(socket_info_t *skt)
return ret;
}
-static int socket_suspend(socket_info_t *skt)
+static int socket_suspend(struct pcmcia_socket *skt)
{
if (skt->state & SOCKET_SUSPEND)
return CS_IN_USE;
@@ -710,7 +793,7 @@ static int socket_suspend(socket_info_t *skt)
* our cached copy. If they are different, the card has been
* replaced, and we need to tell the drivers.
*/
-static int socket_resume(socket_info_t *skt)
+static int socket_resume(struct pcmcia_socket *skt)
{
int ret;
@@ -742,7 +825,7 @@ static int socket_resume(socket_info_t *skt)
static int pccardd(void *__skt)
{
- socket_info_t *skt = __skt;
+ struct pcmcia_socket *skt = __skt;
DECLARE_WAITQUEUE(wait, current);
daemonize("pccardd");
@@ -799,7 +882,7 @@ static int pccardd(void *__skt)
static void parse_events(void *info, u_int events)
{
- socket_info_t *s = info;
+ struct pcmcia_socket *s = info;
spin_lock(&s->thread_lock);
s->thread_events |= events;
@@ -808,68 +891,6 @@ static void parse_events(void *info, u_int events)
wake_up(&s->thread_wait);
} /* parse_events */
-/*======================================================================
-
- Another event handler, for power management events.
-
- This does not comply with the latest PC Card spec for handling
- power management events.
-
-======================================================================*/
-
-void pcmcia_suspend_socket (socket_info_t *skt)
-{
- down(&skt->skt_sem);
- socket_suspend(skt);
- up(&skt->skt_sem);
-}
-
-void pcmcia_resume_socket (socket_info_t *skt)
-{
- down(&skt->skt_sem);
- socket_resume(skt);
- up(&skt->skt_sem);
-}
-
-
-int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level)
-{
- socket_info_t *s;
- int i;
-
- if ((!cls_d) || (level != SUSPEND_SAVE_STATE))
- return 0;
-
- s = (socket_info_t *) cls_d->s_info;
-
- for (i = 0; i < cls_d->nsock; i++) {
- pcmcia_suspend_socket(s);
- s++;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-
-int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level)
-{
- socket_info_t *s;
- int i;
-
- if ((!cls_d) || (level != RESUME_RESTORE_STATE))
- return 0;
-
- s = (socket_info_t *) cls_d->s_info;
-
- for (i = 0; i < cls_d->nsock; i++) {
- pcmcia_resume_socket(s);
- s++;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_resume);
-
/*======================================================================
@@ -877,7 +898,7 @@ EXPORT_SYMBOL(pcmcia_socket_dev_resume);
======================================================================*/
-static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
+static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
ioaddr_t num, u_int lines, char *name)
{
int i;
@@ -941,7 +962,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
return (i == MAX_IO_WIN);
} /* alloc_io_space */
-static void release_io_space(socket_info_t *s, ioaddr_t base,
+static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
ioaddr_t num)
{
int i;
@@ -969,7 +990,7 @@ static void release_io_space(socket_info_t *s, ioaddr_t base,
int pcmcia_access_configuration_register(client_handle_t handle,
conf_reg_t *reg)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
int addr;
u_char val;
@@ -1020,18 +1041,18 @@ int pcmcia_access_configuration_register(client_handle_t handle,
int pcmcia_bind_device(bind_req_t *req)
{
client_t *client;
- socket_info_t *s;
+ struct pcmcia_socket *s;
- if (CHECK_SOCKET(req->Socket))
- return CS_BAD_SOCKET;
- s = SOCKET(req);
+ s = req->Socket;
+ if (!s)
+ return CS_BAD_SOCKET;
client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
if (!client) return CS_OUT_OF_RESOURCE;
memset(client, '\0', sizeof(client_t));
client->client_magic = CLIENT_MAGIC;
strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
- client->Socket = req->Socket;
+ client->Socket = s;
client->Function = req->Function;
client->state = CLIENT_UNBOUND;
client->erase_busy.next = &client->erase_busy;
@@ -1055,12 +1076,12 @@ int pcmcia_bind_device(bind_req_t *req)
int pcmcia_bind_mtd(mtd_bind_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
memory_handle_t region;
- if (CHECK_SOCKET(req->Socket))
- return CS_BAD_SOCKET;
- s = SOCKET(req);
+ s = req->Socket;
+ if (!s)
+ return CS_BAD_SOCKET;
if (req->Attributes & REGION_TYPE_AM)
region = s->a_region;
@@ -1085,10 +1106,10 @@ int pcmcia_bind_mtd(mtd_bind_t *req)
int pcmcia_deregister_client(client_handle_t handle)
{
client_t **client;
- socket_info_t *s;
+ struct pcmcia_socket *s;
memory_handle_t region;
u_long flags;
- int i, sn;
+ int i;
DEBUG(1, "cs: deregister_client(%p)\n", handle);
if (CHECK_HANDLE(handle))
@@ -1109,8 +1130,6 @@ int pcmcia_deregister_client(client_handle_t handle)
if (region->mtd == handle) region->mtd = NULL;
}
- sn = handle->Socket; s = socket_table[sn];
-
if ((handle->state & CLIENT_STALE) ||
(handle->Attributes & INFO_MASTER_CLIENT)) {
spin_lock_irqsave(&s->lock, flags);
@@ -1142,7 +1161,7 @@ int pcmcia_deregister_client(client_handle_t handle)
int pcmcia_get_configuration_info(client_handle_t handle,
config_info_t *config)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
if (CHECK_HANDLE(handle))
@@ -1212,9 +1231,15 @@ int pcmcia_get_configuration_info(client_handle_t handle,
int pcmcia_get_card_services_info(servinfo_t *info)
{
+ unsigned int socket_count = 0;
+ struct list_head *tmp;
info->Signature[0] = 'C';
info->Signature[1] = 'S';
- info->Count = sockets;
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each(tmp, &pcmcia_socket_list)
+ socket_count++;
+ up_read(&pcmcia_socket_list_rwsem);
+ info->Count = socket_count;
info->Revision = CS_RELEASE_CODE;
info->CSLevel = 0x0210;
info->VendorString = (char *)release;
@@ -1231,15 +1256,17 @@ int pcmcia_get_card_services_info(servinfo_t *info)
int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
{
socket_t s;
+ struct pcmcia_socket *socket;
if (req->Attributes & CLIENT_THIS_SOCKET)
s = req->Socket;
else
s = 0;
- if (CHECK_SOCKET(req->Socket))
+ socket = pcmcia_get_socket_by_nr(s);
+ if (!socket)
return CS_BAD_SOCKET;
- if (socket_table[s]->clients == NULL)
+ if (socket->clients == NULL)
return CS_NO_MORE_ITEMS;
- *handle = socket_table[s]->clients;
+ *handle = socket->clients;
return CS_SUCCESS;
} /* get_first_client */
@@ -1247,13 +1274,13 @@ int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if ((handle == NULL) || CHECK_HANDLE(*handle))
return CS_BAD_HANDLE;
if ((*handle)->next == NULL) {
if (req->Attributes & CLIENT_THIS_SOCKET)
return CS_NO_MORE_ITEMS;
- s = SOCKET(*handle);
+ s = (*handle)->Socket;
if (s->clients == NULL)
return CS_NO_MORE_ITEMS;
*handle = s->clients;
@@ -1266,12 +1293,12 @@ int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
window_t *win;
int w;
if (idx == 0)
- s = SOCKET((client_handle_t)*handle);
+ s = ((client_handle_t)*handle)->Socket;
else
s = (*handle)->sock;
if (!(s->state & SOCKET_PRESENT))
@@ -1321,7 +1348,7 @@ int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
struct pci_bus *pcmcia_lookup_bus(client_handle_t handle)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle))
return NULL;
@@ -1345,7 +1372,7 @@ EXPORT_SYMBOL(pcmcia_lookup_bus);
int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
int val;
@@ -1424,7 +1451,7 @@ int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
return CS_BAD_HANDLE;
if (req->Page != 0)
@@ -1445,7 +1472,7 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
int pcmcia_modify_configuration(client_handle_t handle,
modconf_t *mod)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
if (CHECK_HANDLE(handle))
@@ -1522,14 +1549,13 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req)
int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
{
- client_t *client;
- socket_info_t *s;
- socket_t ns;
+ client_t *client = NULL;
+ struct pcmcia_socket *s;
/* Look for unbound client with matching dev_info */
- client = NULL;
- for (ns = 0; ns < sockets; ns++) {
- client = socket_table[ns]->clients;
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ client = s->clients;
while (client != NULL) {
if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
&& (client->state & CLIENT_UNBOUND)) break;
@@ -1537,10 +1563,10 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
}
if (client != NULL) break;
}
+ up_read(&pcmcia_socket_list_rwsem);
if (client == NULL)
return CS_OUT_OF_RESOURCE;
- s = socket_table[ns];
if (++s->real_clients == 1) {
register_callback(s, &parse_events, s);
parse_events(s, SS_DETECT);
@@ -1548,7 +1574,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
*handle = client;
client->state &= ~CLIENT_UNBOUND;
- client->Socket = ns;
+ client->Socket = s;
client->Attributes = req->Attributes;
client->EventMask = req->EventMask;
client->event_handler = req->event_handler;
@@ -1577,8 +1603,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
client, client->Socket, client->dev_info);
if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
- if ((socket_table[ns]->state & SOCKET_PRESENT) &&
- !(socket_table[ns]->state & SOCKET_SETUP_PENDING)) {
+ if ((s->state & SOCKET_PRESENT) &&
+ !(s->state & SOCKET_SETUP_PENDING)) {
if (client->EventMask & CS_EVENT_CARD_INSERTION)
EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
else
@@ -1592,7 +1618,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
int pcmcia_release_configuration(client_handle_t handle)
{
pccard_io_map io = { 0, 0, 0, 0, 1 };
- socket_info_t *s;
+ struct pcmcia_socket *s;
int i;
if (CHECK_HANDLE(handle) ||
@@ -1642,7 +1668,7 @@ int pcmcia_release_configuration(client_handle_t handle)
int pcmcia_release_io(client_handle_t handle, io_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
return CS_BAD_HANDLE;
@@ -1677,7 +1703,7 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req)
int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
return CS_BAD_HANDLE;
handle->state &= ~CLIENT_IRQ_REQ;
@@ -1713,7 +1739,7 @@ int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
int pcmcia_release_window(window_handle_t win)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
return CS_BAD_HANDLE;
@@ -1743,13 +1769,13 @@ int pcmcia_request_configuration(client_handle_t handle,
{
int i;
u_int base;
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
pccard_io_map iomap;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
+ s = SOCKET(handle);
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
@@ -1872,7 +1898,7 @@ int pcmcia_request_configuration(client_handle_t handle,
int pcmcia_request_io(client_handle_t handle, io_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
if (CHECK_HANDLE(handle))
@@ -1936,7 +1962,7 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req)
int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
config_t *c;
int ret = 0, irq = 0;
@@ -2011,14 +2037,14 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
{
- socket_info_t *s;
+ struct pcmcia_socket *s;
window_t *win;
u_long align;
int w;
if (CHECK_HANDLE(*handle))
return CS_BAD_HANDLE;
- s = SOCKET(*handle);
+ s = (*handle)->Socket;
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (req->Attributes & (WIN_PAGED | WIN_SHARED))
@@ -2096,7 +2122,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
{
- socket_info_t *skt;
+ struct pcmcia_socket *skt;
int ret;
if (CHECK_HANDLE(handle))
@@ -2145,7 +2171,7 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
{
- socket_info_t *skt;
+ struct pcmcia_socket *skt;
int ret;
if (CHECK_HANDLE(handle))
@@ -2172,7 +2198,7 @@ int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
{
- socket_info_t *skt;
+ struct pcmcia_socket *skt;
int ret;
if (CHECK_HANDLE(handle))
@@ -2205,7 +2231,7 @@ int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
{
- socket_info_t *skt;
+ struct pcmcia_socket *skt;
int ret;
if (CHECK_HANDLE(handle))
@@ -2234,7 +2260,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
{
- socket_info_t *skt;
+ struct pcmcia_socket *skt;
int ret;
if (CHECK_HANDLE(handle))
@@ -2519,11 +2545,6 @@ EXPORT_SYMBOL(MTDHelperEntry);
EXPORT_SYMBOL(proc_pccard);
#endif
-EXPORT_SYMBOL(pcmcia_register_socket);
-EXPORT_SYMBOL(pcmcia_unregister_socket);
-EXPORT_SYMBOL(pcmcia_suspend_socket);
-EXPORT_SYMBOL(pcmcia_resume_socket);
-
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
};
@@ -2531,8 +2552,8 @@ EXPORT_SYMBOL(pcmcia_socket_class);
static struct class_interface pcmcia_socket = {
.class = &pcmcia_socket_class,
- .add = &pcmcia_register_socket,
- .remove = &pcmcia_unregister_socket,
+ .add = &pcmcia_add_socket,
+ .remove = &pcmcia_remove_socket,
};
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index ffe7980fe161..11c50e4a6049 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -21,13 +21,6 @@
#include <linux/config.h>
-typedef struct erase_busy_t {
- eraseq_entry_t *erase;
- client_handle_t client;
- struct timer_list timeout;
- struct erase_busy_t *prev, *next;
-} erase_busy_t;
-
#define ERASEQ_MAGIC 0xFA67
typedef struct eraseq_t {
u_short eraseq_magic;
@@ -39,7 +32,7 @@ typedef struct eraseq_t {
#define CLIENT_MAGIC 0x51E6
typedef struct client_t {
u_short client_magic;
- socket_t Socket;
+ struct pcmcia_socket *Socket;
u_char Function;
dev_info_t dev_info;
u_int Attributes;
@@ -63,23 +56,6 @@ typedef struct client_t {
#define CLIENT_WIN_REQ(i) (0x20<<(i))
#define CLIENT_CARDBUS 0x8000
-typedef struct io_window_t {
- u_int Attributes;
- ioaddr_t BasePort, NumPorts;
- ioaddr_t InUse, Config;
-} io_window_t;
-
-#define WINDOW_MAGIC 0xB35C
-typedef struct window_t {
- u_short magic;
- u_short index;
- client_handle_t handle;
- struct socket_info_t *sock;
- u_long base;
- u_long size;
- pccard_mem_map ctl;
-} window_t;
-
#define REGION_MAGIC 0xE3C9
typedef struct region_t {
u_short region_magic;
@@ -108,12 +84,6 @@ typedef struct config_t {
} irq;
} config_t;
-/* Maximum number of IO windows per socket */
-#define MAX_IO_WIN 2
-
-/* Maximum number of memory windows per socket */
-#define MAX_WIN 4
-
struct cis_cache_entry {
struct list_head node;
unsigned int addr;
@@ -122,48 +92,6 @@ struct cis_cache_entry {
unsigned char cache[0];
};
-typedef struct socket_info_t {
- spinlock_t lock;
- struct pccard_operations * ss_entry;
- u_int sock;
- socket_state_t socket;
- socket_cap_t cap;
- u_int state;
- u_short functions;
- u_short lock_count;
- client_handle_t clients;
- u_int real_clients;
- pccard_mem_map cis_mem;
- u_char *cis_virt;
- config_t *config;
-#ifdef CONFIG_CARDBUS
- struct resource * cb_cis_res;
- u_char *cb_cis_virt;
-#endif
- struct {
- u_int AssignedIRQ;
- u_int Config;
- } irq;
- io_window_t io[MAX_IO_WIN];
- window_t win[MAX_WIN];
- region_t *c_region, *a_region;
- erase_busy_t erase_busy;
- struct list_head cis_cache;
- u_int fake_cis_len;
- char *fake_cis;
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc;
-#endif
-
- struct semaphore skt_sem; /* protects socket h/w state */
-
- struct task_struct *thread;
- struct completion thread_done;
- wait_queue_head_t thread_wait;
- spinlock_t thread_lock; /* protects thread_events */
- unsigned int thread_events;
-} socket_info_t;
-
/* Flags in config state */
#define CONFIG_LOCKED 0x01
#define CONFIG_IRQ_REQ 0x02
@@ -187,7 +115,7 @@ typedef struct socket_info_t {
#define CHECK_SOCKET(s) \
(((s) >= sockets) || (socket_table[s]->ss_entry == NULL))
-#define SOCKET(h) (socket_table[(h)->Socket])
+#define SOCKET(h) (h->Socket)
#define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
#define CHECK_REGION(r) \
@@ -200,19 +128,19 @@ typedef struct socket_info_t {
((h)->event_handler((e), (p), &(h)->event_callback_args))
/* In cardbus.c */
-int cb_alloc(socket_info_t *s);
-void cb_free(socket_info_t *s);
-int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr);
+int cb_alloc(struct pcmcia_socket *s);
+void cb_free(struct pcmcia_socket *s);
+int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr);
/* In cistpl.c */
-int read_cis_mem(socket_info_t *s, int attr,
+int read_cis_mem(struct pcmcia_socket *s, int attr,
u_int addr, u_int len, void *ptr);
-void write_cis_mem(socket_info_t *s, int attr,
+void write_cis_mem(struct pcmcia_socket *s, int attr,
u_int addr, u_int len, void *ptr);
-void release_cis_mem(socket_info_t *s);
-void destroy_cis_cache(socket_info_t *s);
-int verify_cis_cache(socket_info_t *s);
-void preload_cis_cache(socket_info_t *s);
+void release_cis_mem(struct pcmcia_socket *s);
+void destroy_cis_cache(struct pcmcia_socket *s);
+int verify_cis_cache(struct pcmcia_socket *s);
+void preload_cis_cache(struct pcmcia_socket *s);
int get_first_tuple(client_handle_t handle, tuple_t *tuple);
int get_next_tuple(client_handle_t handle, tuple_t *tuple);
int get_tuple_data(client_handle_t handle, tuple_t *tuple);
@@ -236,11 +164,11 @@ int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf);
int copy_memory(memory_handle_t handle, copy_op_t *req);
/* In rsrc_mgr */
-void validate_mem(socket_info_t *s);
+void validate_mem(struct pcmcia_socket *s);
int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
- char *name, socket_info_t *s);
+ char *name, struct pcmcia_socket *s);
int find_mem_region(u_long *base, u_long num, u_long align,
- int force_low, char *name, socket_info_t *s);
+ int force_low, char *name, struct pcmcia_socket *s);
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj);
@@ -250,9 +178,8 @@ int proc_read_io(char *buf, char **start, off_t pos,
int proc_read_mem(char *buf, char **start, off_t pos,
int count, int *eof, void *data);
-#define MAX_SOCK 8
-extern socket_t sockets;
-extern socket_info_t *socket_table[MAX_SOCK];
+extern struct rw_semaphore pcmcia_socket_list_rwsem;
+extern struct list_head pcmcia_socket_list;
#ifdef CONFIG_PROC_FS
extern struct proc_dir_entry *proc_pccard;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 8f4e8c2e8476..b06d677a1dc3 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -107,8 +107,7 @@ struct pcmcia_bus_socket {
struct work_struct removal;
socket_bind_t *bind;
struct device *socket_dev;
- struct list_head socket_list;
- unsigned int socket_no; /* deprecated */
+ struct pcmcia_socket *parent;
};
#define SOCKET_PRESENT 0x01
@@ -122,10 +121,6 @@ static dev_info_t dev_info = "Driver Services";
static int major_dev = -1;
-/* list of all sockets registered with the pcmcia bus driver */
-static DECLARE_RWSEM(bus_socket_list_rwsem);
-static LIST_HEAD(bus_socket_list);
-
extern struct proc_dir_entry *proc_pccard;
/*====================================================================*/
@@ -164,20 +159,6 @@ EXPORT_SYMBOL(pcmcia_register_driver);
*/
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
- socket_bind_t *b;
- struct pcmcia_bus_socket *bus_sock;
-
- if (driver->use_count > 0) {
- /* Blank out any left-over device instances */
- driver->attach = NULL; driver->detach = NULL;
- down_read(&bus_socket_list_rwsem);
- list_for_each_entry(bus_sock, &bus_socket_list, socket_list) {
- for (b = bus_sock->bind; b; b = b->next)
- if (b->driver == driver)
- b->instance = NULL;
- }
- up_read(&bus_socket_list_rwsem);
- }
driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_unregister_driver);
@@ -319,14 +300,14 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info)
bind_req.dev_info = &mtd_info->dev_info;
bind_req.Attributes = mtd_info->Attributes;
- bind_req.Socket = bus_sock->socket_no;
+ bind_req.Socket = bus_sock->parent;
bind_req.CardOffset = mtd_info->CardOffset;
ret = pcmcia_bind_mtd(&bind_req);
if (ret != CS_SUCCESS) {
cs_error(NULL, BindMTD, ret);
printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
" offset 0x%x\n",
- (char *)bind_req.dev_info, bus_sock->socket_no, bind_req.CardOffset);
+ (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset);
return -ENODEV;
}
return 0;
@@ -351,7 +332,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
if (!s)
return -EINVAL;
- DEBUG(2, "bind_request(%d, '%s')\n", s->socket_no,
+ DEBUG(2, "bind_request(%d, '%s')\n", s->parent->sock,
(char *)bind_info->dev_info);
driver = get_pcmcia_driver(&bind_info->dev_info);
if (!driver)
@@ -366,14 +347,18 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
return -EBUSY;
}
- bind_req.Socket = s->socket_no;
+ if (!try_module_get(driver->owner))
+ return -EINVAL;
+
+ bind_req.Socket = s->parent;
bind_req.Function = bind_info->function;
bind_req.dev_info = (dev_info_t *) driver->drv.name;
ret = pcmcia_bind_device(&bind_req);
if (ret != CS_SUCCESS) {
cs_error(NULL, BindDevice, ret);
printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
- (char *)dev_info, s->socket_no);
+ (char *)dev_info, s->parent->sock);
+ module_put(driver->owner);
return -ENODEV;
}
@@ -383,6 +368,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
if (!b)
{
driver->use_count--;
+ module_put(driver->owner);
return -ENOMEM;
}
b->driver = driver;
@@ -396,6 +382,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
if (b->instance == NULL) {
printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", (char *)bind_info->dev_info);
+ module_put(driver->owner);
return -ENODEV;
}
}
@@ -476,7 +463,7 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
socket_bind_t **b, *c;
- DEBUG(2, "unbind_request(%d, '%s')\n", s->socket_no,
+ DEBUG(2, "unbind_request(%d, '%s')\n", s->parent->sock,
(char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next)
if ((strcmp((char *)(*b)->driver->drv.name,
@@ -492,9 +479,9 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
if (c->instance)
c->driver->detach(c->instance);
}
+ module_put(c->driver->owner);
*b = c->next;
kfree(c);
-
return 0;
} /* unbind_request */
@@ -832,13 +819,13 @@ static struct file_operations ds_fops = {
.poll = ds_poll,
};
-static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr)
+static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
{
+ struct pcmcia_socket *socket = class_dev->class_data;
client_reg_t client_reg;
bind_req_t bind;
- struct pcmcia_bus_socket *s, *tmp_s;
+ struct pcmcia_bus_socket *s;
int ret;
- int i;
s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL);
if(!s)
@@ -855,28 +842,15 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int sock
init_waitqueue_head(&s->queue);
init_waitqueue_head(&s->request);
- /* find the lowest, unused socket no. Please note that this is a
- * temporary workaround until "struct pcmcia_socket" is introduced
- * into cs.c which will include this number, and which will be
- * accessible to ds.c directly */
- i = 0;
- next_try:
- list_for_each_entry(tmp_s, &bus_socket_list, socket_list) {
- if (tmp_s->socket_no == i) {
- i++;
- goto next_try;
- }
- }
- s->socket_no = i;
-
/* initialize data */
- s->socket_dev = dev;
+ s->socket_dev = socket->dev.dev;
INIT_WORK(&s->removal, handle_removal, s);
-
+ s->parent = socket;
+
/* Set up hotline to Card Services */
client_reg.dev_info = bind.dev_info = &dev_info;
- bind.Socket = s->socket_no;
+ bind.Socket = socket;
bind.Function = BIND_FN_ALL;
ret = pcmcia_bind_device(&bind);
if (ret != CS_SUCCESS) {
@@ -901,50 +875,26 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int sock
return -EINVAL;
}
- list_add(&s->socket_list, &bus_socket_list);
+ socket->pcmcia = s;
return 0;
}
-static int pcmcia_bus_add_socket_dev(struct class_device *class_dev)
-{
- struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
- unsigned int i;
- unsigned int ret = 0;
-
- if (!cls_d)
- return -ENODEV;
-
- down_write(&bus_socket_list_rwsem);
- for (i = 0; i < cls_d->nsock; i++)
- ret += pcmcia_bus_add_socket(class_dev->dev, i);
- up_write(&bus_socket_list_rwsem);
-
- return ret;
-}
-
-static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev)
{
- struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
- struct list_head *list_loop;
- struct list_head *tmp_storage;
+ struct pcmcia_socket *socket = class_dev->class_data;
- if (!cls_d)
+ if (!socket || !socket->pcmcia)
return;
flush_scheduled_work();
- down_write(&bus_socket_list_rwsem);
- list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) {
- struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list);
- if (bus_sock->socket_dev == class_dev->dev) {
- pcmcia_deregister_client(bus_sock->handle);
- list_del(&bus_sock->socket_list);
- kfree(bus_sock);
- }
- }
- up_write(&bus_socket_list_rwsem);
+ pcmcia_deregister_client(socket->pcmcia->handle);
+
+ kfree(socket->pcmcia);
+ socket->pcmcia = NULL;
+
return;
}
@@ -952,8 +902,8 @@ static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev)
/* the pcmcia_bus_interface is used to handle pcmcia socket devices */
static struct class_interface pcmcia_bus_interface = {
.class = &pcmcia_socket_class,
- .add = &pcmcia_bus_add_socket_dev,
- .remove = &pcmcia_bus_remove_socket_dev,
+ .add = &pcmcia_bus_add_socket,
+ .remove = &pcmcia_bus_remove_socket,
};
@@ -1008,18 +958,13 @@ module_exit(exit_pcmcia_bus);
/* helpers for backwards-compatible functions */
-
static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr)
{
- struct pcmcia_bus_socket * s;
- down_read(&bus_socket_list_rwsem);
- list_for_each_entry(s, &bus_socket_list, socket_list)
- if (s->socket_no == nr) {
- up_read(&bus_socket_list_rwsem);
- return s;
- }
- up_read(&bus_socket_list_rwsem);
- return NULL;
+ struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr);
+ if (s && s->pcmcia)
+ return s->pcmcia;
+ else
+ return NULL;
}
/* backwards-compatible accessing of driver --- by name! */
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index f998ba48db4c..d3591ae10ebe 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -44,14 +44,12 @@ MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
{
- struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
- return pcmcia_socket_dev_suspend(cls_d, state, 0);
+ return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
}
static int i82092aa_socket_resume (struct pci_dev *dev)
{
- struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
- return pcmcia_socket_dev_resume(cls_d, RESUME_RESTORE_STATE);
+ return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
}
static struct pci_driver i82092aa_pci_drv = {
@@ -82,6 +80,7 @@ static struct pccard_operations i82092aa_operations = {
/* The card can do upto 4 sockets, allocate a structure for each of them */
struct socket_info {
+ int number;
int card_state; /* 0 = no socket,
1 = empty socket,
2 = card but not initialized,
@@ -95,6 +94,7 @@ struct socket_info {
/* callback to the driver of the card */
void *info; /* to be passed to the handler */
+ struct pcmcia_socket socket;
struct pci_dev *dev; /* The PCI device for the socket */
};
@@ -107,7 +107,6 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic
{
unsigned char configbyte;
int i, ret;
- struct pcmcia_socket_class_data *cls_d;
enter("i82092aa_pci_probe");
@@ -146,6 +145,8 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic
sockets[i].cap.map_size = 0x1000;
sockets[i].cap.irq_mask = 0;
sockets[i].cap.pci_irq = dev->irq;
+
+ sockets[i].number = i;
if (card_present(i)) {
sockets[i].card_state = 3;
@@ -166,26 +167,26 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic
goto err_out_free_res;
}
-
- cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL);
- if (!cls_d) {
- printk(KERN_ERR "i82092aa: kmalloc failed\n");
- goto err_out_free_irq;
+ pci_set_drvdata(dev, &sockets[i].socket);
+
+ for (i = 0; i<socket_count; i++) {
+ sockets[i].socket.dev.dev = &dev->dev;
+ sockets[i].socket.ss_entry = &i82092aa_operations;
+ ret = pcmcia_register_socket(&sockets[i].socket);
+ if (ret) {
+ goto err_out_free_sockets;
+ }
}
- memset(cls_d, 0, sizeof(*cls_d));
- cls_d->nsock = socket_count;
- cls_d->ops = &i82092aa_operations;
- pci_set_drvdata(dev, &cls_d);
- cls_d->class_dev.class = &pcmcia_socket_class;
- cls_d->class_dev.dev = &dev->dev;
- strlcpy(cls_d->class_dev.class_id, dev->dev.name, BUS_ID_SIZE);
- class_set_devdata(&cls_d->class_dev, cls_d);
- class_device_register(&cls_d->class_dev);
leave("i82092aa_pci_probe");
return 0;
-err_out_free_irq:
+err_out_free_sockets:
+ if (i) {
+ for (i--;i>=0;i--) {
+ pcmcia_unregister_socket(&sockets[i].socket);
+ }
+ }
free_irq(dev->irq, i82092aa_interrupt);
err_out_free_res:
release_region(pci_resource_start(dev, 0), 2);
@@ -196,16 +197,14 @@ err_out_disable:
static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
{
- struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
+ struct pcmcia_socket *socket = pci_get_drvdata(dev);
enter("i82092aa_pci_remove");
free_irq(dev->irq, i82092aa_interrupt);
- if (cls_d) {
- class_device_unregister(&cls_d->class_dev);
- kfree(cls_d);
- }
+ if (socket)
+ pcmcia_unregister_socket(socket);
leave("i82092aa_pci_remove");
}
@@ -447,7 +446,7 @@ static void set_bridge_state(int sock)
-static int i82092aa_init(unsigned int s)
+static int i82092aa_init(struct pcmcia_socket *sock)
{
int i;
pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -456,21 +455,21 @@ static int i82092aa_init(unsigned int s)
enter("i82092aa_init");
mem.sys_stop = 0x0fff;
- i82092aa_set_socket(s, &dead_socket);
+ i82092aa_set_socket(sock, &dead_socket);
for (i = 0; i < 2; i++) {
io.map = i;
- i82092aa_set_io_map(s, &io);
+ i82092aa_set_io_map(sock, &io);
}
for (i = 0; i < 5; i++) {
mem.map = i;
- i82092aa_set_mem_map(s, &mem);
+ i82092aa_set_mem_map(sock, &mem);
}
leave("i82092aa_init");
return 0;
}
-static int i82092aa_suspend(unsigned int sock)
+static int i82092aa_suspend(struct pcmcia_socket *sock)
{
int retval;
enter("i82092aa_suspend");
@@ -479,8 +478,9 @@ static int i82092aa_suspend(unsigned int sock)
return retval;
}
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
enter("i82092aa_register_callback");
sockets[sock].handler = handler;
sockets[sock].info = info;
@@ -488,8 +488,9 @@ static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *,
return 0;
} /* i82092aa_register_callback */
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
enter("i82092aa_inquire_socket");
*cap = sockets[sock].cap;
leave("i82092aa_inquire_socket");
@@ -497,8 +498,9 @@ static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
} /* i82092aa_inquire_socket */
-static int i82092aa_get_status(unsigned int sock, u_int *value)
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned int status;
enter("i82092aa_get_status");
@@ -539,8 +541,9 @@ static int i82092aa_get_status(unsigned int sock, u_int *value)
}
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state)
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned char reg,vcc,vpp;
enter("i82092aa_get_socket");
@@ -610,8 +613,9 @@ static int i82092aa_get_socket(unsigned int sock, socket_state_t *state)
return 0;
}
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state)
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned char reg;
enter("i82092aa_set_socket");
@@ -706,8 +710,9 @@ static int i82092aa_set_socket(unsigned int sock, socket_state_t *state)
return 0;
}
-static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned char map, ioctl;
enter("i82092aa_set_io_map");
@@ -749,8 +754,9 @@ static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
return 0;
}
-static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem)
{
+ unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned short base, i;
unsigned char map;
@@ -826,7 +832,7 @@ static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
return 0;
}
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base)
{
}
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index 191a3bd92097..eb1c307fbeff 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -28,16 +28,16 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
-static int i82092aa_get_status(unsigned int sock, u_int *value);
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io);
-static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem);
-static int i82092aa_init(unsigned int s);
-static int i82092aa_suspend(unsigned int sock);
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap);
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base);
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
+static int i82092aa_init(struct pcmcia_socket *socket);
+static int i82092aa_suspend(struct pcmcia_socket *socket);
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info);
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap);
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base);
#endif
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 560503d3917d..c5536fe45702 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -91,7 +91,6 @@ static inline int _check_irq(int irq, int flags)
/* Parameters that can be set with 'insmod' */
-#ifdef CONFIG_ISA
/* Default base address for i82365sl and other ISA chips */
static int i365_base = 0x3e0;
/* Should we probe at 0x3e2 for an extra ISA controller? */
@@ -103,7 +102,6 @@ static u_int irq_mask = 0xffff;
static int irq_list[16] = { -1 };
/* The card status change interrupt -- 0 means autoselect */
static int cs_irq = 0;
-#endif
/* Probe for safe interrupts? */
static int do_scan = 1;
@@ -122,14 +120,11 @@ static int setup_time = -1;
static int cmd_time = -1;
static int recov_time = -1;
-#ifdef CONFIG_ISA
/* Vadem options */
static int async_clock = -1;
static int cable_mode = -1;
static int wakeup = 0;
-#endif
-#ifdef CONFIG_ISA
MODULE_PARM(i365_base, "i");
MODULE_PARM(ignore, "i");
MODULE_PARM(extra_sockets, "i");
@@ -139,7 +134,6 @@ MODULE_PARM(cs_irq, "i");
MODULE_PARM(async_clock, "i");
MODULE_PARM(cable_mode, "i");
MODULE_PARM(wakeup, "i");
-#endif
MODULE_PARM(do_scan, "i");
MODULE_PARM(poll_interval, "i");
@@ -164,8 +158,10 @@ typedef struct vg46x_state_t {
u_char ctl, ema;
} vg46x_state_t;
-typedef struct socket_info_t {
+struct i82365_socket {
u_short type, flags;
+ struct pcmcia_socket socket;
+ unsigned int number;
socket_cap_t cap;
ioaddr_t ioaddr;
u_short psock;
@@ -179,26 +175,21 @@ typedef struct socket_info_t {
cirrus_state_t cirrus;
vg46x_state_t vg46x;
} state;
-} socket_info_t;
+};
/* Where we keep track of our sockets... */
static int sockets = 0;
-static socket_info_t socket[8] = {
+static struct i82365_socket socket[8] = {
{ 0, }, /* ... */
};
/* Default ISA interrupt mask */
#define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
-#ifdef CONFIG_ISA
static int grab_irq;
static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
-#else
-#define ISA_LOCK(n, f) do { } while (0)
-#define ISA_UNLOCK(n, f) do { } while (0)
-#endif
static struct timer_list poll_timer;
@@ -209,13 +200,11 @@ static struct timer_list poll_timer;
PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
/* These definitions must match the pcic table! */
-#ifdef CONFIG_ISA
typedef enum pcic_id {
IS_I82365A, IS_I82365B, IS_I82365DF,
IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
IS_PD6710, IS_PD672X, IS_VT83C469,
} pcic_id;
-#endif
/* Flags for classifying groups of controllers */
#define IS_VADEM 0x0001
@@ -237,7 +226,6 @@ typedef struct pcic_t {
} pcic_t;
static pcic_t pcic[] = {
-#ifdef CONFIG_ISA
{ "Intel i82365sl A step", 0 },
{ "Intel i82365sl B step", 0 },
{ "Intel i82365sl DF", IS_DF_PWR },
@@ -249,7 +237,6 @@ static pcic_t pcic[] = {
{ "Cirrus PD6710", IS_CIRRUS },
{ "Cirrus PD672x", IS_CIRRUS },
{ "VIA VT83C469", IS_CIRRUS|IS_VIA },
-#endif
};
#define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t))
@@ -364,7 +351,7 @@ static void cirrus_set_state(u_short s)
static u_int __init cirrus_set_opts(u_short s, char *buf)
{
- socket_info_t *t = &socket[s];
+ struct i82365_socket *t = &socket[s];
cirrus_state_t *p = &socket[s].state.cirrus;
u_int mask = 0xffff;
@@ -421,8 +408,6 @@ static u_int __init cirrus_set_opts(u_short s, char *buf)
======================================================================*/
-#ifdef CONFIG_ISA
-
static void vg46x_get_state(u_short s)
{
vg46x_state_t *p = &socket[s].state.vg46x;
@@ -464,9 +449,6 @@ static u_int __init vg46x_set_opts(u_short s, char *buf)
return 0xffff;
}
-#endif
-
-
/*======================================================================
Generic routines to get and set controller options
@@ -475,18 +457,16 @@ static u_int __init vg46x_set_opts(u_short s, char *buf)
static void get_bridge_state(u_short s)
{
- socket_info_t *t = &socket[s];
+ struct i82365_socket *t = &socket[s];
if (t->flags & IS_CIRRUS)
cirrus_get_state(s);
-#ifdef CONFIG_ISA
else if (t->flags & IS_VADEM)
vg46x_get_state(s);
-#endif
}
static void set_bridge_state(u_short s)
{
- socket_info_t *t = &socket[s];
+ struct i82365_socket *t = &socket[s];
if (t->flags & IS_CIRRUS)
cirrus_set_state(s);
else {
@@ -494,10 +474,8 @@ static void set_bridge_state(u_short s)
i365_set(s, I365_GENCTL, 0x00);
}
i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
-#ifdef CONFIG_ISA
if (t->flags & IS_VADEM)
vg46x_set_state(s);
-#endif
}
static u_int __init set_bridge_opts(u_short s, u_short ns)
@@ -515,10 +493,8 @@ static u_int __init set_bridge_opts(u_short s, u_short ns)
get_bridge_state(i);
if (socket[i].flags & IS_CIRRUS)
m = cirrus_set_opts(i, buf);
-#ifdef CONFIG_ISA
else if (socket[i].flags & IS_VADEM)
m = vg46x_set_opts(i, buf);
-#endif
set_bridge_state(i);
printk(KERN_INFO " host opts [%d]:%s\n", i,
(*buf) ? buf : " none");
@@ -571,7 +547,6 @@ static u_int __init test_irq(u_short sock, int irq)
return (irq_hits != 1);
}
-#ifdef CONFIG_ISA
static u_int __init isa_scan(u_short sock, u_int mask0)
{
@@ -617,7 +592,6 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
return mask1;
}
-#endif /* CONFIG_ISA */
/*====================================================================*/
@@ -630,7 +604,6 @@ static int to_cycles(int ns)
/*====================================================================*/
-#ifdef CONFIG_ISA
static int __init identify(u_short port, u_short sock)
{
@@ -691,8 +664,6 @@ static int __init identify(u_short port, u_short sock)
return type;
} /* identify */
-#endif
-
/*======================================================================
See if a card is present, powered up, in IO mode, and already
@@ -737,7 +708,7 @@ static void __init add_pcic(int ns, int type)
{
u_int mask = 0, i, base;
int use_pci = 0, isa_irq = 0;
- socket_info_t *t = &socket[sockets-ns];
+ struct i82365_socket *t = &socket[sockets-ns];
base = sockets-ns;
if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
@@ -748,23 +719,17 @@ static void __init add_pcic(int ns, int type)
t->ioaddr, t->psock*0x40);
printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
-#ifdef CONFIG_ISA
/* Set host options, build basic interrupt mask */
if (irq_list[0] == -1)
mask = irq_mask;
else
for (i = mask = 0; i < 16; i++)
mask |= (1<<irq_list[i]);
-#endif
mask &= I365_MASK & set_bridge_opts(base, ns);
-#ifdef CONFIG_ISA
/* Scan for ISA interrupts */
mask = isa_scan(base, mask);
-#else
printk(KERN_INFO " PCI card interrupts,");
-#endif
-#ifdef CONFIG_ISA
/* Poll if only two interrupts available */
if (!use_pci && !poll_interval) {
u_int tmp = (mask & 0xff20);
@@ -786,7 +751,6 @@ static void __init add_pcic(int ns, int type)
printk(" status change on irq %d\n", cs_irq);
}
}
-#endif
if (!use_pci && !isa_irq) {
if (poll_interval == 0)
@@ -809,7 +773,6 @@ static void __init add_pcic(int ns, int type)
/*====================================================================*/
-#ifdef CONFIG_ISA
#ifdef CONFIG_PNP
static struct isapnp_device_id id_table[] __initdata = {
@@ -902,7 +865,6 @@ static void __init isa_probe(void)
}
}
-#endif
/*====================================================================*/
@@ -940,9 +902,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
{
int i, j, csc;
u_int events, active;
-#ifdef CONFIG_ISA
u_long flags = 0;
-#endif
int handled = 0;
DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
@@ -1013,8 +973,9 @@ static void pcic_interrupt_wrapper(u_long data)
/*====================================================================*/
-static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
socket[sock].handler = handler;
socket[sock].info = info;
return 0;
@@ -1022,8 +983,9 @@ static int pcic_register_callback(unsigned int sock, void (*handler)(void *, uns
/*====================================================================*/
-static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int pcic_inquire_socket(struct pcmcia_socket *s, socket_cap_t *cap)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
*cap = socket[sock].cap;
return 0;
} /* pcic_inquire_socket */
@@ -1048,7 +1010,6 @@ static int i365_get_status(u_short sock, u_int *value)
*value |= (status & I365_CS_READY) ? SS_READY : 0;
*value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
-#ifdef CONFIG_ISA
if (socket[sock].type == IS_VG469) {
status = i365_get(sock, VG469_VSENSE);
if (socket[sock].psock & 1) {
@@ -1059,7 +1020,6 @@ static int i365_get_status(u_short sock, u_int *value)
*value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
}
}
-#endif
DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
return 0;
@@ -1069,7 +1029,7 @@ static int i365_get_status(u_short sock, u_int *value)
static int i365_get_socket(u_short sock, socket_state_t *state)
{
- socket_info_t *t = &socket[sock];
+ struct i82365_socket *t = &socket[sock];
u_char reg, vcc, vpp;
reg = i365_get(sock, I365_POWER);
@@ -1141,7 +1101,7 @@ static int i365_get_socket(u_short sock, socket_state_t *state)
static int i365_set_socket(u_short sock, socket_state_t *state)
{
- socket_info_t *t = &socket[sock];
+ struct i82365_socket *t = &socket[sock];
u_char reg;
DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
@@ -1337,7 +1297,7 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
static int proc_read_info(char *buf, char **start, off_t pos,
int count, int *eof, void *data)
{
- socket_info_t *s = data;
+ struct i82365_socket *s = data;
char *p = buf;
p += sprintf(p, "type: %s\npsock: %d\n",
pcic[s->type].name, s->psock);
@@ -1347,13 +1307,11 @@ static int proc_read_info(char *buf, char **start, off_t pos,
static int proc_read_exca(char *buf, char **start, off_t pos,
int count, int *eof, void *data)
{
- u_short sock = (socket_info_t *)data - socket;
+ u_short sock = (struct i82365_socket *)data - socket;
char *p = buf;
int i, top;
-#ifdef CONFIG_ISA
u_long flags = 0;
-#endif
ISA_LOCK(sock, flags);
top = 0x40;
for (i = 0; i < top; i += 4) {
@@ -1370,9 +1328,9 @@ static int proc_read_exca(char *buf, char **start, off_t pos,
return (p - buf);
}
-static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void pcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
{
- socket_info_t *s = &socket[sock];
+ struct i82365_socket *s = container_of(sock, struct i82365_socket, socket);
if (s->flags & IS_ALIVE)
return;
@@ -1398,15 +1356,8 @@ static void pcic_proc_remove(u_short sock)
/*====================================================================*/
-/*
- * The locking is rather broken. Why do we only lock for ISA, not for
- * all other cases? If there are reasons to lock, we should lock. Not
- * this silly conditional.
- *
- * Plan: make it bug-for-bug compatible with the old stuff, and clean
- * it up when the infrastructure is done.
- */
-#ifdef CONFIG_ISA
+/* this is horribly ugly... proper locking needs to be done here at
+ * some time... */
#define LOCKED(x) do { \
int retval; \
unsigned long flags; \
@@ -1415,13 +1366,12 @@ static void pcic_proc_remove(u_short sock)
spin_unlock_irqrestore(&isa_lock, flags); \
return retval; \
} while (0)
-#else
-#define LOCKED(x) return x
-#endif
-static int pcic_get_status(unsigned int sock, u_int *value)
+static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
if (socket[sock].flags & IS_ALIVE) {
*value = 0;
return -EINVAL;
@@ -1430,39 +1380,45 @@ static int pcic_get_status(unsigned int sock, u_int *value)
LOCKED(i365_get_status(sock, value));
}
-static int pcic_get_socket(unsigned int sock, socket_state_t *state)
+static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_get_socket(sock, state));
}
-static int pcic_set_socket(unsigned int sock, socket_state_t *state)
+static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_socket(sock, state));
}
-static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_io_map(sock, io));
}
-static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
{
+ unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_mem_map(sock, mem));
}
-static int pcic_init(unsigned int s)
+static int pcic_init(struct pcmcia_socket *s)
{
int i;
pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -1481,7 +1437,7 @@ static int pcic_init(unsigned int s)
return 0;
}
-static int pcic_suspend(unsigned int sock)
+static int pcic_suspend(struct pcmcia_socket *sock)
{
return pcic_set_socket(sock, &dead_socket);
}
@@ -1502,15 +1458,11 @@ static struct pccard_operations pcic_operations = {
/*====================================================================*/
-static struct pcmcia_socket_class_data i82365_data = {
- .ops = &pcic_operations,
-};
-
static struct device_driver i82365_driver = {
.name = "i82365",
.bus = &platform_bus_type,
-/* .suspend = pcmcia_socket_dev_suspend, FIXME? */
-/* .resume = pcmcia_socket_dev_resume, FIXME? */
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device i82365_device = {
@@ -1521,13 +1473,11 @@ static struct platform_device i82365_device = {
},
};
-static struct class_device i82365_class_data = {
- .class = &pcmcia_socket_class,
-};
-
static int __init init_i82365(void)
{
servinfo_t serv;
+ int i, ret;
+
pcmcia_get_card_services_info(&serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "i82365: Card Services release "
@@ -1541,9 +1491,7 @@ static int __init init_i82365(void)
printk(KERN_INFO "Intel PCIC probe: ");
sockets = 0;
-#ifdef CONFIG_ISA
isa_probe();
-#endif
if (sockets == 0) {
printk("not found.\n");
@@ -1551,19 +1499,24 @@ static int __init init_i82365(void)
return -ENODEV;
}
+ platform_device_register(&i82365_device);
+
/* Set up interrupt handler(s) */
-#ifdef CONFIG_ISA
if (grab_irq != 0)
request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
-#endif
- i82365_data.nsock = sockets;
- i82365_class_data.dev = &i82365_device.dev;
- i82365_class_data.class_data = &i82365_data;
- strlcpy(i82365_class_data.class_id, "i82365", BUS_ID_SIZE);
-
- platform_device_register(&i82365_device);
- class_device_register(&i82365_class_data);
+ /* register sockets with the pcmcia core */
+ for (i = 0; i < sockets; i++) {
+ socket[i].socket.dev.dev = &i82365_device.dev;
+ socket[i].socket.ss_entry = &pcic_operations;
+ socket[i].number = i;
+ ret = pcmcia_register_socket(&socket[i].socket);
+ if (ret && i--) {
+ for (; i>= 0; i--)
+ pcmcia_unregister_socket(&socket[i].socket);
+ break;
+ }
+ }
/* Finally, schedule a polling interrupt */
if (poll_interval != 0) {
@@ -1581,23 +1534,23 @@ static int __init init_i82365(void)
static void __exit exit_i82365(void)
{
int i;
+ for (i = 0; i < sockets; i++) {
+ pcmcia_unregister_socket(&socket[i].socket);
#ifdef CONFIG_PROC_FS
- for (i = 0; i < sockets; i++) pcic_proc_remove(i);
+ pcic_proc_remove(i);
#endif
- class_device_unregister(&i82365_class_data);
+ }
platform_device_unregister(&i82365_device);
if (poll_interval != 0)
del_timer_sync(&poll_timer);
-#ifdef CONFIG_ISA
if (grab_irq != 0)
free_irq(cs_irq, pcic_interrupt);
-#endif
for (i = 0; i < sockets; i++) {
/* Turn off all interrupt sources! */
i365_set(i, I365_CSCINT, 0);
release_region(socket[i].ioaddr, 2);
}
-#if defined(CONFIG_ISA) && defined(__ISAPNP__)
+#ifdef __ISAPNP__
if (i82365_pnpdev)
pnp_disable_dev(i82365_pnpdev);
#endif
diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
deleted file mode 100644
index 915a6af9faca..000000000000
--- a/drivers/pcmcia/pci_socket.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Generic PCI pccard driver interface.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * This implements the common parts of PCI pccard drivers,
- * notably detection and infrastructure conversion (ie change
- * from socket index to "struct pci_dev" etc)
- *
- * This does NOT implement the actual low-level driver details,
- * and this has on purpose been left generic enough that it can
- * be used to set up a PCI PCMCIA controller (ie non-cardbus),
- * or to set up a controller.
- *
- * See for example the "yenta" driver for PCI cardbus controllers
- * conforming to the yenta cardbus specifications.
- */
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-
-#include <pcmcia/ss.h>
-
-#include <asm/io.h>
-
-#include "pci_socket.h"
-
-
-/*
- * Arbitrary define. This is the array of active cardbus
- * entries.
- */
-#define MAX_SOCKETS (8)
-static pci_socket_t pci_socket_array[MAX_SOCKETS];
-
-static int pci_init_socket(unsigned int sock)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->init)
- return socket->op->init(socket);
- return -EINVAL;
-}
-
-static int pci_suspend_socket(unsigned int sock)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->suspend)
- return socket->op->suspend(socket);
- return -EINVAL;
-}
-
-static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- socket->handler = handler;
- socket->info = info;
- return 0;
-}
-
-static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- *cap = socket->cap;
- return 0;
-}
-
-static int pci_get_status(unsigned int sock, unsigned int *value)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->get_status)
- return socket->op->get_status(socket, value);
- *value = 0;
- return -EINVAL;
-}
-
-static int pci_get_socket(unsigned int sock, socket_state_t *state)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->get_socket)
- return socket->op->get_socket(socket, state);
- return -EINVAL;
-}
-
-static int pci_set_socket(unsigned int sock, socket_state_t *state)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->set_socket)
- return socket->op->set_socket(socket, state);
- return -EINVAL;
-}
-
-static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->set_io_map)
- return socket->op->set_io_map(socket, io);
- return -EINVAL;
-}
-
-static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->set_mem_map)
- return socket->op->set_mem_map(socket, mem);
- return -EINVAL;
-}
-
-static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
-{
- pci_socket_t *socket = pci_socket_array + sock;
-
- if (socket->op && socket->op->proc_setup)
- socket->op->proc_setup(socket, base);
-}
-
-static struct pccard_operations pci_socket_operations = {
- .owner = THIS_MODULE,
- .init = pci_init_socket,
- .suspend = pci_suspend_socket,
- .register_callback = pci_register_callback,
- .inquire_socket = pci_inquire_socket,
- .get_status = pci_get_status,
- .get_socket = pci_get_socket,
- .set_socket = pci_set_socket,
- .set_io_map = pci_set_io_map,
- .set_mem_map = pci_set_mem_map,
- .proc_setup = pci_proc_setup,
-};
-
-static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
-{
- pci_socket_t *socket = nr + pci_socket_array;
- int err;
-
- memset(socket, 0, sizeof(*socket));
-
- /* prepare class_data */
- socket->cls_d.sock_offset = nr;
- socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses
- this yet */
- socket->cls_d.ops = &pci_socket_operations;
- socket->cls_d.class_dev.class = &pcmcia_socket_class;
- socket->cls_d.class_dev.dev = &dev->dev;
- strlcpy(socket->cls_d.class_dev.class_id, dev->dev.bus_id, BUS_ID_SIZE);
- class_set_devdata(&socket->cls_d.class_dev, &socket->cls_d);
-
- /* prepare pci_socket_t */
- socket->dev = dev;
- socket->op = ops;
- pci_set_drvdata(dev, socket);
- spin_lock_init(&socket->event_lock);
- err = socket->op->open(socket);
- if (err) {
- socket->dev = NULL;
- pci_set_drvdata(dev, NULL);
- } else {
- class_device_register(&socket->cls_d.class_dev);
- }
- return err;
-}
-
-int cardbus_register(struct pci_dev *p_dev)
-{
- return 0;
-}
-
-static int __devinit
-cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
- int s;
-
- for (s = 0; s < MAX_SOCKETS; s++) {
- if (pci_socket_array [s].dev == 0) {
- return add_pci_socket (s, dev, &yenta_operations);
- }
- }
- return -ENODEV;
-}
-
-static void __devexit cardbus_remove (struct pci_dev *dev)
-{
- pci_socket_t *socket = pci_get_drvdata(dev);
-
- /* note: we are already unregistered from the cs core */
- class_device_unregister(&socket->cls_d.class_dev);
- if (socket->op && socket->op->close)
- socket->op->close(socket);
- pci_set_drvdata(dev, NULL);
-}
-
-static int cardbus_suspend (struct pci_dev *dev, u32 state)
-{
- pci_socket_t *socket = pci_get_drvdata(dev);
- return pcmcia_socket_dev_suspend(&socket->cls_d, state, 0);
-}
-
-static int cardbus_resume (struct pci_dev *dev)
-{
- pci_socket_t *socket = pci_get_drvdata(dev);
- return pcmcia_socket_dev_resume(&socket->cls_d, RESUME_RESTORE_STATE);
-}
-
-
-static struct pci_device_id cardbus_table [] __devinitdata = { {
- .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
- .class_mask = ~0,
-
- .vendor = PCI_ANY_ID,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
-}, { /* all zeroes */ }
-};
-MODULE_DEVICE_TABLE(pci, cardbus_table);
-
-static struct pci_driver pci_cardbus_driver = {
- .name = "cardbus",
- .id_table = cardbus_table,
- .probe = cardbus_probe,
- .remove = __devexit_p(cardbus_remove),
- .suspend = cardbus_suspend,
- .resume = cardbus_resume,
-};
-
-static int __init pci_socket_init(void)
-{
- return pci_register_driver (&pci_cardbus_driver);
-}
-
-static void __exit pci_socket_exit (void)
-{
- pci_unregister_driver (&pci_cardbus_driver);
-}
-
-module_init(pci_socket_init);
-module_exit(pci_socket_exit);
diff --git a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h
deleted file mode 100644
index 206eddd05c11..000000000000
--- a/drivers/pcmcia/pci_socket.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * drivers/pcmcia/pci_socket.h
- *
- * (C) Copyright 1999 Linus Torvalds
- */
-
-#ifndef __PCI_SOCKET_H
-#define __PCI_SOCKET_H
-
-struct pci_socket_ops;
-struct socket_info_t;
-
-typedef struct pci_socket {
- struct pci_dev *dev;
- int cb_irq, io_irq;
- void *base;
- void (*handler)(void *, unsigned int);
- void *info;
- struct pci_socket_ops *op;
- socket_cap_t cap;
- spinlock_t event_lock;
- unsigned int events;
- struct work_struct tq_task;
- struct timer_list poll_timer;
-
- struct pcmcia_socket_class_data cls_d;
- /* A few words of private data for the low-level driver.. */
- unsigned int private[8];
-} pci_socket_t;
-
-struct pci_socket_ops {
- int (*open)(struct pci_socket *);
- void (*close)(struct pci_socket *);
-
- int (*init)(struct pci_socket *);
- int (*suspend)(struct pci_socket *);
- int (*get_status)(struct pci_socket *, unsigned int *);
- int (*get_socket)(struct pci_socket *, socket_state_t *);
- int (*set_socket)(struct pci_socket *, socket_state_t *);
- int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
- int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
- void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
-};
-
-extern struct pci_socket_ops yenta_operations;
-extern struct pci_socket_ops ricoh_operations;
-
-#endif
diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h
index 14573f8d3646..a36f2f339d42 100644
--- a/drivers/pcmcia/ricoh.h
+++ b/drivers/pcmcia/ricoh.h
@@ -125,11 +125,26 @@
#define rl_mem(socket) ((socket)->private[3])
#define rl_config(socket) ((socket)->private[4])
+static int ricoh_init(struct pcmcia_socket *sock)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ yenta_init(sock);
+
+ config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
+ config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
+ config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
+ config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
+ config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
+
+ return 0;
+}
+
+
/*
* Magic Ricoh initialization code.. Save state at
* beginning, re-initialize it after suspend.
*/
-static int ricoh_open(pci_socket_t *socket)
+static int ricoh_override(struct yenta_socket *socket)
{
rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
@@ -146,35 +161,11 @@ static int ricoh_open(pci_socket_t *socket)
rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
}
- return 0;
-}
-
-static int ricoh_init(pci_socket_t *socket)
-{
- yenta_init(socket);
+ socket->socket.ss_entry->init = ricoh_init;
- config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
- config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
- config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
- config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
- config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
-
return 0;
}
-static struct pci_socket_ops ricoh_ops = {
- ricoh_open,
- yenta_close,
- ricoh_init,
- yenta_suspend,
- yenta_get_status,
- yenta_get_socket,
- yenta_set_socket,
- yenta_set_io_map,
- yenta_set_mem_map,
- yenta_proc_setup
-};
-
#endif /* CONFIG_CARDBUS */
#endif /* _LINUX_RICOH_H */
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 36e15cfdd73c..9d962c2c1545 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -90,7 +90,7 @@ static DECLARE_MUTEX(rsrc_sem);
typedef struct irq_info_t {
u_int Attributes;
int time_share, dyn_share;
- struct socket_info_t *Socket;
+ struct pcmcia_socket *Socket;
} irq_info_t;
/* Table of IRQ assignments */
@@ -341,7 +341,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
======================================================================*/
/* Validation function for cards with a valid CIS */
-static int cis_readable(socket_info_t *s, u_long base)
+static int cis_readable(struct pcmcia_socket *s, u_long base)
{
cisinfo_t info1, info2;
int ret;
@@ -364,7 +364,7 @@ static int cis_readable(socket_info_t *s, u_long base)
}
/* Validation function for simple memory cards */
-static int checksum(socket_info_t *s, u_long base)
+static int checksum(struct pcmcia_socket *s, u_long base)
{
int i, a, b, d;
s->cis_mem.sys_start = base;
@@ -372,7 +372,7 @@ static int checksum(socket_info_t *s, u_long base)
s->cis_virt = ioremap(base, s->cap.map_size);
s->cis_mem.card_start = 0;
s->cis_mem.flags = MAP_ACTIVE;
- s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+ s->ss_entry->set_mem_map(s, &s->cis_mem);
/* Don't bother checking every word... */
a = 0; b = -1;
for (i = 0; i < s->cap.map_size; i += 44) {
@@ -383,7 +383,7 @@ static int checksum(socket_info_t *s, u_long base)
return (b == -1) ? -1 : (a>>1);
}
-static int checksum_match(socket_info_t *s, u_long base)
+static int checksum_match(struct pcmcia_socket *s, u_long base)
{
int a = checksum(s, base), b = checksum(s, base+s->cap.map_size);
return ((a == b) && (a >= 0));
@@ -397,7 +397,7 @@ static int checksum_match(socket_info_t *s, u_long base)
======================================================================*/
-static int do_mem_probe(u_long base, u_long num, socket_info_t *s)
+static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
{
u_long i, j, bad, fail, step;
@@ -435,7 +435,7 @@ static int do_mem_probe(u_long base, u_long num, socket_info_t *s)
#ifdef CONFIG_PCMCIA_PROBE
-static u_long inv_probe(resource_map_t *m, socket_info_t *s)
+static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
{
u_long ok;
if (m == &mem_db)
@@ -451,7 +451,7 @@ static u_long inv_probe(resource_map_t *m, socket_info_t *s)
return do_mem_probe(m->base, m->num, s);
}
-void validate_mem(socket_info_t *s)
+void validate_mem(struct pcmcia_socket *s)
{
resource_map_t *m, *n;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
@@ -497,7 +497,7 @@ void validate_mem(socket_info_t *s)
#else /* CONFIG_PCMCIA_PROBE */
-void validate_mem(socket_info_t *s)
+void validate_mem(struct pcmcia_socket *s)
{
resource_map_t *m, *n;
static int done = 0;
@@ -529,7 +529,7 @@ void validate_mem(socket_info_t *s)
======================================================================*/
int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
- char *name, socket_info_t *s)
+ char *name, struct pcmcia_socket *s)
{
ioaddr_t try;
resource_map_t *m;
@@ -556,7 +556,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
}
int find_mem_region(u_long *base, u_long num, u_long align,
- int force_low, char *name, socket_info_t *s)
+ int force_low, char *name, struct pcmcia_socket *s)
{
u_long try;
resource_map_t *m;
@@ -726,7 +726,7 @@ void undo_irq(u_int Attributes, int irq)
static int adjust_memory(adjust_t *adj)
{
u_long base, num;
- int i, ret;
+ int ret;
base = adj->resource.memory.Base;
num = adj->resource.memory.Size;
@@ -743,9 +743,11 @@ static int adjust_memory(adjust_t *adj)
case REMOVE_MANAGED_RESOURCE:
ret = sub_interval(&mem_db, base, num);
if (ret == CS_SUCCESS) {
- for (i = 0; i < sockets; i++) {
- release_cis_mem(socket_table[i]);
- }
+ struct pcmcia_socket *socket;
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
+ release_cis_mem(socket);
+ up_read(&pcmcia_socket_list_rwsem);
}
break;
default:
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 6ddba61ba2d8..dee5cdcf82d7 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -106,19 +106,10 @@ static struct device_driver sa11x0_pcmcia_driver = {
.remove = sa11xx_drv_pcmcia_remove,
.name = "sa11x0-pcmcia",
.bus = &platform_bus_type,
- .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
};
-static struct platform_device sa11x0_pcmcia_device = {
- .name = "sa11x0-pcmcia",
- .id = 0,
- .dev = {
- .name = "Intel Corporation SA11x0 [PCMCIA]",
- },
-};
-
/* sa11x0_pcmcia_init()
* ^^^^^^^^^^^^^^^^^^^^
*
@@ -129,16 +120,7 @@ static struct platform_device sa11x0_pcmcia_device = {
*/
static int __init sa11x0_pcmcia_init(void)
{
- int ret;
-
- ret = driver_register(&sa11x0_pcmcia_driver);
- if (ret == 0) {
- ret = platform_device_register(&sa11x0_pcmcia_device);
- if (ret)
- driver_unregister(&sa11x0_pcmcia_driver);
- }
-
- return ret;
+ return driver_register(&sa11x0_pcmcia_driver);
}
/* sa11x0_pcmcia_exit()
@@ -148,7 +130,6 @@ static int __init sa11x0_pcmcia_init(void)
*/
static void __exit sa11x0_pcmcia_exit(void)
{
- platform_device_unregister(&sa11x0_pcmcia_device);
driver_unregister(&sa11x0_pcmcia_driver);
}
diff --git a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c
index 102203779a22..cfe9b4e2368e 100644
--- a/drivers/pcmcia/sa11xx_core.c
+++ b/drivers/pcmcia/sa11xx_core.c
@@ -69,6 +69,8 @@ static struct sa1100_pcmcia_socket sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK];
#define PCMCIA_SOCKET(x) (sa1100_pcmcia_socket + (x))
+#define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket)
+
/*
* sa1100_pcmcia_default_mecr_timing
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -226,9 +228,9 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state
*
* Returns: 0
*/
-static int sa1100_pcmcia_sock_init(unsigned int sock)
+static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, skt->nr);
@@ -248,9 +250,9 @@ static int sa1100_pcmcia_sock_init(unsigned int sock)
*
* Returns: 0
*/
-static int sa1100_pcmcia_suspend(unsigned int sock)
+static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
int ret;
DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, skt->nr);
@@ -348,11 +350,11 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r
* Returns: 0
*/
static int
-sa1100_pcmcia_register_callback(unsigned int sock,
+sa1100_pcmcia_register_callback(struct pcmcia_socket *sock,
void (*handler)(void *, unsigned int),
void *info)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
if (handler) {
if (!try_module_get(skt->ops->owner))
@@ -392,9 +394,9 @@ sa1100_pcmcia_register_callback(unsigned int sock,
* Return value is irrelevant; the pcmcia subsystem ignores it.
*/
static int
-sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
+sa1100_pcmcia_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
int ret = -1;
if (skt) {
@@ -430,9 +432,9 @@ sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
* Returns: 0
*/
static int
-sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status)
+sa1100_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
skt->status = sa1100_pcmcia_skt_state(skt);
*status = skt->status;
@@ -450,9 +452,9 @@ sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status)
* Returns: 0
*/
static int
-sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
+sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
@@ -472,9 +474,9 @@ sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
* Returns: 0
*/
static int
-sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
+sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
@@ -508,9 +510,9 @@ sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
* Returns: 0 on success, -1 on error
*/
static int
-sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
+sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
unsigned short speed = map->speed;
DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
@@ -564,9 +566,9 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
* Returns: 0 on success, -1 on error
*/
static int
-sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
+sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
{
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct resource *res;
unsigned short speed = map->speed;
@@ -708,7 +710,7 @@ sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
* Returns: 0 on success, -1 on error
*/
static void
-sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+sa1100_pcmcia_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
{
struct proc_dir_entry *entry;
@@ -717,7 +719,7 @@ sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
return;
}
entry->read_proc = sa1100_pcmcia_proc_status;
- entry->data = PCMCIA_SOCKET(sock);
+ entry->data = to_sa1100_socket(sock);
}
#else
#define sa1100_pcmcia_proc_setup NULL
@@ -800,22 +802,16 @@ static const char *skt_names[] = {
"PCMCIA socket 1",
};
+struct skt_dev_info {
+ int nskt;
+};
+
int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
{
- struct pcmcia_socket_class_data *cls;
+ struct skt_dev_info *sinfo;
unsigned int cpu_clock;
int ret, i;
- cls = kmalloc(sizeof(struct pcmcia_socket_class_data), GFP_KERNEL);
- if (!cls) {
- ret = -ENOMEM;
- goto out;
- }
-
- memset(cls, 0, sizeof(struct pcmcia_socket_class_data));
- cls->ops = &sa11xx_pcmcia_operations;
- cls->nsock = nr;
-
/*
* set default MECR calculation if the board specific
* code did not specify one...
@@ -823,6 +819,15 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
if (!ops->socket_get_timing)
ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
+ sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
+ if (!sinfo) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memset(sinfo, 0, sizeof(struct skt_dev_info));
+ sinfo->nskt = nr;
+
cpu_clock = cpufreq_get(0);
/*
@@ -832,6 +837,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
memset(skt, 0, sizeof(*skt));
+ skt->socket.ss_entry = &sa11xx_pcmcia_operations;
+ skt->socket.dev.dev = dev;
+
INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
init_timer(&skt->poll_timer);
@@ -898,16 +906,26 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
goto out_err_6;
skt->status = sa1100_pcmcia_skt_state(skt);
+
+ ret = pcmcia_register_socket(&skt->socket);
+ if (ret)
+ goto out_err_7;
+
+ WARN_ON(skt->socket.sock != i);
+
add_timer(&skt->poll_timer);
}
- dev->class_data = cls;
+ dev_set_drvdata(dev, sinfo);
return 0;
do {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
del_timer_sync(&skt->poll_timer);
+ pcmcia_unregister_socket(&skt->socket);
+
+ out_err_7:
flush_scheduled_work();
ops->hw_shutdown(skt);
@@ -925,7 +943,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
i--;
} while (i > 0);
- kfree(cls);
+ kfree(sinfo);
out:
return ret;
@@ -934,19 +952,22 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
int sa11xx_drv_pcmcia_remove(struct device *dev)
{
- struct pcmcia_socket_class_data *cls = dev->class_data;
+ struct skt_dev_info *sinfo = dev_get_drvdata(dev);
int i;
- dev->class_data = NULL;
-
- for (i = 0; i < cls->nsock; i++) {
- struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(cls->sock_offset + i);
+ dev_set_drvdata(dev, NULL);
- skt->ops->hw_shutdown(skt);
+ for (i = 0; i < sinfo->nskt; i++) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
del_timer_sync(&skt->poll_timer);
+
+ pcmcia_unregister_socket(&skt->socket);
+
flush_scheduled_work();
+ skt->ops->hw_shutdown(skt);
+
sa1100_pcmcia_config_skt(skt, &dead_socket);
iounmap(skt->virt_io);
@@ -957,7 +978,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
release_resource(&skt->res_skt);
}
- kfree(cls);
+ kfree(sinfo);
return 0;
}
@@ -977,7 +998,8 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock)
for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
- sa1100_pcmcia_set_mecr(skt, clock);
+ if (skt->ops)
+ sa1100_pcmcia_set_mecr(skt, clock);
}
}
diff --git a/drivers/pcmcia/sa11xx_core.h b/drivers/pcmcia/sa11xx_core.h
index 570491f2d96d..210228ddf752 100644
--- a/drivers/pcmcia/sa11xx_core.h
+++ b/drivers/pcmcia/sa11xx_core.h
@@ -44,6 +44,8 @@ struct pcmcia_state {
* use when responding to a Card Services query of some kind.
*/
struct sa1100_pcmcia_socket {
+ struct pcmcia_socket socket;
+
/*
* Info from low level handler
*/
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index b85d5c8468d6..648d38c57583 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -115,19 +115,20 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
static void tcic_timer(u_long data);
static struct pccard_operations tcic_operations;
-typedef struct socket_info_t {
+struct tcic_socket {
u_short psock;
void (*handler)(void *info, u_int events);
void *info;
u_char last_sstat;
u_char id;
-} socket_info_t;
+ struct pcmcia_socket socket;
+};
static struct timer_list poll_timer;
static int tcic_timer_pending;
static int sockets;
-static socket_info_t socket_table[2];
+static struct tcic_socket socket_table[2];
static socket_cap_t tcic_cap = {
/* only 16-bit cards, memory windows must be size-aligned */
@@ -372,15 +373,11 @@ static int __init get_tcic_id(void)
/*====================================================================*/
-static struct pcmcia_socket_class_data tcic_data = {
- .ops = &tcic_operations,
-};
-
static struct device_driver tcic_driver = {
.name = "tcic-pcmcia",
.bus = &platform_bus_type,
-/* .suspend = pcmcia_socket_dev_suspend, FIXME? */
-/* .resume = pcmcia_socket_dev_resume, FIXME? */
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device tcic_device = {
@@ -391,13 +388,10 @@ static struct platform_device tcic_device = {
},
};
-static struct class_device tcic_class_data = {
- .class = &pcmcia_socket_class,
-};
static int __init init_tcic(void)
{
- int i, sock;
+ int i, sock, ret = 0;
u_int mask, scan;
servinfo_t serv;
@@ -524,13 +518,17 @@ static int __init init_tcic(void)
/* jump start interrupt handler, if needed */
tcic_interrupt(0, NULL, NULL);
- tcic_data.nsock = sockets;
- tcic_class_data.dev = &tcic_device.dev;
- tcic_class_data.class_data = &tcic_data;
- strlcpy(tcic_class_data.class_id, "tcic-pcmcia", BUS_ID_SIZE);
-
platform_device_register(&tcic_device);
- class_device_register(&tcic_class_data);
+
+ for (i = 0; i < sockets; i++) {
+ socket_table[i].socket.ss_entry = &tcic_operations;
+ socket_table[i].socket.dev.dev = &tcic_device.dev;
+ ret = pcmcia_register_socket(&socket_table[i].socket);
+ if (ret && i)
+ pcmcia_unregister_socket(&socket_table[0].socket);
+ }
+
+ return ret;
return 0;
@@ -540,13 +538,19 @@ static int __init init_tcic(void)
static void __exit exit_tcic(void)
{
+ int i;
+
del_timer_sync(&poll_timer);
if (cs_irq != 0) {
tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
free_irq(cs_irq, tcic_interrupt);
}
release_region(tcic_base, 16);
- class_device_unregister(&tcic_class_data);
+
+ for (i = 0; i < sockets; i++) {
+ pcmcia_unregister_socket(&socket_table[i].socket);
+ }
+
platform_device_unregister(&tcic_device);
driver_unregister(&tcic_driver);
} /* exit_tcic */
@@ -640,18 +644,19 @@ static void tcic_timer(u_long data)
/*====================================================================*/
-static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
+static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
{
- socket_table[lsock].handler = handler;
- socket_table[lsock].info = info;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
+ socket_table[psock].handler = handler;
+ socket_table[psock].info = info;
return 0;
} /* tcic_register_callback */
/*====================================================================*/
-static int tcic_get_status(unsigned int lsock, u_int *value)
+static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
{
- u_short psock = socket_table[lsock].psock;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_char reg;
tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
@@ -675,7 +680,7 @@ static int tcic_get_status(unsigned int lsock, u_int *value)
/*====================================================================*/
-static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
{
*cap = tcic_cap;
return 0;
@@ -683,9 +688,9 @@ static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
/*====================================================================*/
-static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- u_short psock = socket_table[lsock].psock;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_char reg;
u_short scf1, scf2;
@@ -736,9 +741,9 @@ static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
/*====================================================================*/
-static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- u_short psock = socket_table[lsock].psock;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_char reg;
u_short scf1, scf2;
@@ -811,9 +816,9 @@ static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
/*====================================================================*/
-static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
{
- u_short psock = socket_table[lsock].psock;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_int addr;
u_short base, len, ioctl;
@@ -848,9 +853,9 @@ static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
/*====================================================================*/
-static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
{
- u_short psock = socket_table[lsock].psock;
+ u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_short addr, ctl;
u_long base, len, mmap;
@@ -892,11 +897,11 @@ static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
/*====================================================================*/
-static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void tcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
{
}
-static int tcic_init(unsigned int s)
+static int tcic_init(struct pcmcia_socket *s)
{
int i;
pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -915,7 +920,7 @@ static int tcic_init(unsigned int s)
return 0;
}
-static int tcic_suspend(unsigned int sock)
+static int tcic_suspend(struct pcmcia_socket *sock)
{
return tcic_set_socket(sock, &dead_socket);
}
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 353cc02b8181..4e3a3768b22f 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -136,6 +136,26 @@
#ifdef CONFIG_CARDBUS
+static int ti_intctl(struct yenta_socket *socket)
+{
+ u8 new, reg = exca_readb(socket, I365_INTCTL);
+
+ new = reg & ~I365_INTR_ENA;
+ if (socket->cb_irq)
+ new |= I365_INTR_ENA;
+ if (new != reg)
+ exca_writeb(socket, I365_INTCTL, new);
+ return 0;
+}
+
+static int ti_init(struct pcmcia_socket *sock)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ yenta_init(sock);
+ ti_intctl(socket);
+ return 0;
+}
+
/*
* Generic TI init - TI has an extension for the
* INTCTL register that sets the PCI CSC interrupt.
@@ -148,70 +168,28 @@
* This makes us correctly get PCI CSC interrupt
* events.
*/
-static int ti_open(pci_socket_t *socket)
+static int ti_override(struct yenta_socket *socket)
{
u8 new, reg = exca_readb(socket, I365_INTCTL);
new = reg & ~I365_INTR_ENA;
if (new != reg)
exca_writeb(socket, I365_INTCTL, new);
+ socket->socket.ss_entry->init = ti_init;
return 0;
}
-static int ti_intctl(pci_socket_t *socket)
-{
- u8 new, reg = exca_readb(socket, I365_INTCTL);
-
- new = reg & ~I365_INTR_ENA;
- if (socket->cb_irq)
- new |= I365_INTR_ENA;
- if (new != reg)
- exca_writeb(socket, I365_INTCTL, new);
- return 0;
-}
-
-static int ti_init(pci_socket_t *socket)
-{
- yenta_init(socket);
- ti_intctl(socket);
- return 0;
-}
-
-static struct pci_socket_ops ti_ops = {
- ti_open,
- yenta_close,
- ti_init,
- yenta_suspend,
- yenta_get_status,
- yenta_get_socket,
- yenta_set_socket,
- yenta_set_io_map,
- yenta_set_mem_map,
- yenta_proc_setup
-};
-
#define ti_sysctl(socket) ((socket)->private[0])
#define ti_cardctl(socket) ((socket)->private[1])
#define ti_devctl(socket) ((socket)->private[2])
#define ti_diag(socket) ((socket)->private[3])
#define ti_irqmux(socket) ((socket)->private[4])
-static int ti113x_open(pci_socket_t *socket)
-{
- ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
- ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
- ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
- ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
- if (socket->cb_irq)
- ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
- ti_open(socket);
- return 0;
-}
-
-static int ti113x_init(pci_socket_t *socket)
+static int ti113x_init(struct pcmcia_socket *sock)
{
- yenta_init(socket);
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ yenta_init(sock);
config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
@@ -220,35 +198,26 @@ static int ti113x_init(pci_socket_t *socket)
return 0;
}
-static struct pci_socket_ops ti113x_ops = {
- ti113x_open,
- yenta_close,
- ti113x_init,
- yenta_suspend,
- yenta_get_status,
- yenta_get_socket,
- yenta_set_socket,
- yenta_set_io_map,
- yenta_set_mem_map,
- yenta_proc_setup
-};
-
-
-static int ti1250_open(pci_socket_t *socket)
+static int ti113x_override(struct yenta_socket *socket)
{
- ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+ ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+ ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
- ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+ ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
if (socket->cb_irq)
- ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
- ti113x_open(socket);
+ ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+ ti_override(socket);
+ socket->socket.ss_entry->init = ti113x_init;
return 0;
}
-static int ti1250_init(pci_socket_t *socket)
+
+static int ti1250_init(struct pcmcia_socket *sock)
{
- yenta_init(socket);
- ti113x_init(socket);
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ yenta_init(sock);
+ ti113x_init(sock);
ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
@@ -260,18 +229,17 @@ static int ti1250_init(pci_socket_t *socket)
return 0;
}
-static struct pci_socket_ops ti1250_ops = {
- ti1250_open,
- yenta_close,
- ti1250_init,
- yenta_suspend,
- yenta_get_status,
- yenta_get_socket,
- yenta_set_socket,
- yenta_set_io_map,
- yenta_set_mem_map,
- yenta_proc_setup
-};
+static int ti1250_override(struct yenta_socket *socket)
+{
+ ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+
+ ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+ if (socket->cb_irq)
+ ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
+ ti113x_override(socket);
+ socket->socket.ss_entry->init = ti1250_init;
+ return 0;
+}
#endif /* CONFIG_CARDBUS */
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
index 2a3a49d0b72f..67eabeb40090 100644
--- a/drivers/pcmcia/yenta.c
+++ b/drivers/pcmcia/yenta.c
@@ -1,5 +1,5 @@
/*
- * Regular lowlevel cardbus driver ("yenta")
+ * Regular cardbus driver ("yenta")
*
* (C) Copyright 1999, 2000 Linus Torvalds
*
@@ -7,6 +7,8 @@
* Aug 2002: Manfred Spraul <manfred@colorfullife.com>
* Dynamically adjust the size of the bridge resource
*
+ * May 2003: Dominik Brodowski <linux@brodo.de>
+ * Merge pci_socket.c and yenta.c into one file
*/
#include <linux/init.h>
#include <linux/pci.h>
@@ -26,6 +28,7 @@
#include "yenta.h"
#include "i82365.h"
+
#if 0
#define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args)
#else
@@ -41,20 +44,20 @@
* regular memory space ("cb_xxx"), configuration space
* ("config_xxx") and compatibility space ("exca_xxxx")
*/
-static inline u32 cb_readl(pci_socket_t *socket, unsigned reg)
+static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
{
u32 val = readl(socket->base + reg);
DEBUG("%p %04x %08x\n", socket, reg, val);
return val;
}
-static inline void cb_writel(pci_socket_t *socket, unsigned reg, u32 val)
+static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
{
DEBUG("%p %04x %08x\n", socket, reg, val);
writel(val, socket->base + reg);
}
-static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
+static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
{
u8 val;
pci_read_config_byte(socket->dev, offset, &val);
@@ -62,7 +65,7 @@ static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
return val;
}
-static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
+static inline u16 config_readw(struct yenta_socket *socket, unsigned offset)
{
u16 val;
pci_read_config_word(socket->dev, offset, &val);
@@ -70,7 +73,7 @@ static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
return val;
}
-static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
+static inline u32 config_readl(struct yenta_socket *socket, unsigned offset)
{
u32 val;
pci_read_config_dword(socket->dev, offset, &val);
@@ -78,32 +81,32 @@ static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
return val;
}
-static inline void config_writeb(pci_socket_t *socket, unsigned offset, u8 val)
+static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
{
DEBUG("%p %04x %02x\n", socket, offset, val);
pci_write_config_byte(socket->dev, offset, val);
}
-static inline void config_writew(pci_socket_t *socket, unsigned offset, u16 val)
+static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
{
DEBUG("%p %04x %04x\n", socket, offset, val);
pci_write_config_word(socket->dev, offset, val);
}
-static inline void config_writel(pci_socket_t *socket, unsigned offset, u32 val)
+static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
{
DEBUG("%p %04x %08x\n", socket, offset, val);
pci_write_config_dword(socket->dev, offset, val);
}
-static inline u8 exca_readb(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
{
u8 val = readb(socket->base + 0x800 + reg);
DEBUG("%p %04x %02x\n", socket, reg, val);
return val;
}
-static inline u8 exca_readw(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg)
{
u16 val;
val = readb(socket->base + 0x800 + reg);
@@ -112,13 +115,13 @@ static inline u8 exca_readw(pci_socket_t *socket, unsigned reg)
return val;
}
-static inline void exca_writeb(pci_socket_t *socket, unsigned reg, u8 val)
+static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
{
DEBUG("%p %04x %02x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
}
-static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
+static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
{
DEBUG("%p %04x %04x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
@@ -129,8 +132,9 @@ static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
*/
-static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
unsigned int val;
u32 state = cb_readl(socket, CB_SOCKET_STATE);
@@ -181,8 +185,9 @@ static int yenta_Vpp_power(u32 control)
}
}
-static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
u8 reg;
u32 control;
@@ -221,7 +226,7 @@ static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
return 0;
}
-static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
+static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
{
u32 reg = 0; /* CB_SC_STPCLK? */
switch (state->Vcc) {
@@ -238,8 +243,9 @@ static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
cb_writel(socket, CB_SOCKET_CONTROL, reg);
}
-static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
u16 bridge;
if (state->flags & SS_DEBOUNCED) {
@@ -300,8 +306,9 @@ static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
return 0;
}
-static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
int map;
unsigned char ioctl, addr, enable;
@@ -333,8 +340,9 @@ static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
return 0;
}
-static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
int map;
unsigned char addr, enable;
unsigned int start, stop, card_start;
@@ -386,12 +394,12 @@ static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
return 0;
}
-static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
+static void yenta_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
{
/* Not done yet */
}
-static unsigned int yenta_events(pci_socket_t *socket)
+static unsigned int yenta_events(struct yenta_socket *socket)
{
u8 csc;
u32 cb_event;
@@ -418,7 +426,7 @@ static unsigned int yenta_events(pci_socket_t *socket)
static void yenta_bh(void *data)
{
- pci_socket_t *socket = data;
+ struct yenta_socket *socket = data;
unsigned int events;
spin_lock_irq(&socket->event_lock);
@@ -432,7 +440,7 @@ static void yenta_bh(void *data)
static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int events;
- pci_socket_t *socket = (pci_socket_t *) dev_id;
+ struct yenta_socket *socket = (struct yenta_socket *) dev_id;
events = yenta_events(socket);
if (events) {
@@ -447,7 +455,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void yenta_interrupt_wrapper(unsigned long data)
{
- pci_socket_t *socket = (pci_socket_t *) data;
+ struct yenta_socket *socket = (struct yenta_socket *) data;
yenta_interrupt(0, (void *)socket, NULL);
socket->poll_timer.expires = jiffies + HZ;
@@ -465,7 +473,7 @@ static void yenta_interrupt_wrapper(unsigned long data)
*/
static u32 isa_interrupts = 0x0ef8;
-static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
+static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask)
{
int i;
unsigned long val;
@@ -509,7 +517,7 @@ static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
/*
* Set static data that doesn't need re-initializing..
*/
-static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask)
+static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask)
{
socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
socket->cap.map_size = 0x1000;
@@ -520,28 +528,38 @@ static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask
printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
}
-static void yenta_clear_maps(pci_socket_t *socket)
+static int yenta_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+ *cap = socket->cap;
+
+ return 0;
+}
+
+
+static void yenta_clear_maps(struct yenta_socket *socket)
{
int i;
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
mem.sys_stop = 0x0fff;
- yenta_set_socket(socket, &dead_socket);
+ yenta_set_socket(&socket->socket, &dead_socket);
for (i = 0; i < 2; i++) {
io.map = i;
- yenta_set_io_map(socket, &io);
+ yenta_set_io_map(&socket->socket, &io);
}
for (i = 0; i < 5; i++) {
mem.map = i;
- yenta_set_mem_map(socket, &mem);
+ yenta_set_mem_map(&socket->socket, &mem);
}
}
/*
* Initialize the standard cardbus registers
*/
-static void yenta_config_init(pci_socket_t *socket)
+static void yenta_config_init(struct yenta_socket *socket)
{
u16 bridge;
struct pci_dev *dev = socket->dev;
@@ -586,8 +604,9 @@ static void yenta_config_init(pci_socket_t *socket)
}
/* Called at resume and initialization events */
-static int yenta_init(pci_socket_t *socket)
+static int yenta_init(struct pcmcia_socket *sock)
{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_config_init(socket);
yenta_clear_maps(socket);
@@ -596,9 +615,11 @@ static int yenta_init(pci_socket_t *socket)
return 0;
}
-static int yenta_suspend(pci_socket_t *socket)
+static int yenta_suspend(struct pcmcia_socket *sock)
{
- yenta_set_socket(socket, &dead_socket);
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+ yenta_set_socket(sock, &dead_socket);
/* Disable interrupts */
cb_writel(socket, CB_SOCKET_MASK, 0x0);
@@ -630,7 +651,7 @@ static int yenta_suspend(pci_socket_t *socket)
#define BRIDGE_IO_MAX 256
#define BRIDGE_IO_MIN 32
-static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
+static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type)
{
struct pci_bus *bus;
struct resource *root, *res;
@@ -711,7 +732,7 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
/*
* Allocate the bridge mappings for the device..
*/
-static void yenta_allocate_resources(pci_socket_t *socket)
+static void yenta_allocate_resources(struct yenta_socket *socket)
{
yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
yenta_allocate_res(socket, 1, IORESOURCE_MEM);
@@ -719,10 +740,11 @@ static void yenta_allocate_resources(pci_socket_t *socket)
yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */
}
+
/*
* Free the bridge mappings for the device..
*/
-static void yenta_free_resources(pci_socket_t *socket)
+static void yenta_free_resources(struct yenta_socket *socket)
{
int i;
for (i=0;i<4;i++) {
@@ -733,11 +755,15 @@ static void yenta_free_resources(pci_socket_t *socket)
res->start = res->end = 0;
}
}
+
+
/*
* Close it down - release our resources and go home..
*/
-static void yenta_close(pci_socket_t *sock)
+static void yenta_close(struct pci_dev *dev)
{
+ struct yenta_socket *sock = pci_get_drvdata(dev);
+
/* Disable all events so we don't die in an IRQ storm */
cb_writel(sock, CB_SOCKET_MASK, 0x0);
exca_writeb(sock, I365_CSCINT, 0);
@@ -750,8 +776,37 @@ static void yenta_close(pci_socket_t *sock)
if (sock->base)
iounmap(sock->base);
yenta_free_resources(sock);
+
+ pcmcia_unregister_socket(&sock->socket);
+ pci_set_drvdata(dev, NULL);
}
+
+static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+ socket->handler = handler;
+ socket->info = info;
+ return 0;
+}
+
+
+static struct pccard_operations yenta_socket_operations = {
+ .owner = THIS_MODULE,
+ .init = yenta_init,
+ .suspend = yenta_suspend,
+ .register_callback = yenta_register_callback,
+ .inquire_socket = yenta_inquire_socket,
+ .get_status = yenta_get_status,
+ .get_socket = yenta_get_socket,
+ .set_socket = yenta_set_socket,
+ .set_io_map = yenta_set_io_map,
+ .set_mem_map = yenta_set_mem_map,
+ .proc_setup = yenta_proc_setup,
+};
+
+
#include "ti113x.h"
#include "ricoh.h"
@@ -760,49 +815,62 @@ static void yenta_close(pci_socket_t *sock)
* initialization sequences etc details. List them here..
*/
#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
-static struct cardbus_override_struct {
+struct cardbus_override_struct {
unsigned short vendor;
unsigned short device;
- struct pci_socket_ops *op;
+ int (*override) (struct yenta_socket *socket);
} cardbus_override[] = {
- { PD(TI,1130), &ti113x_ops },
- { PD(TI,1031), &ti_ops },
- { PD(TI,1131), &ti113x_ops },
- { PD(TI,1250), &ti1250_ops },
- { PD(TI,1220), &ti_ops },
- { PD(TI,1221), &ti_ops },
- { PD(TI,1210), &ti_ops },
- { PD(TI,1450), &ti_ops },
- { PD(TI,1225), &ti_ops },
- { PD(TI,1251A), &ti_ops },
- { PD(TI,1211), &ti_ops },
- { PD(TI,1251B), &ti_ops },
- { PD(TI,1410), &ti1250_ops },
- { PD(TI,1420), &ti_ops },
- { PD(TI,4410), &ti_ops },
- { PD(TI,4451), &ti_ops },
-
- { PD(RICOH,RL5C465), &ricoh_ops },
- { PD(RICOH,RL5C466), &ricoh_ops },
- { PD(RICOH,RL5C475), &ricoh_ops },
- { PD(RICOH,RL5C476), &ricoh_ops },
- { PD(RICOH,RL5C478), &ricoh_ops }
+ { PD(TI,1130), &ti113x_override },
+ { PD(TI,1031), &ti_override },
+ { PD(TI,1131), &ti113x_override },
+ { PD(TI,1250), &ti1250_override },
+ { PD(TI,1220), &ti_override },
+ { PD(TI,1221), &ti_override },
+ { PD(TI,1210), &ti_override },
+ { PD(TI,1450), &ti_override },
+ { PD(TI,1225), &ti_override },
+ { PD(TI,1251A), &ti_override },
+ { PD(TI,1211), &ti_override },
+ { PD(TI,1251B), &ti_override },
+ { PD(TI,1410), ti1250_override },
+ { PD(TI,1420), &ti_override },
+ { PD(TI,4410), &ti_override },
+ { PD(TI,4451), &ti_override },
+
+ { PD(RICOH,RL5C465), &ricoh_override },
+ { PD(RICOH,RL5C466), &ricoh_override },
+ { PD(RICOH,RL5C475), &ricoh_override },
+ { PD(RICOH,RL5C476), &ricoh_override },
+ { PD(RICOH,RL5C478), &ricoh_override },
+
+ { }, /* all zeroes */
};
-#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
-
-
-extern int cardbus_register(struct pci_dev *p_dev);
/*
* Initialize a cardbus controller. Make sure we have a usable
* interrupt, and that we can map the cardbus area. Fill in the
* socket information structure..
*/
-static int yenta_open(pci_socket_t *socket)
+static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
- int i;
- struct pci_dev *dev = socket->dev;
+ struct yenta_socket *socket;
+ struct cardbus_override_struct *d;
+
+ socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
+ if (!socket)
+ return -ENOMEM;
+ memset(socket, 0, sizeof(*socket));
+
+ /* prepare pcmcia_socket */
+ socket->socket.ss_entry = &yenta_socket_operations;
+ socket->socket.dev.dev = &dev->dev;
+ socket->socket.driver_data = socket;
+
+ /* prepare struct yenta_socket */
+ socket->dev = dev;
+ pci_set_drvdata(dev, socket);
+ spin_lock_init(&socket->event_lock);
/*
* Do some basic sanity checking..
@@ -833,16 +901,14 @@ static int yenta_open(pci_socket_t *socket)
socket->cb_irq = dev->irq;
/* Do we have special options for the device? */
- for (i = 0; i < NR_OVERRIDES; i++) {
- struct cardbus_override_struct *d = cardbus_override+i;
- if (dev->vendor == d->vendor && dev->device == d->device) {
- socket->op = d->op;
- if (d->op->open) {
- int retval = d->op->open(socket);
- if (retval < 0)
- return retval;
- }
+ d = cardbus_override;
+ while (d->override) {
+ if ((dev->vendor == d->vendor) && (dev->device == d->device)) {
+ int retval = d->override(socket);
+ if (retval < 0)
+ return retval;
}
+ d++;
}
/* We must finish initialization here */
@@ -864,23 +930,58 @@ static int yenta_open(pci_socket_t *socket)
printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
/* Register it with the pcmcia layer.. */
- return cardbus_register(dev);
+ return pcmcia_register_socket(&socket->socket);
}
-/*
- * Standard plain cardbus - no frills, no extensions
- */
-struct pci_socket_ops yenta_operations = {
- yenta_open,
- yenta_close,
- yenta_init,
- yenta_suspend,
- yenta_get_status,
- yenta_get_socket,
- yenta_set_socket,
- yenta_set_io_map,
- yenta_set_mem_map,
- yenta_proc_setup
+
+static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
+{
+ return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
+}
+
+
+static int yenta_dev_resume (struct pci_dev *dev)
+{
+ return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
+}
+
+
+static struct pci_device_id yenta_table [] __devinitdata = { {
+ .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
+ .class_mask = ~0,
+
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+}, { /* all zeroes */ }
};
-EXPORT_SYMBOL(yenta_operations);
+MODULE_DEVICE_TABLE(pci, yenta_table);
+
+
+static struct pci_driver yenta_cardbus_driver = {
+ .name = "yenta_cardbus",
+ .id_table = yenta_table,
+ .probe = yenta_probe,
+ .remove = __devexit_p(yenta_close),
+ .suspend = yenta_dev_suspend,
+ .resume = yenta_dev_resume,
+};
+
+
+static int __init yenta_socket_init(void)
+{
+ return pci_register_driver (&yenta_cardbus_driver);
+}
+
+
+static void __exit yenta_socket_exit (void)
+{
+ pci_unregister_driver (&yenta_cardbus_driver);
+}
+
+
+module_init(yenta_socket_init);
+module_exit(yenta_socket_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/yenta.h b/drivers/pcmcia/yenta.h
index c8d61c4093c7..9c5c0a35df6a 100644
--- a/drivers/pcmcia/yenta.h
+++ b/drivers/pcmcia/yenta.h
@@ -2,7 +2,6 @@
#define __YENTA_H
#include <asm/io.h>
-#include "pci_socket.h"
#define CB_SOCKET_EVENT 0x00
#define CB_CSTSEVENT 0x00000001 /* Card status event */
@@ -96,4 +95,23 @@
*/
#define CB_MEM_PAGE(map) (0x40 + (map))
+struct yenta_socket {
+ struct pci_dev *dev;
+ int cb_irq, io_irq;
+ void *base;
+ void (*handler)(void *, unsigned int);
+ void *info;
+ socket_cap_t cap;
+ spinlock_t event_lock;
+ unsigned int events;
+ struct work_struct tq_task;
+ struct timer_list poll_timer;
+
+ struct pcmcia_socket socket;
+
+ /* A few words of private data for special stuff of overrides... */
+ unsigned int private[8];
+};
+
+
#endif
diff --git a/drivers/serial/core.c b/drivers/serial/core.c
index 7a40034c9cb7..e56baaf1f0e2 100644
--- a/drivers/serial/core.c
+++ b/drivers/serial/core.c
@@ -2189,11 +2189,11 @@ int uart_register_driver(struct uart_driver *drv)
void uart_unregister_driver(struct uart_driver *drv)
{
struct tty_driver *p = drv->tty_driver;
- drv->tty_driver = NULL;
tty_unregister_driver(p);
kfree(drv->state);
- kfree(drv->tty_driver->termios);
- kfree(drv->tty_driver);
+ kfree(p->termios);
+ kfree(p);
+ drv->tty_driver = NULL;
}
struct tty_driver *uart_console_device(struct console *co, int *index)
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 572bb3983f2d..c632affe5dae 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -1684,7 +1684,14 @@ int devfs_mk_dir(const char *fmt, ...)
}
error = _devfs_append_entry(dir, de, &old);
- if (error) {
+ if (error == -EEXIST) {
+ /*
+ * devfs_mk_dir() of an already-existing directory will
+ * return success.
+ */
+ error = 0;
+ devfs_put(old);
+ } else if (error) {
PRINTK("(%s): could not append to dir: %p \"%s\"\n",
buf, dir, dir->name);
devfs_put(old);
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 303ab9ce478a..ae2db5088ba7 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -36,17 +36,11 @@ extern struct file_operations jfs_file_operations;
struct address_space_operations jfs_aops;
extern int freeZeroLink(struct inode *);
-struct inode *jfs_iget(struct super_block *sb, ino_t ino)
+void jfs_read_inode(struct inode *inode)
{
- struct inode *inode = iget_locked(sb, ino);
-
- if (!inode || !(inode->i_state & I_NEW))
- return inode;
-
if (diRead(inode)) {
make_bad_inode(inode);
- unlock_new_inode(inode);
- return NULL;
+ return;
}
if (S_ISREG(inode->i_mode)) {
@@ -69,8 +63,6 @@ struct inode *jfs_iget(struct super_block *sb, ino_t ino)
init_special_inode(inode, inode->i_mode,
kdev_t_to_nr(inode->i_rdev));
}
- unlock_new_inode(inode);
- return inode;
}
/* This define is from fs/open.c */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index dd5286bf74b1..fd1467521794 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -35,7 +35,6 @@ extern struct address_space_operations jfs_aops;
extern int jfs_fsync(struct file *, struct dentry *, int);
extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern struct inode *jfs_iget(struct super_block *, ino_t);
extern int jfs_init_acl(struct inode *, struct inode *);
/*
@@ -1406,9 +1405,11 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry)
}
}
- ip = jfs_iget(dip->i_sb, inum);
- if (ip == NULL) {
+ ip = iget(dip->i_sb, inum);
+ if (ip == NULL || is_bad_inode(ip)) {
jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
+ if (ip)
+ iput(ip);
return ERR_PTR(-EACCES);
}
@@ -1421,12 +1422,16 @@ struct dentry *jfs_get_parent(struct dentry *dentry)
struct dentry *parent = ERR_PTR(-EACCES);
struct inode *inode;
- inode = jfs_iget(sb, JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
+ inode = iget(sb, JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
if (inode) {
- parent = d_alloc_anon(inode);
- if (!parent) {
- parent = ERR_PTR(-ENOMEM);
+ if (is_bad_inode(inode))
iput(inode);
+ else {
+ parent = d_alloc_anon(inode);
+ if (!parent) {
+ parent = ERR_PTR(-ENOMEM);
+ iput(inode);
+ }
}
}
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index ac23de624a05..74036f743e31 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -58,8 +58,6 @@ MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
/*
* External declarations
*/
-extern struct inode *jfs_iget(struct super_block *, ino_t);
-
extern int jfs_mount(struct super_block *);
extern int jfs_mount_rw(struct super_block *, int);
extern int jfs_umount(struct super_block *);
@@ -69,6 +67,7 @@ extern int jfsIOWait(void *);
extern int jfs_lazycommit(void *);
extern int jfs_sync(void *);
+extern void jfs_read_inode(struct inode *inode);
extern void jfs_dirty_inode(struct inode *inode);
extern void jfs_delete_inode(struct inode *inode);
extern void jfs_write_inode(struct inode *inode, int wait);
@@ -313,7 +312,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_magic = JFS_SUPER_MAGIC;
- inode = jfs_iget(sb, ROOT_I);
+ inode = iget(sb, ROOT_I);
if (!inode || is_bad_inode(inode))
goto out_no_root;
sb->s_root = d_alloc_root(inode);
@@ -397,6 +396,7 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
static struct super_operations jfs_super_operations = {
.alloc_inode = jfs_alloc_inode,
.destroy_inode = jfs_destroy_inode,
+ .read_inode = jfs_read_inode,
.dirty_inode = jfs_dirty_inode,
.write_inode = jfs_write_inode,
.delete_inode = jfs_delete_inode,
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 604a3414082f..dd406043469a 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -188,6 +188,14 @@ nfsd(struct svc_rqst *rqstp)
list_add(&me.list, &nfsd_list);
unlock_kernel();
+
+ /*
+ * We want less throttling in balance_dirty_pages() so that nfs to
+ * localhost doesn't cause nfsd to lock up due to all the client's
+ * dirty pages.
+ */
+ current->flags |= PF_LESS_THROTTLE;
+
/*
* The main request loop
*/
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 78884e3dd038..e5439f1aafa5 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -22,7 +22,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
}
static ssize_t
-read(struct file * file, char * userbuf, size_t count, loff_t * off)
+read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
char *buffer = file->private_data;
struct dentry *dentry = file->f_dentry;
@@ -65,7 +65,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
return attr->write(kobj, buffer, offset, count);
}
-static ssize_t write(struct file * file, const char * userbuf,
+static ssize_t write(struct file * file, const char __user * userbuf,
size_t count, loff_t * off)
{
char *buffer = file->private_data;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 3c9f3ef77a54..1d25a84702b2 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -109,7 +109,7 @@ static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
* the amount they specify each time.
* This may be called continuously until the buffer is empty.
*/
-static int flush_read_buffer(struct sysfs_buffer * buffer, char * buf,
+static int flush_read_buffer(struct sysfs_buffer * buffer, char __user * buf,
size_t count, loff_t * ppos)
{
int error;
@@ -143,7 +143,7 @@ static int flush_read_buffer(struct sysfs_buffer * buffer, char * buf,
*/
static ssize_t
-sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
+sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct sysfs_buffer * buffer = file->private_data;
ssize_t retval = 0;
@@ -169,7 +169,7 @@ sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
*/
static int
-fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count)
+fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
{
int error;
@@ -224,7 +224,7 @@ flush_write_buffer(struct file * file, struct sysfs_buffer * buffer, size_t coun
*/
static ssize_t
-sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
+sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct sysfs_buffer * buffer = file->private_data;
diff --git a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h
index b0c704bd96fd..30ff44607179 100644
--- a/include/asm-arm/arch-iop3xx/iop321.h
+++ b/include/asm-arm/arch-iop3xx/iop321.h
@@ -14,9 +14,16 @@
#ifndef _IOP321_HW_H_
#define _IOP321_HW_H_
+
+#ifndef __ASSEMBLY__
+#define iop_is_321() ((processor_id & 0xfffff7e0) == 0x69052420)
+#endif
+
+
/*
* IOP321 I/O and Mem space regions for PCI autoconfiguration
*/
+
#define IOP321_PCI_IO_BASE 0x90000000
#define IOP321_PCI_IO_SIZE 0x00010000
#define IOP321_PCI_MEM_BASE 0x40000000
@@ -26,6 +33,7 @@
* IOP321 chipset registers
*/
#define IOP321_VIRT_MEM_BASE 0xfff00000 /* chip virtual mem address*/
+
#define IOP321_PHY_MEM_BASE 0xffffe000 /* chip physical memory address */
#define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
@@ -97,12 +105,93 @@
#define IOP321_PCIIRSR (volatile u32 *)IOP321_REG_ADDR(0x000001EC)
/* Messaging Unit 0x00000300 through 0x000003FF */
+
+/* Reserved 0x00000300 through 0x0000030c */
+#define IOP321_IMR0 (volatile u32 *)IOP321_REG_ADDR(0x00000310)
+#define IOP321_IMR1 (volatile u32 *)IOP321_REG_ADDR(0x00000314)
+#define IOP321_OMR0 (volatile u32 *)IOP321_REG_ADDR(0x00000318)
+#define IOP321_OMR1 (volatile u32 *)IOP321_REG_ADDR(0x0000031C)
+#define IOP321_IDR (volatile u32 *)IOP321_REG_ADDR(0x00000320)
+#define IOP321_IISR (volatile u32 *)IOP321_REG_ADDR(0x00000324)
+#define IOP321_IIMR (volatile u32 *)IOP321_REG_ADDR(0x00000328)
+#define IOP321_ODR (volatile u32 *)IOP321_REG_ADDR(0x0000032C)
+#define IOP321_OISR (volatile u32 *)IOP321_REG_ADDR(0x00000330)
+#define IOP321_OIMR (volatile u32 *)IOP321_REG_ADDR(0x00000334)
+/* Reserved 0x00000338 through 0x0000034F */
+#define IOP321_MUCR (volatile u32 *)IOP321_REG_ADDR(0x00000350)
+#define IOP321_QBAR (volatile u32 *)IOP321_REG_ADDR(0x00000354)
+/* Reserved 0x00000358 through 0x0000035C */
+#define IOP321_IFHPR (volatile u32 *)IOP321_REG_ADDR(0x00000360)
+#define IOP321_IFTPR (volatile u32 *)IOP321_REG_ADDR(0x00000364)
+#define IOP321_IPHPR (volatile u32 *)IOP321_REG_ADDR(0x00000368)
+#define IOP321_IPTPR (volatile u32 *)IOP321_REG_ADDR(0x0000036C)
+#define IOP321_OFHPR (volatile u32 *)IOP321_REG_ADDR(0x00000370)
+#define IOP321_OFTPR (volatile u32 *)IOP321_REG_ADDR(0x00000374)
+#define IOP321_OPHPR (volatile u32 *)IOP321_REG_ADDR(0x00000378)
+#define IOP321_OPTPR (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
+#define IOP321_IAR (volatile u32 *)IOP321_REG_ADDR(0x00000380)
+/* Reserved 0x00000384 through 0x000003FF */
+
/* DMA Controller 0x00000400 through 0x000004FF */
+#define IOP321_DMA0_CCR (volatile u32 *)IOP321_REG_ADDR(0x00000400)
+#define IOP321_DMA0_CSR (volatile u32 *)IOP321_REG_ADDR(0x00000404)
+#define IOP321_DMA0_DAR (volatile u32 *)IOP321_REG_ADDR(0x0000040C)
+#define IOP321_DMA0_NDAR (volatile u32 *)IOP321_REG_ADDR(0x00000410)
+#define IOP321_DMA0_PADR (volatile u32 *)IOP321_REG_ADDR(0x00000414)
+#define IOP321_DMA0_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000418)
+#define IOP321_DMA0_LADR (volatile u32 *)IOP321_REG_ADDR(0X0000041C)
+#define IOP321_DMA0_BCR (volatile u32 *)IOP321_REG_ADDR(0x00000420)
+#define IOP321_DMA0_DCR (volatile u32 *)IOP321_REG_ADDR(0x00000424)
+/* Reserved 0x00000428 through 0x0000043C */
+#define IOP321_DMA1_CCR (volatile u32 *)IOP321_REG_ADDR(0x00000440)
+#define IOP321_DMA1_CSR (volatile u32 *)IOP321_REG_ADDR(0x00000444)
+#define IOP321_DMA1_DAR (volatile u32 *)IOP321_REG_ADDR(0x0000044C)
+#define IOP321_DMA1_NDAR (volatile u32 *)IOP321_REG_ADDR(0x00000450)
+#define IOP321_DMA1_PADR (volatile u32 *)IOP321_REG_ADDR(0x00000454)
+#define IOP321_DMA1_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000458)
+#define IOP321_DMA1_LADR (volatile u32 *)IOP321_REG_ADDR(0x0000045C)
+#define IOP321_DMA1_BCR (volatile u32 *)IOP321_REG_ADDR(0x00000460)
+#define IOP321_DMA1_DCR (volatile u32 *)IOP321_REG_ADDR(0x00000464)
+/* Reserved 0x00000468 through 0x000004FF */
+
/* Memory controller 0x00000500 through 0x0005FF */
+
/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
+#define IOP321_PBCR (volatile u32 *)IOP321_REG_ADDR(0x00000680)
+#define IOP321_PBISR (volatile u32 *)IOP321_REG_ADDR(0x00000684)
+#define IOP321_PBBAR0 (volatile u32 *)IOP321_REG_ADDR(0x00000688)
+#define IOP321_PBLR0 (volatile u32 *)IOP321_REG_ADDR(0x0000068C)
+#define IOP321_PBBAR1 (volatile u32 *)IOP321_REG_ADDR(0x00000690)
+#define IOP321_PBLR1 (volatile u32 *)IOP321_REG_ADDR(0x00000694)
+#define IOP321_PBBAR2 (volatile u32 *)IOP321_REG_ADDR(0x00000698)
+#define IOP321_PBLR2 (volatile u32 *)IOP321_REG_ADDR(0x0000069C)
+#define IOP321_PBBAR3 (volatile u32 *)IOP321_REG_ADDR(0x000006A0)
+#define IOP321_PBLR3 (volatile u32 *)IOP321_REG_ADDR(0x000006A4)
+#define IOP321_PBBAR4 (volatile u32 *)IOP321_REG_ADDR(0x000006A8)
+#define IOP321_PBLR4 (volatile u32 *)IOP321_REG_ADDR(0x000006AC)
+#define IOP321_PBBAR5 (volatile u32 *)IOP321_REG_ADDR(0x000006B0)
+#define IOP321_PBLR5 (volatile u32 *)IOP321_REG_ADDR(0x000006B4)
+#define IOP321_PBDSCR (volatile u32 *)IOP321_REG_ADDR(0x000006B8)
+/* Reserved 0x000006BC */
+#define IOP321_PMBR0 (volatile u32 *)IOP321_REG_ADDR(0x000006C0)
+/* Reserved 0x000006C4 through 0x000006DC */
+#define IOP321_PMBR1 (volatile u32 *)IOP321_REG_ADDR(0x000006E0)
+#define IOP321_PMBR2 (volatile u32 *)IOP321_REG_ADDR(0x000006E4)
+
+#define IOP321_PBCR_EN 0x1
+
+#define IOP321_PBISR_BOOR_ERR 0x1
+
+
+
/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
/* Internal arbitration unit 0x00000780 through 0x0007BF */
+/* General Purpose I/O Registers */
+#define IOP321_GPOE (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
+#define IOP321_GPID (volatile u32 *)IOP321_REG_ADDR(0x000007C8)
+#define IOP321_GPOD (volatile u32 *)IOP321_REG_ADDR(0x000007CC)
+
/* Interrupt Controller */
#define IOP321_INTCTL (volatile u32 *)IOP321_REG_ADDR(0x000007D0)
#define IOP321_INTSTR (volatile u32 *)IOP321_REG_ADDR(0x000007D4)
@@ -131,11 +220,40 @@
#define IOP321_TU_TISR (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
#define IOP321_TU_WDTCR (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
+
+
/* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP321_AAUACR (volatile u32 *)IOP321_REG_ADDR(0x00000800)
-#define IOP321_AAUASR (volatile u32 *)IOP321_REG_ADDR(0x00000804)
-#define IOP321_AAUANDAR (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
+#define IOP321_AAU_ACR (volatile u32 *)IOP321_REG_ADDR(0x00000800)
+#define IOP321_AAU_ASR (volatile u32 *)IOP321_REG_ADDR(0x00000804)
+#define IOP321_AAU_ADAR (volatile u32 *)IOP321_REG_ADDR(0x00000808)
+#define IOP321_AAU_ANDAR (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
+#define IOP321_AAU_SAR1 (volatile u32 *)IOP321_REG_ADDR(0x00000810)
+/* SAR2...SAR32 0x00000814 - 0x000008A4 */
+#define IOP321_AAU_DAR (volatile u32 *)IOP321_REG_ADDR(0x00000820)
+#define IOP321_AAU_ABCR (volatile u32 *)IOP321_REG_ADDR(0x00000824)
+#define IOP321_AAU_ADCR (volatile u32 *)IOP321_REG_ADDR(0x00000828)
+#define IOP321_AAU_EDCR0 (volatile u32 *)IOP321_REG_ADDR(0x0000083c)
+#define IOP321_AAU_EDCR1 (volatile u32 *)IOP321_REG_ADDR(0x00000860)
+#define IOP321_AAU_EDCR2 (volatile u32 *)IOP321_REG_ADDR(0x00000884)
+
/* SSP serial port unit 0x00001600 - 0x0000167F */
/* I2C bus interface unit 0x00001680 - 0x000016FF */
+#define IOP321_ICR0 (volatile u32 *)IOP321_REG_ADDR(0x00001680)
+#define IOP321_ISR0 (volatile u32 *)IOP321_REG_ADDR(0x00001684)
+#define IOP321_ISAR0 (volatile u32 *)IOP321_REG_ADDR(0x00001688)
+#define IOP321_IDBR0 (volatile u32 *)IOP321_REG_ADDR(0x0000168C)
+/* Reserved 0x00001690 */
+#define IOP321_IBMR0 (volatile u32 *)IOP321_REG_ADDR(0x00001694)
+/* Reserved 0x00001698 */
+/* Reserved 0x0000169C */
+#define IOP321_ICR1 (volatile u32 *)IOP321_REG_ADDR(0x000016A0)
+#define IOP321_ISR1 (volatile u32 *)IOP321_REG_ADDR(0x000016A4)
+#define IOP321_ISAR1 (volatile u32 *)IOP321_REG_ADDR(0x000016A8)
+#define IOP321_IDBR1 (volatile u32 *)IOP321_REG_ADDR(0x000016AC)
+#define IOP321_IBMR1 (volatile u32 *)IOP321_REG_ADDR(0x000016B4)
+/* Reserved 0x000016B8 through 0x000016FC */
+
+/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
+
#endif // _IOP321_HW_H_
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index 519571a84945..fcd4036eb41f 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -22,7 +22,7 @@ static inline int apic_id_registered(void)
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
static inline unsigned long target_cpus(void)
{
- return ((cpu_online_map < 0xf)?cpu_online_map:0xf);
+ return cpu_online_map;
}
#define TARGET_CPUS (target_cpus())
@@ -151,7 +151,7 @@ static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
printk ("%s: Not a valid mask!\n",__FUNCTION__);
- return TARGET_CPUS;
+ return 0xFF;
}
apicid = apicid | new_apicid;
cpus_found++;
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index c0cdcc5aee41..c02f1cf1ea2e 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -6,7 +6,7 @@
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
-#define TARGET_CPUS (0xf)
+#define TARGET_CPUS (~0UL)
#define NO_BALANCE_IRQ (1)
#define esr_disable (1)
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 255444642524..f13289fef06c 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -20,7 +20,7 @@ static inline unsigned long xapic_phys_to_log_apicid(int phys_apic)
static inline unsigned long target_cpus(void)
{
- return XAPIC_DEST_CPUS_MASK;
+ return (~0UL);
}
#define TARGET_CPUS (target_cpus())
@@ -141,7 +141,7 @@ static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
printk ("%s: Not a valid mask!\n",__FUNCTION__);
- return TARGET_CPUS;
+ return 0xFF;
}
apicid = apicid | new_apicid;
cpus_found++;
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 6d7508ca9b4e..184d9b8ffba3 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -221,6 +221,13 @@ static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, &p
static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
/*
+ * Macro to mark a page protection value as "uncacheable". On processors which do not support
+ * it, this is a no-op.
+ */
+#define pgprot_noncached(prot) ((boot_cpu_data.x86 > 3) \
+ ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) : (prot))
+
+/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 4fcccc01f1ca..832995cd8398 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -153,6 +153,23 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma,
#ifndef __ASSEMBLY__
#include <asm-generic/pgtable.h>
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#ifdef SUN3_PAGE_NOCACHE
+# define __SUN3_PAGE_NOCACHE SUN3_PAGE_NOCACHE
+#else
+# define __SUN3_PAGE_NOCACHE 0
+#endif
+#define pgprot_noncached(prot) \
+ (MMU_IS_SUN3 \
+ ? (__pgprot(pgprot_val(prot) | __SUN3_PAGE_NOCACHE)) \
+ : ((MMU_IS_851 || MMU_IS_030) \
+ ? (__pgprot(pgprot_val(prot) | _PAGE_NOCACHE030)) \
+ : (MMU_IS_040 || MMU_IS_060) \
+ ? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S)) \
+ : (prot)))
+
typedef pte_t *pte_addr_t;
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index eccf8856355f..73a8f18d22cf 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -478,6 +478,11 @@ static inline void ptep_mkdirty(pte_t *ptep)
pte_update(ptep, 0, _PAGE_DIRTY);
}
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
#define pmd_page_kernel(pmd) \
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 6f6a89e3cca4..d2f8ceaf38fa 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -303,6 +303,11 @@ static inline void ptep_mkdirty(pte_t *ptep)
pte_update(ptep, 0, _PAGE_DIRTY);
}
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
/*
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index a4124fe6a8e7..83813096fa26 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -212,8 +212,7 @@ extern char empty_zero_page[PAGE_SIZE];
#define _PAGE_INVALID 0x400 /* HW invalid */
/* Software bits in the page table entry */
-#define _PAGE_MKCLEAN 0x002
-#define _PAGE_ISCLEAN 0x004
+#define _PAGE_ISCLEAN 0x002
/* Mask and four different kinds of invalid pages. */
#define _PAGE_INVALID_MASK 0x601
@@ -320,15 +319,6 @@ extern char empty_zero_page[PAGE_SIZE];
*/
extern inline void set_pte(pte_t *pteptr, pte_t pteval)
{
- if ((pte_val(pteval) & (_PAGE_MKCLEAN|_PAGE_INVALID))
- == _PAGE_MKCLEAN)
- {
- pte_val(pteval) &= ~_PAGE_MKCLEAN;
-
- asm volatile ("sske %0,%1"
- : : "d" (0), "a" (pte_val(pteval)));
- }
-
*pteptr = pteval;
}
@@ -501,7 +491,7 @@ extern inline pte_t pte_mkdirty(pte_t pte)
* sske instruction is slow. It is faster to let the
* next instruction set the dirty bit.
*/
- pte_val(pte) &= ~(_PAGE_MKCLEAN | _PAGE_ISCLEAN);
+ pte_val(pte) &= ~ _PAGE_ISCLEAN;
return pte;
}
@@ -582,30 +572,23 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
pgprot_t __pgprot = (pgprot); \
unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT); \
pte_t __pte = mk_pte_phys(__physpage, __pgprot); \
- \
- if (!(pgprot_val(__pgprot) & _PAGE_ISCLEAN)) { \
- int __users = !!PagePrivate(__page) + !!__page->mapping; \
- if (__users + page_count(__page) == 1) \
- pte_val(__pte) |= _PAGE_MKCLEAN; \
- } \
__pte; \
})
#define pfn_pte(pfn, pgprot) \
({ \
- struct page *__page = mem_map+(pfn); \
pgprot_t __pgprot = (pgprot); \
unsigned long __physpage = __pa((pfn) << PAGE_SHIFT); \
pte_t __pte = mk_pte_phys(__physpage, __pgprot); \
- \
- if (!(pgprot_val(__pgprot) & _PAGE_ISCLEAN)) { \
- int __users = !!PagePrivate(__page) + !!__page->mapping; \
- if (__users + page_count(__page) == 1) \
- pte_val(__pte) |= _PAGE_MKCLEAN; \
- } \
__pte; \
})
+#define arch_set_page_uptodate(__page) \
+ do { \
+ asm volatile ("sske %0,%1" : : "d" (0), \
+ "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
+ } while (0)
+
#ifdef __s390x__
#define pfn_pmd(pfn, pgprot) \
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index dc105425b961..83a902a5550b 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -265,6 +265,11 @@ static inline int ptep_test_and_clear_young(pte_t *ptep) { return test_and_clea
static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); }
static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, ptep); }
+/*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
+
#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
static inline int pmd_large(pmd_t pte) {
return (pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 976551db820e..d2711ab6b024 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -401,6 +401,15 @@ struct pci_dev;
int acpi_pci_irq_enable (struct pci_dev *dev);
int acpi_pci_irq_init (void);
+struct acpi_pci_driver {
+ struct acpi_pci_driver *next;
+ int (*add)(acpi_handle *handle);
+ void (*remove)(acpi_handle *handle);
+};
+
+int acpi_pci_register_driver(struct acpi_pci_driver *driver);
+void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
+
#endif /*CONFIG_ACPI_PCI*/
#ifdef CONFIG_ACPI_EC
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index e76ca2ea4f47..25b474976093 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -563,27 +563,6 @@ COMPATIBLE_IOCTL(ATMTCP_REMOVE)
COMPATIBLE_IOCTL(ATMMPC_CTRL)
COMPATIBLE_IOCTL(ATMMPC_DATA)
#endif
-#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
-COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC)
-COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID)
-COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC)
-COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK)
-COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK)
-COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL)
-COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS)
-COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS)
-COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX)
-COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW)
-COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW)
-COMPATIBLE_IOCTL(DRM_IOCTL_LOCK)
-COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK)
-COMPATIBLE_IOCTL(DRM_IOCTL_FINISH)
-#endif /* DRM */
/* Big W */
/* WIOC_GETSUPPORT not yet implemented -E */
COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
index dd2e43c66905..1c78b593851a 100644
--- a/include/linux/i2c-dev.h
+++ b/include/linux/i2c-dev.h
@@ -34,13 +34,13 @@ struct i2c_smbus_ioctl_data {
__u8 read_write;
__u8 command;
__u32 size;
- union i2c_smbus_data *data;
+ union i2c_smbus_data __user *data;
};
/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
- struct i2c_msg *msgs; /* pointers to i2c_msgs */
- __u32 nmsgs; /* number of i2c_msgs */
+ struct i2c_msg __user *msgs; /* pointers to i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
};
#endif /* _LINUX_I2C_DEV_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 9bccd9f27a3a..ddd328130b5a 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -176,7 +176,7 @@ static inline void *i2c_get_clientdata (struct i2c_client *dev)
static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
#define I2C_DEVNAME(str) .dev = { .name = str }
@@ -261,7 +261,7 @@ static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
/*flags for the driver struct: */
diff --git a/include/linux/node.h b/include/linux/node.h
index 90543a94b86e..d1c28e6a0b18 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -28,7 +28,6 @@ struct node {
extern int register_node(struct node *, int, struct node *);
-#define to_node(_root) container_of(_root, struct node, sysroot)
-#define to_root(_dev) container_of(_dev, struct sys_root, dev)
+#define to_node(sys_device) container_of(sys_device, struct node, sysdev)
#endif /* _LINUX_NODE_H_ */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 2466e79cf76b..e68fb2117527 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -7,6 +7,7 @@
#include <linux/percpu.h>
#include <linux/cache.h>
+#include <asm/pgtable.h>
/*
* Various page->flags bits:
@@ -158,8 +159,16 @@ extern void get_full_page_state(struct page_state *ret);
#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags)
#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
+#ifndef arch_set_page_uptodate
+#define arch_set_page_uptodate(page) do { } while (0)
+#endif
+
#define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags)
-#define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags)
+#define SetPageUptodate(page) \
+ do { \
+ arch_set_page_uptodate(page); \
+ set_bit(PG_uptodate, &(page)->flags); \
+ } while (0)
#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags)
#define PageDirty(page) test_bit(PG_dirty, &(page)->flags)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 99e1f0e19602..1983191d32c8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -807,7 +807,7 @@ extern int pci_pci_problems;
*/
#ifndef CONFIG_PCI_DOMAINS
-#define pci_domain_nr(bus) 0
+static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
#endif
#endif /* __KERNEL__ */
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 5608cfedf709..68b0cb81d986 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -9,6 +9,7 @@
#define LINUX_REBOOT_MAGIC2 672274793
#define LINUX_REBOOT_MAGIC2A 85072278
#define LINUX_REBOOT_MAGIC2B 369367448
+#define LINUX_REBOOT_MAGIC2C 537993216
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b7a364022625..d313e2ccbf42 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -475,6 +475,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00040000 /* I am kswapd */
#define PF_SWAPOFF 0x00080000 /* I am in swapoff */
+#define PF_LESS_THROTTLE 0x01000000 /* Throttle me less: I clena memory */
#ifdef CONFIG_SMP
extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 3e4e5491102c..138bcdf65275 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -62,7 +62,38 @@ extern void *kmem_cache_alloc(kmem_cache_t *, int);
extern void kmem_cache_free(kmem_cache_t *, void *);
extern unsigned int kmem_cache_size(kmem_cache_t *);
-extern void *kmalloc(size_t, int);
+/* Size description struct for general caches. */
+struct cache_sizes {
+ size_t cs_size;
+ kmem_cache_t *cs_cachep;
+ kmem_cache_t *cs_dmacachep;
+};
+extern struct cache_sizes malloc_sizes[];
+extern void *__kmalloc(size_t, int);
+
+static inline void *kmalloc(size_t size, int flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kmalloc_that_much(void);
+ __you_cannot_kmalloc_that_much();
+ }
+found:
+ return kmem_cache_alloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kmalloc(size, flags);
+}
+
extern void kfree(const void *);
extern unsigned int ksize(const void *);
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index 4bc3e22b5104..614200d60389 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -72,6 +72,7 @@ struct sys_device {
u32 id;
struct sysdev_class * cls;
struct kobject kobj;
+ struct list_head entry;
};
extern int sys_device_register(struct sys_device *);
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index e29dfbb82a99..4e0f3cf69b35 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -316,7 +316,7 @@ typedef struct error_info_t {
/* Special stuff for binding drivers to sockets */
typedef struct bind_req_t {
- socket_t Socket;
+ struct pcmcia_socket *Socket;
u_char Function;
dev_info_t *dev_info;
} bind_req_t;
@@ -325,7 +325,7 @@ typedef struct bind_req_t {
#define BIND_FN_ALL 0xff
typedef struct mtd_bind_t {
- socket_t Socket;
+ struct pcmcia_socket *Socket;
u_int Attributes;
u_int CardOffset;
dev_info_t *dev_info;
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 2a3917ce1814..f69b5a8c4bb7 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -31,6 +31,8 @@
#define _LINUX_SS_H
#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
#include <linux/device.h>
/* Definitions for card status flags for GetStatus */
@@ -124,37 +126,138 @@ typedef struct cb_bridge_map {
/*
* Socket operations.
*/
+struct pcmcia_socket;
+
struct pccard_operations {
struct module *owner;
- int (*init)(unsigned int sock);
- int (*suspend)(unsigned int sock);
- int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
- int (*inquire_socket)(unsigned int sock, socket_cap_t *cap);
- int (*get_status)(unsigned int sock, u_int *value);
- int (*get_socket)(unsigned int sock, socket_state_t *state);
- int (*set_socket)(unsigned int sock, socket_state_t *state);
- int (*set_io_map)(unsigned int sock, struct pccard_io_map *io);
- int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
- void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base);
+ int (*init)(struct pcmcia_socket *sock);
+ int (*suspend)(struct pcmcia_socket *sock);
+ int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
+ int (*inquire_socket)(struct pcmcia_socket *sock, socket_cap_t *cap);
+ int (*get_status)(struct pcmcia_socket *sock, u_int *value);
+ int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+ int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+ int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
+ int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
+ void (*proc_setup)(struct pcmcia_socket *sock, struct proc_dir_entry *base);
};
/*
* Calls to set up low-level "Socket Services" drivers
*/
+struct pcmcia_socket;
struct pcmcia_socket_class_data {
unsigned int nsock; /* number of sockets */
unsigned int sock_offset; /* socket # (which is
* returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */
struct pccard_operations *ops; /* see above */
- void *s_info; /* socket_info_t */
+ struct pcmcia_socket *s_info;
struct class_device class_dev; /* generic class structure */
};
+typedef struct erase_busy_t {
+ eraseq_entry_t *erase;
+ client_handle_t client;
+ struct timer_list timeout;
+ struct erase_busy_t *prev, *next;
+} erase_busy_t;
+
+typedef struct io_window_t {
+ u_int Attributes;
+ ioaddr_t BasePort, NumPorts;
+ ioaddr_t InUse, Config;
+} io_window_t;
+
+#define WINDOW_MAGIC 0xB35C
+typedef struct window_t {
+ u_short magic;
+ u_short index;
+ client_handle_t handle;
+ struct pcmcia_socket *sock;
+ u_long base;
+ u_long size;
+ pccard_mem_map ctl;
+} window_t;
+
+/* Maximum number of IO windows per socket */
+#define MAX_IO_WIN 2
+
+/* Maximum number of memory windows per socket */
+#define MAX_WIN 4
+
+struct config_t;
+struct region_t;
+
+struct pcmcia_socket {
+ spinlock_t lock;
+ struct pccard_operations * ss_entry;
+ socket_state_t socket;
+ socket_cap_t cap;
+ u_int state;
+ u_short functions;
+ u_short lock_count;
+ client_handle_t clients;
+ u_int real_clients;
+ pccard_mem_map cis_mem;
+ u_char *cis_virt;
+ struct config_t *config;
+ struct {
+ u_int AssignedIRQ;
+ u_int Config;
+ } irq;
+ io_window_t io[MAX_IO_WIN];
+ window_t win[MAX_WIN];
+ struct region_t *c_region, *a_region;
+ erase_busy_t erase_busy;
+ struct list_head cis_cache;
+ u_int fake_cis_len;
+ char *fake_cis;
+
+ struct list_head socket_list;
+
+ /* deprecated */
+ unsigned int sock; /* socket number */
+
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc;
+#endif
+
+ /* state thread */
+ struct semaphore skt_sem; /* protects socket h/w state */
+
+ struct task_struct *thread;
+ struct completion thread_done;
+ wait_queue_head_t thread_wait;
+ spinlock_t thread_lock; /* protects thread_events */
+ unsigned int thread_events;
+
+ /* pcmcia (16-bit) */
+ struct pcmcia_bus_socket *pcmcia;
+
+ /* cardbus (32-bit) */
+#ifdef CONFIG_CARDBUS
+ struct resource * cb_cis_res;
+ u_char *cb_cis_virt;
+#endif
+
+ /* socket device */
+ struct class_device dev;
+ void *driver_data; /* data internal to the socket driver */
+
+};
+
+struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr);
+
+
+
+extern int pcmcia_register_socket(struct pcmcia_socket *socket);
+extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
+
extern struct class pcmcia_socket_class;
/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level);
-extern int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level);
+extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level);
+extern int pcmcia_socket_dev_resume(struct device *dev, u32 level);
#endif /* _LINUX_SS_H */
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 10ad5bc8cccd..098e5b5db592 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -95,7 +95,8 @@ EXPORT_SYMBOL(kmem_cache_free);
EXPORT_SYMBOL(kmem_cache_size);
EXPORT_SYMBOL(set_shrinker);
EXPORT_SYMBOL(remove_shrinker);
-EXPORT_SYMBOL(kmalloc);
+EXPORT_SYMBOL(malloc_sizes);
+EXPORT_SYMBOL(__kmalloc);
EXPORT_SYMBOL(kfree);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(__alloc_percpu);
diff --git a/kernel/sched.c b/kernel/sched.c
index dca8492046d0..28d7fb9fee73 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1108,7 +1108,7 @@ static void rebalance_tick(runqueue_t *this_rq, int idle)
#endif
if (!(j % IDLE_REBALANCE_TICK)) {
spin_lock(&this_rq->lock);
- load_balance(this_rq, 0, cpu_to_node_mask(this_cpu));
+ load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
spin_unlock(&this_rq->lock);
}
return;
diff --git a/kernel/sys.c b/kernel/sys.c
index 5c2c439ae6bc..eb3e920d557e 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -392,8 +392,10 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
/* For safety, we require "magic" arguments. */
if (magic1 != LINUX_REBOOT_MAGIC1 ||
- (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
- magic2 != LINUX_REBOOT_MAGIC2B))
+ (magic2 != LINUX_REBOOT_MAGIC2 &&
+ magic2 != LINUX_REBOOT_MAGIC2A &&
+ magic2 != LINUX_REBOOT_MAGIC2B &&
+ magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;
lock_kernel();
diff --git a/lib/kobject.c b/lib/kobject.c
index 661bf12797cf..e2378597b989 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -252,14 +252,15 @@ int kobject_add(struct kobject * kobj)
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
- if (parent)
- list_add_tail(&kobj->entry,&parent->entry);
- else {
- list_add_tail(&kobj->entry,&kobj->kset->list);
- kobj->parent = kobject_get(&kobj->kset->kobj);
- }
+
+ if (!parent)
+ parent = kobject_get(&kobj->kset->kobj);
+
+ list_add_tail(&kobj->entry,&kobj->kset->list);
up_write(&kobj->kset->subsys->rwsem);
}
+ kobj->parent = parent;
+
error = create_dir(kobj);
if (error)
unlink(kobj);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 27ddc1244ce9..9e54d17adaaa 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -104,11 +104,13 @@ static void background_writeout(unsigned long _min_pages);
* clamping level.
*/
static void
-get_dirty_limits(struct page_state *ps, long *background, long *dirty)
+get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty)
{
int background_ratio; /* Percentages */
int dirty_ratio;
int unmapped_ratio;
+ long background;
+ long dirty;
get_page_state(ps);
@@ -125,8 +127,14 @@ get_dirty_limits(struct page_state *ps, long *background, long *dirty)
if (background_ratio >= dirty_ratio)
background_ratio = dirty_ratio / 2;
- *background = (background_ratio * total_pages) / 100;
- *dirty = (dirty_ratio * total_pages) / 100;
+ background = (background_ratio * total_pages) / 100;
+ dirty = (dirty_ratio * total_pages) / 100;
+ if (current->flags & PF_LESS_THROTTLE) {
+ background += background / 4;
+ dirty += dirty / 4;
+ }
+ *pbackground = background;
+ *pdirty = dirty;
}
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6f59feb32568..dfd254c2c94b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -898,7 +898,7 @@ void si_meminfo_node(struct sysinfo *val, int nid)
val->totalram = pgdat->node_size;
val->freeram = nr_free_pages_pgdat(pgdat);
- val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].spanned_pages;
+ val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].present_pages;
val->freehigh = pgdat->node_zones[ZONE_HIGHMEM].free_pages;
val->mem_unit = PAGE_SIZE;
}
@@ -1152,8 +1152,11 @@ static void __init calculate_zone_bitmap(struct pglist_data *pgdat,
for (i = 0; i < MAX_NR_ZONES; i++)
size += zones_size[i];
size = LONG_ALIGN((size + 7) >> 3);
- pgdat->valid_addr_bitmap = (unsigned long *)alloc_bootmem_node(pgdat, size);
- memset(pgdat->valid_addr_bitmap, 0, size);
+ if (size) {
+ pgdat->valid_addr_bitmap =
+ (unsigned long *)alloc_bootmem_node(pgdat, size);
+ memset(pgdat->valid_addr_bitmap, 0, size);
+ }
}
/*
diff --git a/mm/slab.c b/mm/slab.c
index aafffa664e67..e236bbbfac21 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -385,11 +385,7 @@ static int slab_break_gfp_order = BREAK_GFP_ORDER_LO;
#define GET_PAGE_SLAB(pg) ((struct slab *)(pg)->list.prev)
/* These are the default caches for kmalloc. Custom caches can have other sizes. */
-static struct cache_sizes {
- size_t cs_size;
- kmem_cache_t *cs_cachep;
- kmem_cache_t *cs_dmacachep;
-} malloc_sizes[] = {
+struct cache_sizes malloc_sizes[] = {
#define CACHE(x) { .cs_size = (x) },
#include <linux/kmalloc_sizes.h>
{ 0, }
@@ -1967,7 +1963,7 @@ void * kmem_cache_alloc (kmem_cache_t *cachep, int flags)
* platforms. For example, on i386, it means that the memory must come
* from the first 16MB.
*/
-void * kmalloc (size_t size, int flags)
+void * __kmalloc (size_t size, int flags)
{
struct cache_sizes *csizep = malloc_sizes;