summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-08-20 20:47:23 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-08-20 20:47:23 -0700
commit658dcd3b0d4340b434353cb8a2b4125bfabb923d (patch)
tree3cfecdde3caab3ae145587a24be28d4ebafb2736
parent5f6e4c742685e7c32dcc3ce3e28c87a9a8741029 (diff)
parentbe974925bc048c419f66e49b3744d98208e54831 (diff)
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
-rw-r--r--Documentation/filesystems/Locking150
-rw-r--r--Documentation/nmi_watchdog.txt2
-rw-r--r--arch/i386/Kconfig4
-rw-r--r--arch/i386/defconfig1
-rw-r--r--arch/i386/kernel/acpi/boot.c1
-rw-r--r--arch/i386/kernel/dmi_scan.c28
-rw-r--r--arch/i386/kernel/setup.c5
-rw-r--r--arch/i386/lib/usercopy.c174
-rw-r--r--drivers/base/power/resume.c2
-rw-r--r--drivers/base/power/suspend.c2
-rw-r--r--drivers/media/video/adv7170.c2
-rw-r--r--drivers/media/video/adv7175.c2
-rw-r--r--drivers/media/video/bt819.c2
-rw-r--r--drivers/media/video/bt856.c2
-rw-r--r--drivers/media/video/saa7110.c2
-rw-r--r--drivers/media/video/saa7111.c2
-rw-r--r--drivers/media/video/saa7114.c2
-rw-r--r--drivers/media/video/saa7185.c2
-rw-r--r--drivers/media/video/tvmixer.c2
-rw-r--r--drivers/media/video/vpx3220.c2
-rw-r--r--drivers/media/video/zoran.h6
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/mtd/chips/sharp.c2
-rw-r--r--drivers/net/irda/vlsi_ir.c20
-rw-r--r--drivers/net/seeq8005.c2
-rw-r--r--drivers/net/tokenring/smctr.c6
-rw-r--r--drivers/net/wan/Kconfig28
-rw-r--r--drivers/net/wan/dscc4.c229
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/scsi/NCR5380.c2
-rw-r--r--drivers/scsi/NCR5380.h4
-rw-r--r--drivers/scsi/aacraid/aacraid.h2
-rw-r--r--drivers/scsi/aha1740.c7
-rw-r--r--drivers/scsi/atari_NCR5380.c2
-rw-r--r--drivers/scsi/g_NCR5380.c2
-rw-r--r--drivers/scsi/mac_NCR5380.c2
-rw-r--r--drivers/scsi/sun3_NCR5380.c2
-rw-r--r--drivers/scsi/ultrastor.c2
-rw-r--r--drivers/usb/serial/console.c2
-rw-r--r--drivers/video/tridentfb.c5
-rw-r--r--fs/block_dev.c48
-rw-r--r--fs/ext3/balloc.c150
-rw-r--r--fs/ext3/namei.c9
-rw-r--r--fs/proc/array.c2
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h2
-rw-r--r--include/asm-i386/mach-es7000/mach_apic.h2
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h2
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h2
-rw-r--r--include/asm-i386/mach-visws/mach_apic.h2
-rw-r--r--include/linux/sched.h4
-rw-r--r--init/Kconfig2
-rw-r--r--init/do_mounts.c2
-rw-r--r--init/do_mounts.h10
-rw-r--r--kernel/fork.c17
-rw-r--r--mm/filemap.c3
-rw-r--r--mm/vmscan.c6
-rw-r--r--sound/isa/opl3sa2.c1
57 files changed, 618 insertions, 364 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 969c8726f208..4c426bdaca02 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -28,8 +28,9 @@ d_iput: no no no yes
--------------------------- inode_operations ---------------------------
prototypes:
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
+ int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+ struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameid
+ata *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -38,13 +39,13 @@ prototypes:
int (*mknod) (struct inode *,struct dentry *,int,dev_t);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
+ int (*readlink) (struct dentry *, char __user *,int);
int (*follow_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
+ int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
+ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
@@ -85,42 +86,55 @@ of the locking scheme for directory operations.
--------------------------- super_operations ---------------------------
prototypes:
+ struct inode *(*alloc_inode)(struct super_block *sb);
+ void (*destroy_inode)(struct inode *);
void (*read_inode) (struct inode *);
+ void (*dirty_inode) (struct inode *);
void (*write_inode) (struct inode *, int);
void (*put_inode) (struct inode *);
void (*drop_inode) (struct inode *);
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
- int (*sync_fs) (struct super_block *sb, int wait);
- int (*statfs) (struct super_block *, struct statfs *);
+ int (*sync_fs)(struct super_block *sb, int wait);
+ void (*write_super_lockfs) (struct super_block *);
+ void (*unlockfs) (struct super_block *);
+ int (*statfs) (struct super_block *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
+ int (*show_options)(struct seq_file *, struct vfsmount *);
locking rules:
All may block.
- BKL s_lock mount_sem
-read_inode: yes (see below)
-write_inode: no
-put_inode: no
-drop_inode: no !!!inode_lock!!!
-delete_inode: no
-clear_inode: no
-put_super: yes yes maybe (see below)
-write_super: no yes maybe (see below)
-sync_fs: no no maybe (see below)
-statfs: no no no
-remount_fs: yes yes maybe (see below)
-umount_begin: yes no maybe (see below)
+ BKL s_lock s_umount
+alloc_inode: no no no
+destroy_inode: no
+read_inode: no (see below)
+dirty_inode: no (must not sleep)
+write_inode: no
+put_inode: no
+drop_inode: no !!!inode_lock!!!
+delete_inode: no
+put_super: yes yes no
+write_super: no yes read
+sync_fs: no no read
+write_super_lockfs: ?
+unlockfs: ?
+statfs: no no no
+remount_fs: no yes maybe (see below)
+clear_inode: no
+umount_begin: yes no no
+show_options: no (vfsmount->sem)
->read_inode() is not a method - it's a callback used in iget().
-rules for mount_sem are not too nice - it is going to die and be replaced
-by better scheme anyway.
+->remount_fs() will have the s_umount lock if it's already mounted.
+When called from get_sb_single, it does NOT have the s_umount lock.
--------------------------- file_system_type ---------------------------
prototypes:
- struct super_block *(*get_sb) (struct file_system_type *, int, const char *, void *);
+ struct super_block *(*get_sb) (struct file_system_type *, int,
+ const char *, void *);
void (*kill_sb) (struct super_block *);
locking rules:
may block BKL
@@ -128,7 +142,7 @@ get_sb yes yes
kill_sb yes yes
->get_sb() returns error or a locked superblock (exclusive on ->s_umount).
-->kill_sb() takes a locked superblock, does all shutdown work on it,
+->kill_sb() takes a write-locked superblock, does all shutdown work on it,
unlocks and drops the reference.
--------------------------- address_space_operations --------------------------
@@ -138,12 +152,15 @@ prototypes:
int (*sync_page)(struct page *);
int (*writepages)(struct address_space *, struct writeback_control *);
int (*set_page_dirty)(struct page *page);
+ int (*readpages)(struct file *filp, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
- int (*bmap)(struct address_space *, long);
+ sector_t (*bmap)(struct address_space *, sector_t);
int (*invalidatepage) (struct page *, unsigned long);
int (*releasepage) (struct page *, int);
- int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
+ int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
locking rules:
All except set_page_dirty may block
@@ -151,15 +168,16 @@ locking rules:
BKL PageLocked(page)
writepage: no yes, unlocks (see below)
readpage: no yes, unlocks
-readpages: no
sync_page: no maybe
writepages: no
set_page_dirty no no
+readpages: no
prepare_write: no yes
commit_write: no yes
bmap: yes
invalidatepage: no yes
releasepage: no yes
+direct_IO: no
->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
may be called from the request handler (/dev/loop).
@@ -253,8 +271,8 @@ prototypes:
locking rules:
BKL may block
fl_notify: yes no
-fl_insert: yes maybe
-fl_remove: yes maybe
+fl_insert: yes no
+fl_remove: yes no
Currently only NLM provides instances of this class. None of the
them block. If you have out-of-tree instances - please, show up. Locking
in that area will change.
@@ -274,57 +292,75 @@ prototypes:
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
- int (*check_media_change) (kdev_t);
- int (*revalidate) (kdev_t);
+ int (*media_changed) (struct gendisk *);
+ int (*revalidate_disk) (struct gendisk *);
+
locking rules:
BKL bd_sem
open: yes yes
release: yes yes
ioctl: yes no
-check_media_change: yes no
-revalidate: yes no
+media_changed: no no
+revalidate_disk: no no
-The last two are called only from check_disk_change(). Prototypes are very
-bad - as soon as we'll get disk_struct they will change (and methods will
-become per-disk instead of per-partition).
+The last two are called only from check_disk_change().
--------------------------- file_operations -------------------------------
prototypes:
loff_t (*llseek) (struct file *, loff_t, int);
- ssize_t (*read) (struct file *, char *, size_t, loff_t *);
- ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
+ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+ ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
+ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+ ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t,
+ loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
- int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+ int (*ioctl) (struct inode *, struct file *, unsigned int,
+ unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
+ int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
- ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
- ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
+ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,
+ loff_t *);
+ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,
+ loff_t *);
+ ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t,
+ void __user *);
+ ssize_t (*sendpage) (struct file *, struct page *, int, size_t,
+ loff_t *, int);
+ unsigned long (*get_unmapped_area)(struct file *, unsigned long,
+ unsigned long, unsigned long, unsigned long);
};
locking rules:
All except ->poll() may block.
- BKL
-llseek: yes (see below)
-read: no
-write: no
-readdir: no
-poll: no
-ioctl: yes (see below)
-mmap: no
-open: maybe (see below)
-flush: no
-release: no
-fsync: yes (see below)
-fasync: yes (see below)
-lock: yes
-readv: no
-writev: no
+ BKL
+llseek: no (see below)
+read: no
+aio_read: no
+write: no
+aio_write: no
+readdir: no
+poll: no
+ioctl: yes (see below)
+mmap: no
+open: maybe (see below)
+flush: no
+release: no
+fsync: no (see below)
+aio_fsync: no
+fasync: yes (see below)
+lock: yes
+readv: no
+writev: no
+sendfile: no
+sendpage: no
+get_unmapped_area: no
->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you
diff --git a/Documentation/nmi_watchdog.txt b/Documentation/nmi_watchdog.txt
index 9c2f2e6bf3e0..c1ba4e6f1ac8 100644
--- a/Documentation/nmi_watchdog.txt
+++ b/Documentation/nmi_watchdog.txt
@@ -12,7 +12,7 @@ This can be used to debug hard kernel lockups. By executing periodic
NMI interrupts, the kernel can monitor whether any CPU has locked up,
and print out debugging messages if so.
-In order to use the NMI watchdoc, you need to have APIC support in your
+In order to use the NMI watchdog, you need to have APIC support in your
kernel. For SMP kernels, APIC support gets compiled in automatically. For
UP, enable either CONFIG_X86_UP_APIC (Processor type and features -> Local
APIC support on uniprocessors) or CONFIG_X86_UP_IOAPIC (Processor type and
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 991f85019a5e..d6062319d10e 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1204,10 +1204,6 @@ source "drivers/pnp/Kconfig"
source "drivers/block/Kconfig"
-config MOUNT_ROOT_FAILED_MSG
- bool
- default y
-
source "drivers/ide/Kconfig"
source "drivers/scsi/Kconfig"
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 0f0a4e7bd699..150ff18161a8 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -228,7 +228,6 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_LBD=y
-CONFIG_MOUNT_ROOT_FAILED_MSG=y
#
# ATA/ATAPI/MFM/RLL support
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 336b2088b808..1486324a3d06 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -34,6 +34,7 @@
#if defined (CONFIG_X86_LOCAL_APIC)
#include <mach_apic.h>
#include <mach_mpparse.h>
+#include <asm/io_apic.h>
#endif
#define PREFIX "ACPI: "
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 058fd47d1137..ef91655c2568 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -162,6 +162,8 @@ enum
static char *dmi_ident[DMI_STRING_MAX];
+#ifdef CONFIG_ACPI_BOOT
+
/* print some information suitable for a blacklist entry. */
static void dmi_dump_system(void)
{
@@ -176,6 +178,8 @@ static void dmi_dump_system(void)
dmi_ident[DMI_BOARD_VERSION]);
}
+#endif
+
/*
* Save a DMI string
*/
@@ -1116,27 +1120,3 @@ void __init dmi_scan_machine(void)
}
EXPORT_SYMBOL(is_unsafe_smbus);
-
-#ifdef CONFIG_MOUNT_ROOT_FAILED_MSG
-/*
- * mount_root_failed_msg()
- *
- * Called from mount_block_root() upon failure to mount root.
- * architecture dependent to give different platforms
- * the opportunity to print different handy messages
- * On x86 this lives here b/c it dumps out some DMI info.
- */
-
-void
-mount_root_failed_msg(void)
-{
-#ifdef CONFIG_ACPI_BOOT
- printk ("Try booting with pci=noacpi, acpi=ht, "
- "or acpi=off on the command line.\n");
- printk ("If one helps, please report the following lines:\n");
-
- dmi_dump_system();
-#endif
-}
-#endif /* CONFIG_MOUNT_ROOT_FAILED_MSG */
-
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index ab2881128c35..8cb06f26888c 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -43,6 +43,7 @@
#include <asm/setup.h>
#include <asm/arch_hooks.h>
#include <asm/sections.h>
+#include <asm/io_apic.h>
#include "setup_arch_pre.h"
#include "mach_resources.h"
@@ -543,11 +544,13 @@ static void __init parse_cmdline_early (char ** cmdline_p)
if (!acpi_force) acpi_disabled = 1;
}
+#ifdef CONFIG_X86_LOCAL_APIC
/* disable IO-APIC */
else if (!memcmp(from, "noapic", 6)) {
skip_ioapic_setup = 1;
}
-#endif
+#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_ACPI_BOOT */
/*
* highmem=size forces highmem to be exactly 'size' bytes.
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 2361c79f8b1d..b9a07ec571e3 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -222,85 +222,105 @@ __copy_user_intel(void *to, const void *from,unsigned long size)
{
int d0, d1;
__asm__ __volatile__(
- " .align 2,0x90\n"
- "0: movl 32(%4), %%eax\n"
- " cmpl $67, %0\n"
- " jbe 1f\n"
- " movl 64(%4), %%eax\n"
- " .align 2,0x90\n"
- "1: movl 0(%4), %%eax\n"
- " movl 4(%4), %%edx\n"
- "2: movl %%eax, 0(%3)\n"
- "21: movl %%edx, 4(%3)\n"
- " movl 8(%4), %%eax\n"
- " movl 12(%4),%%edx\n"
- "3: movl %%eax, 8(%3)\n"
- "31: movl %%edx, 12(%3)\n"
- " movl 16(%4), %%eax\n"
- " movl 20(%4), %%edx\n"
- "4: movl %%eax, 16(%3)\n"
- "41: movl %%edx, 20(%3)\n"
- " movl 24(%4), %%eax\n"
- " movl 28(%4), %%edx\n"
- "10: movl %%eax, 24(%3)\n"
- "51: movl %%edx, 28(%3)\n"
- " movl 32(%4), %%eax\n"
- " movl 36(%4), %%edx\n"
- "11: movl %%eax, 32(%3)\n"
- "61: movl %%edx, 36(%3)\n"
- " movl 40(%4), %%eax\n"
- " movl 44(%4), %%edx\n"
- "12: movl %%eax, 40(%3)\n"
- "71: movl %%edx, 44(%3)\n"
- " movl 48(%4), %%eax\n"
- " movl 52(%4), %%edx\n"
- "13: movl %%eax, 48(%3)\n"
- "81: movl %%edx, 52(%3)\n"
- " movl 56(%4), %%eax\n"
- " movl 60(%4), %%edx\n"
- "14: movl %%eax, 56(%3)\n"
- "91: movl %%edx, 60(%3)\n"
- " addl $-64, %0\n"
- " addl $64, %4\n"
- " addl $64, %3\n"
- " cmpl $63, %0\n"
- " ja 0b\n"
- "5: movl %0, %%eax\n"
- " shrl $2, %0\n"
- " andl $3, %%eax\n"
- " cld\n"
- "6: rep; movsl\n"
- " movl %%eax, %0\n"
- "7: rep; movsb\n"
- "8:\n"
- ".section .fixup,\"ax\"\n"
- "9: lea 0(%%eax,%0,4),%0\n"
- " jmp 8b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 2b,8b\n"
- " .long 21b,8b\n"
- " .long 3b,8b\n"
- " .long 31b,8b\n"
- " .long 4b,8b\n"
- " .long 41b,8b\n"
- " .long 10b,8b\n"
- " .long 51b,8b\n"
- " .long 11b,8b\n"
- " .long 61b,8b\n"
- " .long 12b,8b\n"
- " .long 71b,8b\n"
- " .long 13b,8b\n"
- " .long 81b,8b\n"
- " .long 14b,8b\n"
- " .long 91b,8b\n"
- " .long 6b,9b\n"
- " .long 7b,8b\n"
- ".previous"
+ " .align 2,0x90\n"
+ "1: movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
+ " jbe 3f\n"
+ "2: movl 64(%4), %%eax\n"
+ " .align 2,0x90\n"
+ "3: movl 0(%4), %%eax\n"
+ "4: movl 4(%4), %%edx\n"
+ "5: movl %%eax, 0(%3)\n"
+ "6: movl %%edx, 4(%3)\n"
+ "7: movl 8(%4), %%eax\n"
+ "8: movl 12(%4),%%edx\n"
+ "9: movl %%eax, 8(%3)\n"
+ "10: movl %%edx, 12(%3)\n"
+ "11: movl 16(%4), %%eax\n"
+ "12: movl 20(%4), %%edx\n"
+ "13: movl %%eax, 16(%3)\n"
+ "14: movl %%edx, 20(%3)\n"
+ "15: movl 24(%4), %%eax\n"
+ "16: movl 28(%4), %%edx\n"
+ "17: movl %%eax, 24(%3)\n"
+ "18: movl %%edx, 28(%3)\n"
+ "19: movl 32(%4), %%eax\n"
+ "20: movl 36(%4), %%edx\n"
+ "21: movl %%eax, 32(%3)\n"
+ "22: movl %%edx, 36(%3)\n"
+ "23: movl 40(%4), %%eax\n"
+ "24: movl 44(%4), %%edx\n"
+ "25: movl %%eax, 40(%3)\n"
+ "26: movl %%edx, 44(%3)\n"
+ "27: movl 48(%4), %%eax\n"
+ "28: movl 52(%4), %%edx\n"
+ "29: movl %%eax, 48(%3)\n"
+ "30: movl %%edx, 52(%3)\n"
+ "31: movl 56(%4), %%eax\n"
+ "32: movl 60(%4), %%edx\n"
+ "33: movl %%eax, 56(%3)\n"
+ "34: movl %%edx, 60(%3)\n"
+ " addl $-64, %0\n"
+ " addl $64, %4\n"
+ " addl $64, %3\n"
+ " cmpl $63, %0\n"
+ " ja 1b\n"
+ "35: movl %0, %%eax\n"
+ " shrl $2, %0\n"
+ " andl $3, %%eax\n"
+ " cld\n"
+ "99: rep; movsl\n"
+ "36: movl %%eax, %0\n"
+ "37: rep; movsb\n"
+ "100:\n"
+ ".section .fixup,\"ax\"\n"
+ "101: lea 0(%%eax,%0,4),%0\n"
+ " jmp 100b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 1b,100b\n"
+ " .long 2b,100b\n"
+ " .long 3b,100b\n"
+ " .long 4b,100b\n"
+ " .long 5b,100b\n"
+ " .long 6b,100b\n"
+ " .long 7b,100b\n"
+ " .long 8b,100b\n"
+ " .long 9b,100b\n"
+ " .long 10b,100b\n"
+ " .long 11b,100b\n"
+ " .long 12b,100b\n"
+ " .long 13b,100b\n"
+ " .long 14b,100b\n"
+ " .long 15b,100b\n"
+ " .long 16b,100b\n"
+ " .long 17b,100b\n"
+ " .long 18b,100b\n"
+ " .long 19b,100b\n"
+ " .long 20b,100b\n"
+ " .long 21b,100b\n"
+ " .long 22b,100b\n"
+ " .long 23b,100b\n"
+ " .long 24b,100b\n"
+ " .long 25b,100b\n"
+ " .long 26b,100b\n"
+ " .long 27b,100b\n"
+ " .long 28b,100b\n"
+ " .long 29b,100b\n"
+ " .long 30b,100b\n"
+ " .long 31b,100b\n"
+ " .long 32b,100b\n"
+ " .long 33b,100b\n"
+ " .long 34b,100b\n"
+ " .long 35b,100b\n"
+ " .long 36b,100b\n"
+ " .long 37b,100b\n"
+ " .long 99b,101b\n"
+ ".previous"
: "=&c"(size), "=&D" (d0), "=&S" (d1)
: "1"(to), "2"(from), "0"(size)
- : "eax", "edx", "memory");
+ : "eax", "edx", "memory");
return size;
}
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 544104c6bbd1..6c8653205128 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -150,4 +150,4 @@ void device_resume(u32 level)
printk("%s is deprecated. Called from:\n",__FUNCTION__);
dump_stack();
}
-
+EXPORT_SYMBOL(device_resume);
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 0747e409d0ec..cf1f6c0b7b0e 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -232,4 +232,4 @@ int device_suspend(u32 state, u32 level)
dump_stack();
return -EFAULT;
}
-
+EXPORT_SYMBOL(device_suspend);
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index fabd43bbf282..38b508cff4d2 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -59,7 +59,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(x) (x)->dev.name
+#define I2C_NAME(x) (x)->name
#include <linux/video_encoder.h>
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index fd807e0e78d4..51a0c9b711dd 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/video_encoder.h>
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 3f95d3e50a6c..a7836d4afb27 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -59,7 +59,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/video_decoder.h>
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index a19a5aa1986f..f3a71267ba8f 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -59,7 +59,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/video_encoder.h>
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 99aaad69dc06..4ab1e76f3304 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -42,7 +42,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/videodev.h>
#include <linux/video_decoder.h>
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 1fd2bb529791..834cfd6ad7ed 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/video_decoder.h>
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 9ab344d8c406..7f0c1f1e2075 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -61,7 +61,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(x) (x)->dev.name
+#define I2C_NAME(x) (x)->name
#include <linux/video_decoder.h>
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 9ac7754fed1f..f7e4a47b0e53 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(s) (s)->dev.name
+#define I2C_NAME(s) (s)->name
#include <linux/video_encoder.h>
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 2b6fb3416142..05d9d6870319 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -291,7 +291,7 @@ static int tvmixer_clients(struct i2c_client *client)
devices[i].count = 0;
devices[i].dev = client;
printk("tvmixer: %s (%s) registered with minor %d\n",
- client->dev.name,client->adapter->dev.name,minor);
+ client->name,client->adapter->name,minor);
return 0;
}
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 5af57f799f4f..29eaa94adfc4 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -33,7 +33,7 @@
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-#define I2C_NAME(x) (x)->dev.name
+#define I2C_NAME(x) (x)->name
#include <linux/videodev.h>
#include <linux/video_decoder.h>
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
index 73c651475d5b..53ddb02179d5 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran.h
@@ -146,11 +146,7 @@ Private IOCTL to set up for displaying MJPEG
#define ZORAN_NAME "ZORAN" /* name of the device */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define ZR_DEVNAME(zr) (zr)->name
-#else
-#define ZR_DEVNAME(zr) (zr)->pci_dev->dev.name
-#endif
+#define ZR_DEVNAME(zr) pci_name((zr)->pci_dev)
#define BUZ_MAX_WIDTH (zr->timing->Wa)
#define BUZ_MAX_HEIGHT (zr->timing->Ha)
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 062c3156852d..71600724ac26 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -54,7 +54,7 @@
#include "zoran_device.h"
#include "zoran_procfs.h"
-#define I2C_NAME(x) (x)->dev.name
+#define I2C_NAME(x) (x)->name
extern const struct zoran_format zoran_formats[];
extern const int zoran_num_formats;
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index c5824132a94a..bae10bf297eb 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -435,7 +435,7 @@ static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
- int timeo;
+ unsigned long timeo;
int status;
DECLARE_WAITQUEUE(wait, current);
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index eceb4e945e92..e718cfe77dae 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -164,7 +164,7 @@ static int vlsi_proc_pdev(struct pci_dev *pdev, char *buf, int len)
return 0;
out += sprintf(out, "\n%s (vid/did: %04x/%04x)\n",
- pdev->dev.name, (int)pdev->vendor, (int)pdev->device);
+ pci_name(pdev), (int)pdev->vendor, (int)pdev->device);
out += sprintf(out, "pci-power-state: %u\n", (unsigned) pdev->current_state);
out += sprintf(out, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n",
pdev->irq, (unsigned)pci_resource_start(pdev, 0), (u64)pdev->dma_mask);
@@ -1522,7 +1522,7 @@ static void vlsi_tx_timeout(struct net_device *ndev)
if (vlsi_start_hw(idev))
printk(KERN_CRIT "%s: failed to restart hw - %s(%s) unusable!\n",
- __FUNCTION__, idev->pdev->dev.name, ndev->name);
+ __FUNCTION__, pci_name(idev->pdev), ndev->name);
else
netif_start_queue(ndev);
}
@@ -1772,7 +1772,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->current_state = 0; /* hw must be running now */
printk(KERN_INFO "%s: IrDA PCI controller %s detected\n",
- drivername, pdev->dev.name);
+ drivername, pci_name(pdev));
if ( !pci_resource_start(pdev,0)
|| !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) {
@@ -1867,7 +1867,7 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
* ndev->destructor called (if present) when going to free
*/
- printk(KERN_INFO "%s: %s removed\n", drivername, pdev->dev.name);
+ printk(KERN_INFO "%s: %s removed\n", drivername, pci_name(pdev));
}
#ifdef CONFIG_PM
@@ -1883,7 +1883,7 @@ static int vlsi_irda_save_state(struct pci_dev *pdev, u32 state)
{
if (state < 1 || state > 3 ) {
printk( KERN_ERR "%s - %s: invalid pm state request: %u\n",
- __FUNCTION__, pdev->dev.name, state);
+ __FUNCTION__, pci_name(pdev), state);
return -1;
}
return 0;
@@ -1896,11 +1896,11 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state)
if (state < 1 || state > 3 ) {
printk( KERN_ERR "%s - %s: invalid pm state request: %u\n",
- __FUNCTION__, pdev->dev.name, state);
+ __FUNCTION__, pci_name(pdev), state);
return 0;
}
if (!ndev) {
- printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name);
+ printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pci_name(pdev));
return 0;
}
idev = ndev->priv;
@@ -1912,7 +1912,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state)
}
else
printk(KERN_ERR "%s - %s: invalid suspend request %u -> %u\n",
- __FUNCTION__, pdev->dev.name, pdev->current_state, state);
+ __FUNCTION__, pci_name(pdev), pdev->current_state, state);
up(&idev->sem);
return 0;
}
@@ -1939,14 +1939,14 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
vlsi_irda_dev_t *idev;
if (!ndev) {
- printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name);
+ printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pci_name(pdev));
return 0;
}
idev = ndev->priv;
down(&idev->sem);
if (pdev->current_state == 0) {
up(&idev->sem);
- printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pdev->dev.name);
+ printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pci_name(pdev));
return 0;
}
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index aeb0ffe105a8..8a0754233354 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -706,7 +706,7 @@ static void hardware_send_packet(struct net_device * dev, char *buf, int length)
inline void wait_for_buffer(struct net_device * dev)
{
int ioaddr = dev->base_addr;
- int tmp;
+ unsigned long tmp;
int status;
tmp = jiffies + HZ;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 4aea1df360e8..ef5a3714dd1b 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -1151,14 +1151,14 @@ static int __init smctr_chk_isa(struct net_device *dev)
if(smctr_read_584_chksum(ioaddr))
{
printk(KERN_ERR "%s: EEPROM Checksum Failure\n", dev->name);
- goto out3;
+ free_irq(dev->irq, dev);
+ goto out2;
}
*/
}
return (0);
-out3:
- free_irq(dev->irq, dev);
+
out2:
release_region(ioaddr, SMCTR_IO_EXTENT);
out:
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 929ca4813194..ba88b3dbf51e 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -172,9 +172,6 @@ config COMX_PROTO_FR
<file:Documentation/modules.txt>. The module will be called
comx-proto-fr.
-#
-# The Etinc driver has not been tested as non-modular yet.
-#
config DSCC4
tristate "Etinc PCISYNC serial board support"
depends on WAN && PCI && m
@@ -189,6 +186,31 @@ config DSCC4
The module will be called dscc4. For general information about
modules read <file:Documentation/modules.txt>.
+config DSCC4_PCISYNC
+ bool "Etinc PCISYNC features"
+ depends on DSCC4
+ help
+ Due to Etinc's design choice for its PCISYNC cards, some operations
+ are only allowed on specific ports of the DSCC4. This option is the
+ only way for the driver to know that it shouldn't return a success
+ code for these operations.
+
+ Please say Y if your card is an Etinc's PCISYNC.
+
+config DSCC4_PCI_RST
+ bool "Hard reset support"
+ depends on DSCC4
+ help
+ Various DSCC4 bugs forbid any reliable software reset of the asic.
+ As a replacement, some vendors provide a way to assert the PCI #RST
+ pin of DSCC4 through the GPIO port of the card. If you choose Y,
+ the driver will make use of this feature before module removal
+ (i.e. rmmod).
+ The feature is known to be available on Commtech's cards.
+ Contact your manufacturer for details.
+
+ Say Y if your card supports this feature.
+
#
# Lan Media's board. Currently 1000, 1200, 5200, 5245
#
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 809ec10d4f2a..2c5e1538a69b 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -112,6 +112,11 @@ static const char version[] = "$Id: dscc4.c,v 1.159 2002/04/10 22:05:17 romieu E
static int debug;
static int quartz;
+#ifdef CONFIG_DSCC4_PCI_RST
+static DECLARE_MUTEX(dscc4_sem);
+static u32 dscc4_pci_config_store[16];
+#endif
+
#define DRV_NAME "dscc4"
#undef DSCC4_POLLING
@@ -172,7 +177,7 @@ struct RxFD {
*/
#define TO_STATE_TX(len) cpu_to_le32(((len) & TxSizeMax) << 16)
#define TO_STATE_RX(len) cpu_to_le32((RX_MAX(len) % RxSizeMax) << 16)
-#define RX_MAX(len) ((((len) >> 5) + 1) << 5)
+#define RX_MAX(len) ((((len) >> 5) + 1) << 5) /* Cf RLCR */
#define SCC_REG_START(dpriv) (SCC_START+(dpriv->dev_id)*SCC_OFFSET)
struct dscc4_pci_priv {
@@ -263,6 +268,10 @@ struct dscc4_dev_priv {
#define IMR 0x54
#define ISR 0x58
+#define GPDIR 0x0400
+#define GPDATA 0x0404
+#define GPIM 0x0408
+
/* Bit masks */
#define EncodingMask 0x00700000
#define CrcMask 0x00000003
@@ -291,6 +300,7 @@ struct dscc4_dev_priv {
#define Hold 0x40000000
#define SccBusy 0x10000000
#define PowerUp 0x80000000
+#define Vis 0x00001000
#define FrameOk (FrameVfr | FrameCrc)
#define FrameVfr 0x80
#define FrameRdo 0x40
@@ -327,10 +337,19 @@ struct dscc4_dev_priv {
#define Arf 0x00000002
#define ArAck 0x00000001
-/* Misc */
+/* State flags */
+#define Ready 0x00000000
#define NeedIDR 0x00000001
#define NeedIDT 0x00000002
#define RdoSet 0x00000004
+#define FakeReset 0x00000008
+
+/* Don't mask RDO. Ever. */
+#ifdef DSCC4_POLLING
+#define EventsMask 0xfffeef7f
+#else
+#define EventsMask 0xfffa8f7a
+#endif
/* Functions prototypes */
static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
@@ -495,9 +514,9 @@ inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
skb = dev_alloc_skb(len);
dpriv->rx_skbuff[dirty] = skb;
if (skb) {
- skb->dev = dev;
- skb->protocol = hdlc_type_trans(skb, dev);
- skb->mac.raw = skb->data;
+ skb->dev = dev;
+ skb->protocol = hdlc_type_trans(skb, dev);
+ skb->mac.raw = skb->data;
rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data,
len, PCI_DMA_FROMDEVICE);
} else {
@@ -574,15 +593,18 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
return (i >= 0 ) ? i : -EAGAIN;
}
-/* Requires protection against interrupt */
static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dpriv->pci_priv->lock, flags);
/* Cf errata DS5 p.6 */
writel(0x00000000, dev->base_addr + CH0LRDA + dpriv->dev_id*4);
- scc_writel(~PowerUp & scc_readl(dpriv, CCR0), dpriv, dev, CCR0);
+ scc_patchl(PowerUp, 0, dpriv, dev, CCR0);
readl(dev->base_addr + CH0LRDA + dpriv->dev_id*4);
writel(MTFi|Rdr, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG);
writel(Action, dev->base_addr + GCMDR);
+ spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags);
}
static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
@@ -590,7 +612,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
u16 i = 0;
/* Cf errata DS5 p.7 */
- scc_writel(~PowerUp & scc_readl(dpriv, CCR0), dpriv, dev, CCR0);
+ scc_patchl(PowerUp, 0, dpriv, dev, CCR0);
scc_writel(0x00050000, dpriv, dev, CCR2);
/*
* Must be longer than the time required to fill the fifo.
@@ -815,7 +837,8 @@ err_out:
static void dscc4_init_registers(struct dscc4_dev_priv *dpriv,
struct net_device *dev)
{
- scc_writel(0x80001000, dpriv, dev, CCR0);
+ /* No interrupts, SCC core disabled. Let's relax */
+ scc_writel(0x00000000, dpriv, dev, CCR0);
scc_writel(LengthCheck | (HDLC_MAX_MRU >> 5), dpriv, dev, RLCR);
@@ -823,22 +846,14 @@ static void dscc4_init_registers(struct dscc4_dev_priv *dpriv,
* No address recognition/crc-CCITT/cts enabled
* Shared flags transmission disabled - cf errata DS5 p.11
* Carrier detect disabled - cf errata p.14
+ * FIXME: carrier detection/polarity may be handled more gracefully.
*/
- scc_writel(0x021c8000, dpriv, dev, CCR1);
+ scc_writel(0x02408000, dpriv, dev, CCR1);
/* crc not forwarded - Cf errata DS5 p.11 */
scc_writel(0x00050008 & ~RxActivate, dpriv, dev, CCR2);
// crc forwarded
//scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
-
- /* Don't mask RDO. Ever. */
-#ifdef DSCC4_POLLING
- scc_writel(0xfffeef7f, dpriv, dev, IMR); /* Interrupt mask */
-#else
- //scc_writel(0xfffaef7f, dpriv, dev, IMR); /* Interrupt mask */
- //scc_writel(0xfffaef7e, dpriv, dev, IMR); /* Interrupt mask */
- scc_writel(0xfffa8f7a, dpriv, dev, IMR); /* Interrupt mask */
-#endif
}
static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
@@ -894,6 +909,10 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
dscc4_init_registers(dpriv, d);
dpriv->parity = PARITY_CRC16_PR0_CCITT;
dpriv->encoding = ENCODING_NRZ;
+ if (dscc4_init_ring(d)) {
+ unregister_hdlc_device(hdlc);
+ goto err_unregister;
+ }
}
if (dscc4_set_quartz(root, quartz) < 0)
goto err_unregister;
@@ -903,8 +922,10 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
return 0;
err_unregister:
- while (--i >= 0)
+ while (--i >= 0) {
+ dscc4_release_ring(root + i);
unregister_hdlc_device(&root[i].hdlc);
+ }
kfree(ppriv);
err_free_dev:
kfree(root);
@@ -943,6 +964,46 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv)
return 0;
}
+#ifdef CONFIG_DSCC4_PCI_RST
+/*
+ * Some DSCC4-based cards wires the GPIO port and the PCI #RST pin together
+ * so as to provide a safe way to reset the asic while not the whole machine
+ * rebooting.
+ *
+ * This code doesn't need to be efficient. Keep It Simple
+ */
+static void dscc4_pci_reset(struct pci_dev *pdev, u32 ioaddr)
+{
+ int i;
+
+ down(&dscc4_sem);
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(pdev, i << 2, dscc4_pci_config_store + i);
+
+ /* Maximal LBI clock divider (who cares ?) and whole GPIO range. */
+ writel(0x001c0000, ioaddr + GMODE);
+ /* Configure GPIO port as output */
+ writel(0x0000ffff, ioaddr + GPDIR);
+ /* Disable interruption */
+ writel(0x0000ffff, ioaddr + GPIM);
+
+ writel(0x0000ffff, ioaddr + GPDATA);
+ writel(0x00000000, ioaddr + GPDATA);
+
+ /* Flush posted writes */
+ readl(ioaddr + GSTAR);
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
+ up(&dscc4_sem);
+}
+#else
+#define dscc4_pci_reset(pdev,ioaddr) do {} while (0)
+#endif /* CONFIG_DSCC4_PCI_RST */
+
static int dscc4_open(struct net_device *dev)
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
@@ -958,12 +1019,29 @@ static int dscc4_open(struct net_device *dev)
ppriv = dpriv->pci_priv;
- if ((ret = dscc4_init_ring(dev)))
- goto err_out;
+ /*
+ * Due to various bugs, there is no way to reliably reset a
+ * specific port (manufacturer's dependant special PCI #RST wiring
+ * apart: it affects all ports). Thus the device goes in the best
+ * silent mode possible at dscc4_close() time and simply claims to
+ * be up if it's opened again. It still isn't possible to change
+ * the HDLC configuration without rebooting but at least the ports
+ * can be up/down ifconfig'ed without killing the host.
+ */
+ if (dpriv->flags & FakeReset) {
+ dpriv->flags &= ~FakeReset;
+ scc_patchl(0, PowerUp, dpriv, dev, CCR0);
+ scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
+ scc_writel(EventsMask, dpriv, dev, IMR);
+ printk(KERN_INFO "%s: up again.\n", dev->name);
+ goto done;
+ }
/* IDT+IDR during XPR */
dpriv->flags = NeedIDR | NeedIDT;
+ scc_patchl(0, PowerUp | Vis, dpriv, dev, CCR0);
+
/*
* The following is a bit paranoid...
*
@@ -974,15 +1052,17 @@ static int dscc4_open(struct net_device *dev)
if (scc_readl_star(dpriv, dev) & SccBusy) {
printk(KERN_ERR "%s busy. Try later\n", dev->name);
ret = -EAGAIN;
- goto err_free_ring;
+ goto err_out;
} else
printk(KERN_INFO "%s: available. Good\n", dev->name);
+ scc_writel(EventsMask, dpriv, dev, IMR);
+
/* Posted write is flushed in the wait_ack loop */
scc_writel(TxSccRes | RxSccRes, dpriv, dev, CMDR);
if ((ret = dscc4_wait_ack_cec(dpriv, dev, "Cec")) < 0)
- goto err_free_ring;
+ goto err_disable_scc_events;
/*
* I would expect XPR near CE completion (before ? after ?).
@@ -993,12 +1073,13 @@ static int dscc4_open(struct net_device *dev)
*/
if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
- goto err_free_ring;
+ goto err_disable_scc_events;
}
if (debug > 2)
dscc4_tx_print(dev, dpriv, "Open");
+done:
netif_start_queue(dev);
init_timer(&dpriv->timer);
@@ -1010,7 +1091,10 @@ static int dscc4_open(struct net_device *dev)
return 0;
+err_disable_scc_events:
+ scc_writel(0xffffffff, dpriv, dev, IMR);
err_free_ring:
+ scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
dscc4_release_ring(dpriv);
err_out:
hdlc_close(hdlc);
@@ -1066,21 +1150,19 @@ static int dscc4_close(struct net_device *dev)
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
hdlc_device *hdlc = dev_to_hdlc(dev);
- unsigned long flags;
del_timer_sync(&dpriv->timer);
netif_stop_queue(dev);
- spin_lock_irqsave(&dpriv->pci_priv->lock, flags);
- dscc4_rx_reset(dpriv, dev);
- spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags);
+ scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
+ scc_patchl(0x00050000, 0, dpriv, dev, CCR2);
+ scc_writel(0xffffffff, dpriv, dev, IMR);
- dscc4_tx_reset(dpriv, dev);
+ dpriv->flags |= FakeReset;
hdlc_close(hdlc);
dscc4_release_ring(dpriv);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1088,13 +1170,56 @@ static inline int dscc4_check_clock_ability(int port)
{
int ret = 0;
-#ifdef CONFIG_DSCC4_CLOCK_ON_TWO_PORTS_ONLY
+#ifdef CONFIG_DSCC4_PCISYNC
if (port >= 2)
ret = -1;
#endif
return ret;
}
+/*
+ * DS1 p.137: "There are a total of 13 different clocking modes..."
+ * ^^
+ * Design choices:
+ * - by default, assume a clock is provided on pin RxClk/TxClk (clock mode 0a).
+ * Clock mode 3b _should_ work but the testing seems to make this point
+ * dubious (DIY testing requires setting CCR0 at 0x00000033).
+ * This is supposed to provide least surprise "DTE like" behavior.
+ * - if line rate is specified, clocks are assumed to be locally generated.
+ * A quartz must be available (on pin XTAL1). Modes 6b/7b are used. Choosing
+ * between these it automagically done according on the required frequency
+ * scaling. Of course some rounding may take place.
+ * - no high speed mode (40Mb/s). May be trivial to do but I don't have an
+ * appropriate external clocking device for testing.
+ * - no time-slot/clock mode 5: shameless lazyness.
+ *
+ * The clock signals wiring can be (is ?) manufacturer dependant. Good luck.
+ *
+ * BIG FAT WARNING: if the device isn't provided enough clocking signal, it
+ * won't pass the init sequence. For example, straight back-to-back DTE without
+ * external clock will fail when dscc4_open() (<- 'ifconfig hdlcx xxx') is
+ * called.
+ *
+ * Typos lurk in datasheet (missing divier in clock mode 7a figure 51 p.153
+ * DS0 for example)
+ *
+ * Clock mode related bits of CCR0:
+ * +------------ TOE: output TxClk (0b/2b/3a/3b/6b/7a/7b only)
+ * | +---------- SSEL: sub-mode select 0 -> a, 1 -> b
+ * | | +-------- High Speed: say 0
+ * | | | +-+-+-- Clock Mode: 0..7
+ * | | | | | |
+ * -+-+-+-+-+-+-+-+
+ * x|x|5|4|3|2|1|0| lower bits
+ *
+ * Division factor of BRR: k = (N+1)x2^M (total divider = 16xk in mode 6b)
+ * +-+-+-+------------------ M (0..15)
+ * | | | | +-+-+-+-+-+-- N (0..63)
+ * 0 0 0 0 | | | | 0 0 | | | | | |
+ * ...-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * f|e|d|c|b|a|9|8|7|6|5|4|3|2|1|0| lower bits
+ *
+ */
static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state)
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
@@ -1131,13 +1256,13 @@ static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state)
}
brr = (m << 8) | n;
divider = n << m;
- if (!(*state & 0x00000001)) /* Clock mode 6b */
+ if (!(*state & 0x00000001)) /* ?b mode mask => clock mode 6b */
divider <<= 4;
*bps = xtal / divider;
} else {
/*
* External clock - DTE
- * "state" already reflects Clock mode 0a.
+ * "state" already reflects Clock mode 0a (CCR0 = 0xzzzzzz00).
* Nothing more to be done
*/
brr = 0;
@@ -1176,6 +1301,11 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (dpriv->flags & FakeReset) {
+ printk(KERN_INFO "%s: please reset the device"
+ " before this command\n", dev->name);
+ return -EPERM;
+ }
if (copy_from_user(&dpriv->settings, line, size))
return -EFAULT;
ret = dscc4_set_iface(dpriv, dev);
@@ -1234,7 +1364,7 @@ static int dscc4_clock_setting(struct dscc4_dev_priv *dpriv,
settings->clock_rate = bps;
}
} else { /* DTE */
- state = 0x80001000;
+ state |= PowerUp | Vis;
printk(KERN_DEBUG "%s: external RxClk (DTE)\n", dev->name);
}
scc_writel(state, dpriv, dev, CCR0);
@@ -1342,6 +1472,8 @@ static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs)
handled = 0;
goto out;
}
+ if (debug > 3)
+ printk(KERN_DEBUG "%s: GSTAR = 0x%08x\n", DRV_NAME, state);
writel(state, ioaddr + GSTAR);
if (state & Arf) {
@@ -1388,6 +1520,9 @@ try:
cur = dpriv->iqtx_current%IRQ_RING_SIZE;
state = dpriv->iqtx[cur];
if (!state) {
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx ISR = 0x%08x\n", dev->name,
+ state);
if ((debug > 1) && (loop > 1))
printk(KERN_DEBUG "%s: Tx irq loop=%d\n", dev->name, loop);
if (loop && netif_queue_stopped(dev))
@@ -1474,9 +1609,19 @@ try:
}
if (state & Xpr) {
u32 scc_addr, ring;
+ int i;
+
+ /*
+ * - the busy condition happens (sometimes);
+ * - it doesn't seem to make the handler unreliable.
+ */
+ for (i = 1; i; i <<= 1) {
+ if (!(scc_readl_star(dpriv, dev) & SccBusy))
+ break;
+ }
+ if (!i)
+ printk(KERN_INFO "%s busy in irq\n", dev->name);
- if (scc_readl_star(dpriv, dev) & SccBusy)
- printk(KERN_ERR "%s busy. Fatal\n", dev->name);
scc_addr = dev->base_addr + 0x0c*dpriv->dev_id;
/* Keep this order: IDT before IDR */
if (dpriv->flags & NeedIDT) {
@@ -1511,7 +1656,8 @@ try:
goto try;
}
if (state & Cd) {
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ if (debug > 0)
+ printk(KERN_INFO "%s: CD transition\n", dev->name);
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
@@ -1553,6 +1699,9 @@ try:
if (!(state & SccEvt)){
struct RxFD *rx_fd;
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Rx ISR = 0x%08x\n", dev->name,
+ state);
state &= 0x00ffffff;
if (state & Err) { /* Hold or reset */
printk(KERN_DEBUG "%s: Rx ERR\n", dev->name);
@@ -1807,12 +1956,16 @@ static void __devexit dscc4_remove_one(struct pci_dev *pdev)
root = ppriv->root;
ioaddr = hdlc_to_dev(&root->hdlc)->base_addr;
+
+ dscc4_pci_reset(pdev, ioaddr);
+
free_irq(pdev->irq, root);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), ppriv->iqcfg,
ppriv->iqcfg_dma);
for (i = 0; i < dev_per_card; i++) {
struct dscc4_dev_priv *dpriv = root + i;
+ dscc4_release_ring(dpriv);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32),
dpriv->iqrx, dpriv->iqrx_dma);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32),
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 791d479b7af9..349400d4d95a 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -277,7 +277,7 @@ sbni_pci_probe( struct net_device *dev )
pci_irq_line = pdev->irq;
/* Avoid already found cards from previous calls */
- if( !pci_request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
+ if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
if( subsys != 2 || /* Dual adapter is present */
check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) )
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index bcef6732f6b9..dba125a0db5c 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -852,9 +852,7 @@ char *lprint_command(unsigned char *cmd, char *pos, char *buffer, int len);
static
char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
-#ifndef NCR5380_proc_info
static
-#endif
int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
{
char *pos = buffer;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index de33277d23fb..321540cb403b 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -310,10 +310,8 @@ static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
static int NCR5380_host_reset(Scsi_Cmnd * cmd);
static int NCR5380_device_reset(Scsi_Cmnd * cmd);
static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
-#ifdef NCR5380_proc_info
-int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
+static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
off_t offset, int length, int inout);
-#endif
static void NCR5380_reselect(struct Scsi_Host *instance);
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index e99f6ac7402a..24cb71bf0512 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -549,7 +549,7 @@ struct aac_queue {
/* This is only valid for adapter to host command queues. */
spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */
spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */
- u32 SavedIrql; /* Previous IRQL when the spin lock is taken */
+ unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */
u32 padding; /* Padding - FIXME - can remove I believe */
struct aac_list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */
// struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 9b1e7cace348..481747660fe5 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -602,8 +602,8 @@ static int aha1740_probe (struct device *dev)
outb(G2CNTRL_HRST, G2CNTRL(slotbase));
outb(0, G2CNTRL(slotbase));
}
- printk(KERN_INFO "Configuring %s at IO:%x, IRQ %d\n",
- dev->name, slotbase, irq_level);
+ printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %d\n",
+ edev->slot, slotbase, irq_level);
printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
translation ? "en" : "dis");
shpnt = scsi_host_alloc(&aha1740_template,
@@ -656,8 +656,7 @@ static __devexit int aha1740_remove (struct device *dev)
struct Scsi_Host *shpnt = dev->driver_data;
struct aha1740_hostdata *host = HOSTDATA (shpnt);
- if (scsi_remove_host (shpnt))
- return -EBUSY;
+ scsi_remove_host(shpnt);
free_irq (shpnt->irq, shpnt);
dma_unmap_single (dev, host->ecb_dma_addr,
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 40076ce0754a..cd8ddb7084a2 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -743,9 +743,7 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
static
char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-#ifndef NCR5380_proc_info
static
-#endif
int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
int length, int inout)
{
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 0985bd1775bd..46542d8c93e9 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -780,7 +780,7 @@ static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
* Locks: global cli/lock for queue walk
*/
-int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
+static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
{
int len = 0;
NCR5380_local_declare();
diff --git a/drivers/scsi/mac_NCR5380.c b/drivers/scsi/mac_NCR5380.c
index 15def3d40380..58af823e8187 100644
--- a/drivers/scsi/mac_NCR5380.c
+++ b/drivers/scsi/mac_NCR5380.c
@@ -768,9 +768,7 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
static
char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-#ifndef NCR5380_proc_info
static
-#endif
int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
int length, int inout)
{
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 8501908c3b7f..90811390a37d 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -754,7 +754,7 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
static
char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start,
+static int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start,
off_t offset, int length, int inout)
{
char *pos = buffer;
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index abb52f85a80c..65554c41b026 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -294,7 +294,7 @@ static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt);
/* Always called with host lock held */
-static inline int find_and_clear_bit_16(unsigned short *field)
+static inline int find_and_clear_bit_16(unsigned long *field)
{
int rv;
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 15d8e9b3b8a9..977da0680491 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -143,7 +143,7 @@ static int __init usb_console_setup(struct console *co, char *options)
return -ENODEV;
}
- port = &serial->port[0];
+ port = serial->port[0];
port->tty = NULL;
info->port = port;
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 3cffce0bf2e2..11ee359aa10f 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -454,9 +454,10 @@ static struct accel_switch accel_image = {
static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr)
{
int bpp = info->var.bits_per_pixel;
- int dx,dy,w,h,col;
+ int col;
switch (bpp) {
+ default:
case 8: col = fr->color;
break;
case 16: col = ((u16 *)(info->pseudo_palette))[fr->color];
@@ -1129,7 +1130,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
return -1;
}
- output("%s board found\n", dev->dev.name);
+ output("%s board found\n", pci_name(dev));
#if 0
output("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n",
tridentfb_fix.smem_start, tridentfb_fix.mmio_start, fb_info.screen_base, default_par.io_virt);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index a200cc3420c6..d7a6d259d4a0 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -419,12 +419,34 @@ void bd_forget(struct inode *inode)
int bd_claim(struct block_device *bdev, void *holder)
{
- int res = -EBUSY;
+ int res;
spin_lock(&bdev_lock);
- if (!bdev->bd_holder || bdev->bd_holder == holder) {
- bdev->bd_holder = holder;
+
+ /* first decide result */
+ if (bdev->bd_holder == holder)
+ res = 0; /* already a holder */
+ else if (bdev->bd_holder != NULL)
+ res = -EBUSY; /* held by someone else */
+ else if (bdev->bd_contains == bdev)
+ res = 0; /* is a whole device which isn't held */
+
+ else if (bdev->bd_contains->bd_holder == bd_claim)
+ res = 0; /* is a partition of a device that is being partitioned */
+ else if (bdev->bd_contains->bd_holder != NULL)
+ res = -EBUSY; /* is a partition of a held device */
+ else
+ res = 0; /* is a partition of an un-held device */
+
+ /* now impose change */
+ if (res==0) {
+ /* note that for a whole device bd_holders
+ * will be incremented twice, and bd_holder will
+ * be set to bd_claim before being set to holder
+ */
+ bdev->bd_contains->bd_holders ++;
+ bdev->bd_contains->bd_holder = bd_claim;
bdev->bd_holders++;
- res = 0;
+ bdev->bd_holder = holder;
}
spin_unlock(&bdev_lock);
return res;
@@ -433,6 +455,8 @@ int bd_claim(struct block_device *bdev, void *holder)
void bd_release(struct block_device *bdev)
{
spin_lock(&bdev_lock);
+ if (!--bdev->bd_contains->bd_holders)
+ bdev->bd_contains->bd_holder = NULL;
if (!--bdev->bd_holders)
bdev->bd_holder = NULL;
spin_unlock(&bdev_lock);
@@ -619,6 +643,7 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
int blkdev_open(struct inode * inode, struct file * filp)
{
struct block_device *bdev;
+ int res;
/*
* Preserve backwards compatibility and allow large file access
@@ -631,7 +656,18 @@ int blkdev_open(struct inode * inode, struct file * filp)
bd_acquire(inode);
bdev = inode->i_bdev;
- return do_open(bdev, inode, filp);
+ res = do_open(bdev, inode, filp);
+ if (res)
+ return res;
+
+ if (!(filp->f_flags & O_EXCL) )
+ return 0;
+
+ if (!(res = bd_claim(bdev, filp)))
+ return 0;
+
+ blkdev_put(bdev, BDEV_FILE);
+ return res;
}
int blkdev_put(struct block_device *bdev, int kind)
@@ -680,6 +716,8 @@ int blkdev_put(struct block_device *bdev, int kind)
int blkdev_close(struct inode * inode, struct file * filp)
{
+ if (inode->i_bdev->bd_holder == filp)
+ bd_release(inode->i_bdev);
return blkdev_put(inode->i_bdev, BDEV_FILE);
}
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index bd38d4921a6e..c11a92f9f3b3 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -279,7 +279,8 @@ error_return:
return;
}
-/* For ext3 allocations, we must not reuse any blocks which are
+/*
+ * For ext3 allocations, we must not reuse any blocks which are
* allocated in the bitmap buffer's "last committed data" copy. This
* prevents deletes from freeing up the page for reuse until we have
* committed the delete transaction.
@@ -294,14 +295,21 @@ error_return:
* data-writes at some point, and disable it for metadata allocations or
* sync-data inodes.
*/
-static inline int ext3_test_allocatable(int nr, struct buffer_head *bh,
- int have_access)
+static inline int ext3_test_allocatable(int nr, struct buffer_head *bh)
{
+ int ret;
+ struct journal_head *jh = bh2jh(bh);
+
if (ext3_test_bit(nr, bh->b_data))
return 0;
- if (!have_access || !buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
- return 1;
- return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
+
+ jbd_lock_bh_state(bh);
+ if (!jh->b_committed_data)
+ ret = 1;
+ else
+ ret = !ext3_test_bit(nr, jh->b_committed_data);
+ jbd_unlock_bh_state(bh);
+ return ret;
}
/*
@@ -311,11 +319,12 @@ static inline int ext3_test_allocatable(int nr, struct buffer_head *bh,
* the initial goal; then for a free byte somewhere in the bitmap; then
* for any free bit in the bitmap.
*/
-static int find_next_usable_block(int start, struct buffer_head *bh,
- int maxblocks, int have_access)
+static int
+find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
{
int here, next;
char *p, *r;
+ struct journal_head *jh = bh2jh(bh);
if (start > 0) {
/*
@@ -328,48 +337,38 @@ static int find_next_usable_block(int start, struct buffer_head *bh,
*/
int end_goal = (start + 63) & ~63;
here = ext3_find_next_zero_bit(bh->b_data, end_goal, start);
- if (here < end_goal &&
- ext3_test_allocatable(here, bh, have_access))
+ if (here < end_goal && ext3_test_allocatable(here, bh))
return here;
-
- ext3_debug ("Bit not found near goal\n");
+ ext3_debug("Bit not found near goal\n");
}
here = start;
if (here < 0)
here = 0;
- /*
- * There has been no free block found in the near vicinity of
- * the goal: do a search forward through the block groups,
- * searching in each group first for an entire free byte in the
- * bitmap and then for any free bit.
- *
- * Search first in the remainder of the current group
- */
- p = ((char *) bh->b_data) + (here >> 3);
+ p = ((char *)bh->b_data) + (here >> 3);
r = memscan(p, 0, (maxblocks - here + 7) >> 3);
- next = (r - ((char *) bh->b_data)) << 3;
+ next = (r - ((char *)bh->b_data)) << 3;
- if (next < maxblocks && ext3_test_allocatable(next, bh, have_access))
+ if (next < maxblocks && ext3_test_allocatable(next, bh))
return next;
- /* The bitmap search --- search forward alternately
- * through the actual bitmap and the last-committed copy
- * until we find a bit free in both. */
-
+ /*
+ * The bitmap search --- search forward alternately through the actual
+ * bitmap and the last-committed copy until we find a bit free in
+ * both
+ */
while (here < maxblocks) {
- next = ext3_find_next_zero_bit ((unsigned long *) bh->b_data,
- maxblocks, here);
+ next = ext3_find_next_zero_bit(bh->b_data, maxblocks, here);
if (next >= maxblocks)
return -1;
- if (ext3_test_allocatable(next, bh, have_access))
+ if (ext3_test_allocatable(next, bh))
return next;
-
- if (have_access)
- here = ext3_find_next_zero_bit
- ((unsigned long *) bh2jh(bh)->b_committed_data,
- maxblocks, next);
+ jbd_lock_bh_state(bh);
+ if (jh->b_committed_data)
+ here = ext3_find_next_zero_bit(jh->b_committed_data,
+ maxblocks, next);
+ jbd_unlock_bh_state(bh);
}
return -1;
}
@@ -384,14 +383,20 @@ static int find_next_usable_block(int start, struct buffer_head *bh,
static inline int
claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
{
+ struct journal_head *jh = bh2jh(bh);
+ int ret;
+
if (ext3_set_bit_atomic(lock, block, bh->b_data))
return 0;
- if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data &&
- ext3_test_bit(block, bh2jh(bh)->b_committed_data)) {
+ jbd_lock_bh_state(bh);
+ if (jh->b_committed_data && ext3_test_bit(block,jh->b_committed_data)) {
ext3_clear_bit_atomic(lock, block, bh->b_data);
- return 0;
+ ret = 0;
+ } else {
+ ret = 1;
}
- return 1;
+ jbd_unlock_bh_state(bh);
+ return ret;
}
/*
@@ -403,43 +408,34 @@ static int
ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
struct buffer_head *bitmap_bh, int goal, int *errp)
{
- int i, fatal = 0;
- int have_access = 0;
+ int i;
+ int fatal;
int credits = 0;
*errp = 0;
- if (goal >= 0 && ext3_test_allocatable(goal, bitmap_bh, 0))
- goto got;
-
-repeat:
- goal = find_next_usable_block(goal, bitmap_bh,
- EXT3_BLOCKS_PER_GROUP(sb), have_access);
- if (goal < 0)
+ /*
+ * Make sure we use undo access for the bitmap, because it is critical
+ * that we do the frozen_data COW on bitmap buffers in all cases even
+ * if the buffer is in BJ_Forget state in the committing transaction.
+ */
+ BUFFER_TRACE(bitmap_bh, "get undo access for new block");
+ fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
+ if (fatal) {
+ *errp = fatal;
goto fail;
+ }
- for (i = 0;
- i < 7 && goal > 0 &&
- ext3_test_allocatable(goal - 1, bitmap_bh, have_access);
- i++, goal--);
-
-got:
- if (!have_access) {
- /*
- * Make sure we use undo access for the bitmap, because it is
- * critical that we do the frozen_data COW on bitmap buffers in
- * all cases even if the buffer is in BJ_Forget state in the
- * committing transaction.
- */
- BUFFER_TRACE(bitmap_bh, "get undo access for new block");
- fatal = ext3_journal_get_undo_access(handle, bitmap_bh,
- &credits);
- if (fatal) {
- *errp = fatal;
- goto fail;
- }
- jbd_lock_bh_state(bitmap_bh);
- have_access = 1;
+repeat:
+ if (goal < 0 || !ext3_test_allocatable(goal, bitmap_bh)) {
+ goal = find_next_usable_block(goal, bitmap_bh,
+ EXT3_BLOCKS_PER_GROUP(sb));
+ if (goal < 0)
+ goto fail_access;
+
+ for (i = 0; i < 7 && goal > 0 &&
+ ext3_test_allocatable(goal - 1, bitmap_bh);
+ i++, goal--);
}
if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
@@ -449,29 +445,25 @@ got:
*/
goal++;
if (goal >= EXT3_BLOCKS_PER_GROUP(sb))
- goto fail;
+ goto fail_access;
goto repeat;
}
BUFFER_TRACE(bitmap_bh, "journal_dirty_metadata for bitmap block");
- jbd_unlock_bh_state(bitmap_bh);
fatal = ext3_journal_dirty_metadata(handle, bitmap_bh);
if (fatal) {
*errp = fatal;
goto fail;
}
-
return goal;
+
+fail_access:
+ BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
+ ext3_journal_release_buffer(handle, bitmap_bh, credits);
fail:
- if (have_access) {
- BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
- jbd_unlock_bh_state(bitmap_bh);
- ext3_journal_release_buffer(handle, bitmap_bh, credits);
- }
return -1;
}
-
/*
* ext3_new_block uses a goal block to assist allocation. If the goal is
* free, or there is a free block within 32 blocks of the goal, that block
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 74e53bcc480e..0f89adccfa82 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1284,6 +1284,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
unsigned blocksize;
struct dx_hash_info hinfo;
u32 block;
+ struct fake_dirent *fde;
blocksize = dir->i_sb->s_blocksize;
dxtrace(printk("Creating index\n"));
@@ -1304,7 +1305,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
data1 = bh2->b_data;
/* The 0th block becomes the root, move the dirents out */
- de = (struct ext3_dir_entry_2 *) &root->info;
+ fde = &root->dotdot;
+ de = (struct ext3_dir_entry_2 *)((char *)fde + fde->rec_len);
len = ((char *) root) + blocksize - (char *) de;
memcpy (data1, de, len);
de = (struct ext3_dir_entry_2 *) data1;
@@ -2006,9 +2008,9 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
* recovery. */
inode->i_size = 0;
ext3_orphan_add(handle, inode);
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
ext3_mark_inode_dirty(handle, inode);
dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
@@ -2060,8 +2062,8 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
inode->i_nlink--;
if (!inode->i_nlink)
ext3_orphan_add(handle, inode);
- ext3_mark_inode_dirty(handle, inode);
inode->i_ctime = dir->i_ctime;
+ ext3_mark_inode_dirty(handle, inode);
retval = 0;
end_unlink:
@@ -2220,7 +2222,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
goto end_rename;
} else {
BUFFER_TRACE(new_bh, "get write access");
- BUFFER_TRACE(new_bh, "get_write_access");
ext3_journal_get_write_access(handle, new_bh);
new_de->inode = le32_to_cpu(old_inode->i_ino);
if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 643ccd392f23..a7a3bdaac4ec 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -300,7 +300,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
task_lock(task);
mm = task->mm;
if(mm)
- atomic_inc(&mm->mm_users);
+ mm = mmgrab(mm);
if (task->tty) {
tty_pgrp = task->tty->pgrp;
tty_nr = task->tty->device;
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index a63520b95a36..c21ed08175d5 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -98,6 +98,8 @@ extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu)
{
+ if (cpu >= NR_CPUS)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
}
diff --git a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
index f83d03b0458f..aa7fd107c1c9 100644
--- a/include/asm-i386/mach-es7000/mach_apic.h
+++ b/include/asm-i386/mach-es7000/mach_apic.h
@@ -123,6 +123,8 @@ extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu)
{
+ if (cpu >= NR_CPUS)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
}
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index ceca92723c0e..2f9f19237460 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -60,6 +60,8 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
extern u8 cpu_2_logical_apicid[];
static inline int cpu_to_logical_apicid(int cpu)
{
+ if (cpu >= NR_CPUS)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
}
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 2247c7adca3d..f79d5df55e1a 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -80,6 +80,8 @@ static inline int apicid_to_node(int logical_apicid)
extern u8 cpu_2_logical_apicid[];
static inline int cpu_to_logical_apicid(int cpu)
{
+ if (cpu >= NR_CPUS)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
}
diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
index 2376c50ba6e9..ab40e5c0f3e5 100644
--- a/include/asm-i386/mach-visws/mach_apic.h
+++ b/include/asm-i386/mach-visws/mach_apic.h
@@ -1,6 +1,8 @@
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
+#include <mach_apicdef.h>
+
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
#define no_balance_irq (0)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 61ec12b5b77a..054168543a45 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -638,6 +638,8 @@ static inline void mmdrop(struct mm_struct * mm)
/* mmput gets rid of the mappings and all user-space */
extern void mmput(struct mm_struct *);
+/* Grab a reference to the mm if its not already going away */
+extern struct mm_struct *mmgrab(struct mm_struct *);
/* Remove the current tasks stale references to the old mm_struct */
extern void mm_release(struct task_struct *, struct mm_struct *);
@@ -745,7 +747,7 @@ static inline struct mm_struct * get_task_mm(struct task_struct * task)
task_lock(task);
mm = task->mm;
if (mm)
- atomic_inc(&mm->mm_users);
+ mm = mmgrab(mm);
task_unlock(task);
return mm;
diff --git a/init/Kconfig b/init/Kconfig
index b01e44f573eb..6d2d615c9f15 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -140,7 +140,7 @@ config IKCONFIG
config IKCONFIG_PROC
bool "Enable access to .config through /proc/ikconfig"
- depends on IKCONFIG
+ depends on IKCONFIG && PROC_FS
---help---
This option enables access to kernel configuration file and build
information through /proc/ikconfig.
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 63066472d568..f3812f4fc4f9 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -286,8 +286,6 @@ retry:
root_device_name, b);
printk("Please append a correct \"root=\" boot option\n");
- mount_root_failed_msg(); /* architecture dependent */
-
panic("VFS: Unable to mount root fs on %s", b);
}
panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 7780dd759d9e..b10b9654a2cd 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -80,13 +80,3 @@ static inline void md_run_setup(void) {}
#endif
-#ifdef CONFIG_MOUNT_ROOT_FAILED_MSG
-
-void mount_root_failed_msg(void);
-
-#else
-
-static inline void mount_root_failed_msg(void) {}
-
-#endif
-
diff --git a/kernel/fork.c b/kernel/fork.c
index b65c19fe2dce..690b8d77a04b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -398,6 +398,23 @@ void mmput(struct mm_struct *mm)
}
}
+/*
+ * Checks if the use count of an mm is non-zero and if so
+ * returns a reference to it after bumping up the use count.
+ * If the use count is zero, it means this mm is going away,
+ * so return NULL.
+ */
+struct mm_struct *mmgrab(struct mm_struct *mm)
+{
+ spin_lock(&mmlist_lock);
+ if (!atomic_read(&mm->mm_users))
+ mm = NULL;
+ else
+ atomic_inc(&mm->mm_users);
+ spin_unlock(&mmlist_lock);
+ return mm;
+}
+
/* Please note the differences between mmput and mm_release.
* mmput is called whenever we stop holding onto a mm_struct,
* error success whatever.
diff --git a/mm/filemap.c b/mm/filemap.c
index fcc9fc2735e2..0fe1ba24b8b2 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -67,6 +67,9 @@
* ->mmap_sem
* ->lock_page (access_process_vm)
*
+ * ->mmap_sem
+ * ->i_sem (msync)
+ *
* ->inode_lock
* ->sb_lock (fs/fs-writeback.c)
* ->mapping->page_lock (__sync_single_inode)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index bec66b42ee75..860368990523 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -279,6 +279,7 @@ shrink_list(struct list_head *page_list, unsigned int gfp_mask,
while (!list_empty(page_list)) {
struct page *page;
int may_enter_fs;
+ int referenced;
page = list_entry(page_list->prev, struct page, lru);
list_del(&page->lru);
@@ -298,7 +299,8 @@ shrink_list(struct list_head *page_list, unsigned int gfp_mask,
goto keep_locked;
pte_chain_lock(page);
- if (page_referenced(page) && page_mapping_inuse(page)) {
+ referenced = page_referenced(page);
+ if (referenced && page_mapping_inuse(page)) {
/* In active use or really unfreeable. Activate it. */
pte_chain_unlock(page);
goto activate_locked;
@@ -358,6 +360,8 @@ shrink_list(struct list_head *page_list, unsigned int gfp_mask,
* See swapfile.c:page_queue_congested().
*/
if (PageDirty(page)) {
+ if (referenced)
+ goto keep_locked;
if (!is_page_cache_freeable(page))
goto keep_locked;
if (!mapping)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 4db8a6a814f6..f388ac2b59fd 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -752,6 +752,7 @@ static int __devinit snd_opl3sa2_probe(int dev,
err = -ENOMEM;
goto __error;
}
+ spin_lock_init(&chip->reg_lock);
chip->irq = -1;
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
goto __error;