summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-15 03:32:22 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-15 03:32:22 +0000
commitf1da2c3860e301527d56a1ef0b56c649ee7c4b1b (patch)
tree562b5d2e8b9cb62eb983d78ff6bcf9789e08fcf6 /drivers
parent00f11569ac8ca73cbcdef8822de1583e79aee571 (diff)
Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
The IP22 cache bugs which are plaguing some machines are still unfixed.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/cpu.c307
-rw-r--r--drivers/acpi/driver.c388
-rw-r--r--drivers/acpi/driver.h115
-rw-r--r--drivers/acpi/ec.c191
-rw-r--r--drivers/acpi/os.c379
-rw-r--r--drivers/acpi/osd.c1319
-rw-r--r--drivers/acpi/sys.c182
-rw-r--r--drivers/acpi/tables.c303
-rw-r--r--drivers/block/acsi_slm.c5
-rw-r--r--drivers/block/ll_rw_blk.c84
-rw-r--r--drivers/block/lvm.c9
-rw-r--r--drivers/block/md.c4
-rw-r--r--drivers/block/paride/paride.c27
-rw-r--r--drivers/block/paride/pg.c3
-rw-r--r--drivers/block/paride/pt.c3
-rw-r--r--drivers/block/ps2esdi.c12
-rw-r--r--drivers/block/rd.c14
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/cdrom/sjcd.c2
-rw-r--r--drivers/char/acquirewdt.c3
-rw-r--r--drivers/char/agp/agpgart_fe.c15
-rw-r--r--drivers/char/amikeyb.c2
-rw-r--r--drivers/char/applicom.c26
-rw-r--r--drivers/char/busmouse.c3
-rw-r--r--drivers/char/cyclades.c173
-rw-r--r--drivers/char/dn_keyb.c3
-rw-r--r--drivers/char/drm/ffb_drv.c48
-rw-r--r--drivers/char/drm/gamma_drv.c31
-rw-r--r--drivers/char/drm/tdfx_drv.c15
-rw-r--r--drivers/char/drm/vm.c2
-rw-r--r--drivers/char/dsp56k.c3
-rw-r--r--drivers/char/dtlk.c3
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c106
-rw-r--r--drivers/char/h8.c12
-rw-r--r--drivers/char/i2c-parport.c2
-rw-r--r--drivers/char/i810_rng.c7
-rw-r--r--drivers/char/ip2main.c3
-rw-r--r--drivers/char/joystick/Config.in4
-rw-r--r--drivers/char/lp.c3
-rw-r--r--drivers/char/mixcomwd.c4
-rw-r--r--drivers/char/msp3400.c2
-rw-r--r--drivers/char/nvram.c4
-rw-r--r--drivers/char/pc110pad.c8
-rw-r--r--drivers/char/pc_keyb.c7
-rw-r--r--drivers/char/pcmcia/Config.in6
-rw-r--r--drivers/char/pcwd.c3
-rw-r--r--drivers/char/ppdev.c86
-rw-r--r--drivers/char/qpmouse.c3
-rw-r--r--drivers/char/raw.c3
-rw-r--r--drivers/char/sbc60xxwdt.c3
-rw-r--r--drivers/char/softdog.c7
-rw-r--r--drivers/char/tpqic02.c3
-rw-r--r--drivers/char/tty_io.c2
-rw-r--r--drivers/char/tvmixer.c10
-rw-r--r--drivers/char/videodev.c19
-rw-r--r--drivers/char/wdt.c3
-rw-r--r--drivers/char/wdt285.c7
-rw-r--r--drivers/char/wdt977.c7
-rw-r--r--drivers/char/wdt_pci.c8
-rw-r--r--drivers/i2c/i2c-dev.c6
-rw-r--r--drivers/i2o/i2o_config.c3
-rw-r--r--drivers/ide/ide-tape.c34
-rw-r--r--drivers/ieee1394/raw1394.c3
-rw-r--r--drivers/ieee1394/video1394.c17
-rw-r--r--drivers/isdn/avmb1/capi.c18
-rw-r--r--drivers/isdn/divert/divert_procfs.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_procfs.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c2
-rw-r--r--drivers/isdn/isdn_common.c43
-rw-r--r--drivers/macintosh/adb.c3
-rw-r--r--drivers/macintosh/via-pmu.c3
-rw-r--r--drivers/mtd/Config.in96
-rw-r--r--drivers/mtd/Makefile267
-rw-r--r--drivers/mtd/cfi_cmdset_0001.c8
-rw-r--r--drivers/mtd/cfi_cmdset_0002.c610
-rw-r--r--drivers/mtd/doc2000.c8
-rw-r--r--drivers/mtd/doc2001.c748
-rw-r--r--drivers/mtd/docprobe.c6
-rw-r--r--drivers/mtd/mtdblock.c2
-rw-r--r--drivers/mtd/mtdchar.c10
-rw-r--r--drivers/mtd/mtdcore.c126
-rw-r--r--drivers/mtd/mtdram.c6
-rw-r--r--drivers/mtd/nftl.c4
-rw-r--r--drivers/mtd/nora.c12
-rw-r--r--drivers/mtd/octagon-5066.c6
-rw-r--r--drivers/mtd/pmc551.c11
-rw-r--r--drivers/mtd/pnc2000.c210
-rw-r--r--drivers/net/atari_bionet.c2
-rw-r--r--drivers/net/atari_pamsnet.c2
-rw-r--r--drivers/net/de4x5.c1
-rw-r--r--drivers/net/pcmcia/xircom_tulip_cb.c3
-rw-r--r--drivers/net/ppp_generic.c3
-rw-r--r--drivers/net/sk_g16.c2
-rw-r--r--drivers/net/tulip/tulip_core.c8
-rw-r--r--drivers/net/wan/Makefile3
-rw-r--r--drivers/net/wan/cosa.c6
-rw-r--r--drivers/net/wan/cycx_main.c12
-rw-r--r--drivers/parport/ChangeLog38
-rw-r--r--drivers/parport/init.c4
-rw-r--r--drivers/parport/share.c255
-rw-r--r--drivers/pcmcia/ds.c24
-rw-r--r--drivers/pnp/isapnp_proc.c2
-rw-r--r--drivers/sbus/audio/audio.c4
-rw-r--r--drivers/sbus/char/bpp.c4
-rw-r--r--drivers/sbus/char/flash.c14
-rw-r--r--drivers/sbus/char/jsflash.c3
-rw-r--r--drivers/sbus/char/pcikbd.c6
-rw-r--r--drivers/sbus/char/rtc.c3
-rw-r--r--drivers/sbus/char/sunkbd.c20
-rw-r--r--drivers/sbus/char/sunmouse.c3
-rw-r--r--drivers/sbus/char/vfc_dev.c21
-rw-r--r--drivers/scsi/pluto.c5
-rw-r--r--drivers/scsi/scsi_scan.c4
-rw-r--r--drivers/scsi/sg.c26
-rw-r--r--drivers/scsi/st.c10
-rw-r--r--drivers/sgi/char/graphics.c3
-rw-r--r--drivers/sgi/char/shmiq.c6
-rw-r--r--drivers/sgi/char/streamable.c19
-rw-r--r--drivers/sgi/char/usema.c7
-rw-r--r--drivers/sound/cmpci.c29
-rw-r--r--drivers/sound/dmasound/dmasound_core.c7
-rw-r--r--drivers/sound/emu10k1/audio.c12
-rw-r--r--drivers/sound/emu10k1/midi.c7
-rw-r--r--drivers/sound/es1370.c49
-rw-r--r--drivers/sound/es1371.c49
-rw-r--r--drivers/sound/esssolo1.c29
-rw-r--r--drivers/sound/i810_audio.c26
-rw-r--r--drivers/sound/maestro.c26
-rw-r--r--drivers/sound/msnd.h11
-rw-r--r--drivers/sound/msnd_pinnacle.c72
-rw-r--r--drivers/sound/sonicvibes.c29
-rw-r--r--drivers/sound/soundcard.c13
-rw-r--r--drivers/sound/trident.c34
-rw-r--r--drivers/sound/via82cxxx_audio.c3
-rw-r--r--drivers/sound/vwsnd.c37
-rw-r--r--drivers/sound/wavfront.c3
-rw-r--r--drivers/telephony/ixj.c3
-rw-r--r--drivers/usb/Config.in4
-rw-r--r--drivers/usb/audio.c31
-rw-r--r--drivers/usb/bluetooth.c9
-rw-r--r--drivers/usb/dabusb.c3
-rw-r--r--drivers/usb/dc2xx.c3
-rw-r--r--drivers/usb/devices.c116
-rw-r--r--drivers/usb/evdev.c6
-rw-r--r--drivers/usb/joydev.c6
-rw-r--r--drivers/usb/mdc800.c3
-rw-r--r--drivers/usb/mousedev.c6
-rw-r--r--drivers/usb/printer.c18
-rw-r--r--drivers/usb/usb.c27
-rw-r--r--drivers/video/fbcon-mac.c120
-rw-r--r--drivers/video/fbcon.c10
-rw-r--r--drivers/video/fbmem.c17
-rw-r--r--drivers/video/vesafb.c6
155 files changed, 4697 insertions, 2930 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index c8b888ff1..2c9606663 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -11,7 +11,7 @@ O_TARGET := acpi.o
O_OBJS :=
M_OBJS :=
-ACPI_OBJS := osd.o
+ACPI_OBJS := driver.o ec.o cpu.o os.o sys.o tables.o
ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard */*.c))
EXTRA_CFLAGS += -I./include -D_LINUX
diff --git a/drivers/acpi/cpu.c b/drivers/acpi/cpu.c
new file mode 100644
index 000000000..f1feeb12b
--- /dev/null
+++ b/drivers/acpi/cpu.c
@@ -0,0 +1,307 @@
+/*
+ * cpu.c - Processor handling
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include "acpi.h"
+#include "driver.h"
+
+unsigned long acpi_c2_exit_latency = ACPI_INFINITE;
+unsigned long acpi_c3_exit_latency = ACPI_INFINITE;
+unsigned long acpi_c2_enter_latency = ACPI_INFINITE;
+unsigned long acpi_c3_enter_latency = ACPI_INFINITE;
+
+static unsigned long acpi_pblk = ACPI_INVALID;
+static int acpi_c2_tested = 0;
+static int acpi_c3_tested = 0;
+
+/*
+ * Clear busmaster activity flag
+ */
+static inline void
+acpi_clear_bm_activity(struct acpi_facp *facp)
+{
+ acpi_write_pm1_status(facp, ACPI_BM);
+}
+
+/*
+ * Returns 1 if there has been busmaster activity
+ */
+static inline int
+acpi_bm_activity(struct acpi_facp *facp)
+{
+ return acpi_read_pm1_status(facp) & ACPI_BM;
+}
+
+/*
+ * Set system to sleep through busmaster requests
+ */
+static void
+acpi_sleep_on_busmaster(struct acpi_facp *facp)
+{
+ u32 pm1_cntr = acpi_read_pm1_control(facp);
+ if (pm1_cntr & ACPI_BM_RLD) {
+ pm1_cntr &= ~ACPI_BM_RLD;
+ acpi_write_pm1_control(facp, pm1_cntr);
+ }
+}
+
+/*
+ * Set system to wake on busmaster requests
+ */
+static void
+acpi_wake_on_busmaster(struct acpi_facp *facp)
+{
+ u32 pm1_cntr = acpi_read_pm1_control(facp);
+ if (!(pm1_cntr & ACPI_BM_RLD)) {
+ pm1_cntr |= ACPI_BM_RLD;
+ acpi_write_pm1_control(facp, pm1_cntr);
+ }
+ acpi_clear_bm_activity(facp);
+}
+
+/* The ACPI timer is just the low 24 bits */
+#define TIME_BEGIN(tmr) inl(tmr)
+#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff)
+
+/*
+ * Idle loop (uniprocessor only)
+ */
+static void
+acpi_idle(void)
+{
+ static int sleep_level = 1;
+ struct acpi_facp *facp = &acpi_facp;
+
+ if (!facp
+ || facp->hdr.signature != ACPI_FACP_SIG
+ || !facp->pm_tmr
+ || !acpi_pblk)
+ goto not_initialized;
+
+ /*
+ * start from the previous sleep level..
+ */
+ if (sleep_level == 1)
+ goto sleep1;
+ if (sleep_level == 2)
+ goto sleep2;
+ sleep3:
+ sleep_level = 3;
+ if (!acpi_c3_tested) {
+ printk(KERN_DEBUG "ACPI C3 works\n");
+ acpi_c3_tested = 1;
+ }
+ acpi_wake_on_busmaster(facp);
+ if (facp->pm2_cnt)
+ goto sleep3_with_arbiter;
+
+ for (;;) {
+ unsigned long time;
+ unsigned int pm_tmr = facp->pm_tmr;
+
+ __cli();
+ if (current->need_resched)
+ goto out;
+ if (acpi_bm_activity(facp))
+ goto sleep2;
+
+ time = TIME_BEGIN(pm_tmr);
+ inb(acpi_pblk + ACPI_P_LVL3);
+ /* Dummy read, force synchronization with the PMU */
+ inl(pm_tmr);
+ time = TIME_END(pm_tmr, time);
+
+ __sti();
+ if (time < acpi_c3_exit_latency)
+ goto sleep2;
+ }
+
+ sleep3_with_arbiter:
+ for (;;) {
+ unsigned long time;
+ u8 arbiter;
+ unsigned int pm2_cntr = facp->pm2_cnt;
+ unsigned int pm_tmr = facp->pm_tmr;
+
+ __cli();
+ if (current->need_resched)
+ goto out;
+ if (acpi_bm_activity(facp))
+ goto sleep2;
+
+ time = TIME_BEGIN(pm_tmr);
+ arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS;
+ /* Disable arbiter, park on CPU */
+ outb(arbiter | ACPI_ARB_DIS, pm2_cntr);
+ inb(acpi_pblk + ACPI_P_LVL3);
+ /* Dummy read, force synchronization with the PMU */
+ inl(pm_tmr);
+ time = TIME_END(pm_tmr, time);
+ /* Enable arbiter again.. */
+ outb(arbiter, pm2_cntr);
+
+ __sti();
+ if (time < acpi_c3_exit_latency)
+ goto sleep2;
+ }
+
+ sleep2:
+ sleep_level = 2;
+ if (!acpi_c2_tested) {
+ printk(KERN_DEBUG "ACPI C2 works\n");
+ acpi_c2_tested = 1;
+ }
+ acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */
+ for (;;) {
+ unsigned long time;
+ unsigned int pm_tmr = facp->pm_tmr;
+
+ __cli();
+ if (current->need_resched)
+ goto out;
+
+ time = TIME_BEGIN(pm_tmr);
+ inb(acpi_pblk + ACPI_P_LVL2);
+ /* Dummy read, force synchronization with the PMU */
+ inl(pm_tmr);
+ time = TIME_END(pm_tmr, time);
+
+ __sti();
+ if (time < acpi_c2_exit_latency)
+ goto sleep1;
+ if (acpi_bm_activity(facp)) {
+ acpi_clear_bm_activity(facp);
+ continue;
+ }
+ if (time > acpi_c3_enter_latency)
+ goto sleep3;
+ }
+
+ sleep1:
+ sleep_level = 1;
+ acpi_sleep_on_busmaster(facp);
+ for (;;) {
+ unsigned long time;
+ unsigned int pm_tmr = facp->pm_tmr;
+
+ __cli();
+ if (current->need_resched)
+ goto out;
+ time = TIME_BEGIN(pm_tmr);
+ safe_halt();
+ time = TIME_END(pm_tmr, time);
+ if (time > acpi_c2_enter_latency)
+ goto sleep2;
+ }
+
+ not_initialized:
+ for (;;) {
+ __cli();
+ if (current->need_resched)
+ goto out;
+ safe_halt();
+ }
+
+ out:
+ __sti();
+}
+
+/*
+ * Get processor information
+ */
+static ACPI_STATUS
+acpi_find_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
+{
+ ACPI_OBJECT obj;
+ ACPI_CX_STATE lat[4];
+ ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
+ ACPI_BUFFER buf;
+ int i, count;
+
+ buf.length = sizeof(obj);
+ buf.pointer = &obj;
+ if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
+ return AE_OK;
+
+ printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n",
+ obj.processor.proc_id,
+ obj.processor.pblk_address,
+ obj.processor.pblk_length);
+ if (acpi_pblk != ACPI_INVALID
+ || !obj.processor.pblk_address
+ || obj.processor.pblk_length != 6)
+ return AE_OK;
+
+ acpi_pblk = obj.processor.pblk_address;
+
+ buf.length = sizeof(lat);
+ buf.pointer = lat;
+ if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
+ return AE_OK;
+
+ if (lat[2].latency < MAX_CX_STATE_LATENCY) {
+ printk(KERN_INFO "ACPI: C2 supported\n");
+ acpi_c2_exit_latency = lat[2].latency;
+ }
+ if (lat[3].latency < MAX_CX_STATE_LATENCY) {
+ printk(KERN_INFO "ACPI: C3 supported\n");
+ acpi_c3_exit_latency = lat[3].latency;
+ }
+
+ memset(throttle, 0, sizeof(throttle));
+ buf.length = sizeof(throttle);
+ buf.pointer = throttle;
+
+ if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
+ return AE_OK;
+
+ for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
+ if (throttle[i].percent_of_clock)
+ count++;
+ }
+ count--;
+ if (count > 0)
+ printk(KERN_INFO "ACPI: %d throttling states\n", count);
+
+ return AE_OK;
+}
+
+int
+acpi_cpu_init(void)
+{
+ acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+ ACPI_ROOT_OBJECT,
+ ACPI_INT32_MAX,
+ acpi_find_cpu,
+ NULL,
+ NULL);
+
+#ifdef CONFIG_SMP
+ if (smp_num_cpus == 1)
+ pm_idle = acpi_idle;
+#else
+ pm_idle = acpi_idle;
+#endif
+
+ return 0;
+}
diff --git a/drivers/acpi/driver.c b/drivers/acpi/driver.c
new file mode 100644
index 000000000..0c668f59b
--- /dev/null
+++ b/drivers/acpi/driver.c
@@ -0,0 +1,388 @@
+/*
+ * driver.c - ACPI driver
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include <asm/uaccess.h>
+#include "acpi.h"
+#include "driver.h"
+
+struct acpi_run_entry
+{
+ void (*callback)(void*);
+ void *context;
+ struct tq_struct task;
+};
+
+static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
+static volatile u32 acpi_event_status = 0;
+static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
+static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
+
+static volatile int acpi_thread_pid = -1;
+static DECLARE_TASK_QUEUE(acpi_thread_run);
+static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait);
+
+static struct ctl_table_header *acpi_sysctl = NULL;
+
+/*
+ * Examine/modify value
+ */
+static int
+acpi_do_ulong(ctl_table * ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t * len)
+{
+ char str[2 * sizeof(unsigned long) + 4], *strend;
+ unsigned long val;
+ int size;
+
+ if (!write) {
+ if (file->f_pos) {
+ *len = 0;
+ return 0;
+ }
+
+ val = *(unsigned long *) ctl->data;
+ size = sprintf(str, "0x%08lx\n", val);
+ if (*len >= size) {
+ copy_to_user(buffer, str, size);
+ *len = size;
+ }
+ else
+ *len = 0;
+ }
+ else {
+ size = sizeof(str) - 1;
+ if (size > *len)
+ size = *len;
+ copy_from_user(str, buffer, size);
+ str[size] = '\0';
+ val = simple_strtoul(str, &strend, 0);
+ if (strend == str)
+ return -EINVAL;
+ *(unsigned long *) ctl->data = val;
+ }
+
+ file->f_pos += *len;
+ return 0;
+}
+
+/*
+ * Handle ACPI event
+ */
+static u32
+acpi_event(void *context)
+{
+ unsigned long flags;
+ int event = (int) context;
+ int mask = 0;
+
+ switch (event) {
+ case ACPI_EVENT_POWER_BUTTON: mask = ACPI_PWRBTN; break;
+ case ACPI_EVENT_SLEEP_BUTTON: mask = ACPI_SLPBTN; break;
+ default: return AE_ERROR;
+ }
+
+ if (mask) {
+ // notify process waiting on /dev/acpi
+ spin_lock_irqsave(&acpi_event_lock, flags);
+ acpi_event_status |= mask;
+ spin_unlock_irqrestore(&acpi_event_lock, flags);
+ acpi_event_state = acpi_sleep_state;
+ wake_up_interruptible(&acpi_event_wait);
+ }
+
+ return AE_OK;
+}
+
+/*
+ * Wait for next event
+ */
+static int
+acpi_do_event(ctl_table * ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t * len)
+{
+ u32 event_status = 0;
+ acpi_sstate_t event_state = 0;
+ char str[27];
+ int size;
+
+ if (write)
+ return -EPERM;
+ if (*len < sizeof(str)) {
+ *len = 0;
+ return 0;
+ }
+
+ for (;;) {
+ unsigned long flags;
+
+ // we need an atomic exchange here
+ spin_lock_irqsave(&acpi_event_lock, flags);
+ event_status = acpi_event_status;
+ acpi_event_status = 0;
+ spin_unlock_irqrestore(&acpi_event_lock, flags);
+ event_state = acpi_event_state;
+
+ if (event_status)
+ break;
+
+ // wait for an event to arrive
+ interruptible_sleep_on(&acpi_event_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+
+ size = sprintf(str,
+ "0x%08x 0x%08x 0x%01x\n",
+ event_status,
+ 0,
+ event_state);
+ copy_to_user(buffer, str, size);
+ *len = size;
+ file->f_pos += size;
+
+ return 0;
+}
+
+/*
+ * Enter system sleep state
+ */
+static int
+acpi_do_sleep(ctl_table * ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t * len)
+{
+ if (!write) {
+ if (file->f_pos) {
+ *len = 0;
+ return 0;
+ }
+ }
+ else {
+#ifdef CONFIG_ACPI_S1_SLEEP
+ int status = acpi_enter_sx(ACPI_S1);
+ if (status)
+ return status;
+#endif
+ }
+ file->f_pos += *len;
+ return 0;
+}
+
+/*
+ * Run queued callback
+ */
+static void
+acpi_run_exec(void *context)
+{
+ struct acpi_run_entry *entry
+ = (struct acpi_run_entry*) context;
+ (*entry->callback)(entry->context);
+ kfree(entry);
+}
+
+/*
+ * Queue for execution by the ACPI thread
+ */
+int
+acpi_run(void (*callback)(void*), void *context)
+{
+ struct acpi_run_entry *entry;
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return -1;
+
+ memset(entry, 0, sizeof(entry));
+ entry->callback = callback;
+ entry->context = context;
+ entry->task.routine = acpi_run_exec;
+ entry->task.data = entry;
+
+ queue_task(&entry->task, &acpi_thread_run);
+
+ if (waitqueue_active(&acpi_thread_wait))
+ wake_up(&acpi_thread_wait);
+
+ return 0;
+}
+
+static struct ctl_table acpi_table[] =
+{
+ {ACPI_P_LVL2_LAT, "c2_exit_latency",
+ &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency),
+ 0644, NULL, &acpi_do_ulong},
+
+ {ACPI_ENTER_LVL2_LAT, "c2_enter_latency",
+ &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency),
+ 0644, NULL, &acpi_do_ulong},
+
+ {ACPI_P_LVL3_LAT, "c3_exit_latency",
+ &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency),
+ 0644, NULL, &acpi_do_ulong},
+
+ {ACPI_ENTER_LVL3_LAT, "c3_enter_latency",
+ &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
+ 0644, NULL, &acpi_do_ulong},
+
+ {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
+
+ {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
+
+ {0}
+};
+
+static struct ctl_table acpi_dir_table[] =
+{
+ {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
+ {0}
+};
+
+/*
+ * Initialize and run interpreter within a kernel thread
+ */
+static int
+acpi_thread(void *context)
+{
+ /*
+ * initialize
+ */
+ exit_files(current);
+ daemonize();
+ strcpy(current->comm, "acpi");
+
+ if (!ACPI_SUCCESS(acpi_initialize(NULL))) {
+ printk(KERN_ERR "ACPI: initialize failed\n");
+ return -ENODEV;
+ }
+
+ if (acpi_load_tables())
+ return -ENODEV;
+
+ if (PM_IS_ACTIVE()) {
+ printk(KERN_NOTICE "ACPI: APM is already active.\n");
+ acpi_terminate();
+ return -ENODEV;
+ }
+
+ pm_active = 1;
+
+ if (!ACPI_SUCCESS(acpi_enable())) {
+ printk(KERN_ERR "ACPI: enable failed\n");
+ acpi_terminate();
+ return -ENODEV;
+ }
+
+ acpi_cpu_init();
+ acpi_sys_init();
+ acpi_ec_init();
+
+ if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
+ ACPI_EVENT_POWER_BUTTON,
+ acpi_event,
+ (void *) ACPI_EVENT_POWER_BUTTON))) {
+ printk(KERN_ERR "ACPI: power button enable failed\n");
+ }
+ if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
+ ACPI_EVENT_SLEEP_BUTTON,
+ acpi_event,
+ (void *) ACPI_EVENT_SLEEP_BUTTON))) {
+ printk(KERN_ERR "ACPI: sleep button enable failed\n");
+ }
+
+ acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
+
+ /*
+ * run
+ */
+ for (;;) {
+ interruptible_sleep_on(&acpi_thread_wait);
+ if (signal_pending(current))
+ break;
+ do {
+ run_task_queue(&acpi_thread_run);
+ } while (acpi_thread_run);
+ }
+
+ /*
+ * terminate
+ */
+ unregister_sysctl_table(acpi_sysctl);
+ acpi_terminate();
+
+ acpi_thread_pid = -1;
+
+ return 0;
+}
+
+/*
+ * Start the interpreter
+ */
+int __init
+acpi_init(void)
+{
+ acpi_thread_pid = kernel_thread(acpi_thread,
+ NULL,
+ (CLONE_FS | CLONE_FILES
+ | CLONE_SIGHAND | SIGCHLD));
+ return ((acpi_thread_pid >= 0) ? 0:-ENODEV);
+}
+
+/*
+ * Terminate the interpreter
+ */
+void __exit
+acpi_exit(void)
+{
+ int count;
+
+ if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) {
+ // wait until thread terminates (at most 5 seconds)
+ count = 5 * HZ;
+ while (acpi_thread_pid >= 0 && --count) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ }
+ }
+
+ pm_idle = NULL;
+ pm_power_off = NULL;
+ pm_active = 0;
+}
+
+module_init(acpi_init);
+module_exit(acpi_exit);
diff --git a/drivers/acpi/driver.h b/drivers/acpi/driver.h
new file mode 100644
index 000000000..a26402b40
--- /dev/null
+++ b/drivers/acpi/driver.h
@@ -0,0 +1,115 @@
+/*
+ * driver.h - ACPI driver
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DRIVER_H
+#define __DRIVER_H
+
+#include <linux/tqueue.h>
+#include <linux/wait.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include <asm/io.h>
+
+#define ACPI_MAX_THROTTLE 10
+#define ACPI_INVALID ~0UL
+#define ACPI_INFINITE ~0UL
+
+/*
+ * cpu.c
+ */
+int acpi_cpu_init(void);
+
+extern unsigned long acpi_c2_exit_latency;
+extern unsigned long acpi_c3_exit_latency;
+extern unsigned long acpi_c2_enter_latency;
+extern unsigned long acpi_c3_enter_latency;
+
+/*
+ * driver.c
+ */
+int acpi_run(void (*callback)(void*), void *context);
+
+/*
+ * ec.c
+ */
+int acpi_ec_init(void);
+int acpi_ec_read(int addr, int *value);
+int acpi_ec_write(int addr, int value);
+
+/*
+ * sys.c
+ */
+int acpi_sys_init(void);
+int acpi_enter_sx(acpi_sstate_t state);
+
+extern volatile acpi_sstate_t acpi_sleep_state;
+
+/*
+ * tables.c
+ */
+extern struct acpi_facp acpi_facp;
+
+int acpi_load_tables(void);
+
+/*
+ * access ACPI registers
+ */
+
+extern inline u32
+acpi_read_pm1_control(struct acpi_facp *facp)
+{
+ u32 value = 0;
+ if (facp->pm1a_cnt)
+ value = inw(facp->pm1a_cnt);
+ if (facp->pm1b_cnt)
+ value |= inw(facp->pm1b_cnt);
+ return value;
+}
+
+extern inline void
+acpi_write_pm1_control(struct acpi_facp *facp, u32 value)
+{
+ if (facp->pm1a_cnt)
+ outw(value, facp->pm1a_cnt);
+ if (facp->pm1b_cnt)
+ outw(value, facp->pm1b_cnt);
+}
+
+extern inline u32
+acpi_read_pm1_status(struct acpi_facp *facp)
+{
+ u32 value = 0;
+ if (facp->pm1a_evt)
+ value = inw(facp->pm1a_evt);
+ if (facp->pm1b_evt)
+ value |= inw(facp->pm1b_evt);
+ return value;
+}
+
+extern inline void
+acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
+{
+ if (facp->pm1a_evt)
+ outw(value, facp->pm1a_evt);
+ if (facp->pm1b_evt)
+ outw(value, facp->pm1b_evt);
+}
+
+#endif /* __DRIVER_H */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
new file mode 100644
index 000000000..3e5fe753f
--- /dev/null
+++ b/drivers/acpi/ec.c
@@ -0,0 +1,191 @@
+/*
+ * ec.c - Embedded controller support
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "acpi.h"
+#include "driver.h"
+
+enum
+{
+ ACPI_EC_HID = 0x090cd041,
+};
+
+enum
+{
+ ACPI_EC_SMI = 0x40,
+ ACPI_EC_SCI = 0x20,
+ ACPI_EC_BURST = 0x10,
+ ACPI_EC_CMD = 0x08,
+ ACPI_EC_IBF = 0x02,
+ ACPI_EC_OBF = 0x01
+};
+
+enum
+{
+ ACPI_EC_READ = 0x80,
+ ACPI_EC_WRITE = 0x81,
+ ACPI_EC_BURST_ENABLE = 0x82,
+ ACPI_EC_BURST_DISABLE = 0x83,
+ ACPI_EC_QUERY = 0x84,
+};
+
+
+static int acpi_ec_data = 0;
+static int acpi_ec_status = 0;
+static DECLARE_WAIT_QUEUE_HEAD(acpi_ec_wait);
+
+/*
+ * handle GPE
+ */
+static void
+acpi_ec_gpe(void *context)
+{
+ printk(KERN_INFO "ACPI: EC GPE\n");
+ if (waitqueue_active(&acpi_ec_wait))
+ wake_up_interruptible(&acpi_ec_wait);
+}
+
+/*
+ * wait for read/write status to clear
+ */
+static void
+acpi_ec_wait_control(void)
+{
+ udelay(1);
+ while(inb(acpi_ec_status) & ACPI_EC_IBF)
+ udelay(10);
+}
+
+/*
+ * read a byte from the EC
+ */
+int
+acpi_ec_read(int addr, int *value)
+{
+ if (!acpi_ec_data || !acpi_ec_status)
+ return -1;
+
+ outb(ACPI_EC_READ, acpi_ec_status);
+ acpi_ec_wait_control();
+ outb(addr, acpi_ec_data);
+ acpi_ec_wait_control();
+ interruptible_sleep_on(&acpi_ec_wait);
+ *value = inb(acpi_ec_data);
+
+ return 0;
+}
+
+/*
+ * write a byte to the EC
+ */
+int
+acpi_ec_write(int addr, int value)
+{
+ if (!acpi_ec_data || !acpi_ec_status)
+ return -1;
+
+ outb(ACPI_EC_WRITE, acpi_ec_status);
+ acpi_ec_wait_control();
+ outb(addr, acpi_ec_data);
+ acpi_ec_wait_control();
+ outb(value, acpi_ec_data);
+ acpi_ec_wait_control();
+ interruptible_sleep_on(&acpi_ec_wait);
+
+ return 0;
+}
+
+/*
+ * Get processor information
+ */
+static ACPI_STATUS
+acpi_find_ec(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
+{
+ ACPI_BUFFER buf;
+ ACPI_OBJECT obj;
+ RESOURCE *res;
+ int gpe;
+
+ buf.length = sizeof(obj);
+ buf.pointer = &obj;
+ if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_HID", NULL, &buf))
+ || obj.type != ACPI_TYPE_NUMBER
+ || obj.number.value != ACPI_EC_HID)
+ return AE_OK;
+
+ buf.length = 0;
+ buf.pointer = NULL;
+ if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW)
+ return AE_OK;
+
+ buf.pointer = kmalloc(buf.length, GFP_KERNEL);
+ if (!buf.pointer)
+ return AE_OK;
+
+ if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) {
+ kfree(buf.pointer);
+ return AE_OK;
+ }
+
+ res = (RESOURCE*) buf.pointer;
+ acpi_ec_data = (int) res->data.io.min_base_address;
+ res = (RESOURCE*)((u8*) buf.pointer + res->length);
+ acpi_ec_status = (int) res->data.io.min_base_address;
+
+ kfree(buf.pointer);
+
+ buf.length = sizeof(obj);
+ buf.pointer = &obj;
+ if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
+ || obj.type != ACPI_TYPE_NUMBER)
+ return AE_OK;
+ gpe = (int) obj.number.value;
+
+ printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,%d)\n",
+ acpi_ec_data, acpi_ec_status, gpe);
+
+ if (!ACPI_SUCCESS(acpi_install_gpe_handler(
+ gpe,
+ (ACPI_EVENT_LEVEL_TRIGGERED
+ | ACPI_EVENT_EDGE_TRIGGERED),
+ acpi_ec_gpe,
+ NULL)))
+ return AE_OK;
+
+ return AE_OK;
+}
+
+int
+acpi_ec_init(void)
+{
+ acpi_walk_namespace(ACPI_TYPE_DEVICE,
+ ACPI_ROOT_OBJECT,
+ ACPI_INT32_MAX,
+ acpi_find_ec,
+ NULL,
+ NULL);
+ return 0;
+}
diff --git a/drivers/acpi/os.c b/drivers/acpi/os.c
new file mode 100644
index 000000000..7398534ad
--- /dev/null
+++ b/drivers/acpi/os.c
@@ -0,0 +1,379 @@
+/*
+ * os.c - OS-dependent functions
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include "acpi.h"
+#include "driver.h"
+
+static int acpi_irq_irq = 0;
+static OSD_HANDLER acpi_irq_handler = NULL;
+static void *acpi_irq_context = NULL;
+
+char *
+strupr(char *str)
+{
+ char *s = str;
+ while (*s) {
+ *s = TOUPPER(*s);
+ s++;
+ }
+ return str;
+}
+
+ACPI_STATUS
+acpi_os_initialize(void)
+{
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_terminate(void)
+{
+ if (acpi_irq_handler) {
+ acpi_os_remove_interrupt_handler(acpi_irq_irq,
+ acpi_irq_handler);
+ }
+ return AE_OK;
+}
+
+s32
+acpi_os_printf(const char *fmt,...)
+{
+ s32 size;
+ va_list args;
+ va_start(args, fmt);
+ size = acpi_os_vprintf(fmt, args);
+ va_end(args);
+ return size;
+}
+
+s32
+acpi_os_vprintf(const char *fmt, va_list args)
+{
+ static char buffer[512];
+ int size = vsprintf(buffer, fmt, args);
+ printk(KERN_DEBUG "ACPI: %s", buffer);
+ return size;
+}
+
+void *
+acpi_os_allocate(u32 size)
+{
+ return kmalloc(size, GFP_KERNEL);
+}
+
+void *
+acpi_os_callocate(u32 size)
+{
+ void *ptr = acpi_os_allocate(size);
+ if (ptr)
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+void
+acpi_os_free(void *ptr)
+{
+ kfree(ptr);
+}
+
+ACPI_STATUS
+acpi_os_map_memory(void *phys, u32 size, void **virt)
+{
+ if ((unsigned long) phys < virt_to_phys(high_memory)) {
+ *virt = phys_to_virt((unsigned long) phys);
+ return AE_OK;
+ }
+
+ *virt = ioremap((unsigned long) phys, size);
+ if (!*virt)
+ return AE_ERROR;
+
+ return AE_OK;
+}
+
+void
+acpi_os_unmap_memory(void *virt, u32 size)
+{
+ if (virt >= high_memory)
+ iounmap(virt);
+}
+
+static void
+acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ (*acpi_irq_handler)(acpi_irq_context);
+}
+
+ACPI_STATUS
+acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context)
+{
+ acpi_irq_irq = irq;
+ acpi_irq_handler = handler;
+ acpi_irq_context = context;
+ if (request_irq(irq,
+ acpi_irq,
+ SA_INTERRUPT | SA_SHIRQ,
+ "acpi",
+ acpi_irq)) {
+ printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq);
+ return AE_ERROR;
+ }
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
+{
+ if (acpi_irq_handler) {
+ free_irq(irq, acpi_irq);
+ acpi_irq_handler = NULL;
+ }
+ return AE_OK;
+}
+
+/*
+ * Running in interpreter thread context, safe to sleep
+ */
+
+void
+acpi_os_sleep(u32 sec, u32 ms)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ * sec + (ms * HZ) / 1000);
+}
+
+void
+acpi_os_sleep_usec(u32 us)
+{
+ udelay(us);
+}
+
+u8
+acpi_os_in8(ACPI_IO_ADDRESS port)
+{
+ return inb(port);
+}
+
+u16
+acpi_os_in16(ACPI_IO_ADDRESS port)
+{
+ return inw(port);
+}
+
+u32
+acpi_os_in32(ACPI_IO_ADDRESS port)
+{
+ return inl(port);
+}
+
+void
+acpi_os_out8(ACPI_IO_ADDRESS port, u8 val)
+{
+ outb(val, port);
+}
+
+void
+acpi_os_out16(ACPI_IO_ADDRESS port, u16 val)
+{
+ outw(val, port);
+}
+
+void
+acpi_os_out32(ACPI_IO_ADDRESS port, u32 val)
+{
+ outl(val, port);
+}
+
+ACPI_STATUS
+acpi_os_read_pci_cfg_byte(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u8 * val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!val || !dev || pci_read_config_byte(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_read_pci_cfg_word(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u16 * val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!val || !dev || pci_read_config_word(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_read_pci_cfg_dword(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u32 * val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!val || !dev || pci_read_config_dword(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_write_pci_cfg_byte(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u8 val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!dev || pci_write_config_byte(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_write_pci_cfg_word(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u16 val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!dev || pci_write_config_word(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_write_pci_cfg_dword(
+ u32 bus,
+ u32 func,
+ u32 addr,
+ u32 val)
+{
+ int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
+ struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
+ if (!dev || pci_write_config_dword(dev, addr, val))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+/*
+ * Queue for interpreter thread
+ */
+
+ACPI_STATUS
+acpi_os_queue_for_execution(
+ u32 priority,
+ OSD_EXECUTION_CALLBACK callback,
+ void *context)
+{
+ if (acpi_run(callback, context))
+ return AE_ERROR;
+ return AE_OK;
+}
+
+/*
+ * Semaphores are unused, interpreter access is single threaded
+ */
+
+ACPI_STATUS
+acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle)
+{
+ *handle = (ACPI_HANDLE) 0;
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_delete_semaphore(ACPI_HANDLE handle)
+{
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout)
+{
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units)
+{
+ return AE_OK;
+}
+
+ACPI_STATUS
+acpi_os_breakpoint(char *msg)
+{
+ acpi_os_printf("breakpoint: %s", msg);
+ return AE_OK;
+}
+
+void
+acpi_os_dbg_trap(char *msg)
+{
+ acpi_os_printf("trap: %s", msg);
+}
+
+void
+acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg)
+{
+ acpi_os_printf("assert: %s", msg);
+}
+
+u32
+acpi_os_get_line(char *buffer)
+{
+ return 0;
+}
+
+/*
+ * We just have to assume we're dealing with valid memory
+ */
+
+BOOLEAN
+acpi_os_readable(void *ptr, u32 len)
+{
+ return 1;
+}
+
+BOOLEAN
+acpi_os_writable(void *ptr, u32 len)
+{
+ return 1;
+}
diff --git a/drivers/acpi/osd.c b/drivers/acpi/osd.c
deleted file mode 100644
index 402df75d7..000000000
--- a/drivers/acpi/osd.c
+++ /dev/null
@@ -1,1319 +0,0 @@
-/*
- * osd.c - Linux specific code
- *
- * Copyright (C) 2000 Andrew Henroid
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/pm.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
-#include "acpi.h"
-
-#define ACPI_MAX_THROTTLE 10
-#define ACPI_INVALID ~0UL
-#define ACPI_INFINITE ~0UL
-
-static struct acpi_facp *acpi_facp = NULL;
-
-static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
-static volatile u32 acpi_event_status = 0;
-static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
-static int acpi_irq_irq = 0;
-static OSD_HANDLER acpi_irq_handler = NULL;
-static void *acpi_irq_context = NULL;
-
-static unsigned long acpi_pblk = ACPI_INVALID;
-static unsigned long acpi_c2_exit_latency = ACPI_INFINITE;
-static unsigned long acpi_c3_exit_latency = ACPI_INFINITE;
-static unsigned long acpi_c2_enter_latency = ACPI_INFINITE;
-static unsigned long acpi_c3_enter_latency = ACPI_INFINITE;
-static int acpi_c2_tested = 0;
-static int acpi_c3_tested = 0;
-
-struct acpi_intrp_entry
-{
- int priority;
- OSD_EXECUTION_CALLBACK callback;
- void *context;
- struct list_head list;
-};
-
-struct acpi_enter_sx_ctx
-{
- wait_queue_head_t wait;
- int state;
-};
-
-static volatile int acpi_intrp_pid = -1;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_intrp_wait);
-static LIST_HEAD(acpi_intrp_exec);
-static spinlock_t acpi_intrp_exec_lock = SPIN_LOCK_UNLOCKED;
-
-#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb))
-#define ACPI_SLP_TYPA(value) \
- ((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
-#define ACPI_SLP_TYPB(value) \
- ((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
-
-static volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
-static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
-
-static struct ctl_table_header *acpi_sysctl = NULL;
-
-static int acpi_do_ulong(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len);
-static int acpi_do_sleep(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len);
-static int acpi_do_event(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len);
-
-static struct ctl_table acpi_table[] =
-{
- {ACPI_P_LVL2_LAT, "c2_exit_latency",
- &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_ENTER_LVL2_LAT, "c2_enter_latency",
- &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_P_LVL3_LAT, "c3_exit_latency",
- &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_ENTER_LVL3_LAT, "c3_enter_latency",
- &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
-
- {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
-
- {0}
-};
-
-static struct ctl_table acpi_dir_table[] =
-{
- {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
- {0}
-};
-
-static u32 FASTCALL(acpi_read_pm1_control(struct acpi_facp *));
-static u32 FASTCALL(acpi_read_pm1_status(struct acpi_facp *));
-static void FASTCALL(acpi_write_pm1_control(struct acpi_facp *, u32));
-static void FASTCALL(acpi_write_pm1_status(struct acpi_facp *, u32));
-
-/*
- * Get the value of the PM1 control register (ACPI_SCI_EN, ...)
- */
-static u32
-acpi_read_pm1_control(struct acpi_facp *facp)
-{
- u32 value = 0;
- if (facp->pm1a_cnt)
- value = inw(facp->pm1a_cnt);
- if (facp->pm1b_cnt)
- value |= inw(facp->pm1b_cnt);
- return value;
-}
-
-/*
- * Set the value of the PM1 control register (ACPI_BM_RLD, ...)
- */
-static void
-acpi_write_pm1_control(struct acpi_facp *facp, u32 value)
-{
- if (facp->pm1a_cnt)
- outw(value, facp->pm1a_cnt);
- if (facp->pm1b_cnt)
- outw(value, facp->pm1b_cnt);
-}
-
-/*
- * Get the value of the fixed event status register
- */
-static u32
-acpi_read_pm1_status(struct acpi_facp *facp)
-{
- u32 value = 0;
- if (facp->pm1a_evt)
- value = inw(facp->pm1a_evt);
- if (facp->pm1b_evt)
- value |= inw(facp->pm1b_evt);
- return value;
-}
-
-/*
- * Set the value of the fixed event status register (clear events)
- */
-static void
-acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
-{
- if (facp->pm1a_evt)
- outw(value, facp->pm1a_evt);
- if (facp->pm1b_evt)
- outw(value, facp->pm1b_evt);
-}
-
-/*
- * Examine/modify value
- */
-static int
-acpi_do_ulong(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- char str[2 * sizeof(unsigned long) + 4], *strend;
- unsigned long val;
- int size;
-
- if (!write) {
- if (file->f_pos) {
- *len = 0;
- return 0;
- }
-
- val = *(unsigned long *) ctl->data;
- size = sprintf(str, "0x%08lx\n", val);
- if (*len >= size) {
- copy_to_user(buffer, str, size);
- *len = size;
- }
- else
- *len = 0;
- }
- else {
- size = sizeof(str) - 1;
- if (size > *len)
- size = *len;
- copy_from_user(str, buffer, size);
- str[size] = '\0';
- val = simple_strtoul(str, &strend, 0);
- if (strend == str)
- return -EINVAL;
- *(unsigned long *) ctl->data = val;
- }
-
- file->f_pos += *len;
- return 0;
-}
-
-/*
- * Handle ACPI event
- */
-u32
-acpi_event(void *context)
-{
- unsigned long flags;
- int event = (int) context;
- int mask = 0;
-
- switch (event) {
- case ACPI_EVENT_POWER_BUTTON:
- mask = ACPI_PWRBTN;
- break;
- case ACPI_EVENT_SLEEP_BUTTON:
- mask = ACPI_SLPBTN;
- break;
- }
-
- if (mask) {
- // notify process waiting on /dev/acpi
- spin_lock_irqsave(&acpi_event_lock, flags);
- acpi_event_status |= mask;
- spin_unlock_irqrestore(&acpi_event_lock, flags);
- acpi_event_state = acpi_sleep_state;
- wake_up_interruptible(&acpi_event_wait);
- }
-
- return AE_OK;
-}
-
-/*
- * Wait for next event
- */
-int
-acpi_do_event(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- u32 event_status = 0;
- acpi_sstate_t event_state = 0;
- char str[27];
- int size;
-
- if (write)
- return -EPERM;
- if (*len < sizeof(str)) {
- *len = 0;
- return 0;
- }
-
- for (;;) {
- unsigned long flags;
-
- // we need an atomic exchange here
- spin_lock_irqsave(&acpi_event_lock, flags);
- event_status = acpi_event_status;
- acpi_event_status = 0;
- spin_unlock_irqrestore(&acpi_event_lock, flags);
- event_state = acpi_event_state;
-
- if (event_status)
- break;
-
- // wait for an event to arrive
- interruptible_sleep_on(&acpi_event_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- size = sprintf(str,
- "0x%08x 0x%08x 0x%01x\n",
- event_status,
- 0,
- event_state);
- copy_to_user(buffer, str, size);
- *len = size;
- file->f_pos += size;
-
- return 0;
-}
-
-/*
- * Enter system sleep state
- */
-static void
-acpi_enter_sx(void *context)
-{
- struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context;
- struct acpi_facp *facp = acpi_facp;
- ACPI_OBJECT_LIST arg_list;
- ACPI_OBJECT arg;
- u16 value;
-
- /*
- * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
- */
-
- // run the _PTS method
- memset(&arg_list, 0, sizeof(arg_list));
- arg_list.count = 1;
- arg_list.pointer = &arg;
-
- memset(&arg, 0, sizeof(arg));
- arg.type = ACPI_TYPE_NUMBER;
- arg.number.value = ctx->state;
-
- acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
-
- // clear wake status
- acpi_write_pm1_status(facp, ACPI_WAK);
-
- acpi_sleep_state = ctx->state;
-
- // set ACPI_SLP_TYPA/b and ACPI_SLP_EN
- __cli();
- if (facp->pm1a_cnt) {
- value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
- value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state])
- | ACPI_SLP_EN);
- outw(value, facp->pm1a_cnt);
- }
- if (facp->pm1b_cnt) {
- value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
- value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state])
- | ACPI_SLP_EN);
- outw(value, facp->pm1b_cnt);
- }
- __sti();
-
- if (ctx->state != ACPI_S1) {
- printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
- goto out;
- }
-
- // wait until S1 is entered
- while (!(acpi_read_pm1_status(facp) & ACPI_WAK))
- safe_halt();
-
- // run the _WAK method
- memset(&arg_list, 0, sizeof(arg_list));
- arg_list.count = 1;
- arg_list.pointer = &arg;
-
- memset(&arg, 0, sizeof(arg));
- arg.type = ACPI_TYPE_NUMBER;
- arg.number.value = ctx->state;
-
- acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
-
- out:
- acpi_sleep_state = ACPI_S0;
-
- if (waitqueue_active(&ctx->wait))
- wake_up_interruptible(&ctx->wait);
-}
-
-/*
- * Enter system sleep state and wait for completion
- */
-static int
-acpi_enter_sx_and_wait(acpi_sstate_t state)
-{
- struct acpi_enter_sx_ctx ctx;
-
- if (!acpi_facp
- || acpi_facp->hdr.signature != ACPI_FACP_SIG
- || acpi_slptyp[state] == ACPI_INVALID)
- return -EINVAL;
-
- init_waitqueue_head(&ctx.wait);
- ctx.state = state;
-
- if (acpi_os_queue_for_execution(0, acpi_enter_sx, &ctx))
- return -1;
-
- interruptible_sleep_on(&ctx.wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- return 0;
-}
-
-/*
- * Enter system sleep state
- */
-static int
-acpi_do_sleep(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- if (!write) {
- if (file->f_pos) {
- *len = 0;
- return 0;
- }
- }
- else {
-#ifdef CONFIG_ACPI_S1_SLEEP
- int status = acpi_enter_sx_and_wait(ACPI_S1);
- if (status)
- return status;
-#endif
- }
- file->f_pos += *len;
- return 0;
-}
-
-/*
- * Clear busmaster activity flag
- */
-static inline void
-acpi_clear_bm_activity(struct acpi_facp *facp)
-{
- acpi_write_pm1_status(facp, ACPI_BM);
-}
-
-/*
- * Returns 1 if there has been busmaster activity
- */
-static inline int
-acpi_bm_activity(struct acpi_facp *facp)
-{
- return acpi_read_pm1_status(facp) & ACPI_BM;
-}
-
-/*
- * Set system to sleep through busmaster requests
- */
-static void
-acpi_sleep_on_busmaster(struct acpi_facp *facp)
-{
- u32 pm1_cntr = acpi_read_pm1_control(facp);
- if (pm1_cntr & ACPI_BM_RLD) {
- pm1_cntr &= ~ACPI_BM_RLD;
- acpi_write_pm1_control(facp, pm1_cntr);
- }
-}
-
-/*
- * Set system to wake on busmaster requests
- */
-static void
-acpi_wake_on_busmaster(struct acpi_facp *facp)
-{
- u32 pm1_cntr = acpi_read_pm1_control(facp);
- if (!(pm1_cntr & ACPI_BM_RLD)) {
- pm1_cntr |= ACPI_BM_RLD;
- acpi_write_pm1_control(facp, pm1_cntr);
- }
- acpi_clear_bm_activity(facp);
-}
-
-/* The ACPI timer is just the low 24 bits */
-#define TIME_BEGIN(tmr) inl(tmr)
-#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff)
-
-/*
- * Idle loop (uniprocessor only)
- */
-void
-acpi_idle(void)
-{
- static int sleep_level = 1;
- struct acpi_facp *facp = acpi_facp;
-
- if (!facp
- || facp->hdr.signature != ACPI_FACP_SIG
- || !facp->pm_tmr
- || !acpi_pblk)
- goto not_initialized;
-
- /*
- * start from the previous sleep level..
- */
- if (sleep_level == 1)
- goto sleep1;
- if (sleep_level == 2)
- goto sleep2;
- sleep3:
- sleep_level = 3;
- if (!acpi_c3_tested) {
- printk(KERN_DEBUG "ACPI C3 works\n");
- acpi_c3_tested = 1;
- }
- acpi_wake_on_busmaster(facp);
- if (facp->pm2_cnt)
- goto sleep3_with_arbiter;
-
- for (;;) {
- unsigned long time;
- unsigned int pm_tmr = facp->pm_tmr;
-
- __cli();
- if (current->need_resched)
- goto out;
- if (acpi_bm_activity(facp))
- goto sleep2;
-
- time = TIME_BEGIN(pm_tmr);
- inb(acpi_pblk + ACPI_P_LVL3);
- /* Dummy read, force synchronization with the PMU */
- inl(pm_tmr);
- time = TIME_END(pm_tmr, time);
-
- __sti();
- if (time < acpi_c3_exit_latency)
- goto sleep2;
- }
-
- sleep3_with_arbiter:
- for (;;) {
- unsigned long time;
- u8 arbiter;
- unsigned int pm2_cntr = facp->pm2_cnt;
- unsigned int pm_tmr = facp->pm_tmr;
-
- __cli();
- if (current->need_resched)
- goto out;
- if (acpi_bm_activity(facp))
- goto sleep2;
-
- time = TIME_BEGIN(pm_tmr);
- arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS;
- /* Disable arbiter, park on CPU */
- outb(arbiter | ACPI_ARB_DIS, pm2_cntr);
- inb(acpi_pblk + ACPI_P_LVL3);
- /* Dummy read, force synchronization with the PMU */
- inl(pm_tmr);
- time = TIME_END(pm_tmr, time);
- /* Enable arbiter again.. */
- outb(arbiter, pm2_cntr);
-
- __sti();
- if (time < acpi_c3_exit_latency)
- goto sleep2;
- }
-
- sleep2:
- sleep_level = 2;
- if (!acpi_c2_tested) {
- printk(KERN_DEBUG "ACPI C2 works\n");
- acpi_c2_tested = 1;
- }
- acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */
- for (;;) {
- unsigned long time;
- unsigned int pm_tmr = facp->pm_tmr;
-
- __cli();
- if (current->need_resched)
- goto out;
-
- time = TIME_BEGIN(pm_tmr);
- inb(acpi_pblk + ACPI_P_LVL2);
- /* Dummy read, force synchronization with the PMU */
- inl(pm_tmr);
- time = TIME_END(pm_tmr, time);
-
- __sti();
- if (time < acpi_c2_exit_latency)
- goto sleep1;
- if (acpi_bm_activity(facp)) {
- acpi_clear_bm_activity(facp);
- continue;
- }
- if (time > acpi_c3_enter_latency)
- goto sleep3;
- }
-
- sleep1:
- sleep_level = 1;
- acpi_sleep_on_busmaster(facp);
- for (;;) {
- unsigned long time;
- unsigned int pm_tmr = facp->pm_tmr;
-
- __cli();
- if (current->need_resched)
- goto out;
- time = TIME_BEGIN(pm_tmr);
- safe_halt();
- time = TIME_END(pm_tmr, time);
- if (time > acpi_c2_enter_latency)
- goto sleep2;
- }
-
- not_initialized:
- for (;;) {
- __cli();
- if (current->need_resched)
- goto out;
- safe_halt();
- }
-
- out:
- __sti();
-}
-
-/*
- * Enter soft-off (S5)
- */
-static void
-acpi_power_off(void)
-{
- struct acpi_enter_sx_ctx ctx;
-
- if (!acpi_facp
- || acpi_facp->hdr.signature != ACPI_FACP_SIG
- || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
- return;
-
- init_waitqueue_head(&ctx.wait);
- ctx.state = ACPI_S5;
- acpi_enter_sx(&ctx);
-}
-
-/*
- * Get processor information
- */
-static ACPI_STATUS
-acpi_get_cpu_info(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
-{
- ACPI_OBJECT obj;
- ACPI_CX_STATE lat[4];
- ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
- ACPI_BUFFER buf;
- int i, count;
-
- buf.length = sizeof(obj);
- buf.pointer = &obj;
- if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
- return AE_OK;
-
- printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n",
- obj.processor.proc_id,
- obj.processor.pblk_address,
- obj.processor.pblk_length);
- if (acpi_pblk != ACPI_INVALID
- || !obj.processor.pblk_address
- || obj.processor.pblk_length != 6)
- return AE_OK;
-
- acpi_pblk = obj.processor.pblk_address;
-
- buf.length = sizeof(lat);
- buf.pointer = lat;
- if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
- return AE_OK;
-
- if (lat[2].latency < MAX_CX_STATE_LATENCY) {
- printk(KERN_INFO "ACPI: C2 supported\n");
- acpi_c2_exit_latency = lat[2].latency;
- }
- if (lat[3].latency < MAX_CX_STATE_LATENCY) {
- printk(KERN_INFO "ACPI: C3 supported\n");
- acpi_c3_exit_latency = lat[3].latency;
- }
-
- memset(throttle, 0, sizeof(throttle));
- buf.length = sizeof(throttle);
- buf.pointer = throttle;
-
- if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
- return AE_OK;
-
- for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
- if (throttle[i].percent_of_clock)
- count++;
- }
- count--;
- if (count > 0)
- printk(KERN_INFO "ACPI: %d throttling states\n", count);
-
- return AE_OK;
-}
-
-/*
- * Fetch the FACP information
- */
-static int
-acpi_fetch_facp(void)
-{
- ACPI_BUFFER buffer;
-
- buffer.pointer = acpi_facp;
- buffer.length = sizeof(*acpi_facp);
- if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) {
- printk(KERN_ERR "ACPI: no FACP\n");
- kfree(acpi_facp);
- return -ENODEV;
- }
-
- if (acpi_facp->p_lvl2_lat
- && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
- acpi_c2_exit_latency
- = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl2_lat);
- acpi_c2_enter_latency
- = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
- }
- if (acpi_facp->p_lvl3_lat
- && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
- acpi_c3_exit_latency
- = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat);
- acpi_c3_enter_latency
- = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat * 5);
- }
-
- return 0;
-}
-
-/*
- * Execute callbacks (interpret methods)
- */
-static void
-acpi_intrp_run(void)
-{
- for (;;) {
- struct acpi_intrp_entry *entry;
- unsigned long flags;
-
- interruptible_sleep_on(&acpi_intrp_wait);
- if (signal_pending(current))
- return;
-
- for (;;) {
- entry = NULL;
-
- spin_lock_irqsave(&acpi_intrp_exec_lock, flags);
- if (!list_empty(&acpi_intrp_exec)) {
- entry = list_entry(acpi_intrp_exec.next,
- struct acpi_intrp_entry,
- list);
- list_del(&entry->list);
- }
- spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags);
-
- if (!entry)
- break;
-
- (*entry->callback)(entry->context);
-
- kfree(entry);
- }
- }
-}
-
-/*
- * Initialize and run interpreter within a kernel thread
- */
-static int
-acpi_intrp_thread(void *context)
-{
- ACPI_STATUS status;
- u8 sx, typa, typb;
-
- /*
- * initialize interpreter
- */
- exit_files(current);
- daemonize();
- strcpy(current->comm, "acpi");
-
- if (!ACPI_SUCCESS(acpi_initialize(NULL))) {
- printk(KERN_ERR "ACPI: initialize failed\n");
- return -ENODEV;
- }
-
- if (!ACPI_SUCCESS(acpi_load_firmware_tables())) {
- printk(KERN_ERR "ACPI: table load failed\n");
- acpi_terminate();
- return -ENODEV;
- }
-
- if (acpi_fetch_facp()) {
- acpi_terminate();
- return -ENODEV;
- }
-
- status = acpi_load_namespace();
- if (!ACPI_SUCCESS(status) && status != AE_CTRL_PENDING) {
- printk(KERN_ERR "ACPI: namespace load failed\n");
- acpi_terminate();
- return -ENODEV;
- }
-
- printk(KERN_INFO "ACPI: ACPI support found\n");
-
- acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
- ACPI_ROOT_OBJECT,
- ACPI_INT32_MAX,
- acpi_get_cpu_info,
- NULL,
- NULL);
-
- for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
- int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
- if (ACPI_SUCCESS(
- acpi_hw_obtain_sleep_type_register_data(ca_sx,
- &typa,
- &typb)))
- acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb);
- else
- acpi_slptyp[sx] = ACPI_INVALID;
- }
- if (acpi_slptyp[ACPI_S1] != ACPI_INVALID)
- printk(KERN_INFO "ACPI: S1 supported\n");
- if (acpi_slptyp[ACPI_S5] != ACPI_INVALID)
- printk(KERN_INFO "ACPI: S5 supported\n");
-
- if (!ACPI_SUCCESS(acpi_enable())) {
- printk(KERN_ERR "ACPI: enable failed\n");
- acpi_terminate();
- return -ENODEV;
- }
-
- if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
- ACPI_EVENT_POWER_BUTTON,
- acpi_event,
- (void *) ACPI_EVENT_POWER_BUTTON))) {
- printk(KERN_ERR "ACPI: power button enable failed\n");
- }
- if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
- ACPI_EVENT_SLEEP_BUTTON,
- acpi_event,
- (void *) ACPI_EVENT_SLEEP_BUTTON))) {
- printk(KERN_ERR "ACPI: sleep button enable failed\n");
- }
-
-#ifdef CONFIG_SMP
- if (smp_num_cpus == 1)
- pm_idle = acpi_idle;
-#else
- pm_idle = acpi_idle;
-#endif
- pm_power_off = acpi_power_off;
-
- acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
-
- /*
- * run interpreter
- */
- acpi_intrp_run();
-
- /*
- * terminate interpreter
- */
- unregister_sysctl_table(acpi_sysctl);
- acpi_terminate();
-
- acpi_intrp_pid = -1;
-
- return 0;
-}
-
-/*
- * Start the interpreter
- */
-int __init
-acpi_init(void)
-{
- acpi_facp = kmalloc(sizeof(*acpi_facp), GFP_KERNEL);
- if (!acpi_facp)
- return -ENOMEM;
- memset(acpi_facp, 0, sizeof(*acpi_facp));
-
- acpi_intrp_pid = kernel_thread(acpi_intrp_thread,
- NULL,
- (CLONE_FS | CLONE_FILES
- | CLONE_SIGHAND | SIGCHLD));
- return ((acpi_intrp_pid >= 0) ? 0:-ENODEV);
-}
-
-/*
- * Terminate the interpreter
- */
-void __exit
-acpi_exit(void)
-{
- int count;
-
- if (!kill_proc(acpi_intrp_pid, SIGTERM, 1)) {
- // wait until interpreter thread terminates (at most 5 seconds)
- count = 5 * HZ;
- while (acpi_intrp_pid >= 0 && --count) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
- }
-
- // clean up after the interpreter
-
- if (acpi_irq_handler) {
- acpi_os_remove_interrupt_handler(acpi_irq_irq,
- acpi_irq_handler);
- }
-
- if (pm_power_off == acpi_power_off)
- pm_power_off = NULL;
- if (pm_idle == acpi_idle)
- pm_idle = NULL;
-
- kfree(acpi_facp);
-}
-
-module_init(acpi_init);
-module_exit(acpi_exit);
-
-/*
- * OS-dependent functions
- *
- */
-
-char *
-strupr(char *str)
-{
- char *s = str;
- while (*s) {
- *s = TOUPPER(*s);
- s++;
- }
- return str;
-}
-
-ACPI_STATUS
-acpi_os_initialize(void)
-{
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_terminate(void)
-{
- return AE_OK;
-}
-
-s32
-acpi_os_printf(const char *fmt,...)
-{
- s32 size;
- va_list args;
- va_start(args, fmt);
- size = acpi_os_vprintf(fmt, args);
- va_end(args);
- return size;
-}
-
-s32
-acpi_os_vprintf(const char *fmt, va_list args)
-{
- static char buffer[512];
- int size = vsprintf(buffer, fmt, args);
- printk(KERN_DEBUG "%s", buffer);
- return size;
-}
-
-void *
-acpi_os_allocate(u32 size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-void *
-acpi_os_callocate(u32 size)
-{
- void *ptr = acpi_os_allocate(size);
- if (ptr)
- memset(ptr, 0, size);
- return ptr;
-}
-
-void
-acpi_os_free(void *ptr)
-{
- kfree(ptr);
-}
-
-ACPI_STATUS
-acpi_os_map_memory(void *phys, u32 size, void **virt)
-{
- if ((unsigned long) phys < virt_to_phys(high_memory)) {
- *virt = phys_to_virt((unsigned long) phys);
- return AE_OK;
- }
-
- *virt = ioremap((unsigned long) phys, size);
- if (!*virt)
- return AE_ERROR;
-
- return AE_OK;
-}
-
-void
-acpi_os_unmap_memory(void *virt, u32 size)
-{
- if (virt >= high_memory)
- iounmap(virt);
-}
-
-static void
-acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- (*acpi_irq_handler)(acpi_irq_context);
-}
-
-ACPI_STATUS
-acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context)
-{
- acpi_irq_irq = irq;
- acpi_irq_handler = handler;
- acpi_irq_context = context;
- if (request_irq(irq,
- acpi_irq,
- SA_INTERRUPT | SA_SHIRQ,
- "acpi",
- acpi_irq)) {
- printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq);
- return AE_ERROR;
- }
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
-{
- if (acpi_irq_handler) {
- free_irq(irq, acpi_irq);
- acpi_irq_handler = NULL;
- }
- return AE_OK;
-}
-
-/*
- * Running in interpreter thread context, safe to sleep
- */
-
-void
-acpi_os_sleep(u32 sec, u32 ms)
-{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ * sec + (ms * HZ) / 1000);
-}
-
-void
-acpi_os_sleep_usec(u32 us)
-{
- udelay(us);
-}
-
-u8
-acpi_os_in8(ACPI_IO_ADDRESS port)
-{
- return inb(port);
-}
-
-u16
-acpi_os_in16(ACPI_IO_ADDRESS port)
-{
- return inw(port);
-}
-
-u32
-acpi_os_in32(ACPI_IO_ADDRESS port)
-{
- return inl(port);
-}
-
-void
-acpi_os_out8(ACPI_IO_ADDRESS port, u8 val)
-{
- outb(val, port);
-}
-
-void
-acpi_os_out16(ACPI_IO_ADDRESS port, u16 val)
-{
- outw(val, port);
-}
-
-void
-acpi_os_out32(ACPI_IO_ADDRESS port, u32 val)
-{
- outl(val, port);
-}
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_byte(
- u32 bus,
- u32 func,
- u32 addr,
- u8 * val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!val || !dev || pci_read_config_byte(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_word(
- u32 bus,
- u32 func,
- u32 addr,
- u16 * val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!val || !dev || pci_read_config_word(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_dword(
- u32 bus,
- u32 func,
- u32 addr,
- u32 * val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!val || !dev || pci_read_config_dword(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_byte(
- u32 bus,
- u32 func,
- u32 addr,
- u8 val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!dev || pci_write_config_byte(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_word(
- u32 bus,
- u32 func,
- u32 addr,
- u16 val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!dev || pci_write_config_word(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_dword(
- u32 bus,
- u32 func,
- u32 addr,
- u32 val)
-{
- int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
- if (!dev || pci_write_config_dword(dev, addr, val))
- return AE_ERROR;
- return AE_OK;
-}
-
-/*
- * Queue for interpreter thread
- */
-
-ACPI_STATUS
-acpi_os_queue_for_execution(
- u32 priority,
- OSD_EXECUTION_CALLBACK callback,
- void *context)
-{
- struct acpi_intrp_entry *entry;
- unsigned long flags;
-
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry)
- return AE_ERROR;
-
- memset(entry, 0, sizeof(entry));
- entry->priority = priority;
- entry->callback = callback;
- entry->context = context;
- INIT_LIST_HEAD(&entry->list);
-
- if (!waitqueue_active(&acpi_intrp_wait)) {
- kfree(entry);
- return AE_ERROR;
- }
-
- spin_lock_irqsave(&acpi_intrp_exec_lock, flags);
- list_add(&entry->list, &acpi_intrp_exec);
- wake_up(&acpi_intrp_wait);
- spin_unlock_irqrestore(&acpi_intrp_exec_lock, flags);
-
- return AE_OK;
-}
-
-/*
- * Semaphores are unused, interpreter access is single threaded
- */
-
-ACPI_STATUS
-acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle)
-{
- *handle = (ACPI_HANDLE) 0;
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_delete_semaphore(ACPI_HANDLE handle)
-{
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout)
-{
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units)
-{
- return AE_OK;
-}
-
-ACPI_STATUS
-acpi_os_breakpoint(char *msg)
-{
- acpi_os_printf("breakpoint: %s", msg);
- return AE_OK;
-}
-
-void
-acpi_os_dbg_trap(char *msg)
-{
- acpi_os_printf("trap: %s", msg);
-}
-
-void
-acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg)
-{
- acpi_os_printf("assert: %s", msg);
-}
-
-u32
-acpi_os_get_line(char *buffer)
-{
- return 0;
-}
-
-/*
- * We just have to assume we're dealing with valid memory
- */
-
-BOOLEAN
-acpi_os_readable(void *ptr, u32 len)
-{
- return 1;
-}
-
-BOOLEAN
-acpi_os_writable(void *ptr, u32 len)
-{
- return 1;
-}
diff --git a/drivers/acpi/sys.c b/drivers/acpi/sys.c
new file mode 100644
index 000000000..1a403f86f
--- /dev/null
+++ b/drivers/acpi/sys.c
@@ -0,0 +1,182 @@
+/*
+ * sys.c - System management (suspend, ...)
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include "acpi.h"
+#include "driver.h"
+
+#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb))
+#define ACPI_SLP_TYPA(value) \
+ ((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
+#define ACPI_SLP_TYPB(value) \
+ ((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
+
+struct acpi_enter_sx_ctx
+{
+ wait_queue_head_t wait;
+ int state;
+};
+
+volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
+static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
+
+/*
+ * Enter system sleep state
+ */
+static void
+acpi_enter_sx_async(void *context)
+{
+ struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context;
+ struct acpi_facp *facp = &acpi_facp;
+ ACPI_OBJECT_LIST arg_list;
+ ACPI_OBJECT arg;
+ u16 value;
+
+ /*
+ * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
+ */
+
+ // run the _PTS method
+ memset(&arg_list, 0, sizeof(arg_list));
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.type = ACPI_TYPE_NUMBER;
+ arg.number.value = ctx->state;
+
+ acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
+
+ // clear wake status
+ acpi_write_pm1_status(facp, ACPI_WAK);
+
+ acpi_sleep_state = ctx->state;
+
+ // set ACPI_SLP_TYPA/b and ACPI_SLP_EN
+ __cli();
+ if (facp->pm1a_cnt) {
+ value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
+ value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state])
+ | ACPI_SLP_EN);
+ outw(value, facp->pm1a_cnt);
+ }
+ if (facp->pm1b_cnt) {
+ value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
+ value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state])
+ | ACPI_SLP_EN);
+ outw(value, facp->pm1b_cnt);
+ }
+ __sti();
+
+ if (ctx->state != ACPI_S1) {
+ printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
+ goto out;
+ }
+
+ // wait until S1 is entered
+ while (!(acpi_read_pm1_status(facp) & ACPI_WAK))
+ safe_halt();
+
+ // run the _WAK method
+ memset(&arg_list, 0, sizeof(arg_list));
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.type = ACPI_TYPE_NUMBER;
+ arg.number.value = ctx->state;
+
+ acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
+
+ out:
+ acpi_sleep_state = ACPI_S0;
+
+ if (waitqueue_active(&ctx->wait))
+ wake_up_interruptible(&ctx->wait);
+}
+
+/*
+ * Enter soft-off (S5)
+ */
+static void
+acpi_power_off(void)
+{
+ struct acpi_enter_sx_ctx ctx;
+
+ if (acpi_facp.hdr.signature != ACPI_FACP_SIG
+ || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
+ return;
+
+ init_waitqueue_head(&ctx.wait);
+ ctx.state = ACPI_S5;
+ acpi_enter_sx_async(&ctx);
+}
+
+/*
+ * Enter system sleep state and wait for completion
+ */
+int
+acpi_enter_sx(acpi_sstate_t state)
+{
+ struct acpi_enter_sx_ctx ctx;
+
+ if (acpi_facp.hdr.signature != ACPI_FACP_SIG
+ || acpi_slptyp[state] == ACPI_INVALID)
+ return -EINVAL;
+
+ init_waitqueue_head(&ctx.wait);
+ ctx.state = state;
+
+ if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx))
+ return -1;
+
+ interruptible_sleep_on(&ctx.wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ return 0;
+}
+
+int
+acpi_sys_init(void)
+{
+ u8 sx, typa, typb;
+
+ for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
+ int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
+ if (ACPI_SUCCESS(
+ acpi_hw_obtain_sleep_type_register_data(ca_sx,
+ &typa,
+ &typb)))
+ acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb);
+ else
+ acpi_slptyp[sx] = ACPI_INVALID;
+ }
+ if (acpi_slptyp[ACPI_S1] != ACPI_INVALID)
+ printk(KERN_INFO "ACPI: S1 supported\n");
+ if (acpi_slptyp[ACPI_S5] != ACPI_INVALID)
+ printk(KERN_INFO "ACPI: S5 supported\n");
+
+ pm_power_off = acpi_power_off;
+
+ return 0;
+}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
new file mode 100644
index 000000000..9ec6c58f4
--- /dev/null
+++ b/drivers/acpi/tables.c
@@ -0,0 +1,303 @@
+/*
+ * tables.c - ACPI tables, chipset, and errata handling
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/acpi.h>
+#include "acpi.h"
+#include "driver.h"
+
+struct acpi_facp acpi_facp;
+
+#define ACPI_DUMMY_CHECKSUM 9
+#define ACPI_DUMMY_PBLK 51
+
+static u8 acpi_dummy_dsdt[] =
+{
+ 0x44, 0x53, 0x44, 0x54, // "DSDT"
+ 0x38, 0x00, 0x00, 0x00, // length
+ 0x01, // revision
+ 0x00, // checksum
+ 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x00, // "LINUX"
+ 0x44, 0x55, 0x4d, 0x4d, 0x59, 0x00, 0x00, 0x00, // "DUMMY"
+ 0x01, 0x00, 0x00, 0x00, // OEM rev
+ 0x4c, 0x4e, 0x55, 0x58, // "LNUX"
+ 0x01, 0x00, 0x00, 0x00, // creator rev
+ 0x10, // Scope
+ 0x13, // PkgLength
+ 0x5c, 0x5f, 0x50, 0x52, 0x5f, // \_PR_
+ 0x5b, 0x83, // Processor
+ 0x0b, // PkgLength
+ 0x43, 0x50, 0x55, 0x30, // CPU0
+ 0x00, // ID
+ 0x00, 0x00, 0x00, 0x00, // PBLK
+ 0x06 // PBLK size
+};
+
+/*
+ * Calculate and set ACPI table checksum
+ */
+static void
+acpi_set_checksum(u8 *table, int size)
+{
+ int i, sum = 0;
+ for (i = 0; i < size; i++)
+ sum += (int) table[i];
+ sum = (0x100 - ((sum - table[ACPI_DUMMY_CHECKSUM]) & 0xff));
+ table[ACPI_DUMMY_CHECKSUM] = sum;
+}
+
+/*
+ * Init PIIX4 device, create a fake FACP
+ */
+static int
+acpi_init_piix4(struct pci_dev *dev)
+{
+ u32 base, pblk;
+ u16 cmd;
+ u8 pmregmisc;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_IO))
+ return -ENODEV;
+
+ pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
+ if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
+ return -ENODEV;
+
+ base = pci_resource_start (dev, PCI_BRIDGE_RESOURCES);
+ if (!base)
+ return -ENODEV;
+
+ printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base);
+
+ memset(&acpi_facp, 0, sizeof(acpi_facp));
+ acpi_facp.hdr.signature = ACPI_FACP_SIG;
+ acpi_facp.hdr.length = sizeof(acpi_facp);
+ acpi_facp.int_model = ACPI_PIIX4_INT_MODEL;
+ acpi_facp.sci_int = ACPI_PIIX4_SCI_INT;
+ acpi_facp.smi_cmd = ACPI_PIIX4_SMI_CMD;
+ acpi_facp.acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
+ acpi_facp.acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
+ acpi_facp.s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
+ acpi_facp.pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
+ acpi_facp.pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
+ acpi_facp.pm2_cnt = ACPI_PIIX4_PM2_CNT;
+ acpi_facp.pm_tmr = base + ACPI_PIIX4_PM_TMR;
+ acpi_facp.gpe0 = base + ACPI_PIIX4_GPE0;
+ acpi_facp.pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
+ acpi_facp.pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
+ acpi_facp.pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
+ acpi_facp.pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
+ acpi_facp.gpe0_len = ACPI_PIIX4_GPE0_LEN;
+ acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
+ acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
+
+ acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp));
+ acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp);
+
+ pblk = base + ACPI_PIIX4_P_BLK;
+ memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk));
+ acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt));
+ acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt);
+
+ return 0;
+}
+
+/*
+ * Init VIA ACPI device and create a fake FACP
+ */
+static int
+acpi_init_via(struct pci_dev *dev)
+{
+ u32 base, pblk;
+ u8 tmp, irq;
+
+ pci_read_config_byte(dev, 0x41, &tmp);
+ if (!(tmp & 0x80))
+ return -ENODEV;
+
+ base = pci_resource_start(dev, PCI_BRIDGE_RESOURCES);
+ if (!base) {
+ base = pci_resource_start(dev, PCI_BASE_ADDRESS_4);
+ if (!base)
+ return -ENODEV;
+ }
+
+ pci_read_config_byte(dev, 0x42, &irq);
+
+ printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base);
+
+ memset(&acpi_facp, 0, sizeof(acpi_facp));
+ acpi_facp.hdr.signature = ACPI_FACP_SIG;
+ acpi_facp.hdr.length = sizeof(acpi_facp);
+ acpi_facp.int_model = ACPI_VIA_INT_MODEL;
+ acpi_facp.sci_int = irq;
+ acpi_facp.smi_cmd = base + ACPI_VIA_SMI_CMD;
+ acpi_facp.acpi_enable = ACPI_VIA_ACPI_ENABLE;
+ acpi_facp.acpi_disable = ACPI_VIA_ACPI_DISABLE;
+ acpi_facp.pm1a_evt = base + ACPI_VIA_PM1_EVT;
+ acpi_facp.pm1a_cnt = base + ACPI_VIA_PM1_CNT;
+ acpi_facp.pm_tmr = base + ACPI_VIA_PM_TMR;
+ acpi_facp.gpe0 = base + ACPI_VIA_GPE0;
+
+ acpi_facp.pm1_evt_len = ACPI_VIA_PM1_EVT_LEN;
+ acpi_facp.pm1_cnt_len = ACPI_VIA_PM1_CNT_LEN;
+ acpi_facp.pm_tm_len = ACPI_VIA_PM_TM_LEN;
+ acpi_facp.gpe0_len = ACPI_VIA_GPE0_LEN;
+ acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
+ acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
+
+ acpi_facp.duty_offset = ACPI_VIA_DUTY_OFFSET;
+ acpi_facp.duty_width = ACPI_VIA_DUTY_WIDTH;
+
+ acpi_facp.day_alarm = ACPI_VIA_DAY_ALARM;
+ acpi_facp.mon_alarm = ACPI_VIA_MON_ALARM;
+ acpi_facp.century = ACPI_VIA_CENTURY;
+
+ acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp));
+ acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp);
+
+ pblk = base + ACPI_VIA_P_BLK;
+ memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk));
+ acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt));
+ acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt);
+
+ return 0;
+}
+
+typedef enum
+{
+ CH_UNKNOWN = 0,
+ CH_INTEL_PIIX4,
+ CH_VIA_586,
+ CH_VIA_686A,
+} acpi_chip_t;
+
+/* indexed by value of each enum in acpi_chip_t */
+const static struct
+{
+ int (*chip_init)(struct pci_dev *dev);
+} acpi_chip_info[] =
+{
+ {NULL,},
+ {acpi_init_piix4},
+ {acpi_init_via},
+ {acpi_init_via},
+};
+
+static struct pci_device_id acpi_pci_tbl[] =
+{
+ {0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4},
+ {0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586},
+ {0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A},
+ {0,} /* terminate list */
+};
+
+static int
+acpi_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return acpi_chip_info[id->driver_data].chip_init(dev);
+}
+
+static struct pci_driver acpi_driver =
+{
+ name: "acpi",
+ id_table: acpi_pci_tbl,
+ probe: acpi_probe,
+};
+static int acpi_driver_registered = 0;
+
+/*
+ * Locate a known ACPI chipset
+ */
+static int
+acpi_find_chipset(void)
+{
+ if (pci_register_driver(&acpi_driver) < 1)
+ return -ENODEV;
+ acpi_driver_registered = 1;
+ return 0;
+}
+
+/*
+ * Fetch the FACP information
+ */
+static int
+acpi_fetch_facp(void)
+{
+ ACPI_BUFFER buffer;
+
+ memset(&acpi_facp, 0, sizeof(acpi_facp));
+ buffer.pointer = &acpi_facp;
+ buffer.length = sizeof(acpi_facp);
+ if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) {
+ printk(KERN_ERR "ACPI: missing FACP\n");
+ return -ENODEV;
+ }
+
+ if (acpi_facp.p_lvl2_lat
+ && acpi_facp.p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
+ acpi_c2_exit_latency
+ = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl2_lat);
+ acpi_c2_enter_latency
+ = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
+ }
+ if (acpi_facp.p_lvl3_lat
+ && acpi_facp.p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
+ acpi_c3_exit_latency
+ = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat);
+ acpi_c3_enter_latency
+ = ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat * 5);
+ }
+
+ return 0;
+}
+
+/*
+ * Find and load ACPI tables
+ */
+int
+acpi_load_tables(void)
+{
+ if (ACPI_SUCCESS(acpi_load_firmware_tables()))
+ {
+ printk(KERN_INFO "ACPI: support found\n");
+ }
+ else if (acpi_find_chipset()) {
+ acpi_terminate();
+ return -1;
+ }
+
+ if (acpi_fetch_facp()) {
+ acpi_terminate();
+ return -1;
+ }
+
+ if (!ACPI_SUCCESS(acpi_load_namespace())) {
+ printk(KERN_ERR "ACPI: namespace load failed\n");
+ acpi_terminate();
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 785a0e551..b8f1c693e 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -66,6 +66,7 @@ not be guaranteed. There are several ways to assure this:
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -269,7 +270,7 @@ static int slm_get_pagesize( int device, int *w, int *h );
/************************* End of Prototypes **************************/
-static struct timer_list slm_timer = { NULL, NULL, 0, 0, slm_test_ready };
+static struct timer_list slm_timer = { function: slm_test_ready };
static struct file_operations slm_fops = {
owner: THIS_MODULE,
@@ -799,10 +800,12 @@ static int slm_release( struct inode *inode, struct file *file )
device = MINOR(inode->i_rdev);
sip = &slm_info[device];
+ lock_kernel();
if (file->f_mode & 2)
sip->wbusy = 0;
if (file->f_mode & 1)
sip->rbusy = 0;
+ unlock_kernel();
return( 0 );
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 37e50dbcd..6e094e4d8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -578,7 +578,6 @@ static inline void attempt_front_merge(request_queue_t * q,
static inline void __make_request(request_queue_t * q, int rw,
struct buffer_head * bh)
{
- int major = MAJOR(bh->b_rdev);
unsigned int sector, count;
int max_segments = MAX_SEGMENTS;
struct request * req = NULL;
@@ -590,26 +589,6 @@ static inline void __make_request(request_queue_t * q, int rw,
count = bh->b_size >> 9;
sector = bh->b_rsector;
- if (blk_size[major]) {
- unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
-
- if (maxsector < count || maxsector - count < sector) {
- bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
- if (!blk_size[major][MINOR(bh->b_rdev)])
- goto end_io;
- /* This may well happen - the kernel calls bread()
- without checking the size of the device, e.g.,
- when mounting a device. */
- printk(KERN_INFO
- "attempt to access beyond end of device\n");
- printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
- kdevname(bh->b_rdev), rw,
- (sector + count)>>1,
- blk_size[major][MINOR(bh->b_rdev)]);
- goto end_io;
- }
- }
-
rw_ahead = 0; /* normal case; gets changed below for READA */
switch (rw) {
case READA:
@@ -758,9 +737,35 @@ end_io:
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
}
-int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
+void generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
{
- int ret;
+ int major = MAJOR(bh->b_rdev);
+
+ if (blk_size[major]) {
+ unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
+ unsigned int sector, count;
+
+ count = bh->b_size >> 9;
+ sector = bh->b_rsector;
+
+ if (maxsector < count || maxsector - count < sector) {
+ bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
+ if (blk_size[major][MINOR(bh->b_rdev)]) {
+
+ /* This may well happen - the kernel calls bread()
+ without checking the size of the device, e.g.,
+ when mounting a device. */
+ printk(KERN_INFO
+ "attempt to access beyond end of device\n");
+ printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
+ kdevname(bh->b_rdev), rw,
+ (sector + count)>>1,
+ blk_size[major][MINOR(bh->b_rdev)]);
+ }
+ bh->b_end_io(bh, 0);
+ return;
+ }
+ }
/*
* Resolve the mapping until finished. (drivers are
@@ -768,12 +773,9 @@ int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
* by explicitly returning 0)
*/
while (q->make_request_fn) {
- ret = q->make_request_fn(q, rw, bh);
- if (ret > 0) {
- q = blk_get_queue(bh->b_rdev);
- continue;
- }
- return ret;
+ if (q->make_request_fn(q, rw, bh) == 0)
+ return;
+ q = blk_get_queue(bh->b_rdev);
}
/*
* Does the block device want us to queue
@@ -784,16 +786,13 @@ int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
if (q && !q->plugged)
(q->request_fn)(q);
spin_unlock_irq(&io_request_lock);
-
- return 0;
}
/* This function can be used to request a number of buffers from a block
device. Currently the only restriction is that all buffers must belong to
the same device */
-static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[],
- int haslock)
+void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
{
struct buffer_head *bh;
request_queue_t *q;
@@ -840,13 +839,9 @@ static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[],
bh = bhs[i];
/* Only one thread can actually submit the I/O. */
- if (haslock) {
- if (!buffer_locked(bh))
- BUG();
- } else {
- if (test_and_set_bit(BH_Lock, &bh->b_state))
- continue;
- }
+ if (test_and_set_bit(BH_Lock, &bh->b_state))
+ continue;
+
set_bit(BH_Req, &bh->b_state);
/*
@@ -865,15 +860,6 @@ sorry:
buffer_IO_error(bhs[i]);
}
-void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
-{
- __ll_rw_block(rw, nr, bh, 0);
-}
-
-void ll_rw_block_locked(int rw, int nr, struct buffer_head * bh[])
-{
- __ll_rw_block(rw, nr, bh, 1);
-}
#ifdef CONFIG_STRAM_SWAP
extern int stram_device_init (void);
diff --git a/drivers/block/lvm.c b/drivers/block/lvm.c
index 1e2a21cf1..d8cf20d79 100644
--- a/drivers/block/lvm.c
+++ b/drivers/block/lvm.c
@@ -301,6 +301,7 @@ static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
static struct file_operations lvm_chr_fops =
{
+ owner: THIS_MODULE,
open: lvm_chr_open,
release: lvm_chr_close,
ioctl: lvm_chr_ioctl,
@@ -517,8 +518,6 @@ static int lvm_chr_open(struct inode *inode,
/* Group special file open */
if (VG_CHR(minor) > MAX_VG) return -ENXIO;
- MOD_INC_USE_COUNT;
-
lvm_chr_open_count++;
return 0;
} /* lvm_chr_open() */
@@ -743,6 +742,7 @@ static int lvm_chr_close(struct inode *inode, struct file *file)
"%s -- lvm_chr_close VG#: %d\n", lvm_name, VG_CHR(minor));
#endif
+ lock_kernel();
#ifdef LVM_TOTAL_RESET
if (lvm_reset_spindown > 0) {
lvm_reset_spindown = 0;
@@ -755,10 +755,7 @@ static int lvm_chr_close(struct inode *inode, struct file *file)
lock = 0; /* release lock */
wake_up_interruptible(&lvm_wait);
}
-
-#ifdef MODULE
- if (GET_USE_COUNT(&__this_module) > 0) MOD_DEC_USE_COUNT;
-#endif
+ unlock_kernel();
return 0;
} /* lvm_chr_close() */
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 651c3dd6d..087b5aee1 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -3412,7 +3412,7 @@ repeat:
currspeed = (j-mddev->resync_mark_cnt)/((jiffies-mddev->resync_mark)/HZ +1) +1;
if (currspeed > sysctl_speed_limit_min) {
- current->priority = 19;
+ current->nice = 19;
if ((currspeed > sysctl_speed_limit_max) ||
!is_mddev_idle(mddev)) {
@@ -3422,7 +3422,7 @@ repeat:
goto repeat;
}
} else
- current->priority = -20;
+ current->nice = -20;
}
fsync_dev(read_disk);
printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev));
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 2315e1d30..b36fdab11 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -13,10 +13,11 @@
1.02 GRG 1998.05.05 init_proto, release_proto, ktti
1.03 GRG 1998.08.15 eliminate compiler warning
1.04 GRG 1998.11.28 added support for FRIQ
-
+ 1.05 TMW 2000.06.06 use parport_find_number instead of
+ parport_enumerate
*/
-#define PI_VERSION "1.04"
+#define PI_VERSION "1.05"
#include <linux/module.h>
#include <linux/config.h>
@@ -238,22 +239,25 @@ static void pi_register_parport( PIA *pi, int verbose)
{
#ifdef CONFIG_PARPORT
- struct parport *pp;
-
- pp = parport_enumerate();
+ struct parport *port;
- while((pp)&&(pp->base != pi->port)) pp = pp->next;
+ port = parport_find_base (pi->port);
+ if (!port) return;
- if (!pp) return;
+ pi->pardev = parport_register_device(port,
+ pi->device,NULL,
+ pi_wake_up,NULL,
+ 0,(void *)pi);
+ parport_put_port (port);
+ if (!pi->pardev) return;
- pi->pardev = (void *) parport_register_device(
- pp,pi->device,NULL,pi_wake_up,NULL,0,(void *)pi);
init_waitqueue_head(&pi->parq);
- if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name);
+ if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,
+ port->name);
- pi->parname = (char *)pp->name;
+ pi->parname = (char *)port->name;
#endif
}
@@ -406,6 +410,7 @@ int init_module(void)
{ int k;
for (k=0;k<MAX_PROTOS;k++) protocols[k] = 0;
+
printk("paride: version %s installed\n",PI_VERSION);
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index c282d82a1..e2709ce97 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -171,6 +171,7 @@ static int pg_drive_count;
#include <linux/mtio.h>
#include <linux/pg.h>
#include <linux/wait.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -604,10 +605,12 @@ static int pg_release (struct inode *inode, struct file *file)
if ((unit >= PG_UNITS) || (PG.access <= 0))
return -EINVAL;
+ lock_kernel();
PG.access--;
kfree(PG.bufptr);
PG.bufptr = NULL;
+ unlock_kernel();
return 0;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 0d3e81838..5cb91ae0a 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -149,6 +149,7 @@ static int pt_drive_count;
#include <linux/malloc.h>
#include <linux/mtio.h>
#include <linux/wait.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -773,6 +774,7 @@ static int pt_release (struct inode *inode, struct file *file)
if ((unit >= PT_UNITS) || (PT.access <= 0))
return -EINVAL;
+ lock_kernel();
if (PT.flags & PT_WRITING) pt_write_fm(unit);
if (PT.flags & PT_REWIND) pt_rewind(unit);
@@ -781,6 +783,7 @@ static int pt_release (struct inode *inode, struct file *file)
kfree(PT.bufptr);
PT.bufptr = NULL;
+ unlock_kernel();
return 0;
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 61cb27ec7..8ff56a70a 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -114,14 +114,14 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
int no_int_yet;
-static int access_count[MAX_HD] = {0,};
-static char ps2esdi_valid[MAX_HD] = {0,};
-static int ps2esdi_sizes[MAX_HD << 6] = {0,};
-static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
-static int ps2esdi_drives = 0;
+static int access_count[MAX_HD];
+static char ps2esdi_valid[MAX_HD];
+static int ps2esdi_sizes[MAX_HD << 6];
+static int ps2esdi_blocksizes[MAX_HD << 6];
+static int ps2esdi_drives;
static struct hd_struct ps2esdi[MAX_HD << 6];
static u_short io_base;
-static struct timer_list esdi_timer = {{NULL, NULL}, 0, 0L, ps2esdi_reset_timer};
+static struct timer_list esdi_timer = { function: ps2esdi_reset_timer };
static int reset_status;
static int ps2esdi_slot = -1;
int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 727c1c543..2db08531a 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -59,6 +59,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -298,11 +299,14 @@ static int initrd_release(struct inode *inode,struct file *file)
{
extern void free_initrd_mem(unsigned long, unsigned long);
- if (--initrd_users) return 0;
- blkdev_put(inode->i_bdev, BDEV_FILE);
- iput(inode);
- free_initrd_mem(initrd_start, initrd_end);
- initrd_start = 0;
+ lock_kernel();
+ if (!--initrd_users) {
+ blkdev_put(inode->i_bdev, BDEV_FILE);
+ iput(inode);
+ free_initrd_mem(initrd_start, initrd_end);
+ initrd_start = 0;
+ }
+ unlock_kernel();
return 0;
}
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index 8b551a99d..b71f023aa 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -310,7 +310,7 @@ static char azt_auto_eject = AZT_AUTO_EJECT;
static int AztTimeout, AztTries;
static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static struct timer_list delay_timer = { {NULL, NULL}, 0, 0, NULL };
+static struct timer_list delay_timer;
static struct azt_DiskInfo DiskInfo;
static struct azt_Toc Toc[MAX_TRACKS];
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index b793bac4b..eb102a4a7 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -150,7 +150,7 @@ static struct sjcd_stat statistic;
/*
* Timer.
*/
-static struct timer_list sjcd_delay_timer = { function: NULL };
+static struct timer_list sjcd_delay_timer;
#define SJCD_SET_TIMER( func, tmout ) \
( sjcd_delay_timer.expires = jiffies+tmout, \
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
index eaa9e6bae..b28df7e34 100644
--- a/drivers/char/acquirewdt.c
+++ b/drivers/char/acquirewdt.c
@@ -38,6 +38,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
static int acq_is_open=0;
static spinlock_t acq_lock;
@@ -140,6 +141,7 @@ static int acq_open(struct inode *inode, struct file *file)
static int acq_close(struct inode *inode, struct file *file)
{
+ lock_kernel();
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
spin_lock(&acq_lock);
@@ -149,6 +151,7 @@ static int acq_close(struct inode *inode, struct file *file)
acq_is_open=0;
spin_unlock(&acq_lock);
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c
index e67beef38..d16c62a22 100644
--- a/drivers/char/agp/agpgart_fe.c
+++ b/drivers/char/agp/agpgart_fe.c
@@ -41,6 +41,7 @@
#include <linux/miscdevice.h>
#include <linux/agp_backend.h>
#include <linux/agpgart.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -605,14 +606,17 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
agp_file_private *priv = (agp_file_private *) file->private_data;
agp_kern_info kerninfo;
+ lock_kernel();
AGP_LOCK();
if (agp_fe.backend_acquired != TRUE) {
AGP_UNLOCK();
+ unlock_kernel();
return -EPERM;
}
if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) {
AGP_UNLOCK();
+ unlock_kernel();
return -EPERM;
}
agp_copy_info(&kerninfo);
@@ -624,42 +628,51 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
if ((size + offset) > current_size) {
AGP_UNLOCK();
+ unlock_kernel();
return -EINVAL;
}
client = agp_find_client_by_pid(current->pid);
if (client == NULL) {
AGP_UNLOCK();
+ unlock_kernel();
return -EPERM;
}
if (!agp_find_seg_in_client(client, offset,
size, vma->vm_page_prot)) {
AGP_UNLOCK();
+ unlock_kernel();
return -EINVAL;
}
if (remap_page_range(vma->vm_start,
(kerninfo.aper_base + offset),
size, vma->vm_page_prot)) {
AGP_UNLOCK();
+ unlock_kernel();
return -EAGAIN;
}
AGP_UNLOCK();
+ unlock_kernel();
return 0;
}
if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
if (size != current_size) {
AGP_UNLOCK();
+ unlock_kernel();
return -EINVAL;
}
if (remap_page_range(vma->vm_start, kerninfo.aper_base,
size, vma->vm_page_prot)) {
AGP_UNLOCK();
+ unlock_kernel();
return -EAGAIN;
}
AGP_UNLOCK();
+ unlock_kernel();
return 0;
}
AGP_UNLOCK();
+ unlock_kernel();
return -EPERM;
}
@@ -667,6 +680,7 @@ static int agp_release(struct inode *inode, struct file *file)
{
agp_file_private *priv = (agp_file_private *) file->private_data;
+ lock_kernel();
AGP_LOCK();
if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
@@ -688,6 +702,7 @@ static int agp_release(struct inode *inode, struct file *file)
agp_remove_file_private(priv);
kfree(priv);
AGP_UNLOCK();
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/amikeyb.c b/drivers/char/amikeyb.c
index 15e21be68..73b8fecd2 100644
--- a/drivers/char/amikeyb.c
+++ b/drivers/char/amikeyb.c
@@ -176,7 +176,7 @@ static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
static unsigned char rep_scancode;
static void amikeyb_rep(unsigned long ignore);
-static struct timer_list amikeyb_rep_timer = {NULL, NULL, 0, 0, amikeyb_rep};
+static struct timer_list amikeyb_rep_timer = {function: amikeyb_rep};
static void amikeyb_rep(unsigned long ignore)
{
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index d5091ff4d..c109c5965 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -101,21 +101,18 @@ static unsigned int ReadErrorCount; /* number of read error */
static unsigned int DeviceErrorCount; /* number of device error */
static loff_t ac_llseek(struct file *, loff_t, int);
-static int ac_open(struct inode *, struct file *);
static ssize_t ac_read (struct file *, char *, size_t, loff_t *);
static ssize_t ac_write (struct file *, const char *, size_t, loff_t *);
static int ac_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
-static int ac_release(struct inode *, struct file *);
static void ac_interrupt(int, void *, struct pt_regs *);
struct file_operations ac_fops = {
+ owner:THIS_MODULE,
llseek:ac_llseek,
read:ac_read,
write:ac_write,
ioctl:ac_ioctl,
- open:ac_open,
- release:ac_release,
};
struct miscdevice ac_miscdev = {
@@ -124,6 +121,8 @@ struct miscdevice ac_miscdev = {
&ac_fops
};
+static int dummy; /* dev_id for request_irq() */
+
int ac_register_board(unsigned long physloc, unsigned long loc,
unsigned char boardno)
{
@@ -180,7 +179,7 @@ void cleanup_module(void)
iounmap((void *) apbs[i].RamIO);
if (apbs[i].irq)
- free_irq(apbs[i].irq, &ac_open);
+ free_irq(apbs[i].irq, &dummy);
}
}
@@ -226,7 +225,7 @@ int __init applicom_init(void)
continue;
}
- if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &ac_open)) {
+ if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &dummy)) {
printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
iounmap(RamIO);
apbs[boardno - 1].RamIO = 0;
@@ -277,7 +276,7 @@ int __init applicom_init(void)
printk(KERN_NOTICE "Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq);
if (!numisa) {
- if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open)) {
+ if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &dummy)) {
printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq);
iounmap((void *) RamIO);
apbs[boardno - 1].RamIO = 0;
@@ -346,19 +345,6 @@ static loff_t ac_llseek(struct file *file, loff_t offset, int origin)
return -ESPIPE;
}
-static int ac_open(struct inode *inode, struct file *filp)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int ac_release(struct inode *inode, struct file *file)
-{
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-
static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
{
unsigned int NumCard; /* Board number 1 -> 8 */
diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c
index bc8345cff..9bfe4b2b3 100644
--- a/drivers/char/busmouse.c
+++ b/drivers/char/busmouse.c
@@ -19,6 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -167,6 +168,7 @@ static int busmouse_release(struct inode *inode, struct file *file)
struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
int ret = 0;
+ lock_kernel();
busmouse_fasync(-1, file, 0);
if (--mse->active == 0) {
@@ -178,6 +180,7 @@ static int busmouse_release(struct inode *inode, struct file *file)
}
mse->ready = 0;
}
+ unlock_kernel();
return ret;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index cf4bb1f83..d0e801180 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2,7 +2,7 @@
#define Z_WAKE
#undef Z_EXT_CHARS_IN_BUFFER
static char rcsid[] =
-"$Revision: 2.3.2.7 $$Date: 2000/06/01 18:26:34 $";
+"$Revision: 2.3.2.8 $$Date: 2000/07/06 18:14:16 $";
/*
* linux/drivers/char/cyclades.c
@@ -25,6 +25,11 @@ static char rcsid[] =
* This version supports shared IRQ's (only for PCI boards).
*
* $Log: cyclades.c,v $
+ * Revision 2.3.2.8 2000/07/06 18:14:16 ivan
+ * Fixed the PCI detection function to work properly on Alpha systems.
+ * Implemented support for TIOCSERGETLSR ioctl.
+ * Implemented full support for non-standard baud rates.
+ *
* Revision 2.3.2.7 2000/06/01 18:26:34 ivan
* Request PLX I/O region, although driver doesn't use it, to avoid
* problems with other drivers accessing it.
@@ -1363,9 +1368,16 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
while (char_count-- > 0){
if (!info->xmit_cnt){
- cy_writeb((u_long)base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) &
- ~CyTxRdy);
+ if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) {
+ cy_writeb((u_long)base_addr+(CySRER<<index),
+ cy_readb(base_addr+(CySRER<<index)) &
+ ~CyTxMpty);
+ } else {
+ cy_writeb((u_long)base_addr+(CySRER<<index),
+ ((cy_readb(base_addr+(CySRER<<index))
+ & ~CyTxRdy)
+ | CyTxMpty));
+ }
goto txdone;
}
if (info->xmit_buf == 0){
@@ -3176,6 +3188,30 @@ cy_chars_in_buffer(struct tty_struct *tty)
* ------------------------------------------------------------
*/
+static void
+cyy_baud_calc(struct cyclades_port *info, uclong baud)
+{
+ int co, co_val, bpr;
+ uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000);
+
+ if (baud == 0) {
+ info->tbpr = info->tco = info->rbpr = info->rco = 0;
+ return;
+ }
+
+ /* determine which prescaler to use */
+ for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
+ if (cy_clock / co_val / baud > 63)
+ break;
+ }
+
+ bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
+ if (bpr > 255)
+ bpr = 255;
+
+ info->tbpr = info->rbpr = bpr;
+ info->tco = info->rco = co;
+}
/*
* This routine finds or computes the various line characteristics.
@@ -3189,7 +3225,7 @@ set_line_char(struct cyclades_port * info)
int card,chip,channel,index;
unsigned cflag, iflag;
unsigned short chip_number;
- int baud;
+ int baud, baud_rate = 0;
int i;
@@ -3225,12 +3261,14 @@ set_line_char(struct cyclades_port * info)
index = cy_card[card].bus_index;
/* baud rate */
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
- baud = info->baud;
- } else {
- baud = tty_get_baud_rate(info->tty);
- }
- if (baud > CD1400_MAX_SPEED) {
+ baud = tty_get_baud_rate(info->tty);
+ if ((baud == 38400) &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+ if (info->custom_divisor)
+ baud_rate = info->baud / info->custom_divisor;
+ else
+ baud_rate = info->baud;
+ } else if (baud > CD1400_MAX_SPEED) {
baud = CD1400_MAX_SPEED;
}
/* find the baud index */
@@ -3243,22 +3281,29 @@ set_line_char(struct cyclades_port * info)
i = 19; /* CD1400_MAX_SPEED */
}
-
- if(info->chip_rev >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- info->tbpr = baud_bpr_60[i]; /* Tx BPR */
- info->tco = baud_co_60[i]; /* Tx CO */
- info->rbpr = baud_bpr_60[i]; /* Rx BPR */
- info->rco = baud_co_60[i]; /* Rx CO */
+ if ((baud == 38400) &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+ cyy_baud_calc(info, baud_rate);
} else {
- info->tbpr = baud_bpr_25[i]; /* Tx BPR */
- info->tco = baud_co_25[i]; /* Tx CO */
- info->rbpr = baud_bpr_25[i]; /* Rx BPR */
- info->rco = baud_co_25[i]; /* Rx CO */
+ if(info->chip_rev >= CD1400_REV_J) {
+ /* It is a CD1400 rev. J or later */
+ info->tbpr = baud_bpr_60[i]; /* Tx BPR */
+ info->tco = baud_co_60[i]; /* Tx CO */
+ info->rbpr = baud_bpr_60[i]; /* Rx BPR */
+ info->rco = baud_co_60[i]; /* Rx CO */
+ } else {
+ info->tbpr = baud_bpr_25[i]; /* Tx BPR */
+ info->tco = baud_co_25[i]; /* Tx CO */
+ info->rbpr = baud_bpr_25[i]; /* Rx BPR */
+ info->rco = baud_co_25[i]; /* Rx CO */
+ }
}
if (baud_table[i] == 134) {
- info->timeout = (info->xmit_fifo_size*HZ*15/269) + 2;
/* get it right for 134.5 baud */
+ info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
+ } else if ((baud == 38400) &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+ info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
} else if (baud_table[i]) {
info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
/* this needs to be propagated into the card info */
@@ -3447,19 +3492,24 @@ set_line_char(struct cyclades_port * info)
buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
/* baud rate */
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
- baud = info->baud;
- } else {
- baud = tty_get_baud_rate(info->tty);
- }
- if (baud > CYZ_MAX_SPEED) {
+ baud = tty_get_baud_rate(info->tty);
+ if ((baud == 38400) &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+ if (info->custom_divisor)
+ baud_rate = info->baud / info->custom_divisor;
+ else
+ baud_rate = info->baud;
+ } else if (baud > CYZ_MAX_SPEED) {
baud = CYZ_MAX_SPEED;
}
cy_writel(&ch_ctrl->comm_baud , baud);
if (baud == 134) {
- info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
/* get it right for 134.5 baud */
+ info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
+ } else if ((baud == 38400) &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
+ info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
} else if (baud) {
info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2;
/* this needs to be propagated into the card info */
@@ -3549,8 +3599,6 @@ set_line_char(struct cyclades_port * info)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
}
}
-
-
} /* set_line_char */
@@ -3571,7 +3619,7 @@ get_serial_info(struct cyclades_port * info,
tmp.flags = info->flags;
tmp.close_delay = info->close_delay;
tmp.baud_base = info->baud;
- tmp.custom_divisor = 0; /*!!!*/
+ tmp.custom_divisor = info->custom_divisor;
tmp.hub6 = 0; /*!!!*/
return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0;
} /* get_serial_info */
@@ -3597,6 +3645,7 @@ set_serial_info(struct cyclades_port * info,
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
info->baud = new_serial.baud_base;
+ info->custom_divisor = new_serial.custom_divisor;
goto check_and_exit;
}
@@ -3607,6 +3656,7 @@ set_serial_info(struct cyclades_port * info,
*/
info->baud = new_serial.baud_base;
+ info->custom_divisor = new_serial.custom_divisor;
info->flags = ((info->flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS));
info->close_delay = new_serial.close_delay * HZ/100;
@@ -3621,6 +3671,43 @@ check_and_exit:
}
} /* set_serial_info */
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct cyclades_port *info, unsigned int *value)
+{
+ int card, chip, channel, index;
+ unsigned char status;
+ unsigned int result;
+ unsigned long flags;
+ unsigned char *base_addr;
+
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel>>2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = (unsigned char *)
+ (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+
+ CY_LOCK(info, flags);
+ status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty);
+ CY_UNLOCK(info, flags);
+ result = (status ? 0 : TIOCSER_TEMT);
+ } else {
+ /* Not supported yet */
+ return -EINVAL;
+ }
+ return cy_put_user(result, (unsigned long *) value);
+}
static int
get_modem_info(struct cyclades_port * info, unsigned int *value)
@@ -4247,6 +4334,9 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
case TIOCSSERIAL:
ret_val = set_serial_info(info, (struct serial_struct *) arg);
break;
+ case TIOCSERGETLSR: /* Get line status register */
+ ret_val = get_lsr_info(info, (unsigned int *) arg);
+ break;
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
* - mask passed in arg for lines of interest
@@ -4937,10 +5027,9 @@ cy_detect_pci(void)
i--;
continue;
}
-#else
+#endif
cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Yctl);
cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ywin);
-#endif
#ifdef CY_PCI_DEBUG
printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
@@ -5048,9 +5137,7 @@ cy_detect_pci(void)
printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
(ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
#endif
-#if !defined(__alpha__)
- cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl);
-#endif
+ cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl);
/* Disable interrupts on the PLX before resetting it */
cy_writew(cy_pci_addr0+0x68,
@@ -5078,9 +5165,7 @@ cy_detect_pci(void)
request_region(cy_pci_phys1, CyPCI_Zctl, "Cyclades-Z");
if (mailbox == ZE_V1) {
-#if !defined(__alpha__)
- cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
-#endif
+ cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
if (ZeIndex == NR_CARDS) {
printk("Cyclades-Ze/PCI found at 0x%lx ",
(ulong)cy_pci_phys2);
@@ -5097,9 +5182,7 @@ cy_detect_pci(void)
i--;
continue;
} else {
-#if !defined(__alpha__)
- cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin);
-#endif
+ cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin);
}
#ifdef CY_PCI_DEBUG
@@ -5538,6 +5621,7 @@ cy_init(void)
info->tco = 0;
info->rbpr = 0;
info->rco = 0;
+ info->custom_divisor = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
info->icount.cts = info->icount.dsr =
@@ -5596,6 +5680,7 @@ cy_init(void)
info->cor3 = 0x08; /* _very_ small rcv threshold */
info->cor4 = 0;
info->cor5 = 0;
+ info->custom_divisor = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
info->icount.cts = info->icount.dsr =
diff --git a/drivers/char/dn_keyb.c b/drivers/char/dn_keyb.c
index 8d8766b85..980ee13ba 100644
--- a/drivers/char/dn_keyb.c
+++ b/drivers/char/dn_keyb.c
@@ -51,8 +51,7 @@ static u_char *shadow_buf=&debug_buf2[0];
static short debug_buf_count=0;
static int debug_buf_overrun=0,debug_timer_running=0;
static unsigned long debug_buffer_updated=0;
-static struct timer_list debug_keyb_timer = { NULL, NULL, 0, 0,
- debug_keyb_timer_handler };
+static struct timer_list debug_keyb_timer = { function: debug_keyb_timer_handler };
#endif
static u_short dnplain_map[NR_KEYS] __initdata = {
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index a1ab1f279..5ad4885bf 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -6,6 +6,8 @@
#include "drmP.h"
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <asm/oplib.h>
#include <asm/upa.h>
@@ -44,6 +46,7 @@ extern int ffb_rmctx(struct inode *, struct file *, unsigned int, unsigned long)
extern int ffb_context_switch(drm_device_t *, int, int);
static struct file_operations ffb_fops = {
+ owner: THIS_MODULE,
open: ffb_open,
flush: drm_flush,
release: ffb_release,
@@ -501,7 +504,6 @@ static int ffb_open(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
ret = drm_open_helper(inode, filp, dev);
if (!ret) {
- MOD_INC_USE_COUNT;
atomic_inc(&dev->total_open);
spin_lock(&dev->count_lock);
if (!dev->open_count++) {
@@ -517,9 +519,11 @@ static int ffb_open(struct inode *inode, struct file *filp)
static int ffb_release(struct inode *inode, struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev;
int ret = 0;
+ lock_kernel();
+ dev = priv->dev;
DRM_DEBUG("open_count = %d\n", dev->open_count);
if (dev->lock.hw_lock != NULL
&& _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
@@ -541,7 +545,6 @@ static int ffb_release(struct inode *inode, struct file *filp)
ret = drm_release(inode, filp);
if (!ret) {
- MOD_DEC_USE_COUNT;
atomic_inc(&dev->total_close);
spin_lock(&dev->count_lock);
if (!--dev->open_count) {
@@ -550,14 +553,18 @@ static int ffb_release(struct inode *inode, struct file *filp)
atomic_read(&dev->ioctl_count),
dev->blocked);
spin_unlock(&dev->count_lock);
+ unlock_kernel();
return -EBUSY;
}
spin_unlock(&dev->count_lock);
- return ffb_takedown(dev);
+ ret = ffb_takedown(dev);
+ unlock_kernel();
+ return ret;
}
spin_unlock(&dev->count_lock);
}
+ unlock_kernel();
return ret;
}
@@ -756,6 +763,7 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+ lock_kernel();
minor = MINOR(filp->f_dentry->d_inode->i_rdev);
ffb_priv = NULL;
for (i = 0; i < ffb_dev_table_size; i++) {
@@ -763,13 +771,15 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
if (ffb_priv->miscdev.minor == minor)
break;
}
- if (i >= ffb_dev_table_size)
+ if (i >= ffb_dev_table_size) {
+ unlock_kernel();
return -EINVAL;
-
+ }
/* We don't support/need dma mappings, so... */
- if (!VM_OFFSET(vma))
+ if (!VM_OFFSET(vma)) {
+ unlock_kernel();
return -EINVAL;
-
+ }
for (i = 0; i < dev->map_count; i++) {
unsigned long off;
@@ -781,16 +791,19 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
break;
}
- if (i >= dev->map_count)
+ if (i >= dev->map_count) {
+ unlock_kernel();
return -EINVAL;
-
+ }
if (!map ||
- ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
+ ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
+ unlock_kernel();
return -EPERM;
-
- if (map->size != (vma->vm_end - vma->vm_start))
+ }
+ if (map->size != (vma->vm_end - vma->vm_start)) {
+ unlock_kernel();
return -EINVAL;
-
+ }
/* Set read-only attribute before mappings are created
* so it works for fb/reg maps too.
*/
@@ -813,9 +826,10 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
if (io_remap_page_range(vma->vm_start,
ffb_priv->card_phys_base + VM_OFFSET(vma),
vma->vm_end - vma->vm_start,
- vma->vm_page_prot, 0))
+ vma->vm_page_prot, 0)) {
+ unlock_kernel();
return -EAGAIN;
-
+ }
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
@@ -828,8 +842,10 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_flags |= VM_LOCKED;
break;
default:
+ unlock_kernel();
return -EINVAL; /* This should never happen. */
};
+ unlock_kernel();
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
index 7e0d6e53e..8809d1810 100644
--- a/drivers/char/drm/gamma_drv.c
+++ b/drivers/char/drm/gamma_drv.c
@@ -29,6 +29,8 @@
*/
#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include "drmP.h"
#include "gamma_drv.h"
EXPORT_SYMBOL(gamma_init);
@@ -44,14 +46,15 @@ EXPORT_SYMBOL(gamma_cleanup);
static drm_device_t gamma_device;
static struct file_operations gamma_fops = {
- open: gamma_open,
- flush: drm_flush,
- release: gamma_release,
- ioctl: gamma_ioctl,
- mmap: drm_mmap,
- read: drm_read,
- fasync: drm_fasync,
- poll: drm_poll,
+ owner: THIS_MODULE,
+ open: gamma_open,
+ flush: drm_flush,
+ release: gamma_release,
+ ioctl: gamma_ioctl,
+ mmap: drm_mmap,
+ read: drm_read,
+ fasync: drm_fasync,
+ poll: drm_poll,
};
static struct miscdevice gamma_misc = {
@@ -407,7 +410,6 @@ int gamma_open(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
if (!(retcode = drm_open_helper(inode, filp, dev))) {
- MOD_INC_USE_COUNT;
atomic_inc(&dev->total_open);
spin_lock(&dev->count_lock);
if (!dev->open_count++) {
@@ -422,12 +424,13 @@ int gamma_open(struct inode *inode, struct file *filp)
int gamma_release(struct inode *inode, struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev;
int retcode = 0;
+ lock_kernel();
+ dev = priv->dev;
DRM_DEBUG("open_count = %d\n", dev->open_count);
if (!(retcode = drm_release(inode, filp))) {
- MOD_DEC_USE_COUNT;
atomic_inc(&dev->total_close);
spin_lock(&dev->count_lock);
if (!--dev->open_count) {
@@ -436,13 +439,17 @@ int gamma_release(struct inode *inode, struct file *filp)
atomic_read(&dev->ioctl_count),
dev->blocked);
spin_unlock(&dev->count_lock);
+ unlock_kernel();
return -EBUSY;
}
spin_unlock(&dev->count_lock);
- return gamma_takedown(dev);
+ retcode = gamma_takedown(dev);
+ unlock_kernel();
+ return retcode;
}
spin_unlock(&dev->count_lock);
}
+ unlock_kernel();
return retcode;
}
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
index 23c9c55bf..b0c41c93c 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -30,6 +30,8 @@
*/
#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include "drmP.h"
#include "tdfx_drv.h"
@@ -44,6 +46,7 @@ static drm_device_t tdfx_device;
drm_ctx_t tdfx_res_ctx;
static struct file_operations tdfx_fops = {
+ owner: THIS_MODULE,
open: tdfx_open,
flush: drm_flush,
release: tdfx_release,
@@ -343,7 +346,6 @@ int tdfx_open(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
if (!(retcode = drm_open_helper(inode, filp, dev))) {
- MOD_INC_USE_COUNT;
atomic_inc(&dev->total_open);
spin_lock(&dev->count_lock);
if (!dev->open_count++) {
@@ -358,12 +360,13 @@ int tdfx_open(struct inode *inode, struct file *filp)
int tdfx_release(struct inode *inode, struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev;
int retcode = 0;
+ lock_kernel();
+ dev = priv->dev;
DRM_DEBUG("open_count = %d\n", dev->open_count);
if (!(retcode = drm_release(inode, filp))) {
- MOD_DEC_USE_COUNT;
atomic_inc(&dev->total_close);
spin_lock(&dev->count_lock);
if (!--dev->open_count) {
@@ -372,13 +375,17 @@ int tdfx_release(struct inode *inode, struct file *filp)
atomic_read(&dev->ioctl_count),
dev->blocked);
spin_unlock(&dev->count_lock);
+ unlock_kernel();
return -EBUSY;
}
spin_unlock(&dev->count_lock);
- return tdfx_takedown(dev);
+ retcode = tdfx_takedown(dev);
+ unlock_kernel();
+ return retcode;
}
spin_unlock(&dev->count_lock);
}
+ unlock_kernel();
return retcode;
}
diff --git a/drivers/char/drm/vm.c b/drivers/char/drm/vm.c
index b4c4c5bbf..b6595c88c 100644
--- a/drivers/char/drm/vm.c
+++ b/drivers/char/drm/vm.c
@@ -144,7 +144,6 @@ void drm_vm_open(struct vm_area_struct *vma)
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_inc(&dev->vma_count);
- MOD_INC_USE_COUNT;
#if DRM_DEBUG_CODE
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
@@ -169,7 +168,6 @@ void drm_vm_close(struct vm_area_struct *vma)
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
- MOD_DEC_USE_COUNT;
atomic_dec(&dev->vma_count);
#if DRM_DEBUG_CODE
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 6fe41e118..0ada290ac 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -35,6 +35,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/atarihw.h>
@@ -483,7 +484,9 @@ static int dsp56k_release(struct inode *inode, struct file *file)
{
case DSP56K_DEV_56001:
+ lock_kernel();
dsp56k.in_use = 0;
+ unlock_kernel();
break;
default:
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index 475e1d052..867a7fcec 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -69,6 +69,7 @@
#include <linux/poll.h> /* for POLLIN, etc. */
#include <linux/dtlk.h> /* local header file for DoubleTalk values */
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#ifdef TRACING
#define TRACE_TEXT(str) printk(str);
@@ -333,7 +334,9 @@ static int dtlk_release(struct inode *inode, struct file *file)
}
TRACE_RET;
+ lock_kernel();
del_timer(&dtlk_timer);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index fd81f24ca..a57e3abc1 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -35,15 +35,11 @@
#endif
#include <linux/fcntl.h>
#include <linux/wrapper.h>
+#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/zftape.h>
-#if LINUX_VERSION_CODE >=KERNEL_VER(2,1,16)
#include <linux/init.h>
-#else
-#define __initdata
-#define __initfunc(__arg) __arg
-#endif
#include "../zftape/zftape-init.h"
#include "../zftape/zftape-read.h"
@@ -56,7 +52,6 @@ char zft_src[] __initdata = "$Source: /homes/cvs/ftape-stacked/ftape/zftape/zfta
char zft_rev[] __initdata = "$Revision: 1.8 $";
char zft_dat[] __initdata = "$Date: 1997/11/06 00:48:56 $";
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
"(claus@momo.math.rwth-aachen.de)");
MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
@@ -64,7 +59,6 @@ MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
"Support for QIC-113 compatible volume table "
"and builtin compression (lzrw3 algorithm)");
MODULE_SUPPORTED_DEVICE("char-major-27");
-#endif
/* Global vars.
*/
@@ -90,38 +84,18 @@ static sigset_t orig_sigmask;
*/
static int zft_open (struct inode *ino, struct file *filep);
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,31)
static int zft_close(struct inode *ino, struct file *filep);
-#else
-static void zft_close(struct inode *ino, struct file *filep);
-#endif
static int zft_ioctl(struct inode *ino, struct file *filep,
unsigned int command, unsigned long arg);
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,56)
static int zft_mmap(struct file *filep, struct vm_area_struct *vma);
-#else
-static int zft_mmap(struct inode *ino, struct file *filep,
- struct vm_area_struct *vma);
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
static ssize_t zft_read (struct file *fp, char *buff,
size_t req_len, loff_t *ppos);
static ssize_t zft_write(struct file *fp, const char *buff,
size_t req_len, loff_t *ppos);
-#elif LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long zft_read (struct inode *ino, struct file *fp, char *buff,
- unsigned long req_len);
-static long zft_write(struct inode *ino, struct file *fp, const char *buff,
- unsigned long req_len);
-#else
-static int zft_read (struct inode *ino, struct file *fp, char *buff,
- int req_len);
-static int zft_write(struct inode *ino, struct file *fp, const char *buff,
- int req_len);
-#endif
static struct file_operations zft_cdev =
{
+ owner: THIS_MODULE,
read: zft_read,
write: zft_write,
ioctl: zft_ioctl,
@@ -137,15 +111,6 @@ static int zft_open(struct inode *ino, struct file *filep)
int result;
TRACE_FUN(ft_t_flow);
-#if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
- if (!MOD_IN_USE) {
- MOD_INC_USE_COUNT; /* lock module in memory */
- }
-#else
- MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE,
- * locking is done with can_unload()
- */
-#endif
TRACE(ft_t_flow, "called for minor %d", MINOR(ino->i_rdev));
if (busy_flag) {
TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
@@ -155,11 +120,6 @@ static int zft_open(struct inode *ino, struct file *filep)
>
FTAPE_SEL_D) {
busy_flag = 0;
-#if defined(MODULE) && LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
- if (!zft_dirty()) {
- MOD_DEC_USE_COUNT; /* unlock module in memory */
- }
-#endif
TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr");
}
orig_sigmask = current->blocked;
@@ -168,11 +128,6 @@ static int zft_open(struct inode *ino, struct file *filep)
if (result < 0) {
current->blocked = orig_sigmask; /* restore mask */
busy_flag = 0;
-#if defined(MODULE) && LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
- if (!zft_dirty()) {
- MOD_DEC_USE_COUNT; /* unlock module in memory */
- }
-#endif
TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
} else {
/* Mask signals that will disturb proper operation of the
@@ -191,13 +146,11 @@ static int zft_close(struct inode *ino, struct file *filep)
int result;
TRACE_FUN(ft_t_flow);
+ lock_kernel();
if (!busy_flag || MINOR(ino->i_rdev) != zft_unit) {
TRACE(ft_t_err, "failed: not busy or wrong unit");
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,31)
+ unlock_kernel();
TRACE_EXIT 0;
-#else
- TRACE_EXIT; /* keep busy_flag !(?) */
-#endif
}
sigfillset(&current->blocked);
result = _zft_close();
@@ -206,16 +159,8 @@ static int zft_close(struct inode *ino, struct file *filep)
}
current->blocked = orig_sigmask; /* restore before open state */
busy_flag = 0;
-#if defined(MODULE) && LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
- if (!zft_dirty()) {
- MOD_DEC_USE_COUNT; /* unlock module in memory */
- }
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,31)
+ unlock_kernel();
TRACE_EXIT 0;
-#else
- TRACE_EXIT;
-#endif
}
/* Ioctl for floppy tape device
@@ -241,24 +186,14 @@ static int zft_ioctl(struct inode *ino, struct file *filep,
/* Ioctl for floppy tape device
*/
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,56)
static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
-#else
-static int zft_mmap(struct inode *ino,
- struct file *filep,
- struct vm_area_struct *vma)
-#endif
{
int result = -EIO;
sigset_t old_sigmask;
TRACE_FUN(ft_t_flow);
if (!busy_flag ||
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,56)
MINOR(filep->f_dentry->d_inode->i_rdev) != zft_unit ||
-#else
- MINOR(ino->i_rdev) != zft_unit ||
-#endif
ft_failure)
{
TRACE_ABORT(-EIO, ft_t_err,
@@ -266,34 +201,26 @@ static int zft_mmap(struct inode *ino,
}
old_sigmask = current->blocked; /* save mask */
sigfillset(&current->blocked);
+ lock_kernel();
if ((result = ftape_mmap(vma)) >= 0) {
#ifndef MSYNC_BUG_WAS_FIXED
static struct vm_operations_struct dummy = { NULL, };
vma->vm_ops = &dummy;
#endif
}
+ unlock_kernel();
current->blocked = old_sigmask; /* restore mask */
TRACE_EXIT result;
}
/* Read from floppy tape device
*/
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
static ssize_t zft_read(struct file *fp, char *buff,
size_t req_len, loff_t *ppos)
-#elif LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long zft_read(struct inode *ino, struct file *fp, char *buff,
- unsigned long req_len)
-#else
-static int zft_read(struct inode *ino, struct file *fp, char *buff,
- int req_len)
-#endif
{
int result = -EIO;
sigset_t old_sigmask;
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
struct inode *ino = fp->f_dentry->d_inode;
-#endif
TRACE_FUN(ft_t_flow);
TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
@@ -311,22 +238,12 @@ static int zft_read(struct inode *ino, struct file *fp, char *buff,
/* Write to tape device
*/
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
static ssize_t zft_write(struct file *fp, const char *buff,
size_t req_len, loff_t *ppos)
-#elif LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long zft_write(struct inode *ino, struct file *fp, const char *buff,
- unsigned long req_len)
-#else
-static int zft_write(struct inode *ino, struct file *fp, const char *buff,
- int req_len)
-#endif
{
int result = -EIO;
sigset_t old_sigmask;
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
struct inode *ino = fp->f_dentry->d_inode;
-#endif
TRACE_FUN(ft_t_flow);
TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
@@ -470,9 +387,6 @@ KERN_INFO
&zft_cdev, NULL);
}
-#if LINUX_VERSION_CODE < KERNEL_VER(2,1,18)
- register_symtab(&zft_symbol_table); /* add global zftape symbols */
-#endif
#ifdef CONFIG_ZFT_COMPRESSOR
(void)zft_compressor_init();
#endif
@@ -484,24 +398,20 @@ KERN_INFO
#ifdef MODULE
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
/* Called by modules package before trying to unload the module
*/
static int can_unload(void)
{
- return (zft_dirty() || busy_flag) ? -EBUSY : 0;
+ return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||busy_flag)?-EBUSY:0;
}
-#endif
/* Called by modules package when installing the driver
*/
int init_module(void)
{
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,18)
if (!mod_member_present(&__this_module, can_unload)) {
return -EBUSY;
}
__this_module.can_unload = can_unload;
-#endif
return zft_init();
}
diff --git a/drivers/char/h8.c b/drivers/char/h8.c
index acc898cb8..8a4b4de51 100644
--- a/drivers/char/h8.c
+++ b/drivers/char/h8.c
@@ -106,16 +106,6 @@ static int h8_monitor_timer_active = 0;
static char driver_version[] = "X0.0";/* no spaces */
-static struct file_operations h8_fops = {
- /* twelve lines of crap^WNULLs were here */
-};
-
-static struct miscdevice h8_device = {
- H8_MINOR_DEV,
- "h8",
- &h8_fops
-};
-
union intr_buf intrbuf;
int intr_buf_ptr;
union intr_buf xx;
@@ -297,7 +287,6 @@ static void h8_intr(int irq, void *dev_id, struct pt_regs *regs)
static void __exit h8_cleanup (void)
{
remove_proc_entry("driver/h8", NULL);
- misc_deregister(&h8_device);
release_region(h8_base, 8);
free_irq(h8_irq, NULL);
}
@@ -313,7 +302,6 @@ static int __init h8_init(void)
create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);
- misc_register(&h8_device);
request_region(h8_base, 8, "h8");
h8_alloc_queues();
diff --git a/drivers/char/i2c-parport.c b/drivers/char/i2c-parport.c
index 8304a6ab5..00b574f60 100644
--- a/drivers/char/i2c-parport.c
+++ b/drivers/char/i2c-parport.c
@@ -75,7 +75,7 @@ static void i2c_parport_attach(struct parport *port)
struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus),
GFP_KERNEL);
b->i2c = parport_i2c_bus_template;
- b->i2c.data = port;
+ b->i2c.data = parport_get_port (port);
strncpy(b->i2c.name, port->name, 32);
spin_lock(&bus_list_lock);
b->next = bus_list;
diff --git a/drivers/char/i810_rng.c b/drivers/char/i810_rng.c
index 905d8e8cd..7a6718c02 100644
--- a/drivers/char/i810_rng.c
+++ b/drivers/char/i810_rng.c
@@ -165,6 +165,7 @@
#include <linux/random.h>
#include <linux/sysctl.h>
#include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -626,12 +627,16 @@ err_out:
static int rng_dev_release (struct inode *inode, struct file *filp)
{
- if (rng_enable(0) != 0)
+ lock_kernel();
+ if (rng_enable(0) != 0) {
+ unlock_kernel();
return -EIO;
+ }
spin_lock_bh (&rng_lock);
rng_open = 0;
spin_unlock_bh (&rng_lock);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 449bd2f76..6fbfe22df 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -329,8 +329,7 @@ static long bh_counter = 0;
* selected, the board is serviced periodically to see if anything needs doing.
*/
#define POLL_TIMEOUT (jiffies + 1)
-static struct timer_list PollTimer = { {NULL, NULL}, 0, 0, ip2_poll };
-// next, prev, expires,data, func()
+static struct timer_list PollTimer = { function: ip2_poll };
static char TimerOn = 0;
#ifdef IP2DEBUG_TRACE
diff --git a/drivers/char/joystick/Config.in b/drivers/char/joystick/Config.in
index 1547e5f38..b020f1728 100644
--- a/drivers/char/joystick/Config.in
+++ b/drivers/char/joystick/Config.in
@@ -7,9 +7,7 @@ comment 'Joysticks'
tristate 'Joystick support' CONFIG_JOYSTICK
if [ "$CONFIG_JOYSTICK" != "n" ]; then
-
- define_tristate CONFIG_USB $CONFIG_JOYSTICK
- define_tristate CONFIG_INPUT_JOYDEV $CONFIG_JOYSTICK
+ define_tristate CONFIG_INPUT_JOYDEV $CONFIG_JOYSTICK
comment 'Game port support'
dep_tristate ' ns558 gameports' CONFIG_INPUT_NS558 $CONFIG_JOYSTICK
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 5e212af34..a602e3b3b 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -119,6 +119,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/malloc.h>
#include <linux/fcntl.h>
@@ -407,9 +408,11 @@ static int lp_release(struct inode * inode, struct file * file)
{
unsigned int minor = MINOR(inode->i_rdev);
+ lock_kernel();
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
LP_F(minor) &= ~LP_BUSY;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c
index 6352d6f73..1daff0de7 100644
--- a/drivers/char/mixcomwd.c
+++ b/drivers/char/mixcomwd.c
@@ -43,6 +43,7 @@
#include <linux/watchdog.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -100,9 +101,11 @@ static int mixcomwd_open(struct inode *inode, struct file *file)
static int mixcomwd_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
if(mixcomwd_timer_alive) {
printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+ unlock_kernel();
return -EBUSY;
}
init_timer(&mixcomwd_timer);
@@ -114,6 +117,7 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
#endif
clear_bit(0,&mixcomwd_opened);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c
index dce40c671..5c30ca2f0 100644
--- a/drivers/char/msp3400.c
+++ b/drivers/char/msp3400.c
@@ -1265,8 +1265,10 @@ msp3400c_mixer_release(struct inode *inode, struct file *file)
{
struct i2c_client *client = file->private_data;
+ lock_kernel();
if (client->adapter->dec_use)
client->adapter->dec_use(client->adapter);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index a32cd18df..6fa72fc8e 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -34,6 +34,8 @@
#include <linux/module.h>
#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#define PC 1
#define ATARI 2
@@ -341,11 +343,13 @@ static int nvram_open( struct inode *inode, struct file *file )
static int nvram_release( struct inode *inode, struct file *file )
{
+ lock_kernel();
nvram_open_cnt--;
if (file->f_flags & O_EXCL)
nvram_open_mode &= ~NVRAM_EXCL;
if (file->f_mode & 2)
nvram_open_mode &= ~NVRAM_WRITE;
+ unlock_kernel();
return( 0 );
}
diff --git a/drivers/char/pc110pad.c b/drivers/char/pc110pad.c
index dfef66e39..556d8630e 100644
--- a/drivers/char/pc110pad.c
+++ b/drivers/char/pc110pad.c
@@ -41,6 +41,7 @@
#include <linux/poll.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
#include <asm/signal.h>
#include <asm/io.h>
@@ -583,10 +584,11 @@ static int fasync_pad(int fd, struct file *filp, int on)
static int close_pad(struct inode * inode, struct file * file)
{
+ lock_kernel();
fasync_pad(-1, file, 0);
- if (--active)
- return 0;
- outb(0x30, current_params.io+2); /* switch off digitiser */
+ if (!--active)
+ outb(0x30, current_params.io+2); /* switch off digitiser */
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c
index c265b927f..34e13c97f 100644
--- a/drivers/char/pc_keyb.c
+++ b/drivers/char/pc_keyb.c
@@ -31,6 +31,7 @@
#include <linux/miscdevice.h>
#include <linux/malloc.h>
#include <linux/kbd_kern.h>
+#include <linux/smp_lock.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
@@ -872,12 +873,16 @@ static int fasync_aux(int fd, struct file *filp, int on)
static int release_aux(struct inode * inode, struct file * file)
{
+ lock_kernel();
fasync_aux(-1, file, 0);
- if (--aux_count)
+ if (--aux_count) {
+ unlock_kernel();
return 0;
+ }
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
aux_free_irq(AUX_DEV);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/pcmcia/Config.in b/drivers/char/pcmcia/Config.in
index 766fdd1d0..8baf1932e 100644
--- a/drivers/char/pcmcia/Config.in
+++ b/drivers/char/pcmcia/Config.in
@@ -3,12 +3,12 @@
#
if [ "$CONFIG_SERIAL" = "n" ]; then
- define_bool CONFIG_PCMCIA_SERIAL n
+ define_tristate CONFIG_PCMCIA_SERIAL n
else
if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_PCMCIA" = "m" ]; then
- define_bool CONFIG_PCMCIA_SERIAL m
+ define_tristate CONFIG_PCMCIA_SERIAL m
else
- define_bool CONFIG_PCMCIA_SERIAL y
+ define_tristate CONFIG_PCMCIA_SERIAL y
fi
fi
diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c
index b85a168de..cb197afc5 100644
--- a/drivers/char/pcwd.c
+++ b/drivers/char/pcwd.c
@@ -63,6 +63,7 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -451,6 +452,7 @@ static int pcwd_close(struct inode *ino, struct file *filep)
{
if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
{
+ lock_kernel();
is_open = 0;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
/* Disable the board */
@@ -460,6 +462,7 @@ static int pcwd_close(struct inode *ino, struct file *filep)
outb_p(0xA5, current_readport + 3);
spin_unlock(&io_lock);
}
+ unlock_kernel();
#endif
}
return 0;
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 4e2be3c8b..07877c1a7 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -52,6 +52,7 @@
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/ppdev.h>
+#include <linux/smp_lock.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
#define CHRDEV "ppdev"
@@ -83,64 +84,6 @@ struct pp_struct {
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-struct pp_port_list_struct {
- struct parport *port;
- struct pp_port_list_struct *next;
-};
-static struct pp_port_list_struct *pp_port_list;
-static DECLARE_MUTEX(pp_port_list_lock);
-
-/* pp_attach and pp_detach are for keeping a list of currently
- * available ports, held under a mutex. We do this rather than
- * using parport_enumerate because it stops a load of races.
- */
-
-static void pp_attach (struct parport *port)
-{
- struct pp_port_list_struct *add;
-
- add = kmalloc (sizeof (struct pp_port_list_struct), GFP_KERNEL);
- if (!add) {
- printk (KERN_WARNING CHRDEV ": memory squeeze\n");
- return;
- }
-
- add->port = port;
- down (&pp_port_list_lock);
- add->next = pp_port_list;
- pp_port_list = add;
- up (&pp_port_list_lock);
-}
-
-static void pp_detach (struct parport *port)
-{
- struct pp_port_list_struct *del;
-
- down (&pp_port_list_lock);
- del = pp_port_list;
- if (del->port == port)
- pp_port_list = del->next;
- else {
- struct pp_port_list_struct *prev;
- do {
- prev = del;
- del = del->next;
- } while (del && del->port != port);
- if (del)
- prev->next = del->next;
- }
- up (&pp_port_list_lock);
-
- if (del)
- kfree (del);
-}
-
-static struct parport_driver ppdev_driver = {
- name: CHRDEV,
- attach: pp_attach,
- detach: pp_detach
-};
-
static inline void pp_enable_irq (struct pp_struct *pp)
{
struct parport *port = pp->pdev->port;
@@ -274,7 +217,7 @@ static void pp_irq (int irq, void * private, struct pt_regs * unused)
static int register_device (int minor, struct pp_struct *pp)
{
- struct pp_port_list_struct *ports;
+ struct parport *port;
struct pardevice * pdev = NULL;
char *name;
int fl;
@@ -285,23 +228,17 @@ static int register_device (int minor, struct pp_struct *pp)
sprintf (name, CHRDEV "%x", minor);
- down (&pp_port_list_lock);
- ports = pp_port_list;
- while (ports && ports->port->number != minor)
- ports = ports->next;
- if (ports->port) {
- fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
- pdev = parport_register_device (ports->port, name, NULL,
- NULL, pp_irq, fl, pp);
- }
- up (&pp_port_list_lock);
-
- if (!ports->port) {
+ port = parport_find_number (minor);
+ if (!port) {
printk (KERN_WARNING "%s: no associated port!\n", name);
kfree (name);
return -ENXIO;
}
+ fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
+ pdev = parport_register_device (port, name, NULL,
+ NULL, pp_irq, fl, pp);
+ parport_put_port (port);
if (!pdev) {
printk (KERN_WARNING "%s: failed to register device!\n", name);
@@ -595,6 +532,7 @@ static int pp_release (struct inode * inode, struct file * file)
unsigned int minor = MINOR (inode->i_rdev);
struct pp_struct *pp = file->private_data;
+ lock_kernel();
if (pp->pdev && pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT) {
if (!(pp->flags & PP_CLAIMED)) {
parport_claim_or_block (pp->pdev);
@@ -620,6 +558,7 @@ static int pp_release (struct inode * inode, struct file * file)
printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
minor);
}
+ unlock_kernel();
kfree (pp);
@@ -654,10 +593,6 @@ static devfs_handle_t devfs_handle = NULL;
static int __init ppdev_init (void)
{
- if (parport_register_driver (&ppdev_driver)) {
- printk (KERN_WARNING CHRDEV ": unable to register driver\n");
- return -EIO;
- }
if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) {
printk (KERN_WARNING CHRDEV ": unable to get major %d\n",
PP_MAJOR);
@@ -678,7 +613,6 @@ static void __exit ppdev_cleanup (void)
/* Clean up all parport stuff */
devfs_unregister (devfs_handle);
devfs_unregister_chrdev (PP_MAJOR, CHRDEV);
- parport_unregister_driver (&ppdev_driver);
}
module_init(ppdev_init);
diff --git a/drivers/char/qpmouse.c b/drivers/char/qpmouse.c
index 6fd5a3d65..4db93b1fb 100644
--- a/drivers/char/qpmouse.c
+++ b/drivers/char/qpmouse.c
@@ -36,6 +36,7 @@
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -141,6 +142,7 @@ static int release_qp(struct inode * inode, struct file * file)
{
unsigned char status;
+ lock_kernel();
fasync_qp(-1, file, 0);
if (!--qp_count) {
if (!poll_qp_status())
@@ -151,6 +153,7 @@ static int release_qp(struct inode * inode, struct file * file)
printk("Warning: Mouse device busy in release_qp()\n");
free_irq(QP_IRQ, NULL);
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index a3159c836..4b1281b50 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -14,6 +14,7 @@
#include <linux/blkdev.h>
#include <linux/raw.h>
#include <linux/capability.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#define dprintk(x...)
@@ -126,9 +127,11 @@ int raw_release(struct inode *inode, struct file *filp)
struct block_device *bdev;
minor = MINOR(inode->i_rdev);
+ lock_kernel();
bdev = raw_device_bindings[minor];
blkdev_put(bdev, BDEV_RAW);
raw_device_inuse[minor]--;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c
index a0bea62c0..813594244 100644
--- a/drivers/char/sbc60xxwdt.c
+++ b/drivers/char/sbc60xxwdt.c
@@ -66,6 +66,7 @@
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -207,6 +208,7 @@ static int fop_open(struct inode * inode, struct file * file)
static int fop_close(struct inode * inode, struct file * file)
{
+ lock_kernel();
if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
{
if(wdt_expect_close)
@@ -217,6 +219,7 @@ static int fop_close(struct inode * inode, struct file * file)
}
}
wdt_is_open = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c
index a7620dda0..3d1c57907 100644
--- a/drivers/char/softdog.c
+++ b/drivers/char/softdog.c
@@ -37,6 +37,7 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/reboot.h>
+#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
@@ -79,7 +80,9 @@ static int softdog_open(struct inode *inode, struct file *file)
{
if(timer_alive)
return -EBUSY;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
MOD_INC_USE_COUNT;
+#endif
/*
* Activate timer
*/
@@ -94,11 +97,12 @@ static int softdog_release(struct inode *inode, struct file *file)
* Shut off the timer.
* Lock it in if it's a module and we defined ...NOWAYOUT
*/
+ lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
del_timer(&watchdog_ticktock);
- MOD_DEC_USE_COUNT;
#endif
timer_alive=0;
+ unlock_kernel();
return 0;
}
@@ -146,6 +150,7 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
static struct file_operations softdog_fops=
{
+ owner: THIS_MODULE,
write: softdog_write,
ioctl: softdog_ioctl,
open: softdog_open,
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index 3ca976b6e..14a42682d 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -89,6 +89,7 @@
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/dma.h>
@@ -2411,6 +2412,7 @@ static int qic02_tape_release(struct inode * inode, struct file * filp)
{
kdev_t dev = inode->i_rdev;
+ lock_kernel();
if (TP_DIAGS(dev))
{
printk("qic02_tape_release: dev=%s\n", kdevname(dev));
@@ -2437,6 +2439,7 @@ static int qic02_tape_release(struct inode * inode, struct file * filp)
(void) do_qic_cmd(QCMD_REWIND, TIM_R);
}
}
+ unlock_kernel();
return 0;
} /* qic02_tape_release */
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 60a5c41f5..816f385e1 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1430,7 +1430,9 @@ init_dev_done:
static int tty_release(struct inode * inode, struct file * filp)
{
+ lock_kernel();
release_dev(filp);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/tvmixer.c b/drivers/char/tvmixer.c
index 0ef5bbd03..c3db65bae 100644
--- a/drivers/char/tvmixer.c
+++ b/drivers/char/tvmixer.c
@@ -7,6 +7,7 @@
#include <linux/errno.h>
#include <linux/malloc.h>
#include <linux/i2c.h>
+#include <linux/smp_lock.h>
#include <linux/videodev.h>
#include <asm/semaphore.h>
#include <linux/init.h>
@@ -220,13 +221,18 @@ static int tvmixer_open(struct inode *inode, struct file *file)
static int tvmixer_release(struct inode *inode, struct file *file)
{
struct TVMIXER *mix = file->private_data;
- struct i2c_client *client = mix->dev;
+ struct i2c_client *client;
- if (NULL == client)
+ lock_kernel();
+ client = mix->dev;
+ if (NULL == client) {
+ unlock_kernel();
return -ENODEV;
+ }
if (client->adapter->dec_use)
client->adapter->dec_use(client->adapter);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c
index 5103433e1..3657cb518 100644
--- a/drivers/char/videodev.c
+++ b/drivers/char/videodev.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -158,11 +159,9 @@ static int video_open(struct inode *inode, struct file *file)
if(vfl==NULL) {
char modname[20];
- MOD_INC_USE_COUNT;
sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
request_module(modname);
vfl=video_device[minor];
- MOD_DEC_USE_COUNT;
if (vfl==NULL)
return -ENODEV;
}
@@ -188,10 +187,13 @@ static int video_open(struct inode *inode, struct file *file)
static int video_release(struct inode *inode, struct file *file)
{
- struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
+ struct video_device *vfl;
+ lock_kernel();
+ vfl=video_device[MINOR(inode->i_rdev)];
if(vfl->close)
vfl->close(vfl);
vfl->busy=0;
+ unlock_kernel();
return 0;
}
@@ -229,11 +231,15 @@ static int video_ioctl(struct inode *inode, struct file *file,
int video_mmap(struct file *file, struct vm_area_struct *vma)
{
+ int ret = -EINVAL;
struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
- if(vfl->mmap)
- return vfl->mmap(vfl, (char *)vma->vm_start,
+ if(vfl->mmap) {
+ lock_kernel();
+ ret = vfl->mmap(vfl, (char *)vma->vm_start,
(unsigned long)(vma->vm_end-vma->vm_start));
- return -EINVAL;
+ unlock_kernel();
+ }
+ return ret;
}
/*
@@ -515,6 +521,7 @@ void video_unregister_device(struct video_device *vfd)
static struct file_operations video_fops=
{
+ owner: THIS_MODULE,
llseek: video_lseek,
read: video_read,
write: video_write,
diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c
index 3ac86bf3a..bde40c589 100644
--- a/drivers/char/wdt.c
+++ b/drivers/char/wdt.c
@@ -35,6 +35,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include "wd501p.h"
@@ -372,6 +373,7 @@ static int wdt_open(struct inode *inode, struct file *file)
static int wdt_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
@@ -380,6 +382,7 @@ static int wdt_release(struct inode *inode, struct file *file)
#endif
wdt_is_open=0;
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/char/wdt285.c b/drivers/char/wdt285.c
index 6efdd7f76..66633fd20 100644
--- a/drivers/char/wdt285.c
+++ b/drivers/char/wdt285.c
@@ -26,6 +26,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -74,7 +75,6 @@ static int watchdog_open(struct inode *inode, struct file *file)
{
if(timer_alive)
return -EBUSY;
- MOD_INC_USE_COUNT;
/*
* Ahead watchdog factor ten, Mr Sulu
*/
@@ -86,6 +86,7 @@ static int watchdog_open(struct inode *inode, struct file *file)
request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
#else
*CSR_SA110_CNTL |= 1 << 13;
+ MOD_INC_USE_COUNT;
#endif
timer_alive = 1;
return 0;
@@ -94,9 +95,10 @@ static int watchdog_open(struct inode *inode, struct file *file)
static int watchdog_release(struct inode *inode, struct file *file)
{
#ifdef ONLY_TESTING
+ lock_kernel();
free_irq(IRQ_TIMER4, NULL);
timer_alive = 0;
- MOD_DEC_USE_COUNT;
+ unlock_kernel();
#else
/*
* It's irreversible!
@@ -153,6 +155,7 @@ static int watchdog_ioctl(struct inode *inode, struct file *file,
static struct file_operations watchdog_fops=
{
+ owner: THIS_MODULE,
write: watchdog_write,
ioctl: watchdog_ioctl,
open: watchdog_open,
diff --git a/drivers/char/wdt977.c b/drivers/char/wdt977.c
index 9bfbf0cc6..fef6bc7fc 100644
--- a/drivers/char/wdt977.c
+++ b/drivers/char/wdt977.c
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -38,7 +39,9 @@ static int wdt977_open(struct inode *inode, struct file *file)
{
if(timer_alive)
return -EBUSY;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
MOD_INC_USE_COUNT;
+#endif
timer_alive++;
//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
@@ -88,6 +91,7 @@ static int wdt977_release(struct inode *inode, struct file *file)
* Lock it in if it's a module and we defined ...NOWAYOUT
*/
#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ lock_kernel();
// unlock the SuperIO chip
outb(0x87,0x370);
@@ -118,8 +122,8 @@ static int wdt977_release(struct inode *inode, struct file *file)
// lock the SuperIO chip
outb(0xAA,0x370);
- MOD_DEC_USE_COUNT;
timer_alive=0;
+ unlock_kernel();
printk(KERN_INFO "Watchdog: shutdown.\n");
#endif
@@ -162,6 +166,7 @@ static ssize_t wdt977_write(struct file *file, const char *data, size_t len, lof
static struct file_operations wdt977_fops=
{
+ owner: THIS_MODULE,
write: wdt977_write,
open: wdt977_open,
release: wdt977_release,
diff --git a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
index 2bd09930a..8e960841b 100644
--- a/drivers/char/wdt_pci.c
+++ b/drivers/char/wdt_pci.c
@@ -51,6 +51,7 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <linux/pci.h>
@@ -358,7 +359,9 @@ static int wdtpci_open(struct inode *inode, struct file *file)
case WATCHDOG_MINOR:
if(wdt_is_open)
return -EBUSY;
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
MOD_INC_USE_COUNT;
+#endif
/*
* Activate
*/
@@ -391,7 +394,6 @@ static int wdtpci_open(struct inode *inode, struct file *file)
outb_p(0, WDT_DC); /* Enable */
return 0;
case TEMP_MINOR:
- MOD_INC_USE_COUNT;
return 0;
default:
return -ENODEV;
@@ -414,13 +416,14 @@ static int wdtpci_release(struct inode *inode, struct file *file)
{
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
+ lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
inb_p(WDT_DC); /* Disable counters */
wdtpci_ctr_load(2,0); /* 0 length reset pulses now */
#endif
wdt_is_open=0;
+ unlock_kernel();
}
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -454,6 +457,7 @@ static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
static struct file_operations wdtpci_fops = {
+ owner: THIS_MODULE,
llseek: wdtpci_llseek,
read: wdtpci_read,
write: wdtpci_write,
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index e373ce2f3..47a6292d1 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -32,6 +32,7 @@
#include <linux/fs.h>
#include <linux/malloc.h>
#include <linux/version.h>
+#include <linux/smp_lock.h>
/* If you want debugging uncomment: */
/* #define DEBUG */
@@ -76,6 +77,7 @@ extern
static int i2cdev_cleanup(void);
static struct file_operations i2cdev_fops = {
+ owner: THIS_MODULE,
llseek: i2cdev_lseek,
read: i2cdev_read,
write: i2cdev_write,
@@ -374,7 +376,6 @@ int i2cdev_open (struct inode *inode, struct file *file)
if (i2cdev_adaps[minor]->inc_use)
i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]);
- MOD_INC_USE_COUNT;
#ifdef DEBUG
printk("i2c-dev.o: opened i2c-%d\n",minor);
@@ -390,9 +391,10 @@ static int i2cdev_release (struct inode *inode, struct file *file)
#ifdef DEBUG
printk("i2c-dev.o: Closed: i2c-%d\n", minor);
#endif
- MOD_DEC_USE_COUNT;
+ lock_kernel();
if (i2cdev_adaps[minor]->dec_use)
i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/i2o/i2o_config.c b/drivers/i2o/i2o_config.c
index 7a50f64e9..9a9cfec6e 100644
--- a/drivers/i2o/i2o_config.c
+++ b/drivers/i2o/i2o_config.c
@@ -35,6 +35,7 @@
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -848,6 +849,7 @@ static int cfg_release(struct inode *inode, struct file *file)
struct i2o_cfg_info *p1, *p2;
unsigned int flags;
+ lock_kernel();
p1 = p2 = NULL;
spin_lock_irqsave(&i2o_config_lock, flags);
@@ -870,6 +872,7 @@ static int cfg_release(struct inode *inode, struct file *file)
p1 = p1->next;
}
spin_unlock_irqrestore(&i2o_config_lock, flags);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 911234014..bd89fcc61 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -402,6 +402,7 @@
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/ide.h>
+#include <linux/smp_lock.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -5235,11 +5236,6 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
if (test_and_set_bit (IDETAPE_BUSY, &tape->flags))
return -EBUSY;
- MOD_INC_USE_COUNT;
-#if ONSTREAM_DEBUG
- if (tape->debug_level >= 6)
- printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-1\n");
-#endif
if (!tape->onstream) {
idetape_read_position(drive);
if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags))
@@ -5255,28 +5251,13 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
}
if (idetape_wait_ready(drive, 60 * HZ)) {
clear_bit(IDETAPE_BUSY, &tape->flags);
- MOD_DEC_USE_COUNT;
-#if ONSTREAM_DEBUG
- if (tape->debug_level >= 6)
- printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-1\n");
-#endif
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
return -EBUSY;
}
idetape_read_position(drive);
- MOD_DEC_USE_COUNT;
-#if ONSTREAM_DEBUG
- if (tape->debug_level >= 6)
- printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-2\n");
-#endif
clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
if (tape->chrdev_direction == idetape_direction_none) {
- MOD_INC_USE_COUNT;
-#if ONSTREAM_DEBUG
- if (tape->debug_level >= 6)
- printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-2\n");
-#endif
idetape_create_prevent_cmd(drive, &pc, 1);
if (!idetape_queue_pc_tail (drive,&pc)) {
if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
@@ -5296,10 +5277,12 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
static int idetape_chrdev_release (struct inode *inode, struct file *filp)
{
ide_drive_t *drive = get_drive_ptr (inode->i_rdev);
- idetape_tape_t *tape = drive->driver_data;
+ idetape_tape_t *tape;
idetape_pc_t pc;
unsigned int minor=MINOR (inode->i_rdev);
-
+
+ lock_kernel();
+ tape = drive->driver_data;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3)
printk (KERN_INFO "ide-tape: Reached idetape_chrdev_release\n");
@@ -5337,13 +5320,9 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
if (!idetape_queue_pc_tail (drive,&pc))
tape->door_locked = DOOR_UNLOCKED;
}
- MOD_DEC_USE_COUNT;
-#if ONSTREAM_DEBUG
- if (tape->debug_level >= 6)
- printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_release\n");
-#endif
}
clear_bit (IDETAPE_BUSY, &tape->flags);
+ unlock_kernel();
return 0;
}
@@ -5919,6 +5898,7 @@ static ide_module_t idetape_module = {
* Our character device supporting functions, passed to register_chrdev.
*/
static struct file_operations idetape_fops = {
+ owner: THIS_MODULE,
read: idetape_chrdev_read,
write: idetape_chrdev_write,
ioctl: idetape_chrdev_ioctl,
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 83c1169fe..3c23c45a5 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -17,6 +17,7 @@
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/version.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
@@ -869,6 +870,7 @@ static int dev_release(struct inode *inode, struct file *file)
struct pending_request *req;
int done = 0, i;
+ lock_kernel();
for (i = 0; i < 64; i++) {
if (fi->listen_channels & (1ULL << i)) {
hpsb_unlisten_channel(hl_handle, fi->host, i);
@@ -913,6 +915,7 @@ static int dev_release(struct inode *inode, struct file *file)
kfree(fi);
V22_COMPAT_MOD_DEC_USE_COUNT;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 9f00fd3f0..9afbb58ec 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#include <asm/io.h>
@@ -1043,18 +1044,20 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_card *video =
&video_cards[MINOR(file->f_dentry->d_inode->i_rdev)];
- struct ti_ohci *ohci= video->ohci;
+ struct ti_ohci *ohci;
+ int res = -EINVAL;
+ lock_kernel();
+ ohci = video->ohci;
PRINT(KERN_INFO, ohci->id, "mmap");
if (video->current_ctx == NULL) {
PRINT(KERN_ERR, ohci->id, "current iso context not set");
- return -EINVAL;
- }
-
- return do_iso_mmap(ohci, video->current_ctx,
+ } else
+ res = do_iso_mmap(ohci, video->current_ctx,
(char *)vma->vm_start,
(unsigned long)(vma->vm_end-vma->vm_start));
- return 0;
+ unlock_kernel();
+ return res;
}
static int video1394_open(struct inode *inode, struct file *file)
@@ -1079,6 +1082,7 @@ static int video1394_release(struct inode *inode, struct file *file)
struct ti_ohci *ohci= video->ohci;
int i;
+ lock_kernel();
for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++)
if (video->ir_context[i]) {
if (!test_and_clear_bit(
@@ -1115,6 +1119,7 @@ static int video1394_release(struct inode *inode, struct file *file)
V22_COMPAT_MOD_DEC_USE_COUNT;
PRINT(KERN_INFO, ohci->id, "release");
+ unlock_kernel();
return 0;
}
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index 06ddc8199..4c7e68266 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -182,6 +182,7 @@
#include <linux/fs.h>
#include <linux/signal.h>
#include <linux/mm.h>
+#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/wait.h>
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -379,10 +380,8 @@ struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci)
struct capiminor *mp, **pp;
unsigned int minor = 0;
- MOD_INC_USE_COUNT;
mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC);
if (!mp) {
- MOD_DEC_USE_COUNT;
printk(KERN_ERR "capi: can't alloc capiminor\n");
return 0;
}
@@ -434,7 +433,6 @@ void capiminor_free(struct capiminor *mp)
kfree_skb(skb);
capiminor_del_all_ack(mp);
kmem_cache_free(capiminor_cachep, mp);
- MOD_DEC_USE_COUNT;
#ifdef _DEBUG_REFCOUNT
printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE));
#endif
@@ -1212,7 +1210,6 @@ capi_open(struct inode *inode, struct file *file)
if ((file->private_data = capidev_alloc(file)) == 0)
return -ENOMEM;
- MOD_INC_USE_COUNT;
#ifdef _DEBUG_REFCOUNT
printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE));
#endif
@@ -1224,14 +1221,15 @@ capi_release(struct inode *inode, struct file *file)
{
struct capidev *cdev = (struct capidev *)file->private_data;
+ lock_kernel();
capincci_free(cdev, 0xffffffff);
capidev_free(cdev);
file->private_data = NULL;
- MOD_DEC_USE_COUNT;
#ifdef _DEBUG_REFCOUNT
printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE));
#endif
+ unlock_kernel();
return 0;
}
@@ -1414,11 +1412,13 @@ capinc_raw_release(struct inode *inode, struct file *file)
struct capiminor *mp = (struct capiminor *)file->private_data;
if (mp) {
+ lock_kernel();
mp->file = 0;
if (mp->nccip == 0) {
capiminor_free(mp);
file->private_data = NULL;
}
+ unlock_kernel();
}
#ifdef _DEBUG_REFCOUNT
@@ -2050,8 +2050,6 @@ int capi_init(void)
{
char *p;
- MOD_INC_USE_COUNT;
-
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 2);
p = strchr(rev, '$');
@@ -2061,7 +2059,6 @@ int capi_init(void)
if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
- MOD_DEC_USE_COUNT;
return -EIO;
}
@@ -2069,7 +2066,6 @@ int capi_init(void)
if (devfs_register_chrdev(capi_rawmajor, "capi/r%d", &capinc_raw_fops)) {
devfs_unregister_chrdev(capi_major, "capi20");
printk(KERN_ERR "capi20: unable to get major %d\n", capi_rawmajor);
- MOD_DEC_USE_COUNT;
return -EIO;
}
devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS,
@@ -2085,7 +2081,6 @@ int capi_init(void)
if ((capifuncs = attach_capi_interface(&cuser)) == 0) {
- MOD_DEC_USE_COUNT;
devfs_unregister_chrdev(capi_major, "capi20");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
@@ -2101,7 +2096,6 @@ int capi_init(void)
(void) detach_capi_interface(&cuser);
devfs_unregister_chrdev(capi_major, "capi20");
devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
@@ -2122,7 +2116,6 @@ int capi_init(void)
devfs_unregister(devfs_find_handle(NULL, "capi20",
capi_major, 0,
DEVFS_SPECIAL_CHR, 0));
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -2131,7 +2124,6 @@ int capi_init(void)
printk(KERN_NOTICE "capi20: Rev%s: started up with major %d\n",
rev, capi_major);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index f7d7ee8d5..bd065a48d 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -199,6 +199,7 @@ isdn_divert_close(struct inode *ino, struct file *filep)
struct divert_info *inf;
int flags;
+ lock_kernel();
save_flags(flags);
cli();
if_used--;
@@ -214,6 +215,7 @@ isdn_divert_close(struct inode *ino, struct file *filep)
divert_info_head = divert_info_head->next;
kfree(inf);
}
+ unlock_kernel();
return (0);
} /* isdn_divert_close */
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index c27c926a1..c28aedc1f 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -372,6 +372,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
int retval = 0;
struct proc_dir_entry *pd;
+ lock_kernel();
/* search the addressed card */
card = card_root;
while (card) {
@@ -381,6 +382,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
card = card->next; /* search next entry */
}
if (!card) {
+ unlock_kernel();
return (-ENODEV); /* device is unknown/invalid */
}
if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
@@ -403,6 +405,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
if (filep->private_data)
kfree(filep->private_data); /* release memory */
}
+ unlock_kernel();
return (retval);
} /* hysdn_conf_close */
diff --git a/drivers/isdn/hysdn/hysdn_procfs.c b/drivers/isdn/hysdn/hysdn_procfs.c
index ae07f6597..864935625 100644
--- a/drivers/isdn/hysdn/hysdn_procfs.c
+++ b/drivers/isdn/hysdn/hysdn_procfs.c
@@ -254,7 +254,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
hysdn_card *card;
int flags, retval = 0;
-
+ lock_kernel();
if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
/* write only access -> write debug completely written */
retval = 0; /* success */
@@ -297,6 +297,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
}
} /* read access */
+ unlock_kernel();
return (retval);
} /* hysdn_log_close */
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 1a2980f02..ba454b9dc 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -345,6 +345,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
int flags, retval = 0;
+ lock_kernel();
if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
/* write only access -> write debug level written */
retval = 0; /* success */
@@ -386,6 +387,7 @@ hysdn_log_close(struct inode *ino, struct file *filep)
kfree(inf);
}
} /* read access */
+ unlock_kernel();
return (retval);
} /* hysdn_log_close */
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index f6c326301..b543d8690 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -439,6 +439,7 @@
#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <linux/isdn.h>
+#include <linux/smp_lock.h>
#include "isdn_common.h"
#include "isdn_tty.h"
#include "isdn_net.h"
@@ -485,11 +486,10 @@ static void isdn_register_devfs(int);
static void isdn_unregister_devfs(int);
void
-isdn_MOD_INC_USE_COUNT(void)
+isdn_lock_drivers(void)
{
int i;
- MOD_INC_USE_COUNT;
for (i = 0; i < dev->drivers; i++) {
isdn_ctrl cmd;
@@ -502,11 +502,17 @@ isdn_MOD_INC_USE_COUNT(void)
}
void
-isdn_MOD_DEC_USE_COUNT(void)
+isdn_MOD_INC_USE_COUNT(void)
+{
+ MOD_INC_USE_COUNT;
+ isdn_lock_drivers();
+}
+
+void
+isdn_unlock_drivers(void)
{
int i;
- MOD_DEC_USE_COUNT;
for (i = 0; i < dev->drivers; i++)
if (dev->drv[i]->locks > 0) {
isdn_ctrl cmd;
@@ -519,6 +525,13 @@ isdn_MOD_DEC_USE_COUNT(void)
}
}
+void
+isdn_MOD_DEC_USE_COUNT(void)
+{
+ MOD_DEC_USE_COUNT;
+ isdn_unlock_drivers();
+}
+
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
void
isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
@@ -1976,8 +1989,6 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
/*
* Open the device code.
- * MOD_INC_USE_COUNT make sure that the driver memory is not freed
- * while the device is in use.
*/
static int
isdn_open(struct inode *ino, struct file *filep)
@@ -1990,7 +2001,6 @@ isdn_open(struct inode *ino, struct file *filep)
infostruct *p;
if ((p = (infostruct *) kmalloc(sizeof(infostruct), GFP_KERNEL))) {
- MOD_INC_USE_COUNT;
p->next = (char *) dev->infochain;
p->private = (char *) &(filep->private_data);
dev->infochain = p;
@@ -2011,21 +2021,21 @@ isdn_open(struct inode *ino, struct file *filep)
return -ENODEV;
if (!(dev->drv[drvidx]->online & (1 << chidx)))
return -ENODEV;
- isdn_MOD_INC_USE_COUNT();
+ isdn_lock_drivers();
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
if (drvidx < 0)
return -ENODEV;
- isdn_MOD_INC_USE_COUNT();
+ isdn_lock_drivers();
return 0;
}
#ifdef CONFIG_ISDN_PPP
if (minor <= ISDN_MINOR_PPPMAX) {
int ret;
if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
- isdn_MOD_INC_USE_COUNT();
+ isdn_lock_drivers();
return ret;
}
#endif
@@ -2037,11 +2047,11 @@ isdn_close(struct inode *ino, struct file *filep)
{
uint minor = MINOR(ino->i_rdev);
+ lock_kernel();
if (minor == ISDN_MINOR_STATUS) {
infostruct *p = dev->infochain;
infostruct *q = NULL;
- MOD_DEC_USE_COUNT;
while (p) {
if (p->private == (char *) &(filep->private_data)) {
if (q)
@@ -2049,31 +2059,38 @@ isdn_close(struct inode *ino, struct file *filep)
else
dev->infochain = (infostruct *) (p->next);
kfree(p);
+ unlock_kernel();
return 0;
}
q = p;
p = (infostruct *) (p->next);
}
printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+ unlock_kernel();
return 0;
}
- isdn_MOD_DEC_USE_COUNT();
- if (minor < ISDN_MINOR_CTRL)
+ isdn_unlock_drivers();
+ if (minor < ISDN_MINOR_CTRL) {
+ unlock_kernel();
return 0;
+ }
if (minor <= ISDN_MINOR_CTRLMAX) {
if (dev->profd == current)
dev->profd = NULL;
+ unlock_kernel();
return 0;
}
#ifdef CONFIG_ISDN_PPP
if (minor <= ISDN_MINOR_PPPMAX)
isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
#endif
+ unlock_kernel();
return 0;
}
static struct file_operations isdn_fops =
{
+ owner: THIS_MODULE,
llseek: isdn_lseek,
read: isdn_read,
write: isdn_write,
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index ff6f18ee1..10421b00d 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -25,6 +25,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
@@ -516,6 +517,7 @@ static int adb_release(struct inode *inode, struct file *file)
struct adbdev_state *state = file->private_data;
unsigned long flags;
+ lock_kernel();
if (state) {
file->private_data = NULL;
spin_lock_irqsave(&state->lock, flags);
@@ -528,6 +530,7 @@ static int adb_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&state->lock, flags);
}
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 9ca4a9ae8..efec54db0 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -31,6 +31,7 @@
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/cuda.h>
+#include <linux/smp_lock.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -1539,6 +1540,7 @@ static int pmu_release(struct inode *inode, struct file *file)
struct pmu_private *pp = file->private_data;
unsigned long flags;
+ lock_kernel();
if (pp != 0) {
file->private_data = 0;
spin_lock_irqsave(&all_pvt_lock, flags);
@@ -1546,6 +1548,7 @@ static int pmu_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&all_pvt_lock, flags);
kfree(pp);
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/mtd/Config.in b/drivers/mtd/Config.in
index e2af3489a..5f7622572 100644
--- a/drivers/mtd/Config.in
+++ b/drivers/mtd/Config.in
@@ -1,59 +1,67 @@
+
+# $Id: Config.in,v 1.20 2000/07/13 12:40:46 scote1 Exp $
+
mainmenu_option next_comment
comment 'Memory Technology Devices (MTD)'
tristate 'Memory Technology Device (MTD) support' CONFIG_MTD
if [ "$CONFIG_MTD" != "n" ]; then
- dep_tristate 'M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD
- dep_tristate 'M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD
- dep_tristate 'M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD
- if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then
- define_bool CONFIG_MTD_DOCPROBE y
- else
- if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then
- define_bool CONFIG_MTD_DOCPROBE m
- else
- define_bool CONFIG_MTD_DOCPROBE n
- fi
- fi
- dep_tristate 'Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD
- dep_tristate 'Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD
- if [ "$CONFIG_MTD_PMC551" != "n" ]; then
- bool 'PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
- fi
- dep_tristate 'Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD
+ if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then
+ define_tristate CONFIG_MTD_DOCPROBE y
+ else
+ if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then
+ define_tristate CONFIG_MTD_DOCPROBE m
+ else
+ define_tristate CONFIG_MTD_DOCPROBE n
+ fi
+ fi
+ dep_tristate ' Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD
+ dep_tristate ' Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD
+ if [ "$CONFIG_MTD_PMC551" != "n" ]; then
+ bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
+ fi
+ dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD
+ if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then
+ int 'Device size in kB' CONFIG_MTDRAM_TOTAL_SIZE 4096
+ int 'Size of the erase sectors in kB' CONFIG_MTDRAM_ERASE_SIZE 128
+ fi
-mainmenu_option next_comment
comment 'MTD drivers for mapped chips'
+ dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD
+ dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI
+ dep_tristate ' CFI support for AMD/Fujitsu Standard Command Set chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI
- dep_tristate 'Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD
- dep_tristate 'CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_CFI
- define_bool CONFIG_MTD_JEDEC n
- define_bool CONFIG_MTD_RAM n
- define_bool CONFIG_MTD_ROM n
-mainmenu_option next_comment
-comment 'Drivers for chip mappings'
+# These will later become config-options
+define_bool CONFIG_MTD_JEDEC n
+define_bool CONFIG_MTD_RAM n
+define_bool CONFIG_MTD_ROM n
- dep_tristate 'Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI
- if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then
- hex ' Physical start location of flash chip mapping (0x8000000)' CONFIG_MTD_PHYSMAP_START 0x8000000
- hex ' Physical length of flash chip mapping (0x4000000)' CONFIG_MTD_PHYSMAP_LEN 0x4000000
- fi
- dep_tristate 'Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC
- dep_tristate 'Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI
- dep_tristate 'Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC
- dep_tristate 'Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI
- dep_tristate 'Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC
+ dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI
+ if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then
+ hex 'Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
+ hex 'Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+ fi
+
+comment 'Drivers for chip mappings'
+ dep_tristate ' Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC
+ dep_tristate ' Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI
+ dep_tristate ' Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC
+ dep_tristate ' Flash chip mapping on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI
+ dep_tristate ' Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI
+ dep_tristate ' Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC
-mainmenu_option next_comment
comment 'User modules and translation layers for MTD devices'
- dep_tristate 'Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD
- dep_tristate 'Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD
- dep_tristate 'FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD
- dep_tristate 'NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD
- if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then
- bool 'Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW
- fi
+ dep_tristate ' Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD
+ dep_tristate ' Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD
+ dep_tristate ' FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD
+ dep_tristate ' NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD
+ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then
+ bool ' Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW
+ fi
fi
endmenu
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 53a3906f8..6030b63b3 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,189 +1,110 @@
-# $Id: Makefile,v 1.20 2000/07/04 08:58:10 dwmw2 Exp $
-
-# Uncomment this to enable the DBG macro (see mtd.h)
-#CFLAGS+= -DZDBG
+#
+# Makefile for the memory technology device drivers.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now inherited from the
+# parent makes..
+#
+# $Id: Makefile,v 1.22 2000/07/14 08:10:52 dwmw2 Exp $
ifndef CONFIG_MTD
+
# We're being invoked outside a normal kernel build. Fake it
EXTRA_CFLAGS= -I$(shell pwd)/../include
-HWDRIVERS = slram.o docprobe.o doc1000.o nora.o physmap.o rpxlite.o vmax301.o octagon-5066.o pmc551.o mtdram.o
-USERDRIVERS = ftl.o nftl.o mtdblock.o mtdchar.o
-MIX_OBJS = mtdcore.o mapped.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o
-MI_OBJS = $(HWDRIVERS) $(USERDRIVERS)
-CFLAGS_nftl.o := -DCONFIG_NFTL_RW
-else
-
-O_TARGET := mtdlink.o
-SUB_DIRS :=
-ALL_SUB_DIRS :=
-MOD_LIST_NAME := MTD_MODULES
-
-
-ifeq ($(CONFIG_MTD),y)
- OX_OBJS += mtdcore.o mapped.o
-else
- ifeq ($(CONFIG_MTD),m)
- MX_OBJS += mtdcore.o mapped.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_NORA),y)
- O_OBJS += nora.o
-else
- ifeq ($(CONFIG_MTD_NORA),m)
- M_OBJS += nora.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_RPXLITE),y)
- O_OBJS += rpxlite.o
-else
- ifeq ($(CONFIG_MTD_RPXLITE),m)
- M_OBJS += rpxlite.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_PHYSMAP),y)
- O_OBJS += physmap.o
-else
- ifeq ($(CONFIG_MTD_PHYSMAP),m)
- M_OBJS += physmap.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_CFI),y)
- OX_OBJS += cfi_probe.o
-else
- ifeq ($(CONFIG_MTD_CFI),m)
- MX_OBJS += cfi_probe.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_CFI_INTELEXT),y)
- OX_OBJS += cfi_cmdset_0001.o
-else
- ifeq ($(CONFIG_MTD_CFI_INTELEXT),m)
- MX_OBJS += cfi_cmdset_0001.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_DOC1000),y)
- O_OBJS += doc1000.o
-else
- ifeq ($(CONFIG_MTD_DOC1000),m)
- M_OBJS += doc1000.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_DOC2000),y)
- OX_OBJS += doc2000.o
-else
- ifeq ($(CONFIG_MTD_DOC2000),m)
- MX_OBJS += doc2000.o
- endif
-endif
+MIX_OBJS = mtdcore.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o \
+ map_ram.o map_rom.o cfi_cmdset_0002.o
+MI_OBJS = doc1000.o docprobe.o slram.o pmc551.o mtdram.o physmap.o \
+ nora.o octagon-5066.o pnc2000.o rpxlite.o vmax301.o mtdchar.o \
+ mtdblock.o ftl.o nftl.o
-ifeq ($(CONFIG_MTD_DOC2001),y)
- OX_OBJS += doc2001.o
-else
- ifeq ($(CONFIG_MTD_DOC2001),m)
- MX_OBJS += doc2001.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_DOCPROBE),y)
- O_OBJS += docprobe.o
-else
- ifeq ($(CONFIG_MTD_DOCPROBE),m)
- M_OBJS += docprobe.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_SLRAM),y)
- O_OBJS += slram.o
-else
- ifeq ($(CONFIG_MTD_SLRAM),m)
- M_OBJS += slram.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_OCTAGON),y)
- O_OBJS += octagon-5066.o
-else
- ifeq ($(CONFIG_MTD_OCTAGON),m)
- M_OBJS += octagon-5066.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_PMC551),y)
- O_OBJS += pmc551.o
-else
- ifeq ($(CONFIG_MTD_PMC551),m)
- M_OBJS += pmc551.o
- endif
-endif
-
-ifeq ($(CONFIG_MTD_PMC551_BUGFIX),y)
- CFLAGS_pmc551.o += -DPMC551_DRAM_BUG
-endif
-
-ifeq ($(CONFIG_MTD_VMAX),y)
- O_OBJS += vmax301.o
-else
- ifeq ($(CONFIG_MTD_VMAX),m)
- M_OBJS += vmax301.o
- endif
-endif
+CFLAGS_nftl.o := -DCONFIG_NFTL_RW
+CFLAGS_mtdram.o := -DCONFIG_MTDRAM_TOTAL_SIZE=4096 -DCONFIG_MTDRAM_ERASE_SIZE=128
+CFLAGS_physmap.o := -DCONFIG_MTD_PHYSMAP_START=0x8000000 -DCONFIG_MTD_PHYSMAP_LEN=0x4000000
-ifeq ($(CONFIG_MTD_MIXMEM),y)
- O_OBJS += mixmem.o
-else
- ifeq ($(CONFIG_MTD_MIXMEM),m)
- M_OBJS += mixmem.o
- endif
-endif
+else
-ifeq ($(CONFIG_MTD_MTDRAM),y)
- O_OBJS += mtdram.o
-else
- ifeq ($(CONFIG_MTD_MTDRAM),m)
- M_OBJS += mtdram.o
- endif
-endif
+O_OBJS :=
+OX_OBJS :=
+M_OBJS :=
+MX_OBJS :=
-ifeq ($(CONFIG_FTL),y)
- O_OBJS += ftl.o
-else
- ifeq ($(CONFIG_FTL),m)
- M_OBJS += ftl.o
- endif
-endif
+# Object file lists.
-ifeq ($(CONFIG_NFTL),y)
- O_OBJS += nftl.o
-else
- ifeq ($(CONFIG_NFTL),m)
- M_OBJS += nftl.o
- endif
-endif
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
-ifeq ($(CONFIG_MTD_BLOCK),y)
- O_OBJS += mtdblock.o
-else
- ifeq ($(CONFIG_MTD_BLOCK),m)
- M_OBJS += mtdblock.o
- endif
-endif
+O_TARGET := mtdlink.o
+SUB_DIRS :=
+ALL_SUB_DIRS :=
+MOD_SUB_DIRS :=
+MOD_LIST_NAME := MTD_MODULES
+export-objs := mtdcore.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o cfi_cmdset_0002.o
+list-multi :=
+
+# MTD devices
+obj-$(CONFIG_MTD) += mtdcore.o
+obj-$(CONFIG_MTD_DOC1000) += doc1000.o
+obj-$(CONFIG_MTD_DOC2000) += doc2000.o
+obj-$(CONFIG_MTD_DOC2001) += doc2001.o
+obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
+obj-$(CONFIG_MTD_SLRAM) += slram.o
+obj-$(CONFIG_MTD_PMC551) += pmc551.o
+obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
+
+# Chip drivers
+obj-$(CONFIG_MTD_JEDEC) += jedec.o
+obj-$(CONFIG_MTD_RAM) += map_ram.o
+obj-$(CONFIG_MTD_ROM) += map_rom.o
+obj-$(CONFIG_MTD_CFI) += cfi_probe.o
+obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
+obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
+
+# Chip mappings
+obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
+obj-$(CONFIG_MTD_MIXMEM) += mixmem.o
+obj-$(CONFIG_MTD_NORA) += nora.o
+obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
+obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
+obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
+obj-$(CONFIG_MTD_VMAX) += vmax301.o
+
+# Users
+obj-$(CONFIG_MTD_CHAR) += mtdchar.o
+obj-$(CONFIG_MTD_BLOCK) += mtdblock.o
+obj-$(CONFIG_FTL) += ftl.o
+obj-$(CONFIG_NFTL) += nftl.o
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+
+multi-y := $(filter $(list-multi), $(obj-y))
+multi-m := $(filter $(list-multi), $(obj-m))
+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m := $(filter-out $(obj-y), $(obj-m))
+int-m := $(filter-out $(int-y), $(int-m))
+
+# Take multi-part drivers out of obj-y and put components in.
+
+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-ifeq ($(CONFIG_MTD_CHAR),y)
- O_OBJS += mtdchar.o
-else
- ifeq ($(CONFIG_MTD_CHAR),m)
- M_OBJS += mtdchar.o
- endif
-endif
endif
diff --git a/drivers/mtd/cfi_cmdset_0001.c b/drivers/mtd/cfi_cmdset_0001.c
index 713d8ab05..8c26d43b4 100644
--- a/drivers/mtd/cfi_cmdset_0001.c
+++ b/drivers/mtd/cfi_cmdset_0001.c
@@ -4,7 +4,7 @@
*
* (C) 2000 Red Hat. GPL'd
*
- * $Id: cfi_cmdset_0001.c,v 1.20 2000/07/04 07:36:43 dwmw2 Exp $
+ * $Id: cfi_cmdset_0001.c,v 1.21 2000/07/13 10:36:14 dwmw2 Exp $
*/
#include <linux/module.h>
@@ -455,13 +455,9 @@ static inline int do_write_1_by_16_oneword(struct map_info *map, struct flchip *
chip->word_write_time--;
if (!chip->word_write_time)
chip->word_write_time++;
- else
- printk("decreasing word_write_time to %d µs\n", chip->word_write_time);
}
- if (z > 100) {
+ if (z > 1)
chip->word_write_time++;
- printk("increasing word_write_time to %d µs\n", chip->word_write_time);
- }
/* Done and happy. */
chip->state = FL_STATUS;
diff --git a/drivers/mtd/cfi_cmdset_0002.c b/drivers/mtd/cfi_cmdset_0002.c
new file mode 100644
index 000000000..d2736c024
--- /dev/null
+++ b/drivers/mtd/cfi_cmdset_0002.c
@@ -0,0 +1,610 @@
+/*
+ * Common Flash Interface support:
+ * AMD & Fujitsu Extended Vendor Command Set (ID 0x0002)
+ *
+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
+ *
+ * This code is GPL
+ *
+ * $Id: cfi_cmdset_0002.c,v 1.1 2000/07/11 12:32:09 dwmw2 Exp $
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+
+#if LINUX_VERSION_CODE < 0x20300
+#define set_current_state(x) current->state = (x);
+#endif
+
+static int cfi_amdext_read_2_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int cfi_amdext_write_2_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+static int cfi_amdext_erase_2_by_16 (struct mtd_info *, struct erase_info *);
+static void cfi_amdext_sync (struct mtd_info *);
+static int cfi_amdext_suspend (struct mtd_info *);
+static void cfi_amdext_resume (struct mtd_info *);
+
+static void cfi_amdext_destroy(struct mtd_info *);
+
+void cfi_cmdset_0002(struct map_info *, int, unsigned long);
+EXPORT_SYMBOL(cfi_cmdset_0002);
+
+struct mtd_info *cfi_amdext_setup (struct map_info *);
+
+void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+// struct cfi_pri_intelext *extp;
+
+ __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR;
+
+ printk(" Amd/Fujitsu Extended Query Table at 0x%4.4X\n", adr);
+
+
+ /* If there was an old setup function, decrease its use count */
+ if (cfi->cmdset_setup)
+ put_module_symbol((unsigned long)cfi->cmdset_setup);
+ if (cfi->cmdset_priv)
+ kfree(cfi->cmdset_priv);
+
+ for (i=0; i< cfi->numchips; i++) {
+ cfi->chips[i].word_write_time = 128;
+ cfi->chips[i].buffer_write_time = 128;
+ cfi->chips[i].erase_time = 1024;
+ }
+
+
+ cfi->cmdset_setup = cfi_amdext_setup;
+// cfi->cmdset_priv = extp;
+ MOD_INC_USE_COUNT; /* So the setup function is still there
+ * by the time it's called */
+
+ return;
+}
+
+struct mtd_info *cfi_amdext_setup(struct map_info *map)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ struct mtd_info *mtd;
+
+ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ printk("number of CFI chips: %d\n", cfi->numchips);
+
+ if (!mtd) {
+ printk("Failed to allocate memory for MTD device\n");
+ kfree(cfi->cmdset_priv);
+ return NULL;
+ }
+
+ memset(mtd, 0, sizeof(*mtd));
+ mtd->priv = map;
+ mtd->type = MTD_NORFLASH;
+ mtd->erasesize = 0x20000; /* FIXME */
+ /* Also select the correct geometry setup too */
+ mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips * cfi->interleave;
+ mtd->erase = cfi_amdext_erase_2_by_16;
+ mtd->read = cfi_amdext_read_2_by_16;
+ mtd->write = cfi_amdext_write_2_by_16;
+ mtd->sync = cfi_amdext_sync;
+ mtd->suspend = cfi_amdext_suspend;
+ mtd->resume = cfi_amdext_resume;
+ mtd->flags = MTD_CAP_NORFLASH;
+ map->fldrv_destroy = cfi_amdext_destroy;
+ mtd->name = map->name;
+ return mtd;
+}
+
+static inline int do_read_2_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long timeo = jiffies + HZ;
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+printk("Waiting for chip to read, status = %d\n", chip->state);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ adr += chip->start;
+
+// map->write32(map, cpu_to_le32(0x00F000F0), adr);
+
+ chip->state = FL_READY;
+
+ map->copy_from(map, buf, adr, len);
+
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+
+ return 0;
+}
+
+static int cfi_amdext_read_2_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long ofs;
+ int chipnum;
+ int ret = 0;
+
+ /* ofs: offset within the first chip that the first read should start */
+
+ chipnum = (from >> cfi->chipshift);
+ chipnum /= (cfi->interleave);
+ ofs = from - (chipnum << cfi->chipshift) * (cfi->interleave);
+
+ *retlen = 0;
+
+ while (len) {
+ unsigned long thislen;
+
+ if (chipnum >= cfi->numchips)
+ break;
+
+ if (((len + ofs -1) >> cfi->chipshift) / (cfi->interleave))
+ thislen = (1<<cfi->chipshift) * (cfi->interleave) - ofs;
+ else
+ thislen = len;
+
+ ret = do_read_2_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+ if (ret)
+ break;
+
+ *retlen += thislen;
+ len -= thislen;
+ buf += thislen;
+
+ ofs = 0;
+ chipnum++;
+ }
+ return ret;
+}
+
+static inline int do_write_2_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum)
+{
+ unsigned long timeo = jiffies + HZ;
+ unsigned int Last[4];
+ unsigned long Count = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+printk("Waiting for chip to write, status = %d\n", chip->state);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+printk("Wake up to write:\n");
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ chip->state = FL_WRITING;
+
+ adr += chip->start;
+
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00A000A0), 0x555 *4);
+ map->write32(map, cpu_to_le32(datum), adr);
+
+ spin_unlock_bh(chip->mutex);
+ udelay(chip->word_write_time);
+ spin_lock_bh(chip->mutex);
+
+ Last[0] = map->read32(map, adr);
+ Last[1] = map->read32(map, adr);
+ Last[2] = map->read32(map, adr);
+
+ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
+ udelay(10);
+
+ Last[Count % 4] = map->read32(map, adr);
+ }
+
+ if (Last[(Count - 1) % 4] != datum){
+ map->write32(map, cpu_to_le32(0x00F000F0), adr);
+ ret = -EIO;
+ }
+
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+
+ return ret;
+}
+
+
+static int cfi_amdext_write_2_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int ret = 0;
+ int chipnum;
+ unsigned long ofs;
+
+ *retlen = 0;
+
+ chipnum = (to >> cfi->chipshift);
+ chipnum /= cfi->interleave;
+ ofs = to - (chipnum << cfi->chipshift) * cfi->interleave;
+
+ while(len > 3) {
+
+ ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
+ ofs, *(__u32 *)buf);
+ if (ret)
+ return ret;
+
+ ofs += 4;
+ buf += 4;
+ (*retlen) += 4;
+ len -= 4;
+
+ if ((ofs >> cfi->chipshift) / cfi->interleave) {
+ chipnum ++;
+ ofs = 0;
+ if (chipnum == cfi->numchips)
+ return 0;
+ }
+ }
+
+ if (len) {
+ unsigned int tmp;
+
+ /* Final byte to write */
+#if defined(__LITTLE_ENDIAN)
+ tmp = map->read32(map, ofs);
+
+ tmp = 0xffffffff >> (len*8);
+ tmp = tmp << (len*8);
+
+ tmp |= *(__u32 *)(buf);
+
+ ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
+ ofs, tmp);
+
+#elif defined(__BIG_ENDIAN)
+#error not support big endian yet
+#else
+#error define a sensible endianness
+#endif
+
+ if (ret)
+ return ret;
+
+ (*retlen)+=len;
+ }
+
+ return 0;
+}
+
+
+static inline int do_erase_2_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
+{
+ unsigned int status;
+ unsigned long timeo = jiffies + HZ;
+ DECLARE_WAITQUEUE(wait, current);
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ chip->state = FL_ERASING;
+
+ adr += chip->start;
+
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00800080), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00300030), adr);
+
+
+ timeo = jiffies + (HZ*20);
+
+ spin_unlock_bh(chip->mutex);
+ schedule_timeout(HZ);
+ spin_lock_bh(chip->mutex);
+
+ /* FIXME. Use a timer to check this, and return immediately. */
+ /* Once the state machine's known to be working I'll do that */
+
+ while ( ( (status = le32_to_cpu(map->read32(map, 0x00))) & 0x80808080 ) != 0x80808080 ) {
+ static int z=0;
+
+ if (chip->state != FL_ERASING) {
+ /* Someone's suspended the erase. Sleep */
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+ printk("erase suspended. Sleeping\n");
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if (signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + (HZ*2); /* FIXME */
+ spin_lock_bh(chip->mutex);
+ continue;
+ }
+
+ /* OK Still waiting */
+ if (time_after(jiffies, timeo)) {
+ chip->state = FL_READY;
+ spin_unlock_bh(chip->mutex);
+ printk("waiting for erase to complete timed out.");
+ return -EIO;
+ }
+
+ /* Latency issues. Drop the lock, wait a while and retry */
+ spin_unlock_bh(chip->mutex);
+
+ z++;
+ if ( 0 && !(z % 100 ))
+ printk("chip not ready yet after erase. looping\n");
+
+ udelay(1);
+
+ spin_lock_bh(chip->mutex);
+ continue;
+ }
+
+ /* Done and happy. */
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+ printk("erase ret OK\n");
+ return 0;
+}
+
+static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long adr, len;
+ int chipnum, ret = 0;
+
+//printk("erase : 0x%x 0x%x 0x%x\n", instr->addr, instr->len, mtd->size);
+
+ if (instr->addr & (mtd->erasesize - 1))
+ return -EINVAL;
+
+ if (instr->len & (mtd->erasesize -1))
+ return -EINVAL;
+
+ if ((instr->len + instr->addr) > mtd->size)
+ return -EINVAL;
+
+ chipnum = instr->addr >> cfi->chipshift;
+ chipnum /= cfi->interleave;
+ adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave);
+ len = instr->len;
+
+printk("erase : 0x%x 0x%x 0x%x\n", adr, len, chipnum, mtd->size);
+
+ while(len) {
+//printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift);
+ ret = do_erase_2_by_16_oneblock(map, &cfi->chips[chipnum], adr);
+
+ if (ret)
+ return ret;
+
+ adr += mtd->erasesize;
+ len -= mtd->erasesize;
+
+ if ((adr >> cfi->chipshift) / (cfi->interleave)) {
+ adr = 0;
+ chipnum++;
+
+ if (chipnum >= cfi->numchips)
+ break;
+ }
+ }
+
+ if (instr->callback)
+ instr->callback(instr);
+
+ return 0;
+}
+
+
+
+static void cfi_amdext_sync (struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+ int ret = 0;
+ DECLARE_WAITQUEUE(wait, current);
+printk("sync\n");
+
+ for (i=0; !ret && i<cfi->numchips; i++) {
+ chip = &cfi->chips[i];
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ switch(chip->state) {
+ case FL_READY:
+ case FL_STATUS:
+ case FL_CFI_QUERY:
+ case FL_JEDEC_QUERY:
+ chip->oldstate = chip->state;
+ chip->state = FL_SYNCING;
+ /* No need to wake_up() on this state change -
+ * as the whole point is that nobody can do anything
+ * with the chip now anyway.
+ */
+ spin_unlock_bh(chip->mutex);
+ break;
+
+ default:
+ /* Not an idle state */
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+ schedule();
+
+ goto retry;
+ }
+ }
+
+ /* Unlock the chips again */
+
+ for (i--; i >=0; i--) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_SYNCING) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ spin_unlock_bh(chip->mutex);
+ }
+printk("sync end\n");
+}
+
+
+static int cfi_amdext_suspend(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+ int ret = 0;
+//printk("suspend\n");
+
+ for (i=0; !ret && i<cfi->numchips; i++) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ switch(chip->state) {
+ case FL_READY:
+ case FL_STATUS:
+ case FL_CFI_QUERY:
+ case FL_JEDEC_QUERY:
+ chip->oldstate = chip->state;
+ chip->state = FL_PM_SUSPENDED;
+ /* No need to wake_up() on this state change -
+ * as the whole point is that nobody can do anything
+ * with the chip now anyway.
+ */
+ spin_unlock_bh(chip->mutex);
+ break;
+
+ default:
+ ret = -EAGAIN;
+ break;
+ }
+ }
+
+ /* Unlock the chips again */
+
+ for (i--; i >=0; i--) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_PM_SUSPENDED) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ spin_unlock_bh(chip->mutex);
+ }
+
+ return ret;
+}
+
+static void cfi_amdext_resume(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+//printk("resume\n");
+
+ for (i=0; i<cfi->numchips; i++) {
+
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_PM_SUSPENDED) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ else
+ printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
+
+ spin_unlock_bh(chip->mutex);
+ }
+}
+
+static void cfi_amdext_destroy(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ kfree(cfi->cmdset_priv);
+ kfree(cfi);
+}
+
diff --git a/drivers/mtd/doc2000.c b/drivers/mtd/doc2000.c
index 8385648d1..eeb49a4eb 100644
--- a/drivers/mtd/doc2000.c
+++ b/drivers/mtd/doc2000.c
@@ -2,7 +2,7 @@
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.c,v 1.23 2000/07/03 10:01:38 dwmw2 Exp $ */
+/* $Id: doc2000.c,v 1.24 2000/07/13 10:03:31 dwmw2 Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -36,7 +36,7 @@ static struct mtd_info *doc2klist = NULL;
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-int _DoC_WaitReady (unsigned long docptr)
+static int _DoC_WaitReady (unsigned long docptr)
{
//long c=-1;
short c=-1;
@@ -148,7 +148,7 @@ static inline int DoC_SelectFloor(unsigned long docptr, int floor)
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
int mfr, id, chipshift=0;
char *mfrname=NULL, *idname=NULL;
@@ -302,7 +302,7 @@ int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-void DoC_ScanChips(struct DiskOnChip *this)
+static void DoC_ScanChips(struct DiskOnChip *this)
{
int floor, chip;
int numchips[MAX_FLOORS];
diff --git a/drivers/mtd/doc2001.c b/drivers/mtd/doc2001.c
index 9f63b0b22..26a107722 100644
--- a/drivers/mtd/doc2001.c
+++ b/drivers/mtd/doc2001.c
@@ -1,8 +1,7 @@
-
/* Linux driver for Disk-On-Chip Millennium */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2001.c,v 1.4 2000/07/03 10:01:38 dwmw2 Exp $ */
+/* $Id: doc2001.c,v 1.7 2000/07/13 10:41:39 dwmw2 Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -21,305 +20,238 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/doc2000.h>
-
-
-//#define PRERELEASE
-#if 0
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf);
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf);
+static struct {
+ char * name;
+ int manufacture_id;
+ int model_id;
+ int chipshift;
+} nand_flash_ids[] = {
+ {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21},
+ {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22},
+ {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24},
+ {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25},
+ {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22},
+ {"Toshiba TC58V64DC", NAND_MFR_TOSHIBA, 0xe6, 23},
+ {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21},
+ {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21},
+ {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24},
+ {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25},
+ {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22},
+ {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23},
+ {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21},
+ {NULL,}
+};
+
+static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
+static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eecbuf);
+static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf);
static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
-#endif
static struct mtd_info *docmillist = NULL;
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-
-int _DoC_WaitReady (unsigned long docptr)
+static void DoC_Delay(unsigned long docptr, unsigned short cycles)
{
- //long c=-1;
- short c=-1;
+ volatile char dummy;
+ int i;
- DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n");
+ for (i = 0; i < cycles; i++)
+ dummy = ReadDOC(docptr, NOP);
+}
+
+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
+static int _DoC_WaitReady(unsigned long docptr)
+{
+ unsigned short c = 0xffff;
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
- if (c == 0)
- DEBUG(2, "_DoC_WaitReady timed out.\n");
-
- return (c==0);
+ return (c == 0);
}
-static inline int DoC_WaitReady(unsigned long docptr)
+static __inline__ int DoC_WaitReady(unsigned long docptr)
{
/* This is inline, to optimise the common case, where it's ready instantly */
- volatile char dummy;
int ret = 0;
- /* Out-of-line routine to wait for chip response */
- /* TPW: Add 4 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
-
+ /* 4 read form NOP register should be issued in prior to the read from CDSNControl
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(docptr, 4);
+
if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
- ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */
-
- /* TPW: Add 2 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
+ /* Call the out-of-line routine to wait */
+ ret = _DoC_WaitReady(docptr);
+
+ /* issue 2 read from NOP register after reading from CDSNControl register
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(docptr, 2);
return ret;
}
-
-/* DoC_Command: Send a flash command to the flash chip */
-
-static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags)
+/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to bypass
+ the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
+ writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+static __inline__ void DoC_Command(unsigned long docptr, unsigned char command,
+ unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
/* Send the command */
- WriteDOC(command, docptr, 2k_CDSN_IO);
+ WriteDOC(command, docptr, CDSNSlowIO);
+ WriteDOC(command, docptr, Mil_CDSN_IO);
/* Lower the CLE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
-
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
}
-/* DoC_Address: Set the current address for the flash chip */
-
-static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
+/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to bypass
+ the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
+ writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+static __inline__ void DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
unsigned char xtraflags1, unsigned char xtraflags2)
{
/* Assert the ALE (Address Latch Enable line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
/* Send the address */
- /* Three cases:
- numbytes == 1: Send single byte, bits 0-7.
- numbytes == 2: Send bits 9-16 followed by 17-23
- numbytes == 3: Send 0-7, 9-16, then 17-23
- */
- if (numbytes != 2)
- WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO);
-
- if (numbytes != 1) {
- WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO);
- WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO);
- }
+ switch (numbytes)
+ {
+ case 1:
+ /* Send single byte, bits 0-7. */
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ case 2:
+ /* Send bits 9-16 followed by 17-23 */
+ WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ case 3:
+ /* Send 0-7, 9-16, then 17-23 */
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ default:
+ return;
+ }
+
/* Lower the ALE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
-
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
}
/* DoC_SelectChip: Select a given flash chip within the current floor */
-
-static inline int DoC_SelectChip(unsigned long docptr, int chip)
+static int DoC_SelectChip(unsigned long docptr, int chip)
{
/* Select the individual flash chip requested */
- WriteDOC( chip, docptr, CDSNDeviceSelect);
-
+ WriteDOC(chip, docptr, CDSNDeviceSelect);
+ DoC_Delay(docptr, 4);
+
/* Wait for it to be ready */
return DoC_WaitReady(docptr);
}
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-
-static inline int DoC_SelectFloor(unsigned long docptr, int floor)
+static int DoC_SelectFloor(unsigned long docptr, int floor)
{
/* Select the floor (bank) of chips required */
- WriteDOC( floor, docptr, FloorSelect);
+ WriteDOC(floor, docptr, FloorSelect);
/* Wait for the chip to be ready */
return DoC_WaitReady(docptr);
}
-
-/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
- int mfr, id, chipshift=0;
- char *mfrname=NULL, *idname=NULL;
+ int mfr, id, i;
+ volatile char dummy;
- /* Page in the required floor/chip */
+ /* Page in the required floor/chip
+ FIXME: is this supported by Millennium ?? */
DoC_SelectFloor(doc->virtadr, floor);
DoC_SelectChip(doc->virtadr, chip);
- /* Reset the chip */
- if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) {
- DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip);
- return 0;
- }
-
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
+ DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(doc->virtadr);
+
/* Read the NAND chip ID: 1. Send ReadID command */
- if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) {
- DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip);
- return 0;
- }
+ DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP);
+
+ /* Read the NAND chip ID: 2. Send address byte zero */
+ DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00);
+
+ /* Read the manufacturer and device id codes of the flash device through
+ CDSN Slow IO register see Software Requirement 11.4 item 5.*/
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc->virtadr, 2);
+ mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO);
+
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc->virtadr, 2);
+ id = ReadDOC(doc->virtadr, Mil_CDSN_IO);
- /* Read the NAND chip ID: 2. Send address byte zero
- */
- DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0);
-
- /* Read the manufacturer and device id codes from the device */
- mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO);
- id = ReadDOC(doc->virtadr, 2k_CDSN_IO);
-
/* No response - return failure */
if (mfr == 0xff || mfr == 0)
return 0;
-
- /* Check it's the same as the first chip we identified.
- * M-Systems say that any given DiskOnChip device should only
- * contain _one_ type of flash part, although that's not a
- * hardware restriction. */
- if (doc->mfr) {
- if (doc->mfr == mfr && doc->id == id)
- return 1; /* This is another the same the first */
- else
- printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n",
- floor, chip);
- }
-
- /* Print (and store if first time) the manufacturer and ID codes. */
-
- switch(mfr) {
- case NAND_MFR_TOSHIBA: /* Toshiba */
- mfrname = "Toshiba";
-
- switch(id) {
- case 0x64:
- idname = "TC5816BDC";
- chipshift = 21;
- break;
-
- case 0x6b:
- idname = "TC5832DC";
- chipshift = 22;
- break;
-
- case 0x73:
- idname = "TH58V128DC";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "TC58256FT/DC";
- chipshift = 25;
- break;
-
- case 0xe5:
- idname = "TC58V32DC";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "TC58V64DC";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "TC58V16BDC";
- chipshift = 21;
- break;
- }
- break; /* End of Toshiba parts */
-
- case NAND_MFR_SAMSUNG: /* Samsung */
- mfrname = "Samsung";
-
- switch(id) {
- case 0x64:
- idname = "KM29N16000";
- chipshift = 21;
-
- case 0x73:
- idname = "KM29U128T";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "KM29U256T";
- chipshift = 25;
- break;
- case 0xe3:
- idname = "KM29W32000";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "KM29U64000";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "KM29W16000";
- chipshift = 21;
- break;
- }
- break; /* End of Samsung parts */
- }
-
- /* If we've identified it fully, print the full names */
- if (idname) {
-#ifdef PRERELEASE
- DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n",
- mfr,id,mfrname,idname);
-#endif
- /* If this is the first chip, store the id codes */
- if (!doc->mfr) {
+ /* FIXME: to deal with mulit-flash on multi-Millennium case more carefully */
+ for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ if (mfr == nand_flash_ids[i].manufacture_id &&
+ id == nand_flash_ids[i].model_id) {
+ printk(KERN_INFO "Flash chip found: Manufacture ID: %2.2X, "
+ "Chip ID: %2.2X (%s)\n",
+ mfr, id, nand_flash_ids[i].name);
doc->mfr = mfr;
doc->id = id;
- doc->chipshift = chipshift;
- return 1;
+ doc->chipshift = nand_flash_ids[i].chipshift;
+ break;
}
- return 0;
}
- /* We haven't fully identified the chip. Print as much as we know. */
- if (mfrname)
- printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname,
- id, mfr);
+ if (nand_flash_ids[i].name == NULL)
+ return 0;
else
- printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr);
-
- printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n");
- return 0;
+ return 1;
}
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-
-void DoC_ScanChips(struct DiskOnChip *this)
+static void DoC_ScanChips(struct DiskOnChip *this)
{
int floor, chip;
- int numchips[MAX_FLOORS];
- int ret = 1;
+ int numchips[MAX_FLOORS_MIL];
+ int ret;
this->numchips = 0;
this->mfr = 0;
this->id = 0;
/* For each floor, find the number of valid chips it contains */
- for (floor = 0 ; floor < MAX_FLOORS ; floor++) {
- ret = 1;
- numchips[floor]=0;
- for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) {
-
+ for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) {
+ numchips[floor] = 0;
+ for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) {
ret = DoC_IdentChip(this, floor, chip);
if (ret) {
numchips[floor]++;
@@ -327,7 +259,6 @@ void DoC_ScanChips(struct DiskOnChip *this)
}
}
}
-
/* If there are none at all that we recognise, bail */
if (!this->numchips) {
printk("No flash chips recognised.\n");
@@ -341,11 +272,9 @@ void DoC_ScanChips(struct DiskOnChip *this)
return;
}
- ret = 0;
-
/* Fill out the chip array with {floor, chipno} for each
* detected chip in the device. */
- for (floor = 0; floor < MAX_FLOORS; floor++) {
+ for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
for (chip = 0 ; chip < numchips[floor] ; chip++) {
this->chips[ret].floor = floor;
this->chips[ret].chip = chip;
@@ -357,14 +286,14 @@ void DoC_ScanChips(struct DiskOnChip *this)
/* Calculate and print the total size of the device */
this->totlen = this->numchips * (1 << this->chipshift);
-
- printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips ,
- this->totlen >> 20);
+ printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n",
+ this->numchips ,this->totlen >> 20);
}
static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
{
int tmp1, tmp2, retval;
+
if (doc1->physadr == doc2->physadr)
return 1;
@@ -392,21 +321,19 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
return retval;
}
-
void DoCMil_init(struct mtd_info *mtd)
{
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
struct DiskOnChip *old = NULL;
/* We must avoid being called twice for the same device. */
-
if (docmillist)
old = (struct DiskOnChip *)docmillist->priv;
while (old) {
if (DoCMil_is_alias(this, old)) {
- printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at 0x%lX - already configured\n",
- this->physadr);
+ printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at "
+ "0x%lX - already configured\n", this->physadr);
iounmap((void *)this->virtadr);
kfree(mtd);
return;
@@ -418,14 +345,9 @@ void DoCMil_init(struct mtd_info *mtd)
}
mtd->name = "DiskOnChip Millennium";
- printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",this->physadr);
+ printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",
+ this->physadr);
-#if 1
- printk("Unfortunately, we don't have support for the DiskOnChip Millennium yet.\n");
- iounmap((void *)this->virtadr);
- kfree(mtd);
- return;
-#else
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->size = 0;
@@ -445,8 +367,7 @@ void DoCMil_init(struct mtd_info *mtd)
mtd->sync = NULL;
this->totlen = 0;
- this->numchips = 0;
-
+ this->numchips = 0;
this->curfloor = -1;
this->curchip = -1;
@@ -463,78 +384,90 @@ void DoCMil_init(struct mtd_info *mtd)
add_mtd_device(mtd);
return;
}
-#endif
}
-
EXPORT_SYMBOL(DoCMil_init);
-#if 0
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+
+static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL);
}
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf)
+static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eccbuf)
{
+ int i;
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[from >> (this->chipshift)];
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
-
+
/* Don't allow a single read to cross a 512-byte block boundary */
- if (from + len > ( (from | 0x1ff) + 1))
+ if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
/* Find the chip which is to be used and select it */
- mychip = &this->chips[from >> (this->chipshift)];
-
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
-
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
if (eccbuf) {
- /* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN, docptr, ECCConf);
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_EN, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
+ /* issue the Read0 or Read1 command depend on which half of the page
+ we are accessing. Polling the Flash Ready bit after issue 3 bytes
+ address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO);
+ DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
+ DoC_WaitReady(docptr);
- for (di=0; di < len ; di++) {
- buf[di] = ReadDOC(docptr, 2k_CDSN_IO);
+ /* Read the data via the internal pipeline through CDSN IO register,
+ see Pipelined Read Operations 11.3 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < len-1; i++) {
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
}
+ buf[i] = ReadDOC(docptr, LastDataRead);
/* Let the caller know we completed it */
*retlen = len;
if (eccbuf) {
- /* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
- eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO);
+ /* FIXME: are we reading the ECC from the ECC logic of DOC or
+ the spare data space on the flash chip i.e. How do we
+ control the Spare Area Enable bit of the flash ?? */
+ /* Read the ECC data through the DiskOnChip ECC logic
+ see Reed-Solomon EDC/ECC 11.1 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < 5; i++) {
+ eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO);
}
-
+ eccbuf[i] = ReadDOC(docptr, LastDataRead);
+
/* Flush the pipeline */
- (void) ReadDOC(docptr, 2k_ECCStatus);
- (void) ReadDOC(docptr, 2k_ECCStatus);
-
+ dummy = ReadDOC(docptr, ECCConf);
+ dummy = ReadDOC(docptr, ECCConf);
+
/* Check the ECC Status */
- if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) {
+ if (ReadDOC(docptr, ECCConf) & 0x80) {
/* There was an ECC error */
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
@@ -548,41 +481,40 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *
#ifdef PSYCHO_DEBUG
else
printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4],
- eccbuf[5]);
+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
-
/* Reset the ECC engine */
WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
}
return 0;
}
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
static char as[6];
return doc_write_ecc(mtd, to, len, retlen, buf, as);
}
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf)
+static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf)
{
+ int i;
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0;
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[to >> (this->chipshift)];
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
-#if 0
+
+#if 0
/* Don't allow a single write to cross a 512-byte block boundary */
if (to + len > ( (to | 0x1ff) + 1))
len = ((to | 0x1ff) + 1) - to;
-
#else
/* Don't allow writes which aren't exactly one block */
if (to & 0x1ff || len != 0x200)
@@ -590,8 +522,6 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r
#endif
/* Find the chip which is to be used and select it */
- mychip = &this->chips[to >> (this->chipshift)];
-
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -599,61 +529,75 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r
else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
-
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
- /* Set device to main plane of flash */
+
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(docptr);
+ /* Set device to main plane of flash */
DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP);
if (eccbuf) {
- /* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO);
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
+ DoC_Address(docptr, 3, to, 0x00, 0x00);
- for (di=0; di < len ; di++) {
- WriteDOC(buf[di], docptr, 2k_CDSN_IO);
+ /* Write the data via the internal pipeline through CDSN IO register,
+ see Pipelined Write Operations 11.2 */
+ for (i = 0; i < len; i++) {
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO);
}
-
+ WriteDOC(0x00, docptr, WritePipeTerm);
if (eccbuf) {
- WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl );
-
-#if 1
- /* eduardp@m-sys.com says this shouldn't be necessary,
- * but it doesn't actually work without it, so I've
- * left it in for now. dwmw2.
- */
-
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
-#endif
+ /* Write ECC data to flash, the ECC info is generated by the DiskOnChip DECC logic
+ see Reed-Solomon EDC/ECC 11.1 */
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+
/* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
- eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
+ for (i = 0; i < 6; i++) {
+ eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
}
+
+ /* Write the ECC data to flash */
+ for (i = 0; i < 6; i++) {
+ WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO);
+ }
+ WriteDOC(0x00, docptr, WritePipeTerm);
+
#ifdef PSYCHO_DEBUG
printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long) to, eccbuf[0], eccbuf[1], eccbuf[2],
- eccbuf[3], eccbuf[4], eccbuf[5] );
+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
+
/* Reset the ECC engine */
WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
}
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
-
- DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
- /* There's an implicit DoC_WaitReady() in DoC_Command */
+ /* Commit the Page Program command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
+ DoC_WaitReady(docptr);
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming flash\n");
/* Error in programming */
*retlen = 0;
@@ -666,19 +610,18 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r
return 0;
}
-
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, u_char *buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ volatile char dummy;
int i;
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+
+ /* FIXME: should we restrict the access between 512 to 527 ?? */
+
+ /* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -688,35 +631,43 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *re
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
-
-
+
+ /* FIXME: should we disable ECC engine in this way ?? */
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
+
+ /* issue the Read2 command to read the Spare Data Area.
+ Polling the Flash Ready bit after issue 3 bytes address in
+ Sequence Read Mode, see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0);
-
- for (i=0; i<len; i++)
- buf[i] = ReadDOC(docptr, 2k_CDSN_IO);
-
+ DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00);
+ DoC_WaitReady(docptr);
+
+ /* Read the data out via the internal pipeline through CDSN IO register,
+ see Pipelined Read Operations 11.3 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < len-1; i++) {
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
+ }
+ buf[i] = ReadDOC(docptr, LastDataRead);
+
*retlen = len;
- return 0;
+ return 0;
}
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
int i;
- unsigned long docptr;
- struct Nand *mychip;
-
- // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
- // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
+ volatile char dummy;
+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
- if (this->curfloor != mychip->floor) {
+ /* Find the chip which is to be used and select it */
+ if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
}
@@ -725,49 +676,63 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *r
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
- DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, ofs, 0, 0);
-
- for (i=0; i<len; i++)
- WriteDOC(buf[i], docptr, 2k_CDSN_IO);
+ /* FIXME: should we disable ECC engine in this way ?? */
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
- DoC_Command(docptr, NAND_CMD_STATUS, 0);
- /* DoC_WaitReady() is implicit in DoC_Command */
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
+ DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(docptr);
+ /* issue the Read2 command to read the Spare Data Area. */
+ DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
+ DoC_Address(docptr, 3, ofs, 0x00, 0x00);
+
+ /* Write the data via the internal pipeline through CDSN IO register,
+ see Pipelined Write Operations 11.2 */
+ for (i = 0; i < len; i++)
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO);
+ WriteDOC(0x00, docptr, WritePipeTerm);
+
+ /* Commit the Page Program command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
+ DoC_WaitReady(docptr);
+
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming oob data\n");
- /* There was an error */
*retlen = 0;
return -EIO;
}
*retlen = len;
- return 0;
+ return 0;
}
-
int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
{
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
unsigned long ofs = instr->addr;
unsigned long len = instr->len;
- unsigned long docptr;
- struct Nand *mychip;
-
- if(len != mtd->erasesize)
- printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize);
-
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
+ if (len != mtd->erasesize)
+ printk(KERN_WARNING "Erase not right size (%lx != %lx)n",
+ len, mtd->erasesize);
+
+ /* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -780,32 +745,35 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_PENDING;
- DoC_Command(docptr, NAND_CMD_ERASE1, 0);
- DoC_Address(docptr, 2, ofs, 0, 0);
- DoC_Command(docptr, NAND_CMD_ERASE2, 0);
+ /* issue the Erase Setup command */
+ DoC_Command(docptr, NAND_CMD_ERASE1, 0x00);
+ DoC_Address(docptr, 2, ofs, 0x00, 0x00);
+
+ /* Commit the Erase Start command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_ERASE2, 0x00);
+ DoC_WaitReady(docptr);
instr->state = MTD_ERASING;
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
-
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
- printk("Error writing\n");
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
+ printk("Error Erasing\n");
/* There was an error */
instr->state = MTD_ERASE_FAILED;
- }
- else
+ } else
instr->state = MTD_ERASE_DONE;
if (instr->callback)
instr->callback(instr);
-
+
return 0;
}
-
-
-#endif
-
/****************************************************************************
*
* Module stuff
diff --git a/drivers/mtd/docprobe.c b/drivers/mtd/docprobe.c
index 5feb64901..7ab0a2d74 100644
--- a/drivers/mtd/docprobe.c
+++ b/drivers/mtd/docprobe.c
@@ -3,7 +3,7 @@
/* Probe routines common to all DoC devices */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $ */
+/* $Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $ */
@@ -206,7 +206,7 @@ static void DoC_Probe(unsigned long physadr)
case DOC_ChipID_DocMil:
name="Millennium";
#ifdef CONFIG_MTD_DOC2001
- initroutine = &DocMil_init;
+ initroutine = &DoCMil_init;
#elif CONFIG_MODULES
initroutinedynamic=1;
initroutine = (void *)get_module_symbol(NULL, "DoCMil_init");
@@ -252,7 +252,7 @@ int __init init_doc(void)
printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
#ifdef PRERELEASE
- printk(KERN_INFO "$Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $\n");
+ printk(KERN_INFO "$Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $\n");
#endif
for (i=0; doc_locations[i]; i++) {
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index a69ec9e65..d94d86ff7 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -1,7 +1,7 @@
/*
* Direct MTD block device access
*
- * $Id: mtdblock.c,v 1.16 2000/06/23 09:34:58 dwmw2 Exp $
+ * $Id: mtdblock.c,v 1.17 2000/07/13 14:25:54 dwmw2 Exp $
*/
#ifdef MTDBLOCK_DEBUG
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index d0e79a431..11413556f 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -63,21 +63,16 @@ static int mtd_open(struct inode *inode, struct file *file)
if ((file->f_mode & 2) && (minor & 1))
return -EACCES;
- MOD_INC_USE_COUNT;
-
mtd = get_mtd_device(NULL, devnum);
- if (!mtd) {
- MOD_DEC_USE_COUNT;
+ if (!mtd)
return -ENODEV;
- }
file->private_data = mtd;
/* You can't open it RW if it's not a writeable device */
if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
put_mtd_device(mtd);
- MOD_DEC_USE_COUNT;
return -EACCES;
}
@@ -100,7 +95,6 @@ static release_t mtd_close(struct inode *inode,
put_mtd_device(mtd);
- MOD_DEC_USE_COUNT;
release_return(0);
} /* mtd_close */
@@ -362,7 +356,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
} /* memory_ioctl */
static struct file_operations mtd_fops = {
-
+ owner: THIS_MODULE,
llseek: mtd_lseek, /* lseek */
read: mtd_read, /* read */
write: mtd_write, /* write */
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 7403b6b94..b3f0157eb 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1,5 +1,5 @@
/*
- * $Id: mtdcore.c,v 1.8 2000/06/27 13:40:05 dwmw2 Exp $
+ * $Id: mtdcore.c,v 1.13 2000/07/13 14:27:37 dwmw2 Exp $
*
* Core registration and callback routines for MTD
* drivers and users.
@@ -44,9 +44,18 @@ extern int init_doc1000(void);
#ifdef CONFIG_MTD_DOCPROBE
extern int init_doc(void);
#endif
+#ifdef CONFIG_MTD_PHYSMAP
+extern int init_physmap(void);
+#endif
+#ifdef CONFIG_MTD_RPXLITE
+extern int init_rpxlite(void);
+#endif
#ifdef CONFIG_MTD_OCTAGON
extern int init_octagon5066(void);
#endif
+#ifdef CONFIG_MTD_PNC2000
+extern int init_pnc2000(void);
+#endif
#ifdef CONFIG_MTD_VMAX
extern int init_vmax301(void);
#endif
@@ -76,11 +85,18 @@ extern int init_mtdchar(void);
static DECLARE_MUTEX(mtd_table_mutex);
-
static struct mtd_info *mtd_table[MAX_MTD_DEVICES];
-
static struct mtd_notifier *mtd_notifiers = NULL;
+/**
+ * add_mtd_device - register an MTD device
+ * @mtd: pointer to new MTD device info structure
+ *
+ * Add a device to the list of MTD devices present in the system, and
+ * notify each currently active MTD 'user' of its arrival. Returns
+ * zero on success or 1 on failure, which currently will only happen
+ * if the number of present devices exceeds MAX_MTD_DEVICES (i.e. 16)
+ */
int add_mtd_device(struct mtd_info *mtd)
{
@@ -109,6 +125,15 @@ int add_mtd_device(struct mtd_info *mtd)
return 1;
}
+/**
+ * del_mtd_device - unregister an MTD device
+ * @mtd: pointer to MTD device info structure
+ *
+ * Remove a device from the list of MTD devices present in the system,
+ * and notify each currently active MTD 'user' of its departure.
+ * Returns zero on success or 1 on failure, which currently will happen
+ * if the requested device does not appear to be present in the list.
+ */
int del_mtd_device (struct mtd_info *mtd)
{
@@ -137,7 +162,14 @@ int del_mtd_device (struct mtd_info *mtd)
return 1;
}
-
+/**
+ * register_mtd_user - register a 'user' of MTD devices.
+ * @new: pointer to notifier info structure
+ *
+ * Registers a pair of callbacks function to be called upon addition
+ * or removal of MTD devices. Causes the 'add' callback to be immediately
+ * invoked for each MTD device currently present in the system.
+ */
void register_mtd_user (struct mtd_notifier *new)
{
@@ -157,7 +189,15 @@ void register_mtd_user (struct mtd_notifier *new)
up(&mtd_table_mutex);
}
-
+/**
+ * register_mtd_user - unregister a 'user' of MTD devices.
+ * @new: pointer to notifier info structure
+ *
+ * Removes a callback function pair from the list of 'users' to be
+ * notified upon addition or removal of MTD devices. Causes the
+ * 'remove' callback to be immediately invoked for each MTD device
+ * currently present in the system.
+ */
int unregister_mtd_user (struct mtd_notifier *old)
{
@@ -187,13 +227,17 @@ int unregister_mtd_user (struct mtd_notifier *old)
}
-/* get_mtd_device():
- * Prepare to use an MTD device referenced either by number or address.
+/**
+ * __get_mtd_device - obtain a validated handle for an MTD device
+ * @mtd: last known address of the required MTD device
+ * @num: internal device number of the required MTD device
*
- * If <num> == -1, search the table for an MTD device located at <mtd>.
- * If <mtd> == NULL, return the MTD device with number <num>.
- * If both are set, return the MTD device with number <num> _only_ if it
- * is located at <mtd>.
+ * Given a number and NULL address, return the num'th entry in the device
+ * table, if any. Given an address and num == -1, search the device table
+ * for a device with that address and return if it's still present. Given
+ * both, return the num'th driver only if its address matches. Return NULL
+ * if not. get_mtd_device() increases the use count, but
+ * __get_mtd_device() doesn't - you should generally use get_mtd_device().
*/
struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num)
@@ -224,12 +268,45 @@ EXPORT_SYMBOL(register_mtd_user);
EXPORT_SYMBOL(unregister_mtd_user);
/*====================================================================*/
-/* /proc/mtd support */
+/* Power management code */
+
+#ifdef CONFIG_PM
+
+#include <linux/pm.h>
+
+static struct pm_dev *mtd_pm_dev = NULL;
+
+static int mtd_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ int ret = 0, i;
+
+ if (down_trylock(&mtd_table_mutex))
+ return -EAGAIN;
+ if (rqst == PM_SUSPEND) {
+ for (i = 0; ret == 0 && i < MAX_MTD_DEVICES; i++) {
+ if (mtd_table[i] && mtd_table[i]->suspend)
+ ret = mtd_table[i]->suspend(mtd_table[i]);
+ }
+ } else i = MAX_MTD_DEVICES-1;
+
+ if (rqst == PM_RESUME || ret) {
+ for ( ; i >= 0; i--) {
+ if (mtd_table[i] && mtd_table[i]->resume)
+ mtd_table[i]->resume(mtd_table[i]);
+ }
+ }
+ up(&mtd_table_mutex);
+ return ret;
+}
+#endif
+
+/*====================================================================*/
+/* Support for /proc/mtd */
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-struct proc_dir_entry *proc_mtd;
+static struct proc_dir_entry *proc_mtd;
#endif
static inline int mtd_proc_info (char *buf, int i)
@@ -292,10 +369,10 @@ struct proc_dir_entry mtd_proc_entry = {
};
#endif
-#endif
+#endif /* CONFIG_PROC_FS */
/*====================================================================*/
-
+/* Init code */
#if LINUX_VERSION_CODE < 0x20300
@@ -315,9 +392,18 @@ static inline void init_others(void)
* Theoretically all other DiskOnChip
* devices too. */
#endif
+#ifdef CONFIG_MTD_PHYSMAP
+ init_physmap();
+#endif
+#ifdef CONFIG_MTD_RPXLITE
+ init_rpxlite();
+#endif
#ifdef CONFIG_MTD_OCTAGON
init_octagon5066();
#endif
+#ifdef CONFIG_MTD_PNC2000
+ init_pnc2000();
+#endif
#ifdef CONFIG_MTD_VMAX
init_vmax301();
#endif
@@ -374,13 +460,21 @@ mod_init_t init_mtd(void)
#if LINUX_VERSION_CODE < 0x20300
init_others();
#endif
-
+#ifdef CONFIG_PM
+ mtd_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mtd_pm_callback);
+#endif
return 0;
}
mod_exit_t cleanup_mtd(void)
{
unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#ifdef CONFIG_PM
+ if (mtd_pm_dev) {
+ pm_unregister(mtd_pm_dev);
+ mtd_pm_dev = NULL;
+ }
+#endif
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if (proc_mtd)
diff --git a/drivers/mtd/mtdram.c b/drivers/mtd/mtdram.c
index 674435272..33f3a8116 100644
--- a/drivers/mtd/mtdram.c
+++ b/drivers/mtd/mtdram.c
@@ -1,6 +1,6 @@
/*
* mtdram - a test mtd device
- * $Id: mtdram.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: mtdram.c,v 1.15 2000/07/13 12:40:46 scote1 Exp $
* Author: Alexander Larsson <alex@cendio.se>
*
* Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
@@ -17,8 +17,8 @@
#include <linux/mtd/mtd.h>
-#define MTDRAM_TOTAL_SIZE 1024*1024*8
-#define MTDRAM_ERASE_SIZE 4*1024
+#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
+#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024)
// We could store these in the mtd structure, but we only support 1 device..
diff --git a/drivers/mtd/nftl.c b/drivers/mtd/nftl.c
index 182ec5a96..e7040863f 100644
--- a/drivers/mtd/nftl.c
+++ b/drivers/mtd/nftl.c
@@ -2,7 +2,7 @@
/* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */
-/* $Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $ */
+/* $Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $ */
/*
The contents of this file are distributed under the GNU Public
@@ -1293,7 +1293,7 @@ int __init init_nftl(void)
printk(KERN_NOTICE "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");
#ifdef PRERELEASE
- printk(KERN_INFO"$Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $\n");
+ printk(KERN_INFO"$Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $\n");
#endif
if (register_blkdev(NFTL_MAJOR, "nftl", &nftl_fops)){
diff --git a/drivers/mtd/nora.c b/drivers/mtd/nora.c
index a92e47734..9304d7e62 100644
--- a/drivers/mtd/nora.c
+++ b/drivers/mtd/nora.c
@@ -1,5 +1,5 @@
/*
- * $Id: nora.c,v 1.11 2000/07/04 16:42:50 dwmw2 Exp $
+ * $Id: nora.c,v 1.12 2000/07/13 10:32:33 dwmw2 Exp $
*
* This is so simple I love it.
*/
@@ -125,7 +125,7 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0x1a0000,
+ size: 0x0a0000,
erasesize: 0x20000,
name: "NORA kernel",
module: THIS_MODULE,
@@ -140,9 +140,9 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0xe00000,
+ size: 0xf00000,
erasesize: 0x20000,
- name: "NORA ramdisk",
+ name: "NORA root filesystem",
module: THIS_MODULE,
erase: nora_mtd_erase,
read: nora_mtd_read,
@@ -150,14 +150,14 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
suspend: nora_mtd_suspend,
resume: nora_mtd_resume,
sync: nora_mtd_sync,
- priv: (void *)0x200000
+ priv: (void *)0x100000
},
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
size: 0x1000000,
erasesize: 0x20000,
- name: "NORA filesystem",
+ name: "NORA main filesystem",
module: THIS_MODULE,
erase: nora_mtd_erase,
read: nora_mtd_read,
diff --git a/drivers/mtd/octagon-5066.c b/drivers/mtd/octagon-5066.c
index 167e0da13..b184cd0e7 100644
--- a/drivers/mtd/octagon-5066.c
+++ b/drivers/mtd/octagon-5066.c
@@ -1,4 +1,4 @@
-// $Id: octagon-5066.c,v 1.9 2000/07/03 10:01:38 dwmw2 Exp $
+// $Id: octagon-5066.c,v 1.10 2000/07/13 14:04:23 dwmw2 Exp $
/* ######################################################################
Octagon 5066 MTD Driver.
@@ -56,8 +56,8 @@ static inline void oct5066_page(struct map_info *map, unsigned long ofs)
{
__u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
- if (page_n_dev != byte);
- __oct5066_page(map, byte);
+ if (page_n_dev != byte)
+ __oct5066_page(map, byte);
}
diff --git a/drivers/mtd/pmc551.c b/drivers/mtd/pmc551.c
index 98d5c3069..fdc80cbcf 100644
--- a/drivers/mtd/pmc551.c
+++ b/drivers/mtd/pmc551.c
@@ -1,5 +1,5 @@
/*
- * $Id: pmc551.c,v 1.7 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $
*
* PMC551 PCI Mezzanine Ram Device
*
@@ -53,6 +53,7 @@
* hang w/ a reboot beeing the only chance at recover.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/uaccess.h>
@@ -343,7 +344,7 @@ out:
*/
static u32 fixup_pmc551 (struct pci_dev *dev)
{
-#ifdef PMC551_DRAM_BUG
+#ifdef CONFIG_MTD_PMC551_BUGFIX
u32 dram_data;
#endif
u32 size, dcmd;
@@ -362,7 +363,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
* row mux values. We fix them here, but this will break other
* memory configurations.
*/
-#ifdef PMC551_DRAM_BUG
+#ifdef CONFIG_MTD_PMC551_BUGFIX
pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
@@ -386,7 +387,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
-#endif /* PMC551_DRAM_BUG */
+#endif /* CONFIG_MTD_PMC551_BUGFIX */
/*
* Oops .. something went wrong
@@ -550,7 +551,7 @@ int __init init_pmc551(void)
printk(KERN_NOTICE "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n");
- printk(KERN_INFO "$Id: pmc551.c,v 1.7 2000/07/03 10:01:38 dwmw2 Exp $\n");
+ printk(KERN_INFO "$Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $\n");
if(!pci_present()) {
printk(KERN_NOTICE "pmc551: PCI not enabled.\n");
diff --git a/drivers/mtd/pnc2000.c b/drivers/mtd/pnc2000.c
new file mode 100644
index 000000000..4e4b052a7
--- /dev/null
+++ b/drivers/mtd/pnc2000.c
@@ -0,0 +1,210 @@
+/*
+ * pnc2000.c - mapper for Photron PNC-2000 board.
+ *
+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
+ *
+ * This code is GPL
+ *
+ * $Id: pnc2000.c,v 1.1 2000/07/12 09:34:32 dwmw2 Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+
+
+#define WINDOW_ADDR 0xbf000000
+#define WINDOW_SIZE 0x00400000
+
+/*
+ * MAP DRIVER STUFF
+ */
+
+__u8 pnc_read8(struct map_info *map, unsigned long ofs)
+{
+ return *(__u8 *)(WINDOW_ADDR + ofs);
+}
+
+__u16 pnc_read16(struct map_info *map, unsigned long ofs)
+{
+ return *(__u16 *)(WINDOW_ADDR + ofs);
+}
+
+__u32 pnc_read32(struct map_info *map, unsigned long ofs)
+{
+ return *(volatile unsigned int *)(WINDOW_ADDR + ofs);
+}
+
+void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+ memcpy(to, (void *)(WINDOW_ADDR + from), len);
+}
+
+void pnc_write8(struct map_info *map, __u8 d, unsigned long adr)
+{
+ *(__u8 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_write16(struct map_info *map, __u16 d, unsigned long adr)
+{
+ *(__u16 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_write32(struct map_info *map, __u32 d, unsigned long adr)
+{
+ *(__u32 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+ memcpy((void *)(WINDOW_ADDR + to), from, len);
+}
+
+struct map_info pnc_map = {
+ "PNC-2000",
+ WINDOW_SIZE,
+ 4,
+ pnc_read8,
+ pnc_read16,
+ pnc_read32,
+ pnc_copy_from,
+ pnc_write8,
+ pnc_write16,
+ pnc_write32,
+ pnc_copy_to,
+ 0,
+ 0
+};
+
+
+/*
+ * MTD 'PARTITIONING' STUFF
+ */
+
+/*
+ * This is the _real_ MTD device for which all the others are just
+ * auto-relocating aliases.
+ */
+static struct mtd_info *mymtd;
+
+/*
+ * MTD methods which simply translate the effective address and pass through
+ * to the _real_ device.
+ */
+
+static int pnc_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf);
+}
+
+static int pnc_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+{
+ return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf);
+}
+
+static int pnc_mtd_erase (struct mtd_info *mtd, struct erase_info *instr)
+{
+ instr->addr += (unsigned long)mtd->priv;
+ return mymtd->erase(mymtd, instr);
+}
+
+static void pnc_mtd_sync (struct mtd_info *mtd)
+{
+ mymtd->sync(mymtd);
+}
+
+static int pnc_mtd_suspend (struct mtd_info *mtd)
+{
+ return mymtd->suspend(mymtd);
+}
+
+static void pnc_mtd_resume (struct mtd_info *mtd)
+{
+ mymtd->resume(mymtd);
+}
+
+
+static struct mtd_info pnc_mtds[3] = { /* boot, kernel, fs */
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x20000,
+ erasesize: 0x20000,
+ name: "PNC-2000 boot firmware",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0
+ },
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x1a0000,
+ erasesize: 0x20000,
+ name: "PNC-2000 kernel",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0x20000
+ },
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x240000,
+ erasesize: 0x20000,
+ name: "PNC-2000 filesystem",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0x1c0000
+ }
+};
+
+#if LINUX_VERSION_CODE < 0x20300
+#ifdef MODULE
+#define init_pnc init_module
+#define cleanup_pnc cleanup_module
+#endif
+#endif
+
+int __init init_pnc(void)
+{
+ printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
+
+ mymtd = do_cfi_probe(&pnc_map);
+ if (mymtd) {
+ mymtd->module = THIS_MODULE;
+
+ add_mtd_device(&pnc_mtds[0]); /* boot */
+ add_mtd_device(&pnc_mtds[1]); /* kernel */
+ add_mtd_device(&pnc_mtds[2]); /* file system */
+ return 0;
+ }
+
+ return -ENXIO;
+}
+
+static void __exit cleanup_pnc(void)
+{
+ if (mymtd) {
+ del_mtd_device(&pnc_mtds[2]);
+ del_mtd_device(&pnc_mtds[1]);
+ del_mtd_device(&pnc_mtds[0]);
+ map_destroy(mymtd);
+ }
+}
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index b0d8e73d4..275ef3296 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -158,7 +158,7 @@ static int bionet_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
static void bionet_tick(unsigned long);
-static struct timer_list bionet_timer = { NULL, NULL, 0, 0, bionet_tick };
+static struct timer_list bionet_timer = { function: bionet_tick };
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index f9b1eef79..6aeb737d5 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -168,7 +168,7 @@ static void pamsnet_tick(unsigned long);
static void pamsnet_intr(int irq, void *data, struct pt_regs *fp);
-static struct timer_list pamsnet_timer = { NULL, NULL, 0, 0, pamsnet_tick };
+static struct timer_list pamsnet_timer = { function: amsnet_tick };
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index e136e0132..b749908bd 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -3271,6 +3271,7 @@ srom_map_media(struct net_device *dev)
case ANS:
lp->media = ANS;
+ lp->fdx = lp->params.fdx;
break;
default:
diff --git a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c
index f8075373e..46f37e946 100644
--- a/drivers/net/pcmcia/xircom_tulip_cb.c
+++ b/drivers/net/pcmcia/xircom_tulip_cb.c
@@ -3010,7 +3010,8 @@ static void set_rx_mode(struct net_device *dev)
/* Same setup recently queued, we need not add it. */
} else {
unsigned long flags;
- unsigned int entry, dummy = -1;
+ unsigned int entry;
+ int dummy = -1;
save_flags(flags); cli();
entry = tp->cur_tx++ % TX_RING_SIZE;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index e43e3b394..f59653eef 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -41,6 +41,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <net/slhc_vj.h>
#include <asm/atomic.h>
@@ -319,6 +320,7 @@ static int ppp_release(struct inode *inode, struct file *file)
{
struct ppp_file *pf = (struct ppp_file *) file->private_data;
+ lock_kernel();
if (pf != 0) {
file->private_data = 0;
if (atomic_dec_and_test(&pf->refcnt)) {
@@ -332,6 +334,7 @@ static int ppp_release(struct inode *inode, struct file *file)
}
}
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
index 1a6da6e79..8ecc46db2 100644
--- a/drivers/net/sk_g16.c
+++ b/drivers/net/sk_g16.c
@@ -632,6 +632,8 @@ static int __init SK_init_module (void)
if (!SK_dev)
return -ENOMEM;
+ SK_dev->base_addr = io;
+
rc = SK_init (SK_dev);
if (rc) {
unregister_netdev (SK_dev);
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 9079f8113..4f6252383 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -19,8 +19,6 @@
*/
-static const char version[] = "Linux Tulip driver version 0.9.7 (June 17, 2000)\n";
-
#include <linux/module.h>
#include "tulip.h"
#include <linux/pci.h>
@@ -29,6 +27,9 @@ static const char version[] = "Linux Tulip driver version 0.9.7 (June 17, 2000)\
#include <linux/delay.h>
#include <asm/unaligned.h>
+static char version[] __devinitdata =
+ "Linux Tulip driver version 0.9.8 (July 13, 2000)\n";
+
/* A few user-configurable values. */
@@ -948,7 +949,8 @@ static void set_rx_mode(struct net_device *dev)
if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
/* Same setup recently queued, we need not add it. */
} else {
- unsigned int entry, dummy = -1;
+ unsigned int entry;
+ int dummy = -1;
/* Now add this frame to the Tx list. */
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index d45f0ccfd..371153a47 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -175,6 +175,7 @@ ifeq ($(CONFIG_SDLA),y)
else
ifeq ($(CONFIG_SDLA),m)
M_OBJS += sdla.o
+ endif
endif
ifeq ($(CONFIG_VENDOR_SANGOMA),y)
@@ -194,8 +195,6 @@ ifeq ($(CONFIG_VENDOR_SANGOMA),y)
endif
endif
-endif
-
ifeq ($(CONFIG_VENDOR_SANGOMA),m)
MX_OBJS += sdladrv.o
M_OBJS += wanpipe.o
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index dc0b212f5..be015f195 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -93,6 +93,7 @@
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#undef COSA_SLOW_IO /* for testing purposes only */
#undef REALLY_SLOW_IO
@@ -977,13 +978,16 @@ static int cosa_open(struct inode *inode, struct file *file)
static int cosa_release(struct inode *inode, struct file *file)
{
struct channel_data *channel = (struct channel_data *)file->private_data;
- struct cosa_data *cosa = channel->cosa;
+ struct cosa_data *cosa;
unsigned long flags;
+ lock_kernel();
+ cosa = channel->cosa;
spin_lock_irqsave(&cosa->lock, flags);
cosa->usage--;
channel->usage--;
spin_unlock_irqrestore(&cosa->lock, flags);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index eff2559d0..207c9e21c 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -13,6 +13,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
+* 2000/07/13 acme remove useless #ifdef MODULE and crap
+* #if KERNEL_VERSION > blah
* 2000/07/06 acme __exit at cyclomx_cleanup
* 2000/04/02 acme dprintk and cycx_debug
* module_init/module_exit
@@ -50,22 +52,18 @@
unsigned int cycx_debug = 0;
-#ifdef MODULE
MODULE_AUTHOR("Arnaldo Carvalho de Melo");
MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "cyclomx debug level");
-#endif
/* Defines & Macros */
#define DRV_VERSION 0 /* version number */
-#define DRV_RELEASE 8 /* release (minor version) number */
+#define DRV_RELEASE 9 /* release (minor version) number */
#define MAX_CARDS 1 /* max number of adapters */
-#ifndef CONFIG_CYCLOMX_CARDS /* configurable option */
#define CONFIG_CYCLOMX_CARDS 1
-#endif
/* Function Prototypes */
@@ -225,11 +223,7 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
card->hw.dpmsize = CYCX_WINDOWSIZE;
card->hw.fwid = CFID_X25_2X;
card->lock = SPIN_LOCK_UNLOCKED;
-#if LINUX_VERSION_CODE >= 0x020300
init_waitqueue_head(&card->wait_stats);
-#else
- card->wait_stats = NULL;
-#endif
err = cycx_setup(&card->hw, conf->data, conf->data_size);
if (err) {
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
index d408c8796..34446db01 100644
--- a/drivers/parport/ChangeLog
+++ b/drivers/parport/ChangeLog
@@ -1,4 +1,40 @@
-2000-06-30 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de>
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c: Documentation for parport_{get,port}_port,
+ parport_find_{number,base}.
+
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c (parport_unregister_device): Remove unneeded locking
+ (test cad==dev).
+ (parport_claim): Likewise.
+ (parport_find_number): New function.
+
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c (parport_register_port): Hold the parportlist_lock while
+ looking for a free parport number.
+ (parport_register_driver): Make sure that attach can block.
+ (attach_driver_chain): Likewise.
+
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c (call_driver_chain): Do reference counting things.
+ (parport_get_port): New function.
+ (parport_put_port): New function.
+ (parport_register_port): Initialise reference count to zero.
+ (parport_unregister_port): Check reference count rather than
+ driver list to see if we can free the port.
+
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c: Clarifications in doc comments.
+
+2000-07-12 Tim Waugh <twaugh@redhat.com>
+
+ * share.c (parport_unregister_port): Fix typo in comment.
+
+2000-07-11 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de>
* parport_pc.c: Support for the full range of Timedia cards.
diff --git a/drivers/parport/init.c b/drivers/parport/init.c
index 416ca51cb..90280e371 100644
--- a/drivers/parport/init.c
+++ b/drivers/parport/init.c
@@ -180,6 +180,10 @@ EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
+EXPORT_SYMBOL(parport_get_port);
+EXPORT_SYMBOL(parport_put_port);
+EXPORT_SYMBOL(parport_find_number);
+EXPORT_SYMBOL(parport_find_base);
EXPORT_SYMBOL(parport_negotiate);
EXPORT_SYMBOL(parport_write);
EXPORT_SYMBOL(parport_read);
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 9fe0bb4be..92618e7b4 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -88,17 +88,57 @@ static struct parport_operations dead_ops = {
dead_read /* byte */
};
-static void call_driver_chain(int attach, struct parport *port)
+/* Call attach(port) for each registered driver. */
+static void attach_driver_chain(struct parport *port)
{
struct parport_driver *drv;
+ void (**attach) (struct parport *);
+ int count = 0, i;
+
+ /* This is complicated because attach() must be able to block,
+ * but we can't let it do that while we're holding a
+ * spinlock. */
spin_lock (&driverlist_lock);
- for (drv = driver_chain; drv; drv = drv->next) {
- if (attach)
- drv->attach (port);
- else
- drv->detach (port);
+ for (drv = driver_chain; drv; drv = drv->next)
+ count++;
+ spin_unlock (&driverlist_lock);
+
+ /* Drivers can unregister here; that's okay. If they register
+ * they'll be given an attach during parport_register_driver,
+ * so that's okay too. The only worry is that someone might
+ * get given an attach twice if they registered just before
+ * this function gets called. */
+
+ /* Hmm, this could be fixed with a generation number..
+ * FIXME */
+
+ attach = kmalloc (sizeof (void(*)(struct parport *)) * count,
+ GFP_KERNEL);
+ if (!attach) {
+ printk (KERN_WARNING "parport: not enough memory to attach\n");
+ return;
}
+
+ spin_lock (&driverlist_lock);
+ for (i = 0, drv = driver_chain; drv && i < count; drv = drv->next)
+ attach[i++] = drv->attach;
+ spin_unlock (&driverlist_lock);
+
+ for (count = 0; count < i; count++)
+ (*attach[i]) (port);
+
+ kfree (attach);
+}
+
+/* Call detach(port) for each registered driver. */
+static void detach_driver_chain(struct parport *port)
+{
+ struct parport_driver *drv;
+
+ spin_lock (&driverlist_lock);
+ for (drv = driver_chain; drv; drv = drv->next)
+ drv->detach (port);
spin_unlock (&driverlist_lock);
}
@@ -121,27 +161,62 @@ static void get_lowlevel_driver (void)
* The @drv structure is allocated by the caller and must not be
* deallocated until after calling parport_unregister_driver().
*
+ * The driver's attach() function may block. The port that
+ * attach() is given will be valid for the duration of the
+ * callback, but if the driver wants to take a copy of the
+ * pointer it must call parport_get_port() to do so. Calling
+ * parport_register_device() on that port will do this for you.
+ *
+ * The driver's detach() function may not block. The port that
+ * detach() is given will be valid for the duration of the
+ * callback, but if the driver wants to take a copy of the
+ * pointer it must call parport_get_port() to do so.
+ *
* Returns 0 on success. Currently it always succeeds.
**/
int parport_register_driver (struct parport_driver *drv)
{
struct parport *port;
+ struct parport **ports;
+ int count = 0, i;
- spin_lock (&driverlist_lock);
- drv->next = driver_chain;
- driver_chain = drv;
- spin_unlock (&driverlist_lock);
+ if (!portlist)
+ get_lowlevel_driver ();
/* We have to take the portlist lock for this to be sure
* that port is valid for the duration of the callback. */
+
+ /* This is complicated by the fact that attach must be allowed
+ * to block, so we can't be holding any spinlocks when we call
+ * it. But we need to hold a spinlock to iterate over the
+ * list of ports.. */
+
spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next)
- drv->attach (port);
+ count++;
spin_unlock (&parportlist_lock);
- if (!portlist)
- get_lowlevel_driver ();
+ ports = kmalloc (sizeof (struct parport *) * count, GFP_KERNEL);
+ if (!ports)
+ printk (KERN_WARNING "parport: not enough memory to attach\n");
+ else {
+ spin_lock (&parportlist_lock);
+ for (i = 0, port = portlist; port && i < count;
+ port = port->next)
+ ports[i++] = port;
+ spin_unlock (&parportlist_lock);
+
+ for (count = 0; count < i; count++)
+ drv->attach (ports[count]);
+
+ kfree (ports);
+ }
+
+ spin_lock (&driverlist_lock);
+ drv->next = driver_chain;
+ driver_chain = drv;
+ spin_unlock (&driverlist_lock);
return 0;
}
@@ -162,6 +237,11 @@ int parport_register_driver (struct parport_driver *drv)
* If the caller's attach() function can block, it is their
* responsibility to make sure to wait for it to exit before
* unloading.
+ *
+ * All the driver's detach() calls are guaranteed to have
+ * finished by the time this function returns.
+ *
+ * The driver's detach() call is not allowed to block.
**/
void parport_unregister_driver (struct parport_driver *arg)
@@ -194,6 +274,57 @@ void parport_unregister_driver (struct parport_driver *arg)
}
}
+static void free_port (struct parport *port)
+{
+ int d;
+ for (d = 0; d < 5; d++) {
+ if (port->probe_info[d].class_name)
+ kfree (port->probe_info[d].class_name);
+ if (port->probe_info[d].mfr)
+ kfree (port->probe_info[d].mfr);
+ if (port->probe_info[d].model)
+ kfree (port->probe_info[d].model);
+ if (port->probe_info[d].cmdset)
+ kfree (port->probe_info[d].cmdset);
+ if (port->probe_info[d].description)
+ kfree (port->probe_info[d].description);
+ }
+
+ kfree(port->name);
+ kfree(port);
+}
+
+/**
+ * parport_get_port - increment a port's reference count
+ * @port: the port
+ *
+ * This ensure's that a struct parport pointer remains valid
+ * until the matching parport_put_port() call.
+ **/
+
+struct parport *parport_get_port (struct parport *port)
+{
+ atomic_inc (&port->ref_count);
+ return port;
+}
+
+/**
+ * parport_put_port - decrement a port's reference count
+ * @port: the port
+ *
+ * This should be called once for each call to parport_get_port(),
+ * once the port is no longer needed.
+ **/
+
+void parport_put_port (struct parport *port)
+{
+ if (atomic_dec_and_test (&port->ref_count))
+ /* Can destroy it now. */
+ free_port (port);
+
+ return;
+}
+
/**
* parport_enumerate - return a list of the system's parallel ports
*
@@ -260,6 +391,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
}
/* Search for the lowest free parport number. */
+
+ spin_lock_irq (&parportlist_lock);
for (portnum = 0; ; portnum++) {
struct parport *itr = portlist;
while (itr) {
@@ -274,6 +407,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
/* Got to the end of the list. */
break;
}
+ spin_unlock_irq (&parportlist_lock);
/* Init our structure */
memset(tmp, 0, sizeof(struct parport));
@@ -296,6 +430,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
tmp->spintime = parport_default_spintime;
+ atomic_set (&tmp->ref_count, 1);
name = kmalloc(15, GFP_KERNEL);
if (!name) {
@@ -372,27 +507,7 @@ void parport_announce_port (struct parport *port)
#endif
/* Let drivers know that a new port has arrived. */
- call_driver_chain (1, port);
-}
-
-static void free_port (struct parport *port)
-{
- int d;
- for (d = 0; d < 5; d++) {
- if (port->probe_info[d].class_name)
- kfree (port->probe_info[d].class_name);
- if (port->probe_info[d].mfr)
- kfree (port->probe_info[d].mfr);
- if (port->probe_info[d].model)
- kfree (port->probe_info[d].model);
- if (port->probe_info[d].cmdset)
- kfree (port->probe_info[d].cmdset);
- if (port->probe_info[d].description)
- kfree (port->probe_info[d].description);
- }
-
- kfree(port->name);
- kfree(port);
+ attach_driver_chain (port);
}
/**
@@ -421,7 +536,7 @@ void parport_unregister_port(struct parport *port)
port->ops = &dead_ops;
/* Spread the word. */
- call_driver_chain (0, port);
+ detach_driver_chain (port);
#ifdef CONFIG_PARPORT_1284
/* Forget the IEEE1284.3 topology of the port. */
@@ -431,7 +546,7 @@ void parport_unregister_port(struct parport *port)
spin_lock(&parportlist_lock);
/* We are protected from other people changing the list, but
- * they can see see it (using parport_enumerate). So be
+ * they can still see it (using parport_enumerate). So be
* careful about the order of writes.. */
if (portlist == port) {
if ((portlist = port->next) == NULL)
@@ -449,8 +564,7 @@ void parport_unregister_port(struct parport *port)
spin_unlock(&parportlist_lock);
/* Yes, parport_enumerate _is_ unsafe. Don't use it. */
- if (!port->devices)
- free_port (port);
+ parport_put_port (port);
}
/**
@@ -552,6 +666,7 @@ parport_register_device(struct parport *port, const char *name,
parport_register_device.. */
inc_parport_count();
port->ops->inc_use_count();
+ parport_get_port (port);
tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
if (tmp == NULL) {
@@ -623,6 +738,7 @@ parport_register_device(struct parport *port, const char *name,
out:
dec_parport_count();
port->ops->dec_use_count();
+ parport_put_port (port);
return NULL;
}
@@ -636,7 +752,6 @@ parport_register_device(struct parport *port, const char *name,
void parport_unregister_device(struct pardevice *dev)
{
struct parport *port;
- unsigned long flags;
#ifdef PARPORT_PARANOID
if (dev == NULL) {
@@ -649,14 +764,11 @@ void parport_unregister_device(struct pardevice *dev)
port = dev->port->physport;
- read_lock_irqsave (&port->cad_lock, flags);
if (port->cad == dev) {
- read_unlock_irqrestore (&port->cad_lock, flags);
printk(KERN_DEBUG "%s: %s forgot to release port\n",
port->name, dev->name);
parport_release (dev);
}
- read_unlock_irqrestore (&port->cad_lock, flags);
spin_lock(&port->pardevice_lock);
if (dev->next)
@@ -676,11 +788,7 @@ void parport_unregister_device(struct pardevice *dev)
dec_parport_count();
port->ops->dec_use_count();
-
- /* If this was the last device on a port that's already gone away,
- * free up the resources. */
- if (port->ops == &dead_ops && !port->devices)
- free_port (port);
+ parport_put_port (port);
/* Yes, that's right, someone _could_ still have a pointer to
* port, if they used parport_enumerate. That's why they
@@ -689,6 +797,56 @@ void parport_unregister_device(struct pardevice *dev)
}
/**
+ * parport_find_number - find a parallel port by number
+ * @number: parallel port number
+ *
+ * This returns the parallel port with the specified number, or
+ * %NULL if there is none.
+ *
+ * There is an implicit parport_get_port() done already; to throw
+ * away the reference to the port that parport_find_number()
+ * gives you, use parport_put_port().
+ */
+
+struct parport *parport_find_number (int number)
+{
+ struct parport *port, *result = NULL;
+ spin_lock (&parportlist_lock);
+ for (port = portlist; port; port = port->next)
+ if (port->number == number) {
+ result = parport_get_port (port);
+ break;
+ }
+ spin_unlock (&parportlist_lock);
+ return result;
+}
+
+/**
+ * parport_find_base - find a parallel port by base address
+ * @base: base I/O address
+ *
+ * This returns the parallel port with the specified base
+ * address, or %NULL if there is none.
+ *
+ * There is an implicit parport_get_port() done already; to throw
+ * away the reference to the port that parport_find_base()
+ * gives you, use parport_put_port().
+ */
+
+struct parport *parport_find_base (unsigned long base)
+{
+ struct parport *port, *result = NULL;
+ spin_lock (&parportlist_lock);
+ for (port = portlist; port; port = port->next)
+ if (port->base == base) {
+ result = parport_get_port (port);
+ break;
+ }
+ spin_unlock (&parportlist_lock);
+ return result;
+}
+
+/**
* parport_claim - claim access to a parallel port device
* @dev: pointer to structure representing a device on the port
*
@@ -706,14 +864,11 @@ int parport_claim(struct pardevice *dev)
struct parport *port = dev->port->physport;
unsigned long flags;
- read_lock_irqsave (&port->cad_lock, flags);
if (port->cad == dev) {
- read_unlock_irqrestore (&port->cad_lock, flags);
printk(KERN_INFO "%s: %s already owner\n",
dev->port->name,dev->name);
return 0;
}
- read_unlock_irqrestore (&port->cad_lock, flags);
/* Preempt any current device */
write_lock_irqsave (&port->cad_lock, flags);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 11e4330c5..f536e42cb 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -42,6 +42,7 @@
#include <linux/mm.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/ioctl.h>
#include <linux/proc_fs.h>
@@ -561,7 +562,6 @@ static int ds_open(struct inode *inode, struct file *file)
user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
if (!user) return -ENOMEM;
- MOD_INC_USE_COUNT;
user->event_tail = user->event_head = 0;
user->next = s->user;
user->user_magic = USER_MAGIC;
@@ -584,10 +584,11 @@ static int ds_release(struct inode *inode, struct file *file)
DEBUG(0, "ds_release(socket %d)\n", i);
if ((i >= sockets) || (sockets == 0))
return 0;
+ lock_kernel();
s = &socket_table[i];
user = file->private_data;
if (CHECK_USER(user))
- return 0;
+ goto out;
/* Unlink user data structure */
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
@@ -596,12 +597,12 @@ static int ds_release(struct inode *inode, struct file *file)
for (link = &s->user; *link; link = &(*link)->next)
if (*link == user) break;
if (link == NULL)
- return 0;
+ goto out;
*link = user->next;
user->user_magic = 0;
kfree(user);
-
- MOD_DEC_USE_COUNT;
+out:
+ unlock_kernel();
return 0;
} /* ds_release */
@@ -854,12 +855,13 @@ static int ds_ioctl(struct inode * inode, struct file * file,
/*====================================================================*/
static struct file_operations ds_fops = {
- open: ds_open,
- release: ds_release,
- ioctl: ds_ioctl,
- read: ds_read,
- write: ds_write,
- poll: ds_poll,
+ owner: THIS_MODULE,
+ open: ds_open,
+ release: ds_release,
+ ioctl: ds_ioctl,
+ read: ds_read,
+ write: ds_write,
+ poll: ds_poll,
};
EXPORT_SYMBOL(register_pccard_driver);
diff --git a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c
index 3472225b8..ee4c2aee3 100644
--- a/drivers/pnp/isapnp_proc.c
+++ b/drivers/pnp/isapnp_proc.c
@@ -187,10 +187,12 @@ static int isapnp_info_entry_release(struct inode *inode, struct file *file)
if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
return -EINVAL;
mode = file->f_flags & O_ACCMODE;
+ lock_kernel();
if (mode == O_WRONLY)
isapnp_info_write(buffer);
vfree(buffer->buffer);
kfree(buffer);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c
index be7e9de06..6ee5c6d3c 100644
--- a/drivers/sbus/audio/audio.c
+++ b/drivers/sbus/audio/audio.c
@@ -24,6 +24,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/tqueue.h>
#include <linux/major.h>
@@ -1910,6 +1911,7 @@ static int sparcaudio_release(struct inode * inode, struct file * file)
struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
+ lock_kernel();
if (file->f_mode & FMODE_READ) {
/* Stop input */
drv->ops->stop_input(drv);
@@ -1951,11 +1953,13 @@ static int sparcaudio_release(struct inode * inode, struct file * file)
kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
wake_up_interruptible(&drv->open_wait);
+ unlock_kernel();
return 0;
}
static struct file_operations sparcaudio_fops = {
+ owner: THIS_MODULE,
llseek: sparcaudio_lseek,
read: sparcaudio_read,
write: sparcaudio_write,
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index ebe9928c2..56f9d38af 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/major.h>
@@ -456,10 +457,13 @@ static int bpp_open(struct inode *inode, struct file *f)
static int bpp_release(struct inode *inode, struct file *f)
{
unsigned minor = MINOR(inode->i_rdev);
+
+ lock_kernel();
instances[minor].opened = 0;
if (instances[minor].mode != COMPATIBILITY)
terminate(minor);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 8bdee5e04..7a03036b6 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -13,6 +13,7 @@
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -37,23 +38,28 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long addr;
unsigned long size;
+ lock_kernel();
if (flash.read_base == flash.write_base) {
addr = flash.read_base;
size = flash.read_size;
} else {
if ((vma->vm_flags & VM_READ) &&
- (vma->vm_flags & VM_WRITE))
+ (vma->vm_flags & VM_WRITE)) {
+ unlock_kernel();
return -EINVAL;
-
+ }
if (vma->vm_flags & VM_READ) {
addr = flash.read_base;
size = flash.read_size;
} else if (vma->vm_flags & VM_WRITE) {
addr = flash.write_base;
size = flash.write_size;
- } else
+ } else {
+ unlock_kernel();
return -ENXIO;
+ }
}
+ unlock_kernel();
if ((vma->vm_pgoff << PAGE_SHIFT) > size)
return -ENXIO;
@@ -121,7 +127,9 @@ flash_open(struct inode *inode, struct file *file)
static int
flash_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
flash.busy = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index b01f26969..f87850b2c 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -35,6 +35,7 @@
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/smp_lock.h>
/*
* <linux/blk.h> is controlled from the outside with these definitions.
@@ -504,7 +505,9 @@ static int jsfd_open(struct inode *inode, struct file *file)
static int jsf_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
jsf0.busy = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c
index 93673e3b8..ecce4db4b 100644
--- a/drivers/sbus/char/pcikbd.c
+++ b/drivers/sbus/char/pcikbd.c
@@ -24,6 +24,7 @@
#include <linux/kbd_kern.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/ebus.h>
@@ -745,9 +746,10 @@ static int aux_release(struct inode * inode, struct file * file)
{
unsigned long flags;
+ lock_kernel();
aux_fasync(-1, file, 0);
if (--aux_count)
- return 0;
+ goto out;
spin_lock_irqsave(&pcikbd_lock, flags);
@@ -760,6 +762,8 @@ static int aux_release(struct inode * inode, struct file * file)
poll_aux_status();
spin_unlock_irqrestore(&pcikbd_lock, flags);
+out:
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index bda9e3a26..7a02f543f 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -19,6 +19,7 @@
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/mostek.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -129,7 +130,9 @@ static int rtc_open(struct inode *inode, struct file *file)
static int rtc_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
rtc_busy = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
index 8004569ab..191194287 100644
--- a/drivers/sbus/char/sunkbd.c
+++ b/drivers/sbus/char/sunkbd.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/sysrq.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/kbio.h>
@@ -1527,16 +1528,15 @@ kbd_open (struct inode *i, struct file *f)
static int
kbd_close (struct inode *i, struct file *f)
{
- if (--kbd_active)
- return 0;
-
- if (kbd_redirected)
- kbd_table [kbd_redirected-1].kbdmode = VC_XLATE;
-
- kbd_redirected = 0;
- kbd_opened = 0;
-
- kbd_fasync (-1, f, 0);
+ lock_kernel();
+ if (!--kbd_active) {
+ if (kbd_redirected)
+ kbd_table [kbd_redirected-1].kbdmode = VC_XLATE;
+ kbd_redirected = 0;
+ kbd_opened = 0;
+ kbd_fasync (-1, f, 0);
+ }
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c
index 46d335c2a..b9dd25653 100644
--- a/drivers/sbus/char/sunmouse.c
+++ b/drivers/sbus/char/sunmouse.c
@@ -49,6 +49,7 @@
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -411,8 +412,10 @@ static int sun_mouse_fasync (int fd, struct file *filp, int on)
static int
sun_mouse_close(struct inode *inode, struct file *file)
{
+ lock_kernel();
sun_mouse_fasync (-1, file, 0);
sunmouse.active--;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index eed298c6e..7b7a59ea2 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -21,6 +21,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/smp_lock.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -203,16 +204,19 @@ static int vfc_open(struct inode *inode, struct file *file)
return 0;
}
-static void vfc_release(struct inode *inode,struct file *file)
+static int vfc_release(struct inode *inode,struct file *file)
{
struct vfc_dev *dev;
+ lock_kernel();
dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
- if (dev == NULL)
- return;
- if (!dev->busy)
- return;
+ if (!dev || !dev->busy) {
+ unlock_kernel();
+ return -EINVAL;
+ }
dev->busy = 0;
+ unlock_kernel();
+ return 0;
}
static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg)
@@ -606,10 +610,12 @@ static int vfc_mmap(struct inode *inode, struct file *file,
unsigned int map_size, ret, map_offset;
struct vfc_dev *dev;
+ lock_kernel();
dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
- if(dev == NULL)
+ if(dev == NULL) {
+ unlock_kernel();
return -ENODEV;
-
+ }
map_size = vma->vm_end - vma->vm_start;
if(map_size > sizeof(struct vfc_regs))
map_size = sizeof(struct vfc_regs);
@@ -619,6 +625,7 @@ static int vfc_mmap(struct inode *inode, struct file *file,
map_offset = (unsigned int) (long)dev->phys_regs;
ret = io_remap_page_range(vma->vm_start, map_offset, map_size,
vma->vm_page_prot, dev->which_io);
+ unlock_kernel();
if(ret)
return -EAGAIN;
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 518f1e26e..b4ebd88f3 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -48,7 +48,6 @@ static struct ctrl_inquiry {
} *fcs __initdata = { 0 };
static int fcscount __initdata = 0;
static atomic_t fcss __initdata = ATOMIC_INIT(0);
-static struct timer_list fc_timer __initdata = { function: NULL };
DECLARE_MUTEX_LOCKED(fc_sem);
static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
@@ -92,6 +91,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
int i, retry, nplutos;
fc_channel *fc;
Scsi_Device dev;
+ struct timer_list fc_timer = { function: pluto_detect_timeout };
tpnt->proc_name = "pluto";
fcscount = 0;
@@ -121,7 +121,6 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
memset (fcs, 0, sizeof (struct ctrl_inquiry) * fcscount);
memset (&dev, 0, sizeof(dev));
atomic_set (&fcss, fcscount);
- fc_timer.function = pluto_detect_timeout;
i = 0;
for_each_online_fc_channel(fc) {
@@ -192,7 +191,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
if (!atomic_read(&fcss))
break; /* All fc channels have answered us */
}
- del_timer(&fc_timer);
+ del_timer_sync(&fc_timer);
PLND(("Finished search\n"))
for (i = 0, nplutos = 0; i < fcscount; i++) {
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 056b2f1b5..fd705d425 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -138,6 +138,10 @@ static struct dev_info device_list[] =
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
{"TOSHIBA","CDROM","*", BLIST_ISROM},
{"MegaRAID", "LD", "*", BLIST_FORCELUN},
+ {"DGC", "RAID", "*", BLIST_SPARSELUN}, // Dell PV 650F (tgt @ LUN 0)
+ {"DGC", "DISK", "*", BLIST_SPARSELUN}, // Dell PV 650F (no tgt @ LUN 0)
+ {"DELL", "PV530F", "*", BLIST_SPARSELUN}, // Dell PV 530F
+ {"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders
/*
* Must be at end of list...
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4bfdc59f4..4ac3dbcfb 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -52,6 +52,7 @@
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -304,8 +305,6 @@ static int sg_open(struct inode * inode, struct file * filp)
if (sdp->device->host->hostt->module)
__MOD_INC_USE_COUNT(sdp->device->host->hostt->module);
- if (sg_template.module)
- __MOD_INC_USE_COUNT(sg_template.module);
return 0;
}
@@ -315,8 +314,11 @@ static int sg_release(struct inode * inode, struct file * filp)
Sg_device * sdp;
Sg_fd * sfp;
- if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
+ lock_kernel();
+ if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
+ unlock_kernel();
return -ENXIO;
+ }
SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
sg_fasync(-1, filp, 0); /* remove filp from async notification list */
sg_remove_sfp(sdp, sfp);
@@ -325,10 +327,9 @@ static int sg_release(struct inode * inode, struct file * filp)
if (sdp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
- if(sg_template.module)
- __MOD_DEC_USE_COUNT(sg_template.module);
sdp->exclude = 0;
wake_up_interruptible(&sdp->o_excl_wait);
+ unlock_kernel();
return 0;
}
@@ -1094,13 +1095,14 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
}
static struct file_operations sg_fops = {
- read: sg_read,
- write: sg_write,
- poll: sg_poll,
- ioctl: sg_ioctl,
- open: sg_open,
- release: sg_release,
- fasync: sg_fasync,
+ owner: THIS_MODULE,
+ read: sg_read,
+ write: sg_write,
+ poll: sg_poll,
+ ioctl: sg_ioctl,
+ open: sg_open,
+ release: sg_release,
+ fasync: sg_fasync,
};
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index a605233c0..2ac10c832 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -31,6 +31,7 @@
#include <linux/ioctl.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -620,8 +621,6 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
- if (st_template.module)
- __MOD_INC_USE_COUNT(st_template.module);
if (mode != STp->current_mode) {
DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n",
@@ -859,8 +858,6 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
STp->in_use = 0;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
- if (st_template.module)
- __MOD_DEC_USE_COUNT(st_template.module);
return retval;
}
@@ -995,6 +992,7 @@ static int scsi_tape_close(struct inode *inode, struct file *filp)
int dev;
dev = TAPE_NR(devt);
+ lock_kernel();
read_lock(&st_dev_arr_lock);
STp = scsi_tapes[dev];
read_unlock(&st_dev_arr_lock);
@@ -1010,8 +1008,7 @@ static int scsi_tape_close(struct inode *inode, struct file *filp)
STp->in_use = 0;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
- if (st_template.module)
- __MOD_DEC_USE_COUNT(st_template.module);
+ unlock_kernel();
return result;
}
@@ -3428,6 +3425,7 @@ __setup("st=", st_setup);
static struct file_operations st_fops =
{
+ owner: THIS_MODULE,
read: st_read,
write: st_write,
ioctl: st_ioctl,
diff --git a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c
index a060e9895..62ca3c5e6 100644
--- a/drivers/sgi/char/graphics.c
+++ b/drivers/sgi/char/graphics.c
@@ -33,6 +33,7 @@
#include <linux/mman.h>
#include <linux/malloc.h>
#include <linux/module.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include "gconsole.h"
#include "graphics.h"
@@ -194,6 +195,7 @@ sgi_graphics_close (struct inode *inode, struct file *file)
int board = GRAPHICS_CARD (inode->i_rdev);
/* Tell the rendering manager that one client is going away */
+ lock_kernel();
rrm_close (inode, file);
/* Was this file handle from the board owner?, clear it */
@@ -203,6 +205,7 @@ sgi_graphics_close (struct inode *inode, struct file *file)
(*cards [board].g_reset_console)();
enable_gconsole ();
}
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c
index 03eab91e2..1438030b3 100644
--- a/drivers/sgi/char/shmiq.c
+++ b/drivers/sgi/char/shmiq.c
@@ -329,9 +329,12 @@ shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma)
size = vma->vm_end - vma->vm_start;
start = vma->vm_start;
+ lock_kernel();
mem = (unsigned long) shmiqs [minor].shmiq_vaddr = vmalloc_uncached (size);
- if (!mem)
+ if (!mem) {
+ unlock_kernel();
return -EINVAL;
+ }
/* Prevent the swapper from considering these pages for swap and touching them */
vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
@@ -345,6 +348,7 @@ shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma)
shmiqs [minor].tail = 0;
/* Init the shared memory input queue */
memset (shmiqs [minor].shmiq_vaddr, 0, size);
+ unlock_kernel();
return error;
}
diff --git a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c
index 1f354d80f..1d2a65c2a 100644
--- a/drivers/sgi/char/streamable.c
+++ b/drivers/sgi/char/streamable.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/shmiq.h>
#include <asm/keyboard.h>
@@ -50,20 +51,6 @@ get_sioc (struct strioctl *sioc, unsigned long arg)
/* /dev/gfx device */
static int
-sgi_gfx_open (struct inode *inode, struct file *file)
-{
- printk ("GFX: Opened by %d\n", current->pid);
- return 0;
-}
-
-static int
-sgi_gfx_close (struct inode *inode, struct file *file)
-{
- printk ("GFX: Closed by %d\n", current->pid);
- return 0;
-}
-
-static int
sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
printk ("GFX: ioctl 0x%x %ld called\n", cmd, arg);
@@ -73,8 +60,6 @@ sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigne
struct file_operations sgi_gfx_fops = {
ioctl: sgi_gfx_ioctl,
- open: sgi_gfx_open,
- release: sgi_gfx_close,
};
static struct miscdevice dev_gfx = {
@@ -236,7 +221,9 @@ sgi_mouse_open (struct inode *inode, struct file *file)
static int
sgi_mouse_close (struct inode *inode, struct file *filp)
{
+ lock_kernel();
mouse_opened = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
index c9fbe87d4..4ae9d2e2b 100644
--- a/drivers/sgi/char/usema.c
+++ b/drivers/sgi/char/usema.c
@@ -163,17 +163,10 @@ sgi_usemaclone_open(struct inode *inode, struct file *filp)
return 0;
}
-static int
-sgi_usemaclone_release(struct inode *inode, struct file *filp)
-{
- return 0;
-}
-
struct file_operations sgi_usemaclone_fops = {
poll: sgi_usemaclone_poll,
ioctl: sgi_usemaclone_ioctl,
open: sgi_usemaclone_open,
- release: sgi_usemaclone_release,
};
static struct miscdevice dev_usemaclone = {
diff --git a/drivers/sound/cmpci.c b/drivers/sound/cmpci.c
index 3b5639054..cc55d508e 100644
--- a/drivers/sound/cmpci.c
+++ b/drivers/sound/cmpci.c
@@ -114,6 +114,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
@@ -1397,29 +1398,35 @@ static int cm_mmap(struct file *file, struct vm_area_struct *vma)
{
struct cm_state *s = (struct cm_state *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(s, 1)) != 0)
- return ret;
+ goto out;
db = &s->dma_dac;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(s, 0)) != 0)
- return ret;
+ goto out;
db = &s->dma_adc;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
db->mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -1771,6 +1778,7 @@ static int cm_release(struct inode *inode, struct file *file)
struct cm_state *s = (struct cm_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -1785,6 +1793,7 @@ static int cm_release(struct inode *inode, struct file *file)
s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
@@ -2021,6 +2030,7 @@ static int cm_midi_release(struct inode *inode, struct file *file)
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
__set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
@@ -2058,6 +2068,7 @@ static int cm_midi_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&s->lock, flags);
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
@@ -2212,6 +2223,7 @@ static int cm_dmfm_release(struct inode *inode, struct file *file)
unsigned int regb;
VALIDATE_STATE(s);
+ lock_kernel();
down(&s->open_sem);
s->open_mode &= ~FMODE_DMFM;
for (regb = 0xb0; regb < 0xb9; regb++) {
@@ -2222,6 +2234,7 @@ static int cm_dmfm_release(struct inode *inode, struct file *file)
}
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/dmasound/dmasound_core.c b/drivers/sound/dmasound/dmasound_core.c
index da60c783b..1d8804b36 100644
--- a/drivers/sound/dmasound/dmasound_core.c
+++ b/drivers/sound/dmasound/dmasound_core.c
@@ -111,6 +111,7 @@
#include <linux/sound.h>
#include <linux/init.h>
#include <linux/soundcard.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -501,8 +502,10 @@ static int mixer_open(struct inode *inode, struct file *file)
static int mixer_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
mixer.busy = 0;
dmasound.mach.release();
+ unlock_kernel();
return 0;
}
static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
@@ -905,6 +908,7 @@ static int sq_release(struct inode *inode, struct file *file)
{
int rc = 0;
+ lock_kernel();
if (write_sq.busy)
rc = sq_fsync(file, file->f_dentry);
dmasound.soft = dmasound.dsp;
@@ -923,6 +927,7 @@ static int sq_release(struct inode *inode, struct file *file)
/* Wake up a process waiting for the queue being released.
* Note: There may be several processes waiting for a call
* to open() returning. */
+ unlock_kernel();
return rc;
}
@@ -1141,8 +1146,10 @@ static int state_open(struct inode *inode, struct file *file)
static int state_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
state.busy = 0;
dmasound.mach.release();
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/emu10k1/audio.c b/drivers/sound/emu10k1/audio.c
index 06f84dfc3..9e2ee24d1 100644
--- a/drivers/sound/emu10k1/audio.c
+++ b/drivers/sound/emu10k1/audio.c
@@ -36,6 +36,8 @@
#include "cardwi.h"
#include "recmgr.h"
#include "audio.h"
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
static void calculate_ofrag(struct woinst *);
static void calculate_ifrag(struct wiinst *);
@@ -890,6 +892,7 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
if (vma_get_pgoff(vma) != 0)
return -ENXIO;
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
struct woinst *woinst = wave_dev->woinst;
struct wave_out *wave_out;
@@ -907,6 +910,7 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
if (emu10k1_waveout_open(wave_dev) != CTSTATUS_SUCCESS) {
spin_unlock_irqrestore(&woinst->lock, flags);
ERROR();
+ unlock_kernel();
return -EINVAL;
}
@@ -921,12 +925,14 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
if (size > (PAGE_SIZE * wave_out->wavexferbuf->numpages)) {
spin_unlock_irqrestore(&woinst->lock, flags);
+ unlock_kernel();
return -EINVAL;
}
for (i = 0; i < wave_out->wavexferbuf->numpages; i++) {
if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(wave_out->pagetable[i]), PAGE_SIZE, vma->vm_page_prot)) {
spin_unlock_irqrestore(&woinst->lock, flags);
+ unlock_kernel();
return -EAGAIN;
}
}
@@ -944,6 +950,7 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
wiinst->mapped = 1;
spin_unlock_irqrestore(&wiinst->lock, flags);
}
+ unlock_kernel();
return 0;
}
@@ -1098,9 +1105,11 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
static int emu10k1_audio_release(struct inode *inode, struct file *file)
{
struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct emu10k1_card *card = wave_dev->card;
+ struct emu10k1_card *card;
unsigned long flags;
+ lock_kernel();
+ card = wave_dev->card;
DPF(2, "emu10k1_audio_release()\n");
if (file->f_mode & FMODE_WRITE) {
@@ -1171,6 +1180,7 @@ static int emu10k1_audio_release(struct inode *inode, struct file *file)
kfree(wave_dev);
wake_up_interruptible(&card->open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/emu10k1/midi.c b/drivers/sound/emu10k1/midi.c
index 04b1424a8..d7e0a4a87 100644
--- a/drivers/sound/emu10k1/midi.c
+++ b/drivers/sound/emu10k1/midi.c
@@ -32,6 +32,8 @@
#define __NO_VERSION__
#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include "hwaccess.h"
@@ -183,8 +185,10 @@ static int emu10k1_midi_open(struct inode *inode, struct file *file)
static int emu10k1_midi_release(struct inode *inode, struct file *file)
{
struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
- struct emu10k1_card *card = midi_dev->card;
+ struct emu10k1_card *card;
+ lock_kernel();
+ card = midi_dev->card;
DPF(2, "emu10k1_midi_release()\n");
if (file->f_mode & FMODE_WRITE) {
@@ -227,6 +231,7 @@ static int emu10k1_midi_release(struct inode *inode, struct file *file)
card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
up(&card->open_sem);
wake_up_interruptible(&card->open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 47d1d875f..ae004f10f 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -149,6 +149,7 @@
#include <linux/malloc.h>
#include <linux/soundcard.h>
#include <linux/pci.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/init.h>
@@ -1306,24 +1307,38 @@ static int es1370_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf_dac2(s)) != 0)
+ if ((ret = prog_dmabuf_dac2(s)) != 0) {
+ unlock_kernel();
return ret;
+ }
db = &s->dma_dac2;
} else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf_adc(s)) != 0)
+ if ((ret = prog_dmabuf_adc(s)) != 0) {
+ unlock_kernel();
return ret;
+ }
db = &s->dma_adc;
- } else
+ } else {
+ unlock_kernel();
return -EINVAL;
- if (vma->vm_pgoff != 0)
+ }
+ if (vma->vm_pgoff != 0) {
+ unlock_kernel();
return -EINVAL;
+ }
size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << db->buforder))
+ if (size > (PAGE_SIZE << db->buforder)) {
+ unlock_kernel();
return -EINVAL;
- if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+ }
+ if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) {
+ unlock_kernel();
return -EAGAIN;
+ }
db->mapped = 1;
+ unlock_kernel();
return 0;
}
@@ -1717,6 +1732,7 @@ static int es1370_release(struct inode *inode, struct file *file)
struct es1370_state *s = (struct es1370_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac2(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -1733,6 +1749,7 @@ static int es1370_release(struct inode *inode, struct file *file)
wake_up(&s->open_wait);
up(&s->open_sem);
return 0;
+ unlock_kernel();
}
static /*const*/ struct file_operations es1370_audio_fops = {
@@ -1850,17 +1867,23 @@ static int es1370_mmap_dac(struct file *file, struct vm_area_struct *vma)
VALIDATE_STATE(s);
if (!(vma->vm_flags & VM_WRITE))
return -EINVAL;
+ lock_kernel();
if ((ret = prog_dmabuf_dac1(s)) != 0)
- return ret;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
s->dma_dac1.mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2122,6 +2145,7 @@ static int es1370_release_dac(struct inode *inode, struct file *file)
struct es1370_state *s = (struct es1370_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
drain_dac1(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
stop_dac1(s);
@@ -2129,6 +2153,7 @@ static int es1370_release_dac(struct inode *inode, struct file *file)
s->open_mode &= ~FMODE_DAC;
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
@@ -2366,6 +2391,7 @@ static int es1370_midi_release(struct inode *inode, struct file *file)
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
@@ -2399,6 +2425,7 @@ static int es1370_midi_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&s->lock, flags);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index 109ac71c0..58d7923ab 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -121,6 +121,7 @@
#include <linux/bitops.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -1494,24 +1495,38 @@ static int es1371_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf_dac2(s)) != 0)
+ if ((ret = prog_dmabuf_dac2(s)) != 0) {
+ unlock_kernel();
return ret;
+ }
db = &s->dma_dac2;
} else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf_adc(s)) != 0)
+ if ((ret = prog_dmabuf_adc(s)) != 0) {
+ unlock_kernel();
return ret;
+ }
db = &s->dma_adc;
- } else
+ } else {
+ unlock_kernel();
return -EINVAL;
- if (vma->vm_pgoff != 0)
+ }
+ if (vma->vm_pgoff != 0) {
+ unlock_kernel();
return -EINVAL;
+ }
size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << db->buforder))
+ if (size > (PAGE_SIZE << db->buforder)) {
+ unlock_kernel();
return -EINVAL;
- if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+ }
+ if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) {
+ unlock_kernel();
return -EAGAIN;
+ }
db->mapped = 1;
+ unlock_kernel();
return 0;
}
@@ -1903,6 +1918,7 @@ static int es1371_release(struct inode *inode, struct file *file)
struct es1371_state *s = (struct es1371_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac2(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -1917,6 +1933,7 @@ static int es1371_release(struct inode *inode, struct file *file)
s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
@@ -2035,17 +2052,23 @@ static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma)
VALIDATE_STATE(s);
if (!(vma->vm_flags & VM_WRITE))
return -EINVAL;
+ lock_kernel();
if ((ret = prog_dmabuf_dac1(s)) != 0)
- return ret;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
s->dma_dac1.mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2297,6 +2320,7 @@ static int es1371_release_dac(struct inode *inode, struct file *file)
struct es1371_state *s = (struct es1371_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
drain_dac1(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
stop_dac1(s);
@@ -2304,6 +2328,7 @@ static int es1371_release_dac(struct inode *inode, struct file *file)
s->open_mode &= ~FMODE_DAC;
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
@@ -2540,6 +2565,7 @@ static int es1371_midi_release(struct inode *inode, struct file *file)
unsigned count, tmo;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
@@ -2573,6 +2599,7 @@ static int es1371_midi_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&s->lock, flags);
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c
index cfc89d3ee..e2e0c3b12 100644
--- a/drivers/sound/esssolo1.c
+++ b/drivers/sound/esssolo1.c
@@ -90,6 +90,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
@@ -1192,29 +1193,35 @@ static int solo1_mmap(struct file *file, struct vm_area_struct *vma)
{
struct solo1_state *s = (struct solo1_state *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf_dac(s)) != 0)
- return ret;
+ goto out;
db = &s->dma_dac;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf_adc(s)) != 0)
- return ret;
+ goto out;
db = &s->dma_adc;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
db->mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -1510,6 +1517,7 @@ static int solo1_release(struct inode *inode, struct file *file)
struct solo1_state *s = (struct solo1_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -1527,6 +1535,7 @@ static int solo1_release(struct inode *inode, struct file *file)
s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
@@ -1881,6 +1890,7 @@ static int solo1_midi_release(struct inode *inode, struct file *file)
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
@@ -1914,6 +1924,7 @@ static int solo1_midi_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&s->lock, flags);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
@@ -2083,6 +2094,7 @@ static int solo1_dmfm_release(struct inode *inode, struct file *file)
unsigned int regb;
VALIDATE_STATE(s);
+ lock_kernel();
down(&s->open_sem);
s->open_mode &= ~FMODE_DMFM;
for (regb = 0xb0; regb < 0xb9; regb++) {
@@ -2094,6 +2106,7 @@ static int solo1_dmfm_release(struct inode *inode, struct file *file)
release_region(s->sbbase, FMSYNTH_EXTENT);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/i810_audio.c b/drivers/sound/i810_audio.c
index f04636a65..792f670af 100644
--- a/drivers/sound/i810_audio.c
+++ b/drivers/sound/i810_audio.c
@@ -76,6 +76,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
@@ -1227,29 +1228,34 @@ static int i810_mmap(struct file *file, struct vm_area_struct *vma)
{
struct i810_state *state = (struct i810_state *)file->private_data;
struct dmabuf *dmabuf = &state->dmabuf;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(state, 0)) != 0)
- return ret;
+ goto out;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(state, 1)) != 0)
- return ret;
+ goto out;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << dmabuf->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
dmabuf->mapped = 1;
-
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -1608,6 +1614,7 @@ static int i810_release(struct inode *inode, struct file *file)
struct i810_state *state = (struct i810_state *)file->private_data;
struct dmabuf *dmabuf = &state->dmabuf;
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
i810_clear_tail(state);
drain_dac(state, file->f_flags & O_NONBLOCK);
@@ -1632,6 +1639,7 @@ static int i810_release(struct inode *inode, struct file *file)
kfree(state->card->states[state->virt]);
state->card->states[state->virt] = NULL;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c
index cd5a2bc27..cc54f784c 100644
--- a/drivers/sound/maestro.c
+++ b/drivers/sound/maestro.c
@@ -197,6 +197,8 @@
#include <linux/version.h>
#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
@@ -2422,13 +2424,14 @@ static int ess_mmap(struct file *file, struct vm_area_struct *vma)
{
struct ess_state *s = (struct ess_state *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(s, 1)) != 0)
- return ret;
+ goto out;
db = &s->dma_dac;
} else
#if 0
@@ -2436,20 +2439,25 @@ static int ess_mmap(struct file *file, struct vm_area_struct *vma)
we can turn this back on. */
if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(s, 0)) != 0)
- return ret;
+ goto out;
db = &s->dma_adc;
} else
#endif
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (SILLY_OFFSET(vma) != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
db->mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2985,6 +2993,7 @@ ess_release(struct inode *inode, struct file *file)
struct ess_state *s = (struct ess_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -3006,6 +3015,7 @@ ess_release(struct inode *inode, struct file *file)
}
up(&s->open_sem);
wake_up(&s->open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/msnd.h b/drivers/sound/msnd.h
index 219a6bfe0..7b361921e 100644
--- a/drivers/sound/msnd.h
+++ b/drivers/sound/msnd.h
@@ -160,13 +160,6 @@
# define inb inb_p
#endif
-#ifdef LINUX20
-# define __initfunc(f) f
-# define __initdata /* nothing */
-# define spin_lock_irqsave(junk,flags) do { save_flags(flags); cli(); } while (0)
-# define spin_unlock_irqrestore(junk,flags) do { restore_flags(flags); } while (0)
-#endif
-
/* JobQueueStruct */
#define JQS_wStart 0x00
#define JQS_wSize 0x02
@@ -236,9 +229,7 @@ typedef struct multisound_dev {
wait_queue_head_t writeblock;
wait_queue_head_t readblock;
wait_queue_head_t writeflush;
-#ifndef LINUX20
spinlock_t lock;
-#endif
int nresets;
unsigned long recsrc;
int left_levels[16];
@@ -250,8 +241,6 @@ typedef struct multisound_dev {
int rec_sample_size, rec_sample_rate, rec_channels;
int rec_ndelay;
BYTE bCurrentMidiPatch;
- void (*inc_ref)(void);
- void (*dec_ref)(void);
/* Digital audio FIFOs */
msnd_fifo DAPF, DARF;
diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c
index b220433ce..91c7d2306 100644
--- a/drivers/sound/msnd_pinnacle.c
+++ b/drivers/sound/msnd_pinnacle.c
@@ -35,16 +35,12 @@
#include <linux/config.h>
#include <linux/version.h>
-#if LINUX_VERSION_CODE < 0x020101
-# define LINUX20
-#endif
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/types.h>
#include <linux/delay.h>
-#ifndef LINUX20
-# include <linux/init.h>
-#endif
+#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/irq.h>
#include <asm/io.h>
#include "sound_config.h"
@@ -747,16 +743,6 @@ static void set_default_audio_parameters(void)
set_default_rec_audio_parameters();
}
-static void mod_inc_ref(void)
-{
- MOD_INC_USE_COUNT;
-}
-
-static void mod_dec_ref(void)
-{
- MOD_DEC_USE_COUNT;
-}
-
static int dev_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
@@ -789,43 +775,23 @@ static int dev_open(struct inode *inode, struct file *file)
} else
err = -EINVAL;
- if (err >= 0)
- mod_inc_ref();
-
return err;
}
-#ifdef LINUX20
-static void dev_release(struct inode *inode, struct file *file)
-#else
static int dev_release(struct inode *inode, struct file *file)
-#endif
{
int minor = MINOR(inode->i_rdev);
-#ifndef LINUX20
int err = 0;
-#endif
- if (minor == dev.dsp_minor) {
-#ifndef LINUX20
- err =
-#endif
- dsp_release(file);
- }
+ lock_kernel();
+ if (minor == dev.dsp_minor)
+ err = dsp_release(file);
else if (minor == dev.mixer_minor) {
/* nothing */
- }
-#ifndef LINUX20
- else
+ } else
err = -EINVAL;
-
- if (err >= 0)
-#endif
- mod_dec_ref();
-
-#ifndef LINUX20
+ unlock_kernel();
return err;
-#endif
}
static __inline__ int pack_DARQ_to_DARF(register int bank)
@@ -1002,30 +968,18 @@ static int dsp_write(const char *buf, size_t len)
return len - count;
}
-#ifdef LINUX20
-static int dev_read(struct inode *inode, struct file *file, char *buf, int count)
-{
- int minor = MINOR(inode->i_rdev);
-#else
static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off)
{
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
-#endif
if (minor == dev.dsp_minor)
return dsp_read(buf, count);
else
return -EINVAL;
}
-#ifdef LINUX20
-static int dev_write(struct inode *inode, struct file *file, const char *buf, int count)
-{
- int minor = MINOR(inode->i_rdev);
-#else
static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_t *off)
{
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
-#endif
if (minor == dev.dsp_minor)
return dsp_write(buf, count);
else
@@ -1042,15 +996,8 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
if (pack_DAPF_to_DAPQ(0) <= 0) {
if (!test_bit(F_WRITEBLOCK, &dev.flags)) {
-#ifdef LINUX20
- if (test_bit(F_WRITEFLUSH, &dev.flags)) {
- clear_bit(F_WRITEFLUSH, &dev.flags);
- wake_up_interruptible(&dev.writeflush);
- }
-#else
if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags))
wake_up_interruptible(&dev.writeflush);
-#endif
}
clear_bit(F_WRITING, &dev.flags);
}
@@ -1122,6 +1069,7 @@ static void intr(int irq, void *dev_id, struct pt_regs *regs)
}
static struct file_operations dev_fileops = {
+ owner: THIS_MODULE,
read: dev_read,
write: dev_write,
ioctl: dev_ioctl,
@@ -1881,8 +1829,6 @@ int __init msnd_pinnacle_init(void)
dev.recsrc = 0;
dev.dspq_data_buff = DSPQ_DATA_BUFF;
dev.dspq_buff_size = DSPQ_BUFF_SIZE;
- dev.inc_ref = mod_inc_ref;
- dev.dec_ref = mod_dec_ref;
if (write_ndelay == -1)
write_ndelay = CONFIG_MSND_WRITE_NDELAY;
if (write_ndelay)
@@ -1898,9 +1844,7 @@ int __init msnd_pinnacle_init(void)
init_waitqueue_head(&dev.writeflush);
msnd_fifo_init(&dev.DAPF);
msnd_fifo_init(&dev.DARF);
-#ifndef LINUX20
spin_lock_init(&dev.lock);
-#endif
printk(KERN_INFO LOGNAME ": %u byte audio FIFOs (x2)\n", dev.fifosize);
if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) {
printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n");
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index c9c66a73f..8a082552a 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -108,6 +108,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
@@ -1509,29 +1510,35 @@ static int sv_mmap(struct file *file, struct vm_area_struct *vma)
{
struct sv_state *s = (struct sv_state *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
VALIDATE_STATE(s);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(s, 1)) != 0)
- return ret;
+ goto out;
db = &s->dma_dac;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(s, 0)) != 0)
- return ret;
+ goto out;
db = &s->dma_adc;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
db->mapped = 1;
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -1907,6 +1914,7 @@ static int sv_release(struct inode *inode, struct file *file)
struct sv_state *s = (struct sv_state *)file->private_data;
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
@@ -1921,6 +1929,7 @@ static int sv_release(struct inode *inode, struct file *file)
s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
@@ -2167,6 +2176,7 @@ static int sv_midi_release(struct inode *inode, struct file *file)
VALIDATE_STATE(s);
+ lock_kernel();
if (file->f_mode & FMODE_WRITE) {
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
@@ -2200,6 +2210,7 @@ static int sv_midi_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&s->lock, flags);
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
@@ -2363,6 +2374,7 @@ static int sv_dmfm_release(struct inode *inode, struct file *file)
unsigned int regb;
VALIDATE_STATE(s);
+ lock_kernel();
down(&s->open_sem);
s->open_mode &= ~FMODE_DMFM;
for (regb = 0xb0; regb < 0xb9; regb++) {
@@ -2373,6 +2385,7 @@ static int sv_dmfm_release(struct inode *inode, struct file *file)
}
wake_up(&s->open_wait);
up(&s->open_sem);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index 0351fe7ce..d56b8f77f 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -270,6 +270,7 @@ static int sound_release(struct inode *inode, struct file *file)
{
int dev = MINOR(inode->i_rdev);
+ lock_kernel();
DEB(printk("sound_release(dev=%d)\n", dev));
switch (dev & 0x0f) {
case SND_DEV_CTL:
@@ -297,6 +298,7 @@ static int sound_release(struct inode *inode, struct file *file)
notifier_call_chain(&sound_locker, 0, 0);
lock_depth--;
+ unlock_kernel();
return 0;
}
@@ -449,29 +451,35 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
return -EINVAL;
}
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */
dmap = audio_devs[dev]->dmap_out;
else if (vma->vm_flags & VM_READ)
dmap = audio_devs[dev]->dmap_in;
else {
printk(KERN_ERR "Sound: Undefined mmap() access\n");
+ unlock_kernel();
return -EINVAL;
}
if (dmap == NULL) {
printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
+ unlock_kernel();
return -EIO;
}
if (dmap->raw_buf == NULL) {
printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
+ unlock_kernel();
return -EIO;
}
if (dmap->mapping_flags) {
printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
+ unlock_kernel();
return -EIO;
}
if (vma->vm_pgoff != 0) {
printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
+ unlock_kernel();
return -EINVAL;
}
size = vma->vm_end - vma->vm_start;
@@ -481,8 +489,10 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
}
if (remap_page_range(vma->vm_start, virt_to_phys(dmap->raw_buf),
vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ vma->vm_page_prot)) {
+ unlock_kernel();
return -EAGAIN;
+ }
dmap->mapping_flags |= DMA_MAP_MAPPED;
@@ -492,6 +502,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
memset(dmap->raw_buf,
dmap->neutral_byte,
dmap->bytes_in_use);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index 6e2b70791..f19cb1740 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -107,6 +107,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
@@ -1560,30 +1561,35 @@ static int trident_mmap(struct file *file, struct vm_area_struct *vma)
{
struct trident_state *state = (struct trident_state *)file->private_data;
struct dmabuf *dmabuf = &state->dmabuf;
- int ret;
+ int ret = -EINVAL;
unsigned long size;
VALIDATE_STATE(state);
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(state, 0)) != 0)
- return ret;
+ goto out;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(state, 1)) != 0)
- return ret;
- } else
- return -EINVAL;
+ goto out;
+ } else
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << dmabuf->buforder))
- return -EINVAL;
+ goto out;
+ ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
size, vma->vm_page_prot))
- return -EAGAIN;
+ goto out;
dmabuf->mapped = 1;
-
- return 0;
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
}
static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2009,9 +2015,12 @@ static int trident_open(struct inode *inode, struct file *file)
static int trident_release(struct inode *inode, struct file *file)
{
struct trident_state *state = (struct trident_state *)file->private_data;
- struct trident_card *card = state->card;
- struct dmabuf *dmabuf = &state->dmabuf;
+ struct trident_card *card;
+ struct dmabuf *dmabuf;
+ lock_kernel();
+ card = state->card;
+ dmabuf = &state->dmabuf;
VALIDATE_STATE(state);
if (file->f_mode & FMODE_WRITE) {
@@ -2038,6 +2047,7 @@ static int trident_release(struct inode *inode, struct file *file)
/* we're covered by the open_sem */
up(&card->open_sem);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c
index ab14427d6..be3b1c9ca 100644
--- a/drivers/sound/via82cxxx_audio.c
+++ b/drivers/sound/via82cxxx_audio.c
@@ -30,6 +30,7 @@
#include <linux/poll.h>
#include <linux/soundcard.h>
#include <linux/ac97_codec.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
@@ -2207,6 +2208,7 @@ static int via_dsp_release(struct inode *inode, struct file *file)
card = file->private_data;
assert (card != NULL);
+ lock_kernel();
if (file->f_mode & FMODE_READ)
via_chan_free (card, &card->ch_in);
@@ -2220,6 +2222,7 @@ static int via_dsp_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore (&card->lock, flags);
wake_up (&card->open_wait);
+ unlock_kernel();
DPRINTK("EXIT, returning 0\n");
return 0;
diff --git a/drivers/sound/vwsnd.c b/drivers/sound/vwsnd.c
index 19cca5ee0..d46abd569 100644
--- a/drivers/sound/vwsnd.c
+++ b/drivers/sound/vwsnd.c
@@ -84,10 +84,9 @@
* Locking Notes
*
* INC_USE_COUNT and DEC_USE_COUNT keep track of the number of
- * open descriptors to this driver. When the driver is compiled
- * as a module, they call MOD_{INC,DEC}_USE_COUNT; otherwise they
- * bump vwsnd_use_count. The global device list, vwsnd_dev_list,
- * is immutable when the IN_USE is true.
+ * open descriptors to this driver. They store it in vwsnd_use_count.
+ * The global device list, vwsnd_dev_list, is immutable when the IN_USE
+ * is true.
*
* devc->open_lock is a semaphore that is used to enforce the
* single reader/single writer rule for /dev/audio. The rule is
@@ -141,6 +140,7 @@
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#include <asm/fixmap.h>
#include <asm/cobalt.h>
#include <asm/semaphore.h>
@@ -1517,22 +1517,12 @@ typedef struct vwsnd_dev {
static vwsnd_dev_t *vwsnd_dev_list; /* linked list of all devices */
-#ifdef MODULE
-
-# define INC_USE_COUNT MOD_INC_USE_COUNT
-# define DEC_USE_COUNT MOD_DEC_USE_COUNT
-# define IN_USE MOD_IN_USE
-
-#else
-
static atomic_t vwsnd_use_count = ATOMIC_INIT(0);
# define INC_USE_COUNT (atomic_inc(&vwsnd_use_count))
# define DEC_USE_COUNT (atomic_dec(&vwsnd_use_count))
# define IN_USE (atomic_read(&vwsnd_use_count) != 0)
-#endif
-
/*
* Lithium can only DMA multiples of 32 bytes. Its DMA buffer may
* be up to 8 Kb. This driver always uses 8 Kb.
@@ -2998,6 +2988,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
vwsnd_port_t *wport = NULL, *rport = NULL;
int err = 0;
+ lock_kernel();
down(&devc->io_sema);
{
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
@@ -3023,13 +3014,14 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
}
up(&devc->open_sema);
wake_up(&devc->open_wait);
- DBGDO(if (IN_USE)) /* see hack in vwsnd_mixer_release() */
- DEC_USE_COUNT;
+ DEC_USE_COUNT;
DBGR();
+ unlock_kernel();
return err;
}
static struct file_operations vwsnd_audio_fops = {
+ owner: THIS_MODULE,
llseek: vwsnd_audio_llseek,
read: vwsnd_audio_read,
write: vwsnd_audio_write,
@@ -3069,15 +3061,7 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
static int vwsnd_mixer_release(struct inode *inode, struct file *file)
{
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
-
- /*
- * hack -- opening/closing the mixer device zeroes use count
- * so driver can be unloaded.
- * Use only while debugging module, and then use it carefully.
- */
-
- DBGDO(while (IN_USE))
- DEC_USE_COUNT;
+ DEC_USE_COUNT;
return 0;
}
@@ -3234,6 +3218,7 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
}
static struct file_operations vwsnd_mixer_fops = {
+ owner: THIS_MODULE,
llseek: vwsnd_mixer_llseek,
ioctl: vwsnd_mixer_ioctl,
open: vwsnd_mixer_open,
@@ -3429,8 +3414,6 @@ static int unload_vwsnd(struct address_info *hw_config)
DBGE("()\n");
- if (IN_USE)
- return -EBUSY;
devcp = &vwsnd_dev_list;
while ((devc = *devcp)) {
if (devc->audio_minor == hw_config->slots[0]) {
diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c
index a8f826031..3fb7cce2e 100644
--- a/drivers/sound/wavfront.c
+++ b/drivers/sound/wavfront.c
@@ -67,6 +67,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/ptrace.h>
#include <linux/fcntl.h>
#include <linux/ioport.h>
@@ -1959,8 +1960,10 @@ wavefront_open (struct inode *inode, struct file *file)
static int
wavefront_release(struct inode *inode, struct file *file)
{
+ lock_kernel();
dev.opened = 0;
dev.debug = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 043d57bbc..47485dbde 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -50,6 +50,7 @@ static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.4 1999/12/16 22:18:36 root Exp root
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/segment.h>
@@ -1056,6 +1057,7 @@ int ixj_release(struct inode *inode, struct file *file_p)
if (ixjdebug > 0)
printk(KERN_INFO "Closing board %d\n", NUM(inode->i_rdev));
+ lock_kernel();
daa_set_mode(board, SOP_PU_SLEEP);
ixj_set_port(board, PORT_POTS);
aec_stop(board);
@@ -1189,6 +1191,7 @@ int ixj_release(struct inode *inode, struct file *file_p)
j->rec_frame_size = j->play_frame_size = 0;
ixj_fasync(-1, file_p, 0); // remove from list of async notification
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index 55b8b1df5..7e29c7807 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -28,6 +28,9 @@ comment 'USB Controllers'
comment 'USB Devices'
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
+ fi
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
@@ -68,7 +71,6 @@ comment 'USB Devices'
dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET
dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV
- dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB
fi
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index 67f1635a6..4560ad602 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -171,6 +171,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/sound.h>
#include <linux/soundcard.h>
@@ -1944,10 +1945,13 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
static int usb_audio_release_mixdev(struct inode *inode, struct file *file)
{
struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
- struct usb_audio_state *s = ms->state;
+ struct usb_audio_state *s;
+ lock_kernel();
+ s = ms->state;
down(&open_sem);
release(s);
+ unlock_kernel();
return 0;
}
@@ -2283,23 +2287,28 @@ static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma)
{
struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf_out(as)) != 0)
- return ret;
+ goto out;
db = &as->usbout.dma;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf_in(as)) != 0)
- return ret;
+ goto out;
db = &as->usbin.dma;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
- return dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ ret = dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
+out:
+ unlock_kernel();
+ return ret;
}
static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2615,10 +2624,13 @@ static int usb_audio_open(struct inode *inode, struct file *file)
static int usb_audio_release(struct inode *inode, struct file *file)
{
struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
- struct usb_audio_state *s = as->state;
- struct usb_device *dev = s->usbdev;
+ struct usb_audio_state *s;
+ struct usb_device *dev;
struct usb_interface *iface;
+ lock_kernel();
+ s = as->state;
+ dev = s->usbdev;
if (file->f_mode & FMODE_WRITE)
drain_out(as, file->f_flags & O_NONBLOCK);
down(&open_sem);
@@ -2643,6 +2655,7 @@ static int usb_audio_release(struct inode *inode, struct file *file)
as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
release(s);
wake_up(&open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
index aaea67a4c..bd7be69e8 100644
--- a/drivers/usb/bluetooth.c
+++ b/drivers/usb/bluetooth.c
@@ -1,11 +1,15 @@
/*
- * bluetooth.c Version 0.1
+ * bluetooth.c Version 0.2
*
* Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
*
*
+ * (07/11/2000) Version 0.2 gkh
+ * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe
+ * function.
+ *
* (07/09/2000) Version 0.1 gkh
* Initial release. Has support for sending ACL data (which is really just
* a HCI frame.) Raw HCI commands and HCI events are not supported.
@@ -619,6 +623,7 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum)
memset(bluetooth, 0, sizeof(struct usb_bluetooth));
+ bluetooth->magic = USB_BLUETOOTH_MAGIC;
bluetooth->dev = dev;
bluetooth->minor = minor;
bluetooth->tqueue.routine = bluetooth_softint;
@@ -676,6 +681,8 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum)
tty_register_devfs (&bluetooth_tty_driver, 0, minor);
info("Bluetooth converter now attached to ttyBLUE%d (or usb/ttblue/%d for devfs)", minor, minor);
+ bluetooth_table[minor] = bluetooth;
+
return bluetooth; /* success */
probe_error:
diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
index 8b1df4edf..9b3bc24fa 100644
--- a/drivers/usb/dabusb.c
+++ b/drivers/usb/dabusb.c
@@ -38,6 +38,7 @@
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/usb.h>
+#include <linux/smp_lock.h>
#include "dabusb.h"
#include "dabfirmware.h"
@@ -613,6 +614,7 @@ static int dabusb_release (struct inode *inode, struct file *file)
dbg("dabusb_release");
+ lock_kernel();
down (&s->mutex);
dabusb_stop (s);
dabusb_free_buffers (s);
@@ -626,6 +628,7 @@ static int dabusb_release (struct inode *inode, struct file *file)
wake_up (&s->remove_ok);
s->opened = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
index 4fcfa640c..bb960a4af 100644
--- a/drivers/usb/dc2xx.c
+++ b/drivers/usb/dc2xx.c
@@ -60,6 +60,7 @@
#include <linux/module.h>
#undef DEBUG
#include <linux/usb.h>
+#include <linux/smp_lock.h>
@@ -298,10 +299,12 @@ static int camera_release (struct inode *inode, struct file *file)
kfree (camera->buf);
/* If camera was unplugged with open file ... */
+ lock_kernel();
if (!camera->dev) {
minor_data [camera->subminor] = NULL;
kfree (camera);
}
+ unlock_kernel();
dbg ("close");
diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c
index c99f86973..df02bcf2a 100644
--- a/drivers/usb/devices.c
+++ b/drivers/usb/devices.c
@@ -45,6 +45,9 @@
* up an eventual usbd
* 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
* Turned into its own filesystem
+ * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
+ * Converted file reading routine to dump to buffer once
+ * per device, not per bus
*
* $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
*/
@@ -367,23 +370,40 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de
/*****************************************************************/
-static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
- struct usb_bus *bus, int level, int index, int count)
+/* This is a recursive function. Parameters:
+ * buffer - the user-space buffer to write data into
+ * nbytes - the maximum number of bytes to write
+ * skip_bytes - the number of bytes to skip before writing anything
+ * file_offset - the offset into the devices file on completion
+ */
+static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
+ struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
{
int chix;
- int cnt = 0;
+ int ret, cnt = 0;
int parent_devnum = 0;
-
+ char *pages_start, *data_end;
+ unsigned int length;
+ ssize_t total_written = 0;
+
+ /* don't bother with anything else if we're not writing any data */
+ if (*nbytes <= 0)
+ return 0;
+
if (level > MAX_TOPO_LEVEL)
- return start;
+ return total_written;
+ /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
+ if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
+ return -ENOMEM;
+
if (usbdev->parent && usbdev->parent->devnum != -1)
parent_devnum = usbdev->parent->devnum;
/*
* So the root hub's parent is 0 and any device that is
* plugged into the root hub has a parent of 0.
*/
- start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count,
- usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
+ data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count,
+ usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
/*
* level = topology-tier level;
* parent_devnum = parent device number;
@@ -392,30 +412,58 @@ static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
*/
/* If this is the root hub, display the bandwidth information */
if (level == 0)
- start += sprintf(start, format_bandwidth, bus->bandwidth_allocated,
+ data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
FRAME_TIME_MAX_USECS_ALLOC,
(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
- start = usb_dump_desc(start, end, usbdev);
- if (start > end)
- return start + sprintf(start, "(truncated)\n");
+
+ data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
+
+ if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
+ data_end += sprintf(data_end, "(truncated)\n");
+
+ length = data_end - pages_start;
+ /* if we can start copying some data to the user */
+ if (length > *skip_bytes) {
+ length -= *skip_bytes;
+ if (length > *nbytes)
+ length = *nbytes;
+ if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
+ free_pages((unsigned long)pages_start, 1);
+
+ if (total_written == 0)
+ return -EFAULT;
+ return total_written;
+ }
+ *nbytes -= length;
+ *file_offset += length;
+ total_written += length;
+ *buffer += length;
+ *skip_bytes = 0;
+ } else
+ *skip_bytes -= length;
+
+ free_pages((unsigned long)pages_start, 1);
+
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
- if (start > end)
- return start;
- if (usbdev->children[chix])
- start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
+ if (usbdev->children[chix]) {
+ ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix],
+ bus, level + 1, chix, ++cnt);
+ if (ret == -EFAULT)
+ return total_written;
+ total_written += ret;
+ }
}
- return start;
+ return total_written;
}
static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
{
struct list_head *buslist;
struct usb_bus *bus;
- char *page, *end;
- ssize_t ret = 0;
- unsigned int pos, len;
+ ssize_t ret, total_written = 0;
+ loff_t skip_bytes = *ppos;
if (*ppos < 0)
return -EINVAL;
@@ -423,34 +471,18 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff
return 0;
if (!access_ok(VERIFY_WRITE, buf, nbytes))
return -EFAULT;
- if (!(page = (char*) __get_free_pages(GFP_KERNEL,1)))
- return -ENOMEM;
- pos = *ppos;
+
/* enumerate busses */
for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
/* print devices for this bus */
bus = list_entry(buslist, struct usb_bus, bus_list);
- end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0);
- len = end - page;
- if (len > pos) {
- len -= pos;
- if (len > nbytes)
- len = nbytes;
- if (copy_to_user(buf, page + pos, len)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- nbytes -= len;
- buf += len;
- ret += len;
- pos = 0;
- *ppos += len;
- } else
- pos -= len;
+ /* recurse through all children of the root hub */
+ ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+ if (ret < 0)
+ return ret;
+ total_written += ret;
}
- free_pages((unsigned long)page, 1);
- return ret;
+ return total_written;
}
/* Kernel lock for "lastev" protection */
diff --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c
index 7eca5e304..e11327cef 100644
--- a/drivers/usb/evdev.c
+++ b/drivers/usb/evdev.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/smp_lock.h>
struct evdev {
int exist;
@@ -91,8 +92,10 @@ static int evdev_fasync(int fd, struct file *file, int on)
static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
- struct evdev_list **listptr = &list->evdev->list;
+ struct evdev_list **listptr;
+ lock_kernel();
+ listptr = &list->evdev->list;
evdev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -110,6 +113,7 @@ static int evdev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c
index 5349d515c..2210ad0d1 100644
--- a/drivers/usb/joydev.c
+++ b/drivers/usb/joydev.c
@@ -44,6 +44,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#define JOYDEV_MINOR_BASE 0
#define JOYDEV_MINORS 32
@@ -160,8 +161,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
static int joydev_release(struct inode * inode, struct file * file)
{
struct joydev_list *list = file->private_data;
- struct joydev_list **listptr = &list->joydev->list;
+ struct joydev_list **listptr;
+ lock_kernel();
+ listptr = &list->joydev->list;
joydev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -179,6 +182,7 @@ static int joydev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
index dc578df33..80a1ebbf4 100644
--- a/drivers/usb/mdc800.c
+++ b/drivers/usb/mdc800.c
@@ -76,6 +76,7 @@
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/module.h>
+#include <linux/smp_lock.h>
#include <linux/usb.h>
@@ -582,6 +583,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
int retval=0;
dbg ("Mustek MDC800 device closed.");
+ lock_kernel();
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
mdc800->open=0;
@@ -593,6 +595,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
{
retval=-EIO;
}
+ unlock_kernel();
return retval;
}
diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c
index 5c871a88d..ea5ad301b 100644
--- a/drivers/usb/mousedev.c
+++ b/drivers/usb/mousedev.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/config.h>
+#include <linux/smp_lock.h>
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
#define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
@@ -159,8 +160,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
static int mousedev_release(struct inode * inode, struct file * file)
{
struct mousedev_list *list = file->private_data;
- struct mousedev_list **listptr = &list->mousedev->list;
+ struct mousedev_list **listptr;
+ lock_kernel();
+ listptr = &list->mousedev->list;
mousedev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -197,6 +200,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 4dc11aee0..987f1a8b5 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/signal.h>
#include <linux/poll.h>
#include <linux/init.h>
@@ -167,17 +168,19 @@ static int usblp_open(struct inode *inode, struct file *file)
if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV;
+ lock_kernel();
usblp = usblp_table[minor];
+ retval = -ENODEV;
if (!usblp || !usblp->dev)
- return -ENODEV;
+ goto out;
+ retval = -EBUSY;
if (usblp->used)
- return -EBUSY;
+ goto out;
- if ((retval = usblp_check_status(usblp))) {
- return retval;
- }
+ if ((retval = usblp_check_status(usblp)))
+ goto out;
usblp->used = 1;
file->private_data = usblp;
@@ -189,8 +192,9 @@ static int usblp_open(struct inode *inode, struct file *file)
usblp->readcount = 0;
usb_submit_urb(&usblp->readurb);
}
-
- return 0;
+out:
+ unlock_kernel();
+ return retval;
}
static int usblp_release(struct inode *inode, struct file *file)
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 3fba783e0..9c650cfdc 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -58,8 +58,6 @@ static struct usb_driver *usb_minors[16];
int usb_register(struct usb_driver *new_driver)
{
- struct list_head *tmp;
-
if (new_driver->fops != NULL) {
if (usb_minors[new_driver->minor/16]) {
err("error registering %s driver", new_driver->name);
@@ -75,13 +73,22 @@ int usb_register(struct usb_driver *new_driver)
/* Add it to the list of known drivers */
list_add(&new_driver->driver_list, &usb_driver_list);
- /*
- * We go through all existing devices, and see if any of them would
- * be acceptable to the new driver.. This is done using a depth-first
- * search for devices without a registered driver already, then
- * running 'probe' with each of the drivers registered on every one
- * of these.
- */
+ usb_scan_devices();
+
+ return 0;
+}
+
+/*
+ * We go through all existing devices, and see if any of them would
+ * be acceptable to the new driver.. This is done using a depth-first
+ * search for devices without a registered driver already, then
+ * running 'probe' with each of the drivers registered on every one
+ * of these.
+ */
+void usb_scan_devices(void)
+{
+ struct list_head *tmp;
+
tmp = usb_bus_list.next;
while (tmp != &usb_bus_list) {
struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
@@ -89,7 +96,6 @@ int usb_register(struct usb_driver *new_driver)
tmp = tmp->next;
usb_check_support(bus->root_hub);
}
- return 0;
}
/*
@@ -1772,6 +1778,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL(usb_scan_devices);
EXPORT_SYMBOL(usb_alloc_bus);
EXPORT_SYMBOL(usb_free_bus);
EXPORT_SYMBOL(usb_register_bus);
diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c
index 0b3e816e7..2d021dd87 100644
--- a/drivers/video/fbcon-mac.c
+++ b/drivers/video/fbcon-mac.c
@@ -100,8 +100,8 @@ void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
err_buf[cnt] = 0x700 | err_str[cnt];
fbcon_mac_putcs(p->conp, p, err_buf, len, 0, 0);
/* pause for the user */
- for(cnt = 0; cnt < 50000; cnt++)
- udelay(100);
+ printk( "ERROR: shift algorithm...\n" );
+ mdelay(5000);
return;
}
}
@@ -318,12 +318,25 @@ void fbcon_mac_revc(struct display *p, int xx, int yy)
}
}
+static inline void plot_helper(u8 *dest, u8 bit, int bw)
+{
+ switch (bw) {
+ case PIXEL_BLACK_MAC:
+ fb_writeb( fb_readb(dest) | bit, dest );
+ break;
+ case PIXEL_WHITE_MAC:
+ fb_writeb( fb_readb(dest) & (~bit), dest );
+ break;
+ case PIXEL_INVERT_MAC:
+ fb_writeb( fb_readb(dest) ^ bit, dest );
+ break;
+ default:
+ printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ }
+}
+
/*
* plot_pixel_mac
- *
- * bw == 0 = black
- * 1 = white
- * 2 = invert
*/
static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
{
@@ -333,10 +346,8 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
/* There *are* 68k Macs that support more than 832x624, you know :-) */
if (pixel_x < 0 || pixel_y < 0 || pixel_x >= p->var.xres || pixel_y >= p->var.yres) {
- int cnt;
printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
- for(cnt = 0; cnt < 100000; cnt++)
- udelay(100);
+ mdelay(1000);
return;
}
@@ -344,90 +355,36 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
case 1:
dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
bit = 0x80 >> (pixel_x & 7);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 2:
dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
bit = 0xC0 >> ((pixel_x & 3) << 1);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 4:
- dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
+ dest = (u8 *) ((pixel_x >> 1) + p->screen_base + pixel_y * p->next_line);
bit = 0xF0 >> ((pixel_x & 1) << 2);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 8:
dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
bit = 0xFF;
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
+/* FIXME: You can't access framebuffer directly like this! */
case 16:
dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
pix16 = 0xFFFF;
switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest16 = ~pix16;
- break;
- case PIXEL_WHITE_MAC:
- *dest16 = pix16;
- break;
- case PIXEL_INVERT_MAC:
- *dest16 ^= pix16;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ case PIXEL_BLACK_MAC: *dest16 = ~pix16; break;
+ case PIXEL_WHITE_MAC: *dest16 = pix16; break;
+ case PIXEL_INVERT_MAC: *dest16 ^= pix16; break;
+ default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
}
break;
@@ -435,17 +392,10 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
pix32 = 0xFFFFFFFF;
switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest32 = ~pix32;
- break;
- case PIXEL_WHITE_MAC:
- *dest32 = pix32;
- break;
- case PIXEL_INVERT_MAC:
- *dest32 ^= pix32;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ case PIXEL_BLACK_MAC: *dest32 = ~pix32; break;
+ case PIXEL_WHITE_MAC: *dest32 = pix32; break;
+ case PIXEL_INVERT_MAC: *dest32 ^= pix32; break;
+ default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
}
break;
}
@@ -497,7 +447,7 @@ static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y)
*/
struct display_switch fbcon_mac = {
- fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc,
+ fbcon_mac_setup, fbcon_redraw_bmove, fbcon_redraw_clear, fbcon_mac_putc,
fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,8)
};
diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c
index c2611d0a6..bf74fa162 100644
--- a/drivers/video/fbcon.c
+++ b/drivers/video/fbcon.c
@@ -1124,6 +1124,15 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p,
}
}
+void fbcon_redraw_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ int x, y;
+ for (y=0; y<height; y++)
+ for (x=0; x<width; x++)
+ fbcon_putc(conp, ' ', sy+y, sx+x);
+}
+
/* This cannot be used together with ypan or ywrap */
void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w)
{
@@ -2422,5 +2431,6 @@ struct display_switch fbcon_dummy = {
EXPORT_SYMBOL(fb_display);
EXPORT_SYMBOL(fbcon_redraw_bmove);
+EXPORT_SYMBOL(fbcon_redraw_clear);
EXPORT_SYMBOL(fbcon_dummy);
EXPORT_SYMBOL(fb_con);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 2ab527f02..30bd06d32 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/malloc.h>
@@ -473,8 +474,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
off = vma->vm_pgoff << PAGE_SHIFT;
if (!fb)
return -ENODEV;
- if (fb->fb_mmap)
- return fb->fb_mmap(info, file, vma);
+ if (fb->fb_mmap) {
+ int res;
+ lock_kernel();
+ res = fb->fb_mmap(info, file, vma);
+ unlock_kernel();
+ return res;
+ }
#if defined(__sparc__) && !defined(__sparc_v9__)
/* Should never get here, all fb drivers should have their own
@@ -483,6 +489,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
#else
/* !sparc32... */
+ lock_kernel();
fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
/* frame buffer memory */
@@ -497,6 +504,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
start = fix.mmio_start;
len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len);
}
+ unlock_kernel();
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
@@ -612,12 +620,15 @@ static int
fb_release(struct inode *inode, struct file *file)
{
int fbidx = GET_FB_IDX(inode->i_rdev);
- struct fb_info *info = registered_fb[fbidx];
+ struct fb_info *info;
+ lock_kernel();
+ info = registered_fb[fbidx];
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
if (info->fbops->owner)
__MOD_DEC_USE_COUNT(info->fbops->owner);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 261ce3d3c..c465bafc7 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -30,6 +30,7 @@
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
+#include <video/fbcon-mac.h>
#define dac_reg (0x3c8)
#define dac_val (0x3c9)
@@ -220,8 +221,13 @@ static void vesafb_set_disp(int con)
break;
#endif
default:
+#ifdef FBCON_HAS_MAC
+ sw = &fbcon_mac;
+ break;
+#else
sw = &fbcon_dummy;
return;
+#endif
}
memcpy(&vesafb_sw, sw, sizeof(*sw));
display->dispsw = &vesafb_sw;