Commit ca1ba071 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/tmp3
parents be76fe34 bf4a3963
......@@ -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
......
......@@ -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
......
......@@ -437,10 +437,8 @@ M: hpa@zytor.com
S: Maintained
CRAMFS FILESYSTEM
P: Daniel Quinlan
M: quinlan@transmeta.com
W: http://sourceforge.net/projects/cramfs/
S: Maintained
W: http://sourceforge.net/projects/cramfs/
S: Orphan
CREDITS FILE
P: John A. Martin
......
......@@ -33,13 +33,6 @@
# error NR_IRQS < MARVEL_NR_IRQS !!!
#endif
/* ??? Should probably be generic. */
#ifdef CONFIG_PCI_NAMES
#define pci_pretty_name(x) ((x)->pretty_name)
#else
#define pci_pretty_name(x) ""
#endif
/*
* Interrupt handling.
......
......@@ -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"
......
......@@ -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
......
......@@ -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: "
......
......@@ -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 */
......@@ -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"
......
......@@ -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;
}
......
......@@ -31,12 +31,6 @@
#include <asm/kdebug.h>
#include <asm/proto.h>
#ifdef CONFIG_PCI_NAMES
#define pci_pretty_name(dev) ((dev)->pretty_name)
#else
#define pci_pretty_name(dev) ""
#endif
dma_addr_t bad_dma_address;
unsigned long iommu_bus_base; /* GART remapping area (physical) */
......
......@@ -150,4 +150,4 @@ void device_resume(u32 level)
printk("%s is deprecated. Called from:\n",__FUNCTION__);
dump_stack();
}
EXPORT_SYMBOL(device_resume);
......@@ -232,4 +232,4 @@ int device_suspend(u32 state, u32 level)
dump_stack();
return -EFAULT;
}
EXPORT_SYMBOL(device_suspend);
......@@ -5,16 +5,6 @@
menu "Video For Linux"
depends on VIDEO_DEV!=n
config VIDEO_PROC_FS
bool "V4L information in proc filesystem"
depends on PROC_FS
help
If you say Y here, you are able to access video device information
in /proc/video.
To use this option, you have to check, that the "/proc file system
support" (CONFIG_PROC_FS) is enabled too.
comment "Video Adapters"
config VIDEO_BT848
......
......@@ -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;
......
......@@ -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
#
......
......@@ -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 @@ static int __init dscc4_init_one(struct pci_dev *pdev,
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 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
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 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
}
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 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
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 @@ static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
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),
......
......@@ -34,7 +34,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
......
......@@ -31,7 +31,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
......
......@@ -80,14 +80,14 @@ void __devinit pci_name_device(struct pci_dev *dev)
}
/* Ok, found the vendor, but unknown device */
sprintf(name, "PCI device %04x:%04x (%." DEVICE_NAME_HALF "s)",
sprintf(name, "PCI device %04x:%04x (%." PCI_NAME_HALF "s)",
dev->vendor, dev->device, vendor_p->name);
return;
/* Full match */
match_device: {
char *n = name + sprintf(name, "%." DEVICE_NAME_HALF
"s %." DEVICE_NAME_HALF "s",
char *n = name + sprintf(name, "%." PCI_NAME_HALF
"s %." PCI_NAME_HALF "s",
vendor_p->name, device_p->name);
int nr = device_p->seen + 1;
device_p->seen = nr;
......
......@@ -122,10 +122,8 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
if (!pci_dev->driver && drv->probe) {
error = pci_device_probe_static(drv, pci_dev);
if (error >= 0)
return error;
error = pci_device_probe_dynamic(drv, pci_dev);
if (error == -ENODEV)
error = pci_device_probe_dynamic(drv, pci_dev);
}
return error;
}
......
......@@ -203,11 +203,6 @@ pci_setup_bridge(struct pci_bus *bus)
Enable ISA in either case (FIXME!). */
l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
/* Make sure the bridge COMMAND register has the appropriate
bits set, just in case...
*/
pcibios_enable_device(bridge, 0xfff);
}
/* Check whether the bridge supports optional I/O and
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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,
......
......@@ -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)
{
......
......@@ -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();
......
......@@ -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)
{
......
......@@ -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;
......
......@@ -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;
......
......@@ -130,6 +130,9 @@ static void rvfree(void *mem, unsigned long size)
*
***************************************************************************/
#warning please convert me from procfs to sysfs
#undef CONFIG_VIDEO_PROC_FS
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
static struct proc_dir_entry *se401_proc_entry = NULL;
......
......@@ -519,6 +519,9 @@ static int stv_init (struct usb_stv *stv680)
* /proc interface
*******************************************************************/
#warning please convert me from procfs to sysfs
#undef CONFIG_VIDEO_PROC_FS
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
static struct proc_dir_entry *stv680_proc_entry = NULL;
......
......@@ -37,6 +37,8 @@
static int video_nr = -1;
MODULE_PARM(video_nr, "i");
#warning please convert me from procfs to sysfs
#define USES_PROC_FS 0
/*
* Local prototypes.
*/
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -218,7 +218,8 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
/* check at 512 byte offset */
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
if (super.magic != CRAMFS_MAGIC) {
printk(KERN_ERR "cramfs: wrong magic\n");
if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
goto out;
}
}
......
......@@ -279,7 +279,8 @@ void ext3_free_blocks (handle_t *handle, struct inode * inode,
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 @@ void ext3_free_blocks (handle_t *handle, struct inode * inode,
* 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 @@ ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
*/
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
......
......@@ -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,
......
......@@ -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;
......
......@@ -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];
}
......
......@@ -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];
}
......
......@@ -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];
}
......
......@@ -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];
}
......
#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)
......
......@@ -420,7 +420,9 @@ struct pci_dev {
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
#ifdef CONFIG_PCI_NAMES
char pretty_name[DEVICE_NAME_SIZE]; /* pretty name for users to see */
#define PCI_NAME_SIZE 50
#define PCI_NAME_HALF __stringify(20) /* less than half to handle slop */
char pretty_name[PCI_NAME_SIZE]; /* pretty name for users to see */
#endif
};
......@@ -524,6 +526,32 @@ struct pci_driver {
#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
/**
* PCI_DEVICE - macro used to describe a specific pci device
* @vend: the 16 bit PCI Vendor ID
* @dev: the 16 bit PCI Device ID
*
* This macro is used to create a struct pci_device_id that matches a
* specific device. The subvendor and subdevice fields will be set to
* PCI_ANY_ID.
*/
#define PCI_DEVICE(vend,dev) \
.vendor = (vend), .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
/**
* PCI_DEVICE_CLASS - macro used to describe a specific pci device class
* @dev_class: the class, subclass, prog-if triple for this device
* @dev_class_mask: the class mask for this device
*
* This macro is used to create a struct pci_device_id that matches a
* specific PCI class. The vendor, device, subvendor, and subdevice
* fields will be set to PCI_ANY_ID.
*/
#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \
.class = (dev_class), .class_mask = (dev_class_mask), \
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
/* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI
......@@ -814,6 +842,13 @@ static inline char *pci_name(struct pci_dev *pdev)
return pdev->dev.bus_id;
}
/* Some archs want to see the pretty pci name, so use this macro */
#ifdef CONFIG_PCI_NAMES
#define pci_pretty_name(dev) ((dev)->pretty_name)
#else
#define pci_pretty_name(dev) ""
#endif
/*
* The world is not perfect and supplies us with broken PCI devices.
* For at least a part of these bugs we need a work-around, so both
......
......@@ -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;
......
......@@ -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.
......
......@@ -286,8 +286,6 @@ void __init mount_block_root(char *name, int flags)
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));
......
......@@ -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
......@@ -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.
......
......@@ -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)
......
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment