diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle
--- a/Documentation/CodingStyle Sun Jul 13 20:39:55 2003
+++ b/Documentation/CodingStyle Sun Jul 13 20:39:55 2003
@@ -140,7 +140,7 @@
maximum limits all the more closely. Use helper functions with
descriptive names (you can ask the compiler to in-line them if you think
it's performance-critical, and it will probably do a better job of it
-that you would have done).
+than you would have done).
Another measure of the function is the number of local variables. They
shouldn't exceed 5-10, or you're doing something wrong. Re-think the
@@ -200,7 +200,7 @@
But even if you fail in getting emacs to do sane formatting, not
everything is lost: use "indent".
-Now, again, GNU indent has the same brain dead settings that GNU emacs
+Now, again, GNU indent has the same brain-dead settings that GNU emacs
has, which is why you need to give it a few command line options.
However, that's not too bad, because even the makers of GNU indent
recognize the authority of K&R (the GNU people aren't evil, they are
@@ -232,7 +232,7 @@
Generally, CONFIG_EXPERIMENTAL should surround all options not considered
stable. All options that are known to trash data (experimental write-
support for file-systems, for instance) should be denoted (DANGEROUS), other
-Experimental options should be denoted (EXPERIMENTAL).
+experimental options should be denoted (EXPERIMENTAL).
Chapter 8: Data structures
@@ -258,7 +258,7 @@
the number of subclass users, and decrements the global count just once
when the subclass count goes to zero.
-Examples of this kind of "multi-reference-counting" can be found in
+Examples of this kind of "multi-level-reference-counting" can be found in
memory management ("struct mm_struct": mm_users and mm_count), and in
filesystem code ("struct super_block": s_count and s_active).
diff -Nru a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
--- a/Documentation/DocBook/procfs-guide.tmpl Sun Jul 13 20:39:56 2003
+++ b/Documentation/DocBook/procfs-guide.tmpl Sun Jul 13 20:39:56 2003
@@ -253,41 +253,6 @@
-
-
-
-
- Creating a device
-
-
-
- struct proc_dir_entry* proc_mknod
- const char* name
- mode_t mode
- struct proc_dir_entry* parent
- kdev_t rdev
-
-
-
-
- Creates a device file name with mode
- mode in the procfs directory
- parent. The device file will work on
- the device rdev, which can be generated
- by using the MKDEV macro from
- linux/kdev_t.h. The
- mode parameter
- must contain S_IFBLK
- or S_IFCHR to create a device
- node. Compare with userland mknod
- --mode=mode
- name rdev.
-
-
-
-
-
-
Creating a directory
diff -Nru a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
--- a/Documentation/DocBook/procfs_example.c Sun Jul 13 20:39:56 2003
+++ b/Documentation/DocBook/procfs_example.c Sun Jul 13 20:39:56 2003
@@ -63,7 +63,7 @@
static struct proc_dir_entry *example_dir, *foo_file,
- *bar_file, *jiffies_file, *tty_device, *symlink;
+ *bar_file, *jiffies_file, *symlink;
struct fb_data_t foo_data, bar_data;
@@ -173,16 +173,6 @@
bar_file->write_proc = proc_write_foobar;
bar_file->owner = THIS_MODULE;
- /* create tty device */
- tty_device = proc_mknod("tty", S_IFCHR | 0666,
- example_dir, MKDEV(5, 0));
- if(tty_device == NULL) {
- rv = -ENOMEM;
- goto no_tty;
- }
-
- tty_device->owner = THIS_MODULE;
-
/* create symlink */
symlink = proc_symlink("jiffies_too", example_dir,
"jiffies");
diff -Nru a/Documentation/filesystems/cifs.txt b/Documentation/filesystems/cifs.txt
--- a/Documentation/filesystems/cifs.txt Sun Jul 13 20:39:55 2003
+++ b/Documentation/filesystems/cifs.txt Sun Jul 13 20:39:55 2003
@@ -1,33 +1,51 @@
-This module, cifs, is a filesystem that implements the SMB/CIFS
-protocol, which is the protocol used by Windows based operating systems
-(including Windows 2000 and its successors) as well as Samba, OS/2 and
-many others operating systems and network file server appliances. The
-Cifs VFS filesystem module is designed to work well with servers that
-implement the newer versions (dialects) of the SMB/CIFS protocol such as
-Samba, the program written by Andrew Tridgell that turns any Unix host
-into a file server for DOS or Windows clients, as well as Windows NT,
-Windows 2000 and its successors. It is not designed to handle older smb
-servers well, those that implement older versions of the dialect (such
-as OS/2 or Windows 95), for this purpose use smbfs.
-
-This module can support mounting without a mount helper program. The
-mount syntax is:
- mount //server_ip/share_name /mnt -o user=username,password=your_password
-
-where "username", "your_password" and "server_ip" and "share_name"
-should be replaced with specific values (supplied by the user) e.g.
- mount //9.53.216.16/public /mnt -o user=jsmith,password=openup
-
-This cifs implementation is designed to handle network caching (safely)
-as well as to implement locking, large file (64 bit access), distributed
-file system ("dfs") and other advanced protocol features. It also
-implements the SNIA standard for Unix extensions to CIFS (when
-communicating with servers such as Samba 2.2.3 or later which support it).
-
-For more information contact sfrench@us.ibm.com
-
-Cifs is an SMB client (or gateway). For more info on the SMB/CIFS
-protocol and Samba, including documentation, please go to
-http://www.samba.org/ and then on to your nearest mirror. For more
-information about the cifs vfs, go to the project page at:
- http://us1.samba.org/samba/Linux_CIFS_client.html
+ This is the client VFS module for the Common Internet File System
+ (CIFS) protocol which is the successor to the Server Message Block
+ (SMB) protocol, the native file sharing mechanism for most early
+ PC operating systems. CIFS is fully supported by current network
+ file servers such as Windows 2000, Windows 2003 (including
+ Windows XP) as well by Samba (which provides excellent CIFS
+ server support for Linux and many other operating systems), so
+ this network filesystem client can mount to a wide variety of
+ servers. The smbfs module should be used instead of this cifs module
+ for mounting to older SMB servers such as OS/2. The smbfs and cifs
+ modules can coexist and do not conflict. The CIFS VFS filesystem
+ module is designed to work well with servers that implement the
+ newer versions (dialects) of the SMB/CIFS protocol such as Samba,
+ the program written by Andrew Tridgell that turns any Unix host
+ into a SMB/CIFS file server.
+
+ The intent of this module is to provide the most advanced network
+ file system function for CIFS compliant servers, including better
+ POSIX compliance, secure per-user session establishment, high
+ performance safe distributed caching (oplock), optional packet
+ signing, large files, Unicode support and other internationalization
+ improvements. Since both Samba server and this filesystem client support
+ the CIFS Unix extensions, the combination can provide a reasonable
+ alternative to NFSv4 for fileserving in some Linux to Linux environments,
+ not just in Linux to Windows environments.
+
+ This filesystem has an optional mount utility (mount.cifs) that can
+ be obtained from the project page and installed in the path in the same
+ directory with the other mount helpers (such as mount.smbfs).
+ Mounting using the cifs filesystem without installing the mount helper
+ requires specifying the server's ip address.
+
+ For Linux 2.4:
+ mount //anything/here /mnt_target -o
+ user=username,pass=password,unc=//ip_address_of_server/sharename
+
+ For Linux 2.5:
+ mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
+
+
+ For more information on the module see the project page at
+
+ http://us1.samba.org/samba/Linux_CIFS_client.html
+
+ For more information on CIFS see:
+
+ http://www.snia.org/tech_activities/CIFS
+
+ or the Samba site:
+
+ http://www.samba.org
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt Sun Jul 13 20:39:56 2003
+++ b/Documentation/kernel-parameters.txt Sun Jul 13 20:39:56 2003
@@ -772,7 +772,7 @@
Ranges are in pairs (memory base and size).
profile= [KNL] Enable kernel profiling via /proc/profile
- Format:
+ (param: profile step/bucket size as a power of 2)
prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
before loading.
diff -Nru a/Documentation/nbd.txt b/Documentation/nbd.txt
--- a/Documentation/nbd.txt Sun Jul 13 20:39:56 2003
+++ b/Documentation/nbd.txt Sun Jul 13 20:39:56 2003
@@ -1,57 +1,47 @@
Network Block Device (TCP version)
- Note: Network Block Device is now experimental, which approximately
- means, that it works on my computer, and it worked on one of school
- computers.
+ What is it: With this compiled in the kernel (or as a module), Linux
+ can use a remote server as one of its block devices. So every time
+ the client computer wants to read, e.g., /dev/nb0, it sends a
+ request over TCP to the server, which will reply with the data read.
+ This can be used for stations with low disk space (or even diskless -
+ if you boot from floppy) to borrow disk space from another computer.
+ Unlike NFS, it is possible to put any filesystem on it, etc. It should
+ even be possible to use NBD as a root filesystem (I've never tried),
+ but it requires a user-level program to be in the initrd to start.
+ It also allows you to run block-device in user land (making server
+ and client physically the same computer, communicating using loopback).
- What is it: With this compiled in the kernel, Linux can use a remote
- server as one of its block devices. So every time the client computer
- wants to read /dev/nd0, it sends a request over TCP to the server, which
- will reply with the data read. This can be used for stations with
- low disk space (or even diskless - if you boot from floppy) to
- borrow disk space from another computer. Unlike NFS, it is possible to
- put any filesystem on it etc. It is impossible to use NBD as a root
- filesystem, since it requires a user-level program to start. It also
- allows you to run block-device in user land (making server and client
- physically the same computer, communicating using loopback).
+ Current state: It currently works. Network block device is stable.
+ I originally thought that it was impossible to swap over TCP. It
+ turned out not to be true - swapping over TCP now works and seems
+ to be deadlock-free, but it requires heavy patches into Linux's
+ network layer.
- Current state: It currently works. Network block device looks like
- being pretty stable. I originally thought that it is impossible to swap
- over TCP. It turned out not to be true - swapping over TCP now works
- and seems to be deadlock-free, but it requires heavy patches into
- Linux's network layer.
-
- Devices: Network block device uses major 43, minors 0..n (where n is
- configurable in nbd.h). Create these files by mknod when needed. After
- that, your ls -l /dev/ should look like:
-
-brw-rw-rw- 1 root root 43, 0 Apr 11 00:28 nd0
-brw-rw-rw- 1 root root 43, 1 Apr 11 00:28 nd1
-...
-
- Protocol: Userland program passes file handle with connected TCP
- socket to actual kernel driver. This way, the kernel does not have to
- care about connecting etc. Protocol is rather simple: If the driver is
- asked to read from block device, it sends packet of following form
- "request" (all data are in network byte order):
-
- __u32 magic; must be equal to 0x12560953
- __u32 from; position in bytes to read from / write at
- __u32 len; number of bytes to be read / written
- __u64 handle; handle of operation
- __u32 type; 0 = read
- 1 = write
- ... in case of write operation, this is
- immediately followed len bytes of data
+ For more information, or to download the nbd-client and nbd-server
+ tools, go to http://nbd.sf.net/.
- When operation is completed, server responds with packet of following
- structure "reply":
-
- __u32 magic; must be equal to
- __u64 handle; handle copied from request
- __u32 error; 0 = operation completed successfully,
- else error code
- ... in case of read operation with no error,
- this is immediately followed len bytes of data
+ Howto: To setup nbd, you can simply do the following:
+
+ First, serve a device or file from a remote server:
+
+ nbd-server
+
+ e.g.,
+ root@server1 # nbd-server 1234 /dev/sdb1
+
+ (serves sdb1 partition on TCP port 1234)
+
+ Then, on the local (client) system:
+
+ nbd-client /dev/nb[0-n]
+
+ e.g.,
+ root@client1 # nbd-client server1 1234 /dev/nb0
+
+ (creates the nb0 device on client1)
- For more information, look at http://nbd.sf.net/.
+ The nbd kernel module need only be installed on the client
+ system, as the nbd-server is completely in userspace. In fact,
+ the nbd-server has been successfully ported to other operating
+ systems, including Windows.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS Sun Jul 13 20:39:55 2003
+++ b/MAINTAINERS Sun Jul 13 20:39:55 2003
@@ -879,6 +879,8 @@
S: Supported
IDE DRIVER [GENERAL]
+P: Bartlomiej Zolnierkiewicz
+M: B.Zolnierkiewicz@elka.pw.edu.pl
L: linux-kernel@vger.kernel.org
L: linux-ide@vger.kernel.org
S: Maintained
@@ -1910,7 +1912,7 @@
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
-USB BLUETOOTH DRIVER
+USB BLUETOOTH TTY CONVERTER DRIVER
P: Greg Kroah-Hartman
M: greg@kroah.com
L: linux-usb-users@lists.sourceforge.net
diff -Nru a/Makefile b/Makefile
--- a/Makefile Sun Jul 13 20:39:55 2003
+++ b/Makefile Sun Jul 13 20:39:56 2003
@@ -1,7 +1,7 @@
VERSION = 2
-PATCHLEVEL = 5
-SUBLEVEL = 75
-EXTRAVERSION =
+PATCHLEVEL = 6
+SUBLEVEL = 0
+EXTRAVERSION = -test1
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -35,7 +35,7 @@
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
- -e s/s390x/s390/ )
+ -e s/s390x/s390/ -e s/parisc64/parisc/ )
# Remove hyphens since they have special meaning in RPM filenames
KERNELPATH=kernel-$(subst -,,$(KERNELRELEASE))
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig Sun Jul 13 20:39:56 2003
+++ b/arch/alpha/Kconfig Sun Jul 13 20:39:56 2003
@@ -269,17 +269,6 @@
(MCA) or VESA. ISA is an older system, now being displaced by PCI;
newer boards don't support it. If you have ISA, say Y, otherwise N.
-config SBUS
- bool
-
-config MCA
- bool
- help
- MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- (and especially the web page given
- there) before attempting to build an MCA bus kernel.
-
config PCI
bool
depends on !ALPHA_JENSEN
diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
--- a/arch/alpha/kernel/systbls.S Sun Jul 13 20:39:55 2003
+++ b/arch/alpha/kernel/systbls.S Sun Jul 13 20:39:55 2003
@@ -443,6 +443,7 @@
.quad sys_clock_getres
.quad sys_clock_nanosleep
.quad sys_semtimedop
+ .quad sys_tgkill
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/alpha/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -451,8 +451,9 @@
int
do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
unsigned long delta_nsec;
- long sec, nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -474,30 +475,18 @@
delta_nsec *= 1000;
#endif
- sec = tv->tv_sec;
- nsec = tv->tv_nsec;
nsec -= delta_nsec;
- if (nsec < 0) {
- nsec += NSEC_PER_SEC;
- sec -= 1;
- }
- xtime.tv_sec = sec;
- xtime.tv_nsec = nsec;
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
-
- wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
- wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
- if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
- wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
- wall_to_monotonic.tv_sec++;
- } else if (wall_to_monotonic.tv_nsec < 0) {
- wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
- wall_to_monotonic.tv_sec--;
- }
write_sequnlock_irq(&xtime_lock);
return 0;
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig Sun Jul 13 20:39:55 2003
+++ b/arch/arm/Kconfig Sun Jul 13 20:39:55 2003
@@ -1061,14 +1061,6 @@
you are concerned with the code size or don't want to see these
messages.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- depends on DEBUG_KERNEL
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
bool "Kernel low-level debugging functions"
diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig
--- a/arch/arm26/Kconfig Sun Jul 13 20:39:55 2003
+++ b/arch/arm26/Kconfig Sun Jul 13 20:39:55 2003
@@ -391,14 +391,6 @@
you are concerned with the code size or don't want to see these
messages.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- depends on DEBUG_KERNEL
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
bool "Kernel low-level debugging functions"
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig Sun Jul 13 20:39:55 2003
+++ b/arch/i386/Kconfig Sun Jul 13 20:39:55 2003
@@ -1354,13 +1354,6 @@
This options enables addition error checking for high memory systems.
Disable for production systems.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
help
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S Sun Jul 13 20:39:55 2003
+++ b/arch/i386/kernel/entry.S Sun Jul 13 20:39:55 2003
@@ -876,6 +876,7 @@
.long sys_clock_nanosleep
.long sys_statfs64
.long sys_fstatfs64
- .long sys_tgkill
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
nr_syscalls=(.-sys_call_table)/4
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c Sun Jul 13 20:39:55 2003
+++ b/arch/i386/kernel/microcode.c Sun Jul 13 20:39:55 2003
@@ -380,7 +380,6 @@
return -ENODATA;
default:
- printk(KERN_ERR "microcode: unknown ioctl cmd=%d\n", cmd);
return -EINVAL;
}
return -EINVAL;
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/i386/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -115,6 +115,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -125,28 +128,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
- tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
+ nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
- wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
- wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
- if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
- wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
- wall_to_monotonic.tv_sec++;
- }
- if (wall_to_monotonic.tv_nsec < 0) {
- wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
- wall_to_monotonic.tv_sec--;
- }
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig Sun Jul 13 20:39:56 2003
+++ b/arch/ia64/Kconfig Sun Jul 13 20:39:56 2003
@@ -667,14 +667,6 @@
Say Y here if you are developing drivers or trying to debug and
identify kernel problems.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- depends on DEBUG_KERNEL
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
config IA64_PRINT_HAZARDS
bool "Print possible IA-64 dependency violations to console"
depends on DEBUG_KERNEL
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/ia64/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -104,21 +104,6 @@
.reset = itc_reset
};
-static inline void
-set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
-{
- while (nsec > NSEC_PER_SEC) {
- nsec -= NSEC_PER_SEC;
- ++sec;
- }
- while (nsec < 0) {
- nsec += NSEC_PER_SEC;
- --sec;
- }
- ts->tv_sec = sec;
- ts->tv_nsec = nsec;
-}
-
int
do_settimeofday (struct timespec *tv)
{
diff -Nru a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
--- a/arch/m68k/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/m68k/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -103,6 +103,7 @@
time.tm_hour, time.tm_min, time.tm_sec);
xtime.tv_nsec = 0;
}
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt);
}
@@ -140,6 +141,8 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
extern unsigned long wall_jiffies;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -152,16 +155,15 @@
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
- tv->tv_nsec -= 1000 * (mach_gettimeoffset() +
+ nsec -= 1000 * (mach_gettimeoffset() +
(jiffies - wall_jiffies) * (1000000 / HZ));
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
--- a/arch/m68knommu/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/m68knommu/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -131,6 +131,7 @@
year += 100;
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_nsec = 0;
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt);
}
@@ -165,6 +166,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -177,15 +181,14 @@
* would have done, and then undo it!
*/
if (mach_gettimeoffset)
- tv->tv_nsec -= (mach_gettimeoffset() * 1000);
+ nsec -= (mach_gettimeoffset() * 1000);
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/mips/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -98,6 +98,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -108,16 +111,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
- tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+ nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+ nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
@@ -499,6 +501,9 @@
xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) {
diff -Nru a/arch/mips64/kernel/time.c b/arch/mips64/kernel/time.c
--- a/arch/mips64/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/mips64/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -98,6 +98,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -108,16 +111,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
- tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+ nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+ nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - tsec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
@@ -499,6 +501,8 @@
xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) {
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig Sun Jul 13 20:39:55 2003
+++ b/arch/parisc/Kconfig Sun Jul 13 20:39:55 2003
@@ -1,6 +1,6 @@
#
# For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "Linux/PA-RISC Kernel Configuration"
@@ -287,13 +287,13 @@
keys are documented in . Don't say Y
unless you really know what this hack does.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- depends on DEBUG_KERNEL
+config FRAME_POINTER
+ bool "Compile the kernel with frame pointers"
help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
+ If you say Y here the resulting kernel image will be slightly larger
+ and slower, but it will give very useful debugging information.
+ If you don't debug the kernel, you can say N, but we may not be able
+ to solve problems without frame pointers.
endmenu
diff -Nru a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
--- a/arch/parisc/hpux/sys_hpux.c Sun Jul 13 20:39:55 2003
+++ b/arch/parisc/hpux/sys_hpux.c Sun Jul 13 20:39:55 2003
@@ -121,7 +121,7 @@
{
struct super_block *s;
struct hpux_ustat tmp; /* Changed to hpux_ustat */
- struct statfs sbuf;
+ struct kstatfs sbuf;
int err = -EINVAL;
s = user_get_super(dev);
diff -Nru a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
--- a/arch/parisc/kernel/drivers.c Sun Jul 13 20:39:56 2003
+++ b/arch/parisc/kernel/drivers.c Sun Jul 13 20:39:56 2003
@@ -112,7 +112,9 @@
static int parisc_driver_remove(struct device *dev)
{
struct parisc_device *pa_dev = to_parisc_device(dev);
-
+ struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
+ if (pa_drv->remove)
+ pa_drv->remove(pa_dev);
release_mem_region(pa_dev->hpa, 0x1000);
return 0;
diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
--- a/arch/parisc/kernel/ioctl32.c Sun Jul 13 20:39:54 2003
+++ b/arch/parisc/kernel/ioctl32.c Sun Jul 13 20:39:54 2003
@@ -36,8 +36,9 @@
#include
#include
#include
-#include
+#include
#include
+#include
#include
#include
#include
diff -Nru a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
--- a/arch/parisc/kernel/module.c Sun Jul 13 20:39:56 2003
+++ b/arch/parisc/kernel/module.c Sun Jul 13 20:39:56 2003
@@ -671,6 +671,11 @@
const Elf_Shdr *sechdrs,
struct module *me)
{
+ int i;
+ unsigned long nsyms;
+ const char *strtab = NULL;
+ Elf_Sym *newptr, *oldptr;
+ Elf_Shdr *symhdr = NULL;
#ifdef DEBUG
struct fdesc_entry *entry;
u32 *addr;
@@ -690,7 +695,49 @@
me->arch.got_count, me->arch.got_max,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
-
+
+ /* haven't filled in me->symtab yet, so have to find it
+ * ourselves */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if(sechdrs[i].sh_type == SHT_SYMTAB
+ && (sechdrs[i].sh_type & SHF_ALLOC)) {
+ int strindex = sechdrs[i].sh_link;
+ /* FIXME: AWFUL HACK
+ * The cast is to drop the const from
+ * the sechdrs pointer */
+ symhdr = (Elf_Shdr *)&sechdrs[i];
+ strtab = (char *)sechdrs[strindex].sh_addr;
+ break;
+ }
+ }
+
+ printk("module %s: strtab %p, symhdr %p\n",
+ me->name, strtab, symhdr);
+
+ /* no symbol table */
+ if(symhdr == NULL)
+ return 0;
+
+ oldptr = (void *)symhdr->sh_addr;
+ newptr = oldptr + 1; /* we start counting at 1 */
+ nsyms = symhdr->sh_size / sizeof(Elf_Sym);
+ DEBUGP("OLD num_symtab %lu\n", nsyms);
+
+ for (i = 1; i < nsyms; i++) {
+ oldptr++; /* note, count starts at 1 so preincrement */
+ if(strncmp(strtab + oldptr->st_name,
+ ".L", 2) == 0)
+ continue;
+
+ if(newptr != oldptr)
+ *newptr++ = *oldptr;
+ else
+ newptr++;
+
+ }
+ nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
+ DEBUGP("NEW num_symtab %lu\n", nsyms);
+ symhdr->sh_size = nsyms * sizeof(Elf_Sym);
return 0;
}
diff -Nru a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
--- a/arch/parisc/kernel/pci.c Sun Jul 13 20:39:54 2003
+++ b/arch/parisc/kernel/pci.c Sun Jul 13 20:39:54 2003
@@ -10,11 +10,12 @@
* Copyright (C) 1999-2001 Grant Grundler
*/
#include
-#include
+#include
+#include
#include
-#include /* for __init and __devinit */
#include
#include
+#include
#include
#include
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c Sun Jul 13 20:39:55 2003
+++ b/arch/parisc/kernel/sys_parisc32.c Sun Jul 13 20:39:55 2003
@@ -418,11 +418,11 @@
}
asmlinkage int
-sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz)
{
struct timeval ktv;
struct timezone ktz;
- extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+ extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
if (tv) {
if (get_compat_timeval(tv, &ktv))
diff -Nru a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
--- a/arch/parisc/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/parisc/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -188,8 +188,11 @@
}
int
-do_settimeofday (struct timeval *tv)
+do_settimeofday (struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -202,16 +205,15 @@
* Discover what correction gettimeofday would have
* done, and then undo it!
*/
- tv->tv_nsec -= gettimeoffset() * 1000;
- tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+ nsec -= gettimeoffset() * 1000;
+ nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
@@ -243,6 +245,8 @@
write_seqlock_irq(&xtime_lock);
xtime.tv_sec = tod_data.tod_sec;
xtime.tv_nsec = tod_data.tod_usec * 1000;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irq(&xtime_lock);
} else {
printk(KERN_ERR "Error reading tod clock\n");
diff -Nru a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
--- a/arch/parisc/kernel/traps.c Sun Jul 13 20:39:56 2003
+++ b/arch/parisc/kernel/traps.c Sun Jul 13 20:39:56 2003
@@ -126,7 +126,7 @@
void dump_stack(void)
{
unsigned long stack;
- show_trace(&stack);
+ show_trace(current, &stack);
}
@@ -136,7 +136,7 @@
static int kstack_depth_to_print = 128 * 4;
#endif
-void show_stack(unsigned long *sp)
+void show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long *stack;
int i;
@@ -145,8 +145,10 @@
* debugging aid: "show_stack(NULL);" prints the
* back trace for this cpu.
*/
- if (sp==NULL)
+ if (task==NULL)
sp = (unsigned long*)&sp;
+ else if(sp == NULL)
+ sp = (unsigned long*)task->thread.regs.ksp;
stack = sp;
printk("\n" KERN_CRIT "Stack Dump:\n");
@@ -160,11 +162,11 @@
printk(RFMT " ", *stack--);
}
printk("\n" KERN_CRIT "\n");
- show_trace(sp);
+ show_trace(task, sp);
}
-void show_trace(unsigned long *stack)
+void show_trace(struct task_struct *task, unsigned long *stack)
{
unsigned long *startstack;
unsigned long addr;
@@ -201,7 +203,7 @@
void show_trace_task(struct task_struct *tsk)
{
- show_trace((unsigned long *)tsk->thread.regs.ksp);
+ show_trace(tsk, (unsigned long *)tsk->thread.regs.ksp);
}
void die_if_kernel(char *str, struct pt_regs *regs, long err)
@@ -426,7 +428,7 @@
if (code == 1)
transfer_pim_to_trap_frame(regs);
- show_stack((unsigned long *)regs->gr[30]);
+ show_stack(NULL, (unsigned long *)regs->gr[30]);
printk("\n");
printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
diff -Nru a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
--- a/arch/parisc/kernel/unaligned.c Sun Jul 13 20:39:55 2003
+++ b/arch/parisc/kernel/unaligned.c Sun Jul 13 20:39:55 2003
@@ -92,6 +92,15 @@
#define OPCODE_STWA OPCODE1(0x03,1,0xe)
#define OPCODE_STDA OPCODE1(0x03,1,0xf)
+#define OPCODE_FLDWX OPCODE1(0x09,0,0x0)
+#define OPCODE_FSTWX OPCODE1(0x09,0,0x4)
+#define OPCODE_FLDWS OPCODE1(0x09,1,0x0)
+#define OPCODE_FSTWS OPCODE1(0x09,1,0x4)
+#define OPCODE_FLDDX OPCODE1(0x0b,0,0x0)
+#define OPCODE_FSTDX OPCODE1(0x0b,0,0x4)
+#define OPCODE_FLDDS OPCODE1(0x0b,1,0x0)
+#define OPCODE_FSTDS OPCODE1(0x0b,1,0x4)
+
#define OPCODE_LDD_L OPCODE2(0x14,0)
#define OPCODE_FLDD_L OPCODE2(0x14,1)
#define OPCODE_STD_L OPCODE2(0x1c,0)
@@ -113,6 +122,7 @@
#define R1(i) (((i)>>21)&0x1f)
#define R2(i) (((i)>>16)&0x1f)
#define R3(i) ((i)&0x1f)
+#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
#define IM5_2(i) IM((i)>>16,5)
#define IM5_3(i) IM((i),5)
@@ -146,7 +156,7 @@
return 0;
}
-static int emulate_ldw(struct pt_regs *regs, int toreg)
+static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
{
unsigned long saddr = regs->ior;
unsigned long val = 0;
@@ -169,20 +179,26 @@
DPRINTF("val = 0x" RFMT "\n", val);
- if (toreg)
+ if (flop)
+ ((__u32*)(regs->fr))[toreg] = val;
+ else if (toreg)
regs->gr[toreg] = val;
return 0;
}
-#ifdef __LP64__
-static int emulate_ldd(struct pt_regs *regs, int toreg)
+static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
{
unsigned long saddr = regs->ior;
- unsigned long val = 0;
+ __u64 val = 0;
DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n",
regs->isr, regs->ior, toreg);
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+ if (!flop)
+ return -1;
+#endif
__asm__ __volatile__ (
" depd,z %2,60,3,%%r19\n" /* r19=(ofs&7)*8 */
" mtsp %3, %%sr1\n"
@@ -195,15 +211,36 @@
: "=r" (val)
: "0" (val), "r" (saddr), "r" (regs->isr)
: "r19", "r20" );
+#else
+ {
+ unsigned long valh=0,vall=0;
+ __asm__ __volatile__ (
+" zdep %4,29,2,%%r19\n" /* r19=(ofs&3)*8 */
+" mtsp %5, %%sr1\n"
+" dep %%r0,31,2,%4\n"
+" ldw 0(%%sr1,%5),%0\n"
+" ldw 4(%%sr1,%5),%1\n"
+" ldw 8(%%sr1,%5),%%r20\n"
+" subi 32,%%r19,%%r19\n"
+" mtsar %%r19\n"
+" vshd %0,%1,%0\n"
+" vshd %1,%%r20,%1\n"
+ : "=r" (valh), "=r" (vall)
+ : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
+ : "r19", "r20" );
+ val=((__u64)valh<<32)|(__u64)vall;
+ }
+#endif
DPRINTF("val = 0x" RFMT "\n", val);
- if (toreg)
+ if (flop)
+ regs->fr[toreg] = val;
+ else if (toreg)
regs->gr[toreg] = val;
return 0;
}
-#endif
static int emulate_sth(struct pt_regs *regs, int frreg)
{
@@ -212,7 +249,7 @@
val = 0;
DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg,
- regs->gr[frreg], regs->isr, regs->ior);
+ val, regs->isr, regs->ior);
__asm__ __volatile__ (
" mtsp %2, %%sr1\n"
@@ -225,14 +262,19 @@
return 0;
}
-static int emulate_stw(struct pt_regs *regs, int frreg)
+static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
{
- unsigned long val = regs->gr[frreg];
- if (!frreg)
+ unsigned long val;
+
+ if (flop)
+ val = ((__u32*)(regs->fr))[frreg];
+ else if (frreg)
+ val = regs->gr[frreg];
+ else
val = 0;
DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg,
- regs->gr[frreg], regs->isr, regs->ior);
+ val, regs->isr, regs->ior);
__asm__ __volatile__ (
@@ -257,17 +299,25 @@
return 0;
}
-#ifdef __LP64__
-static int emulate_std(struct pt_regs *regs, int frreg)
+static int emulate_std(struct pt_regs *regs, int frreg, int flop)
{
- unsigned long val = regs->gr[frreg];
- if (!frreg)
- val = 0;
+ __u64 val;
- DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 8 bytes\n", frreg,
- regs->gr[frreg], regs->isr, regs->ior);
+ if (flop)
+ val = regs->fr[frreg];
+ else if (frreg)
+ val = regs->gr[frreg];
+ else
+ val = 0;
+ DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg,
+ val, regs->isr, regs->ior);
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+ if (!flop)
+ return -1;
+#endif
__asm__ __volatile__ (
" mtsp %2, %%sr1\n"
" depd,z %1, 60, 3, %%r19\n"
@@ -287,19 +337,45 @@
:
: "r" (val), "r" (regs->ior), "r" (regs->isr)
: "r19", "r20", "r21", "r22", "r1" );
+#else
+ {
+ unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+ __asm__ __volatile__ (
+" mtsp %3, %%sr1\n"
+" zdep %1, 29, 2, %%r19\n"
+" dep %%r0, 31, 2, %1\n"
+" mtsar %%r19\n"
+" zvdepi -2, 32, %%r19\n"
+" ldw 0(%%sr1,%2),%%r20\n"
+" ldw 8(%%sr1,%2),%%r21\n"
+" vshd %0, %1, %%r1\n"
+" vshd %%r0, %0, %0\n"
+" vshd %1, %%r0, %1\n"
+" and %%r20, %%r19, %%r20\n"
+" andcm %%r21, %%r19, %%r21\n"
+" or %0, %%r20, %0\n"
+" or %1, %%r21, %1\n"
+" stw %0,0(%%sr1,%2)\n"
+" stw %%r1,4(%%sr1,%2)\n"
+" stw %1,8(%%sr1,%2)\n"
+ :
+ : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
+ : "r19", "r20", "r21", "r1" );
+ }
+#endif
return 0;
}
-#endif
void handle_unaligned(struct pt_regs *regs)
{
unsigned long unaligned_count = 0;
unsigned long last_time = 0;
- unsigned long newbase = regs->gr[R1(regs->iir)];
+ unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
int modify = 0;
int ret = -1;
struct siginfo si;
+ register int flop=0; /* true if this is a flop */
/* if the unaligned access is inside the kernel:
* if the access is caused by a syscall, then we fault the calling
@@ -383,9 +459,9 @@
case OPCODE_LDDA_I:
shift= 3; break;
}
- newbase += regs->gr[R2(regs->iir)]<iir)?regs->gr[R2(regs->iir)]:0)<gr[R2(regs->iir)];
+ newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
}
break;
case 0x13:
@@ -438,7 +514,7 @@
case OPCODE_LDWA_I:
case OPCODE_LDW_S:
case OPCODE_LDWA_S:
- ret = emulate_ldw(regs, R3(regs->iir));
+ ret = emulate_ldw(regs, R3(regs->iir),0);
break;
case OPCODE_STH:
@@ -447,23 +523,47 @@
case OPCODE_STW:
case OPCODE_STWA:
- ret = emulate_stw(regs, R2(regs->iir));
+ ret = emulate_stw(regs, R2(regs->iir),0);
break;
-#ifdef __LP64__
+#ifdef CONFIG_PA20
case OPCODE_LDD_I:
case OPCODE_LDDA_I:
case OPCODE_LDD_S:
case OPCODE_LDDA_S:
- ret = emulate_ldd(regs, R3(regs->iir));
+ ret = emulate_ldd(regs, R3(regs->iir),0);
break;
case OPCODE_STD:
case OPCODE_STDA:
- ret = emulate_std(regs, R2(regs->iir));
+ ret = emulate_std(regs, R2(regs->iir),0);
break;
#endif
+ case OPCODE_FLDWX:
+ case OPCODE_FLDWS:
+ flop=1;
+ ret = emulate_ldw(regs,FR3(regs->iir),1);
+ break;
+
+ case OPCODE_FLDDX:
+ case OPCODE_FLDDS:
+ flop=1;
+ ret = emulate_ldd(regs,R3(regs->iir),1);
+ break;
+
+ case OPCODE_FSTWX:
+ case OPCODE_FSTWS:
+ flop=1;
+ ret = emulate_stw(regs,FR3(regs->iir),1);
+ break;
+
+ case OPCODE_FSTDX:
+ case OPCODE_FSTDS:
+ flop=1;
+ ret = emulate_std(regs,R3(regs->iir),1);
+ break;
+
case OPCODE_LDCD_I:
case OPCODE_LDCW_I:
case OPCODE_LDCD_S:
@@ -471,30 +571,44 @@
ret = -1; /* "undefined", but lets kill them. */
break;
}
-#ifdef __LP64__
+#ifdef CONFIG_PA20
switch (regs->iir & OPCODE2_MASK)
{
- case OPCODE_LDD_L:
case OPCODE_FLDD_L:
- ret = emulate_ldd(regs, R2(regs->iir));
+ flop=1;
+ ret = emulate_ldd(regs,R2(regs->iir),1);
+ break;
+ case OPCODE_FSTD_L:
+ flop=1;
+ ret = emulate_std(regs, R2(regs->iir),1);
break;
+#ifdef CONFIG_PA20
+ case OPCODE_LDD_L:
+ ret = emulate_ldd(regs, R2(regs->iir),0);
+ break;
case OPCODE_STD_L:
- case OPCODE_FSTD_L:
- ret = emulate_std(regs, R2(regs->iir));
+ ret = emulate_std(regs, R2(regs->iir),0);
break;
+#endif
}
#endif
switch (regs->iir & OPCODE3_MASK)
{
- case OPCODE_LDW_M:
case OPCODE_FLDW_L:
- ret = emulate_ldw(regs, R2(regs->iir));
+ flop=1;
+ ret = emulate_ldw(regs, R2(regs->iir),0);
+ break;
+ case OPCODE_LDW_M:
+ ret = emulate_ldw(regs, R2(regs->iir),1);
break;
case OPCODE_FSTW_L:
+ flop=1;
+ ret = emulate_stw(regs, R2(regs->iir),1);
+ break;
case OPCODE_STW_M:
- ret = emulate_stw(regs, R2(regs->iir));
+ ret = emulate_stw(regs, R2(regs->iir),0);
break;
}
switch (regs->iir & OPCODE4_MASK)
@@ -504,19 +618,18 @@
break;
case OPCODE_LDW_L:
case OPCODE_LDWM:
- ret = emulate_ldw(regs, R2(regs->iir));
+ ret = emulate_ldw(regs, R2(regs->iir),0);
break;
case OPCODE_STH_L:
ret = emulate_sth(regs, R2(regs->iir));
break;
case OPCODE_STW_L:
case OPCODE_STWM:
- ret = emulate_stw(regs, R2(regs->iir));
+ ret = emulate_stw(regs, R2(regs->iir),0);
break;
}
- /* XXX LJ - need to handle float load/store */
- if (modify)
+ if (modify && R1(regs->iir))
regs->gr[R1(regs->iir)] = newbase;
@@ -540,9 +653,8 @@
return;
}
- /* else we handled it, advance the PC.... */
- regs->iaoq[0] = regs->iaoq[1];
- regs->iaoq[1] = regs->iaoq[0] + 4;
+ /* else we handled it, let life go on. */
+ regs->gr[0]|=PSW_N;
}
/*
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig Sun Jul 13 20:39:56 2003
+++ b/arch/ppc/Kconfig Sun Jul 13 20:39:56 2003
@@ -1449,13 +1449,6 @@
This options enables additional error checking for high memory
systems. Disable for production systems.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
depends on DEBUG_KERNEL
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c Sun Jul 13 20:39:56 2003
+++ b/arch/ppc/kernel/time.c Sun Jul 13 20:39:56 2003
@@ -241,6 +241,8 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, new_sec = tv->tv_sec;
+ long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags;
int tb_delta, new_nsec, new_sec;
@@ -268,14 +270,14 @@
*/
tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
- new_sec = tv->tv_sec;
- new_nsec = tv->tv_nsec - 1000 * mulhwu(tb_to_us, tb_delta);
- while (new_nsec < 0) {
- new_sec--;
- new_nsec += NSEC_PER_SEC;
- }
- xtime.tv_nsec = new_nsec;
- xtime.tv_sec = new_sec;
+
+ new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+
+ set_normalized_timespec(&xtime, new_sec, new_nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
/* In case of a large backwards jump in time with NTP, we want the
* clock to be updated as soon as the PLL is again in lock.
@@ -347,6 +349,8 @@
sys_tz.tz_dsttime = 0;
xtime.tv_sec -= time_offset;
}
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
}
#define FEBRUARY 2
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c Sun Jul 13 20:39:56 2003
+++ b/arch/ppc64/kernel/time.c Sun Jul 13 20:39:56 2003
@@ -339,9 +339,11 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, new_sec = tv->tv_sec;
+ long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags;
unsigned long delta_xsec;
- long int tb_delta, new_nsec, new_sec;
+ long int tb_delta;
unsigned long new_xsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -364,14 +366,13 @@
tb_delta = tb_ticks_since(tb_last_stamp);
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
- new_sec = tv->tv_sec;
- new_nsec = tv->tv_nsec - (tb_delta / tb_ticks_per_usec / 1000);
- while (new_nsec < 0) {
- new_sec--;
- new_nsec += NSEC_PER_SEC;
- }
- xtime.tv_nsec = new_nsec;
- xtime.tv_sec = new_sec;
+ new_nsec -= tb_delta / tb_ticks_per_usec / 1000;
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+
+ set_normalized_timespec(&xtime, new_sec, new_nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
/* In case of a large backwards jump in time with NTP, we want the
* clock to be updated as soon as the PLL is again in lock.
@@ -484,6 +485,8 @@
xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* Not exact, but the timer interrupt takes care of this */
diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c Sun Jul 13 20:39:54 2003
+++ b/arch/s390/kernel/time.c Sun Jul 13 20:39:54 2003
@@ -104,6 +104,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -114,15 +117,14 @@
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
- tv->tv_nsec -= do_gettimeoffset() * 1000;
+ nsec -= do_gettimeoffset() * 1000;
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
@@ -263,6 +265,8 @@
set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
(0x3c26700LL*1000000*4096);
tod_to_timeval(set_time_cc, &xtime);
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
/* request the 0x1004 external interrupt */
if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
diff -Nru a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
--- a/arch/sh/kernel/time.c Sun Jul 13 20:39:54 2003
+++ b/arch/sh/kernel/time.c Sun Jul 13 20:39:54 2003
@@ -179,6 +179,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -189,16 +192,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= 1000 * (do_gettimeoffset() +
- (jiffies - wall_jiffies) * (1000000 / HZ));
+ nsec -= 1000 * (do_gettimeoffset() +
+ (jiffies - wall_jiffies) * (1000000 / HZ));
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
@@ -417,6 +419,9 @@
current_cpu_data.module_clock = timer_freq * 4;
rtc_get_time(&xtime);
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
if (board_timer_setup) {
board_timer_setup(&irq0);
diff -Nru a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
--- a/arch/sparc/boot/Makefile Sun Jul 13 20:39:56 2003
+++ b/arch/sparc/boot/Makefile Sun Jul 13 20:39:56 2003
@@ -32,3 +32,6 @@
$(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE
$(call if_changed,btfix)
+
+clean:
+ rm $(obj)/System.map
diff -Nru a/arch/sparc/defconfig b/arch/sparc/defconfig
--- a/arch/sparc/defconfig Sun Jul 13 20:39:56 2003
+++ b/arch/sparc/defconfig Sun Jul 13 20:39:56 2003
@@ -138,29 +138,61 @@
CONFIG_SCSI=y
#
-# SCSI support type (disk, tape, CDrom)
+# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_REPORT_LUNS=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
#
# SCSI low-level drivers
#
-CONFIG_SCSI_SUNESP=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLOGICPTI=m
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_SUNESP=y
#
# Fibre Channel support
diff -Nru a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
--- a/arch/sparc/kernel/Makefile Sun Jul 13 20:39:56 2003
+++ b/arch/sparc/kernel/Makefile Sun Jul 13 20:39:56 2003
@@ -12,8 +12,9 @@
sys_sparc.o sunos_asm.o systbls.o \
time.o windows.o cpu.o devices.o sclow.o \
tadpole.o tick14.o ptrace.o sys_solaris.o \
- unaligned.o muldiv.o pcic.o semaphore.o sparc_ksyms.o
+ unaligned.o muldiv.o semaphore.o sparc_ksyms.o
+obj-$(CONFIG_PCI) += pcic.o
obj-$(CONFIG_SUN4) += sun4setup.o
obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o
obj-$(CONFIG_SUN_AUXIO) += auxio.o
diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc/kernel/pcic.c Sun Jul 13 20:39:55 2003
@@ -35,27 +35,6 @@
#include
#include
-#ifndef CONFIG_PCI
-
-asmlinkage int sys_pciconfig_read(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- return -EINVAL;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- return -EINVAL;
-}
-
-#else
struct pci_fixup pcibios_fixups[] = {
{ 0 }
@@ -1044,5 +1023,3 @@
}
subsys_initcall(pcic_init);
-
-#endif
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc/kernel/process.c Sun Jul 13 20:39:55 2003
@@ -287,13 +287,22 @@
rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
}
+/*
+ * The show_stack is an external API which we do not use ourselves.
+ * The oops is printed in die_if_kernel.
+ */
void show_stack(struct task_struct *tsk, unsigned long *_ksp)
{
unsigned long pc, fp;
- unsigned long task_base = (unsigned long) tsk;
+ unsigned long task_base;
struct reg_window *rw;
int count = 0;
+ if (tsk != NULL)
+ task_base = (unsigned long) tsk->thread_info;
+ else
+ task_base = (unsigned long) current_thread_info();
+
fp = (unsigned long) _ksp;
do {
/* Bogus frame pointer? */
@@ -306,13 +315,6 @@
fp = rw->ins[6];
} while (++count < 16);
printk("\n");
-}
-
-void show_trace_task(struct task_struct *tsk)
-{
- if (tsk)
- show_stack(tsk,
- (unsigned long *) tsk->thread_info->ksp);
}
/*
diff -Nru a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
--- a/arch/sparc/kernel/sys_sparc.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc/kernel/sys_sparc.c Sun Jul 13 20:39:55 2003
@@ -123,7 +123,10 @@
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- err = sys_semop (first, (struct sembuf __user *)ptr, second);
+ err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
+ goto out;
+ case SEMTIMEDOP:
+ err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, (const struct timespec __user *) fifth);
goto out;
case SEMGET:
err = sys_semget (first, second, third);
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -408,9 +408,9 @@
mon = MSTK_REG_MONTH(mregs);
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
mregs->creg &= ~MSTK_CREG_READ;
spin_unlock_irq(&mostek_lock);
#ifdef CONFIG_SUN4
@@ -441,9 +441,9 @@
intersil_start(iregs);
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);
}
#endif
@@ -512,6 +512,9 @@
static int sbus_do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -521,28 +524,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= 1000 * (do_gettimeoffset() +
+ nsec -= 1000 * (do_gettimeoffset() +
(jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
-
- wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
- wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
- if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
- wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
- wall_to_monotonic.tv_sec++;
- }
- if (wall_to_monotonic.tv_nsec < 0) {
- wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
- wall_to_monotonic.tv_sec--;
- }
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc/mm/srmmu.c Sun Jul 13 20:39:55 2003
@@ -148,6 +148,9 @@
/* 1 bit <=> 256 bytes of nocache <=> 64 PTEs */
#define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)
+/* The context table is a nocache user with the biggest alignment needs. */
+#define SRMMU_NOCACHE_ALIGN_MAX (sizeof(ctxd_t)*SRMMU_MAX_CONTEXTS)
+
void *srmmu_nocache_pool;
void *srmmu_nocache_bitmap;
static struct bit_map srmmu_nocache_map;
@@ -320,6 +323,10 @@
printk("Size 0x%x unaligned int nocache request\n", size);
size += SRMMU_NOCACHE_BITMAP_SHIFT-1;
}
+ if (align > SRMMU_NOCACHE_ALIGN_MAX) {
+ BUG();
+ return 0;
+ }
offset = bit_map_string_get(&srmmu_nocache_map,
size >> SRMMU_NOCACHE_BITMAP_SHIFT,
@@ -425,7 +432,8 @@
bitmap_bits = srmmu_nocache_size >> SRMMU_NOCACHE_BITMAP_SHIFT;
- srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size, PAGE_SIZE, 0UL);
+ srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size,
+ SRMMU_NOCACHE_ALIGN_MAX, 0UL);
memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
srmmu_nocache_bitmap = __alloc_bootmem(bitmap_bits >> 3, SMP_CACHE_BYTES, 0UL);
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig Sun Jul 13 20:39:56 2003
+++ b/arch/sparc64/Kconfig Sun Jul 13 20:39:56 2003
@@ -924,13 +924,6 @@
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
-config KALLSYMS
- bool "Load all symbols for debugging/ksymoops"
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
help
diff -Nru a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
--- a/arch/sparc64/kernel/entry.S Sun Jul 13 20:39:54 2003
+++ b/arch/sparc64/kernel/entry.S Sun Jul 13 20:39:54 2003
@@ -1749,8 +1749,8 @@
cmp %o0, -ENOIOCTLCMD
sllx %g2, 32, %g2
bgeu,pn %xcc, 1f
-
andcc %l0, _TIF_SYSCALL_TRACE, %l6
+80:
andn %g3, %g2, %g3 /* System call success, clear Carry condition code. */
stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
bne,pn %icc, linux_syscall_trace2
@@ -1760,9 +1760,21 @@
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1:
+ /* Really a failure? Check if force_successful_syscall_return()
+ * was invoked.
+ */
+ ldx [%curptr + TI_FLAGS], %l0 ! Load
+ andcc %l0, _TIF_SYSCALL_SUCCESS, %g0
+ be,pt %icc, 1f
+ andcc %l0, _TIF_SYSCALL_TRACE, %l6
+ andn %l0, _TIF_SYSCALL_SUCCESS, %l0
+ ba,pt %xcc, 80b
+ stx %l0, [%curptr + TI_FLAGS]
+
/* System call failure, set Carry condition code.
* Also, get abs(errno) to return to the process.
*/
+1:
sub %g0, %o0, %o0
or %g3, %g2, %g3
stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
diff -Nru a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
--- a/arch/sparc64/kernel/sys_sparc.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc64/kernel/sys_sparc.c Sun Jul 13 20:39:55 2003
@@ -46,8 +46,10 @@
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
{
- struct vm_area_struct * vmm;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct * vma;
unsigned long task_size = TASK_SIZE;
+ unsigned long start_addr;
int do_color_align;
if (flags & MAP_FIXED) {
@@ -63,30 +65,54 @@
task_size = 0xf0000000UL;
if (len > task_size || len > -PAGE_OFFSET)
return -ENOMEM;
- if (!addr)
- addr = TASK_UNMAPPED_BASE;
do_color_align = 0;
if (filp || (flags & MAP_SHARED))
do_color_align = 1;
+ if (addr) {
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+ if (task_size - len >= addr &&
+ (!vma || addr + len <= vma->vm_start))
+ return addr;
+ }
+
+ start_addr = addr = mm->free_area_cache;
+
+ task_size -= len;
+
+full_search:
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
else
addr = PAGE_ALIGN(addr);
- task_size -= len;
- for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
- /* At this point: (!vmm || addr < vmm->vm_end). */
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) {
addr = PAGE_OFFSET;
- vmm = find_vma(current->mm, PAGE_OFFSET);
+ vma = find_vma(mm, PAGE_OFFSET);
}
- if (task_size < addr)
+ if (task_size < addr) {
+ if (start_addr != TASK_UNMAPPED_BASE) {
+ start_addr = addr = TASK_UNMAPPED_BASE;
+ goto full_search;
+ }
return -ENOMEM;
- if (!vmm || addr + len <= vmm->vm_start)
+ }
+ if (!vma || addr + len <= vma->vm_start) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+ mm->free_area_cache = addr + len;
return addr;
- addr = vmm->vm_end;
+ }
+ addr = vma->vm_end;
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
}
@@ -182,7 +208,10 @@
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- err = sys_semop (first, (struct sembuf *)ptr, second);
+ err = sys_semtimedop (first, (struct sembuf *)ptr, second, NULL);
+ goto out;
+ case SEMTIMEDOP:
+ err = sys_semtimedop (first, (struct sembuf *)ptr, second, (const struct timespec *) fifth);
goto out;
case SEMGET:
err = sys_semget (first, second, (int)third);
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc64/kernel/sys_sparc32.c Sun Jul 13 20:39:55 2003
@@ -480,7 +480,7 @@
static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
{
- struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+ struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
struct msgbuf32 *up = (struct msgbuf32 *)uptr;
mm_segment_t old_fs;
int err;
@@ -522,12 +522,12 @@
msgtyp = ipck.msgtyp;
}
err = -ENOMEM;
- p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+ p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
if (!p)
goto out;
old_fs = get_fs ();
set_fs (KERNEL_DS);
- err = sys_msgrcv (first, p, second + 4, msgtyp, third);
+ err = sys_msgrcv (first, p, second, msgtyp, third);
set_fs (old_fs);
if (err < 0)
goto free_then_out;
@@ -736,6 +736,22 @@
return err;
}
+static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
+ const struct compat_timespec *timeout32)
+{
+ struct compat_timespec t32;
+ struct timespec *t64 = compat_alloc_user_space(sizeof(*t64));
+
+ if (copy_from_user(&t32, timeout32, sizeof(t32)))
+ return -EFAULT;
+
+ if (put_user(t32.tv_sec, &t64->tv_sec) ||
+ put_user(t32.tv_nsec, &t64->tv_nsec))
+ return -EFAULT;
+
+ return sys_semtimedop(semid, tsems, nsems, t64);
+}
+
asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
int version, err;
@@ -747,8 +763,10 @@
switch (call) {
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
- err = sys_semop (first, (struct sembuf *)AA(ptr), second);
+ err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL);
goto out;
+ case SEMTIMEDOP:
+ err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct compat_timespec *) AA(fifth));
case SEMGET:
err = sys_semget (first, second, third);
goto out;
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/sparc64/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -703,9 +703,9 @@
}
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
if (mregs) {
tmp = mostek_read(mregs + MOSTEK_CREG);
@@ -743,9 +743,9 @@
(unsigned int) (long) &unix_tod);
prom_feval(obp_gettod);
xtime.tv_sec = unix_tod;
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
return;
}
@@ -1090,6 +1090,9 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -1103,28 +1106,15 @@
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= do_gettimeoffset() * 1000;
- tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
-
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
+ nsec -= do_gettimeoffset() * 1000;
+ nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
- wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
- if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
- wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
- wall_to_monotonic.tv_sec++;
- }
- if (wall_to_monotonic.tv_nsec < 0) {
- wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
- wall_to_monotonic.tv_sec--;
- }
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
--- a/arch/v850/kernel/bug.c Sun Jul 13 20:39:56 2003
+++ b/arch/v850/kernel/bug.c Sun Jul 13 20:39:56 2003
@@ -17,6 +17,7 @@
#include
#include
+#include
#include
/* We should use __builtin_return_address, but it doesn't work in gcc-2.90
@@ -100,12 +101,21 @@
}
}
-void show_stack (unsigned long *sp)
-{
- unsigned long end;
- unsigned long addr = (unsigned long)sp;
-
- if (! addr)
+/*
+ * TASK is a pointer to the task whose backtrace we want to see (or NULL
+ * for current task), SP is the stack pointer of the first frame that
+ * should be shown in the back trace (or NULL if the entire call-chain of
+ * the task should be shown).
+ */
+void show_stack (struct task_struct *task, unsigned long *sp)
+{
+ unsigned long addr, end;
+
+ if (sp)
+ addr = (unsigned long)sp;
+ else if (task)
+ addr = task_sp (task);
+ else
addr = stack_addr ();
addr = addr & ~3;
@@ -125,5 +135,5 @@
void dump_stack ()
{
- show_stack (0);
+ show_stack (0, 0);
}
diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
--- a/arch/v850/kernel/gbus_int.c Sun Jul 13 20:39:56 2003
+++ b/arch/v850/kernel/gbus_int.c Sun Jul 13 20:39:56 2003
@@ -1,8 +1,8 @@
/*
* arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
*
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 Miles Bader
+ * Copyright (C) 2001,02,03 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03 Miles Bader
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
@@ -99,9 +99,11 @@
/* Handle a shared GINT interrupt by passing to the appropriate GBUS
interrupt handler. */
-static void gbus_int_handle_irq (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id,
+ struct pt_regs *regs)
{
unsigned w;
+ irqreturn_t rval = IRQ_NONE;
unsigned gint = irq - IRQ_GINT (0);
for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
@@ -127,6 +129,7 @@
/* Recursively call handle_irq to handle it. */
handle_irq (irq, regs);
+ rval = IRQ_HANDLED;
} while (status);
}
}
@@ -136,6 +139,8 @@
still pending, and so result in another CPU interrupt. */
GBUS_INT_ENABLE (0, gint) &= ~0x1;
GBUS_INT_ENABLE (0, gint) |= 0x1;
+
+ return rval;
}
diff -Nru a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
--- a/arch/v850/kernel/simcons.c Sun Jul 13 20:39:56 2003
+++ b/arch/v850/kernel/simcons.c Sun Jul 13 20:39:56 2003
@@ -30,7 +30,7 @@
V850_SIM_SYSCALL (write, 1, buf, len);
}
-static int simcons_read (struct console *co, const char *buf, unsigned len)
+static int simcons_read (struct console *co, char *buf, unsigned len)
{
return V850_SIM_SYSCALL (read, 0, buf, len);
}
diff -Nru a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
--- a/arch/v850/kernel/time.c Sun Jul 13 20:39:55 2003
+++ b/arch/v850/kernel/time.c Sun Jul 13 20:39:55 2003
@@ -51,7 +51,7 @@
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static void timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
+static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
{
#if 0
/* last time the cmos clock got updated */
@@ -106,6 +106,8 @@
}
#endif /* CONFIG_HEARTBEAT */
#endif /* 0 */
+
+ return IRQ_HANDLED;
}
/*
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig Sun Jul 13 20:39:56 2003
+++ b/arch/x86_64/Kconfig Sun Jul 13 20:39:56 2003
@@ -540,13 +540,6 @@
Fill __init and __initdata at the end of boot. This helps debugging
illegal uses of __init and __initdata after initialization.
-config KALLSYMS
- bool "Load all symbols for debugging/kksymoops"
- help
- Say Y here to let the kernel print out symbolic crash information and
- symbolic stack backtraces. This increases the size of the kernel
- somewhat, as all symbols have to be loaded into the kernel image.
-
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
help
diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
--- a/arch/x86_64/boot/setup.S Sun Jul 13 20:39:56 2003
+++ b/arch/x86_64/boot/setup.S Sun Jul 13 20:39:56 2003
@@ -350,6 +350,11 @@
sse_ok:
popw %ds
+# tell BIOS we want to go to long mode
+ movl $0xec00,%eax # declare target operating mode
+ movl $2,%ebx # long mode
+ int $0x15
+
# Get memory size (extended mem, kB)
xorl %eax, %eax
diff -Nru a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c
--- a/arch/x86_64/ia32/ipc32.c Sun Jul 13 20:39:55 2003
+++ b/arch/x86_64/ia32/ipc32.c Sun Jul 13 20:39:55 2003
@@ -271,7 +271,7 @@
fourth.__pad = &s;
old_fs = get_fs();
set_fs(KERNEL_DS);
- err = sys_semctl(first, second, third|IPC_64, fourth);
+ err = sys_semctl(first, second, third, fourth);
set_fs(old_fs);
if (!err)
err = put_semid((void *)A(pad), &s, version);
@@ -396,7 +396,7 @@
case MSG_STAT:
old_fs = get_fs();
set_fs(KERNEL_DS);
- err = sys_msgctl(first, second|IPC_64, (void *) &m64);
+ err = sys_msgctl(first, second, (void *) &m64);
set_fs(old_fs);
if (version == IPC_64) {
if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
@@ -529,7 +529,7 @@
case IPC_INFO:
old_fs = get_fs();
set_fs(KERNEL_DS);
- err = sys_shmctl(first, second|IPC_64, (struct shmid_ds *)&smi);
+ err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
set_fs(old_fs);
if (version == IPC_64) {
@@ -587,7 +587,7 @@
case SHM_STAT:
old_fs = get_fs();
set_fs(KERNEL_DS);
- err = sys_shmctl(first, second|IPC_64, (void *) &s64);
+ err = sys_shmctl(first, second, (void *) &s64);
set_fs(old_fs);
if (err < 0)
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c Sun Jul 13 20:39:56 2003
+++ b/arch/x86_64/kernel/time.c Sun Jul 13 20:39:56 2003
@@ -125,33 +125,22 @@
int do_settimeofday(struct timespec *tv)
{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
write_seqlock_irq(&xtime_lock);
- tv->tv_nsec -= do_gettimeoffset() * 1000 +
+ nsec -= do_gettimeoffset() * 1000 +
(jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ);
- while (tv->tv_nsec < 0) {
- tv->tv_nsec += NSEC_PER_SEC;
- tv->tv_sec--;
- }
-
- wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
- wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
-
- if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
- wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
- wall_to_monotonic.tv_sec++;
- }
- if (wall_to_monotonic.tv_nsec < 0) {
- wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
- wall_to_monotonic.tv_sec--;
- }
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_nsec = tv->tv_nsec;
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
@@ -603,8 +592,8 @@
xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = 0;
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
if (!hpet_init()) {
vxtime_hz = (1000000000000000L + hpet_period / 2) /
diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
--- a/arch/x86_64/kernel/x8664_ksyms.c Sun Jul 13 20:39:55 2003
+++ b/arch/x86_64/kernel/x8664_ksyms.c Sun Jul 13 20:39:55 2003
@@ -214,5 +214,7 @@
EXPORT_SYMBOL(clear_page);
+#ifdef CONFIG_SMP
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL_GPL(flush_tlb_all);
+#endif
diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig Sun Jul 13 20:39:55 2003
+++ b/drivers/block/Kconfig Sun Jul 13 20:39:55 2003
@@ -237,29 +237,20 @@
root file system inside a DOS FAT file using this loop device
driver.
- The loop device driver can also be used to "hide" a file system in a
- disk partition, floppy, or regular file, either using encryption
+ To use the loop device, you need the losetup utility, found in the
+ util-linux package, see
+ .
+
+ The loop device driver can also be used to "hide" a file system in
+ a disk partition, floppy, or regular file, either using encryption
(scrambling the data) or steganography (hiding the data in the low
bits of, say, a sound file). This is also safe if the file resides
- on a remote file server. If you want to do this, you will first have
- to acquire and install a kernel patch from
- , and then you need to
- say Y to this option.
-
- Note that alternative ways to use encrypted file systems are
- provided by the cfs package, which can be gotten from
- , and the newer tcfs
- package, available at . You do not need
- to say Y here if you want to use one of these. However, using cfs
- requires saying Y to "NFS file system support" below while using
- tcfs requires applying a kernel patch. An alternative steganography
- solution is provided by StegFS, also available from
- .
-
- To use the loop device, you need the losetup utility and a recent
- version of the mount program, both contained in the util-linux
- package. The location and current version number of util-linux is
- contained in the file .
+ on a remote file server.
+
+ There are several ways of doing this. Some of these require kernel
+ patches. The vanilla kernel offers the cryptoloop option. If you
+ want to use that, say Y to both LOOP and CRYPTOLOOP, and make sure
+ you have a recent (version 2.12 or later) version of util-linux.
Note that this loop device has nothing to do with the loopback
device used for network connections from the machine to itself.
@@ -270,6 +261,14 @@
will be called loop.
Most users will answer N here.
+
+config BLK_DEV_CRYPTOLOOP
+ tristate "Cryptoloop Support"
+ depends on BLK_DEV_LOOP
+ ---help---
+ Say Y here if you want to be able to use the ciphers that are
+ provided by the CryptoAPI as loop transformation. This might be
+ used as hard disk encryption.
config BLK_DEV_NBD
tristate "Network block device support"
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile Sun Jul 13 20:39:56 2003
+++ b/drivers/block/Makefile Sun Jul 13 20:39:56 2003
@@ -36,3 +36,4 @@
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
+obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
--- a/drivers/block/as-iosched.c Sun Jul 13 20:39:54 2003
+++ b/drivers/block/as-iosched.c Sun Jul 13 20:39:54 2003
@@ -837,7 +837,7 @@
aic->seek_total += 256*seek_dist;
if (aic->seek_samples) {
aic->seek_mean = aic->seek_total + 128;
- do_div(aic->seek_mean, aic->seek_samples);
+ sector_div(aic->seek_mean, aic->seek_samples);
}
aic->seek_samples = (aic->seek_samples>>1)
+ (aic->seek_samples>>2);
diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/block/cryptoloop.c Sun Jul 13 20:39:56 2003
@@ -0,0 +1,182 @@
+/*
+ Linux loop encryption enabling module
+
+ Copyright (C) 2002 Herbert Valerio Riedel
+ Copyright (C) 2003 Fruhwirth Clemens
+
+ This module is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This module is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this module; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI");
+MODULE_AUTHOR("Herbert Valerio Riedel ");
+
+#define LOOP_IV_SECTOR_BITS 9
+#define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS)
+
+static int
+cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
+{
+ int err = -EINVAL;
+ char cms[LO_NAME_SIZE]; /* cipher-mode string */
+ char *cipher;
+ char *mode;
+ char *cmsp = cms; /* c-m string pointer */
+ struct crypto_tfm *tfm = NULL;
+
+ /* encryption breaks for non sector aligned offsets */
+
+ if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
+ goto out;
+
+ strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE);
+ cms[LO_NAME_SIZE - 1] = 0;
+ cipher = strsep(&cmsp, "-");
+ mode = strsep(&cmsp, "-");
+
+ if (mode == NULL || strcmp(mode, "cbc") == 0)
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC);
+ else if (strcmp(mode, "ecb") == 0)
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB);
+ if (tfm == NULL)
+ return -EINVAL;
+
+ err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key,
+ info->lo_encrypt_key_size);
+
+ if (err != 0)
+ goto out_free_tfm;
+
+ lo->key_data = tfm;
+ return 0;
+
+ out_free_tfm:
+ crypto_free_tfm(tfm);
+
+ out:
+ return err;
+}
+
+typedef int (*encdec_t)(struct crypto_tfm *tfm,
+ struct scatterlist *sg_out,
+ struct scatterlist *sg_in,
+ unsigned int nsg, u8 *iv);
+
+static int
+cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
+ char *loop_buf, int size, sector_t IV)
+{
+ struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+ struct scatterlist sg_out = { 0, };
+ struct scatterlist sg_in = { 0, };
+
+ encdec_t encdecfunc;
+ char const *in;
+ char *out;
+
+ if (cmd == READ) {
+ in = raw_buf;
+ out = loop_buf;
+ encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv;
+ } else {
+ in = loop_buf;
+ out = raw_buf;
+ encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv;
+ }
+
+ while (size > 0) {
+ const int sz = min(size, LOOP_IV_SECTOR_SIZE);
+ u32 iv[4] = { 0, };
+ iv[0] = cpu_to_le32(IV & 0xffffffff);
+
+ sg_in.page = virt_to_page(in);
+ sg_in.offset = (unsigned long)in & ~PAGE_MASK;
+ sg_in.length = sz;
+
+ sg_out.page = virt_to_page(out);
+ sg_out.offset = (unsigned long)out & ~PAGE_MASK;
+ sg_out.length = sz;
+
+ encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv);
+
+ IV++;
+ size -= sz;
+ in += sz;
+ out += sz;
+ }
+
+ return 0;
+}
+
+
+static int
+cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)
+{
+ return -EINVAL;
+}
+
+static int
+cryptoloop_release(struct loop_device *lo)
+{
+ struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+ if (tfm != NULL) {
+ crypto_free_tfm(tfm);
+ lo->key_data = NULL;
+ return 0;
+ }
+ printk(KERN_ERR "cryptoloop_release(): tfm == NULL?\n");
+ return -EINVAL;
+}
+
+static struct loop_func_table cryptoloop_funcs = {
+ .number = LO_CRYPT_CRYPTOAPI,
+ .init = cryptoloop_init,
+ .ioctl = cryptoloop_ioctl,
+ .transfer = cryptoloop_transfer,
+ .release = cryptoloop_release,
+ .owner = THIS_MODULE
+};
+
+static int __init
+init_cryptoloop(void)
+{
+ int rc = loop_register_transfer(&cryptoloop_funcs);
+
+ if (rc)
+ printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
+ return rc;
+}
+
+static void __exit
+cleanup_cryptoloop(void)
+{
+ if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI))
+ printk(KERN_ERR
+ "cryptoloop: loop_unregister_transfer failed\n");
+}
+
+module_init(init_cryptoloop);
+module_exit(cleanup_cryptoloop);
diff -Nru a/drivers/block/floppy98.c b/drivers/block/floppy98.c
--- a/drivers/block/floppy98.c Sun Jul 13 20:39:55 2003
+++ b/drivers/block/floppy98.c Sun Jul 13 20:39:55 2003
@@ -4064,21 +4064,32 @@
static char *table[] =
{"",
#if 0
-"d360",
+ "d360",
#else
-"h1232",
+ "h1232",
#endif
-"h1200", "u360", "u720", "h360", "h720",
-"u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
-"u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
-"h880", "u1040", "u1120", "h1600", "u1760", "u1920",
-"u3200", "u3520", "u3840", "u1840", "u800", "u1600",
+ "h1200", "u360", "u720", "h360", "h720",
+ "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
+ "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
+ "h880", "u1040", "u1120", "h1600", "u1760", "u1920",
+ "u3200", "u3520", "u3840", "u1840", "u800", "u1600",
NULL
};
-static int t360[] = {1,0}, t1200[] = {2,5,6,10,12,14,16,18,20,23,0},
-t3in[] = {8,9,26,27,28, 7,11,15,19,24,25,29,31, 3,4,13,17,21,22,30,0};
-static int *table_sup[] =
-{NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
+
+static int t360[] = {
+ 1,0
+};
+static int t1200[] = {
+ 2,5,6,10,12,14,16,18,20,23,0
+};
+static int t3in[] = {
+ 8, 9,26,27,28, 7,11,15,19,24,25,
+ 29,31, 3, 4,13,17,21,22,30, 0
+};
+
+static int *table_sup[] = {
+ NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in
+};
static void __init register_devfs_entries (int drive)
{
@@ -4402,7 +4413,7 @@
return 0;
out1:
- del_timer(&fd_timeout);
+ del_timer_sync(&fd_timeout);
out2:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR,"fd");
@@ -4430,11 +4441,9 @@
return 0;
}
spin_unlock_irqrestore(&floppy_usage_lock, flags);
- MOD_INC_USE_COUNT;
if (fd_request_irq()) {
DPRINT("Unable to grab IRQ%d for the floppy driver\n",
FLOPPY_IRQ);
- MOD_DEC_USE_COUNT;
spin_lock_irqsave(&floppy_usage_lock, flags);
usage_count--;
spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4444,7 +4453,6 @@
DPRINT("Unable to grab DMA%d for the floppy driver\n",
FLOPPY_DMA);
fd_free_irq();
- MOD_DEC_USE_COUNT;
spin_lock_irqsave(&floppy_usage_lock, flags);
usage_count--;
spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4521,7 +4529,6 @@
release_region(0x04be, 1);
}
}
- MOD_DEC_USE_COUNT;
spin_lock_irqsave(&floppy_usage_lock, flags);
usage_count--;
spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4587,7 +4594,6 @@
}
}
fdc = old_fdc;
- MOD_DEC_USE_COUNT;
}
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c Sun Jul 13 20:39:54 2003
+++ b/drivers/block/ll_rw_blk.c Sun Jul 13 20:39:54 2003
@@ -1546,7 +1546,7 @@
{
int rw = rq_data_dir(rq);
- if (!rq->rq_disk)
+ if (!blk_fs_request(rq) || !rq->rq_disk)
return;
if (rw == READ) {
@@ -2354,7 +2354,7 @@
struct gendisk *disk = req->rq_disk;
struct completion *waiting = req->waiting;
- if (disk) {
+ if (disk && blk_fs_request(req)) {
unsigned long duration = jiffies - req->start_time;
switch (rq_data_dir(req)) {
case WRITE:
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c Sun Jul 13 20:39:55 2003
+++ b/drivers/block/loop.c Sun Jul 13 20:39:55 2003
@@ -140,7 +140,8 @@
sector_t x;
/* Compute loopsize in bytes */
- size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size;
+ size = i_size_read(lo->lo_backing_file->f_dentry->
+ d_inode->i_mapping->host);
offset = lo->lo_offset;
loopsize = size - offset;
if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
@@ -840,7 +841,8 @@
lo->lo_flags = 0;
lo->lo_queue.queuedata = NULL;
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
- memset(lo->lo_name, 0, LO_NAME_SIZE);
+ memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
+ memset(lo->lo_file_name, 0, LO_NAME_SIZE);
invalidate_bdev(bdev, 0);
set_capacity(disks[lo->lo_number], 0);
filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp;
@@ -892,7 +894,10 @@
return -EFBIG;
}
- strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE);
+ memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
+ memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
+ lo->lo_file_name[LO_NAME_SIZE-1] = 0;
+ lo->lo_crypt_name[LO_NAME_SIZE-1] = 0;
if (!xfer)
xfer = &none_funcs;
@@ -931,7 +936,8 @@
info->lo_offset = lo->lo_offset;
info->lo_sizelimit = lo->lo_sizelimit;
info->lo_flags = lo->lo_flags;
- strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE);
+ memcpy(info->lo_file_name, lo->lo_file_name, LO_NAME_SIZE);
+ memcpy(info->lo_crypt_name, lo->lo_crypt_name, LO_NAME_SIZE);
info->lo_encrypt_type =
lo->lo_encryption ? lo->lo_encryption->number : 0;
if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
@@ -957,7 +963,10 @@
info64->lo_flags = info->lo_flags;
info64->lo_init[0] = info->lo_init[0];
info64->lo_init[1] = info->lo_init[1];
- memcpy(info64->lo_name, info->lo_name, LO_NAME_SIZE);
+ if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info64->lo_crypt_name, info->lo_name, LO_NAME_SIZE);
+ else
+ memcpy(info64->lo_file_name, info->lo_name, LO_NAME_SIZE);
memcpy(info64->lo_encrypt_key, info->lo_encrypt_key, LO_KEY_SIZE);
}
@@ -975,8 +984,11 @@
info->lo_flags = info64->lo_flags;
info->lo_init[0] = info64->lo_init[0];
info->lo_init[1] = info64->lo_init[1];
- memcpy(info->lo_name, info64->lo_name, LO_NAME_SIZE);
- memcpy(info->lo_encrypt_key,info64->lo_encrypt_key,LO_KEY_SIZE);
+ if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+ else
+ memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
+ memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
/* error in case values were truncated */
if (info->lo_device != info64->lo_device ||
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c Sun Jul 13 20:39:55 2003
+++ b/drivers/block/nbd.c Sun Jul 13 20:39:55 2003
@@ -31,13 +31,17 @@
* 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
* memory corruption from module removal and possible memory corruption
* from sending/receiving disk data.
+ * 03-06-23 Cosmetic changes.
+ * 03-06-23 Enhance diagnostics support.
+ * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
+ *
+ * 03-06-24 Cleanup PARANOIA usage & code.
*
* possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
* why not: would need verify_area and friends, would share yet another
* structure with userland
*/
-#define PARANOIA
#include
#include
@@ -60,9 +64,27 @@
#include
#include
+/* Define PARANOIA in linux/nbd.h to turn on extra sanity checking */
#include
+#ifdef PARANOIA
#define LO_MAGIC 0x68797548
+#endif
+
+#ifdef NDEBUG
+#define dprintk(flags, fmt...)
+#else /* NDEBUG */
+#define dprintk(flags, fmt...) do { \
+ if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
+} while (0)
+#define DBG_IOCTL 0x0004
+#define DBG_INIT 0x0010
+#define DBG_EXIT 0x0020
+#define DBG_BLKDEV 0x0100
+#define DBG_RX 0x0200
+#define DBG_TX 0x0400
+static unsigned int debugflags;
+#endif /* NDEBUG */
static struct nbd_device nbd_dev[MAX_NBD];
@@ -78,12 +100,40 @@
*/
static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
-#define DEBUG( s )
-/* #define DEBUG( s ) printk( s )
- */
-
+#ifdef PARANOIA
static int requests_in;
static int requests_out;
+#endif
+
+#ifndef NDEBUG
+static const char *ioctl_cmd_to_ascii(int cmd)
+{
+ switch (cmd) {
+ case NBD_SET_SOCK: return "set-sock";
+ case NBD_SET_BLKSIZE: return "set-blksize";
+ case NBD_SET_SIZE: return "set-size";
+ case NBD_DO_IT: return "do-it";
+ case NBD_CLEAR_SOCK: return "clear-sock";
+ case NBD_CLEAR_QUE: return "clear-que";
+ case NBD_PRINT_DEBUG: return "print-debug";
+ case NBD_SET_SIZE_BLOCKS: return "set-size-blocks";
+ case NBD_DISCONNECT: return "disconnect";
+ case BLKROSET: return "set-read-only";
+ case BLKFLSBUF: return "flush-buffer-cache";
+ }
+ return "unknown";
+}
+
+static const char *nbdcmd_to_ascii(int cmd)
+{
+ switch (cmd) {
+ case NBD_CMD_READ: return "read";
+ case NBD_CMD_WRITE: return "write";
+ case NBD_CMD_DISC: return "disconnect";
+ }
+ return "invalid";
+}
+#endif /* NDEBUG */
static void nbd_end_request(struct request *req)
{
@@ -91,6 +141,8 @@
request_queue_t *q = req->q;
unsigned long flags;
+ dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
+ req, uptodate? "done": "failed");
#ifdef PARANOIA
requests_out++;
#endif
@@ -101,17 +153,11 @@
spin_unlock_irqrestore(q->queue_lock, flags);
}
-static int nbd_open(struct inode *inode, struct file *file)
-{
- struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
- lo->refcnt++;
- return 0;
-}
-
/*
* Send or receive packet.
*/
-static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags)
+static int sock_xmit(struct socket *sock, int send, void *buf, int size,
+ int msg_flags)
{
mm_segment_t oldfs;
int result;
@@ -131,7 +177,6 @@
recalc_sigpending();
spin_unlock_irqrestore(¤t->sighand->siglock, flags);
-
do {
sock->sk->sk_allocation = GFP_NOIO;
iov.iov_base = buf;
@@ -153,7 +198,7 @@
if (signal_pending(current)) {
siginfo_t info;
spin_lock_irqsave(¤t->sighand->siglock, flags);
- printk(KERN_WARNING "NBD (pid %d: %s) got signal %d\n",
+ printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
current->pid, current->comm,
dequeue_signal(current, ¤t->blocked, &info));
spin_unlock_irqrestore(¤t->sighand->siglock, flags);
@@ -163,8 +208,8 @@
if (result <= 0) {
#ifdef PARANOIA
- printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n",
- send ? "send" : "receive", (long) sock, (long) buf, size, result);
+ printk(KERN_ERR "nbd: %s - sock=%p at buf=%p, size=%d returned %d.\n",
+ send? "send": "receive", sock, buf, size, result);
#endif
break;
}
@@ -186,14 +231,12 @@
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = nbd_xmit(1, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+ result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
flags);
kunmap(bvec->bv_page);
return result;
}
-#define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); goto error_out; }
-
void nbd_send_req(struct nbd_device *lo, struct request *req)
{
int result, i, flags;
@@ -201,24 +244,31 @@
unsigned long size = req->nr_sectors << 9;
struct socket *sock = lo->sock;
- DEBUG("NBD: sending control, ");
-
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(nbd_cmd(req));
- request.from = cpu_to_be64( (u64) req->sector << 9);
+ request.from = cpu_to_be64((u64) req->sector << 9);
request.len = htonl(size);
memcpy(request.handle, &req, sizeof(req));
down(&lo->tx_lock);
if (!sock || !lo->sock) {
- printk(KERN_ERR "NBD: Attempted sendmsg to closed socket\n");
+ printk(KERN_ERR "%s: Attempted send on closed socket\n",
+ lo->disk->disk_name);
goto error_out;
}
- result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0);
- if (result <= 0)
- FAIL("Sendmsg failed for control.");
+ dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
+ lo->disk->disk_name, req,
+ nbdcmd_to_ascii(nbd_cmd(req)),
+ req->sector << 9, req->nr_sectors << 9);
+ result = sock_xmit(sock, 1, &request, sizeof(request),
+ (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
+ if (result <= 0) {
+ printk(KERN_ERR "%s: Send control failed (result %d)\n",
+ lo->disk->disk_name, result);
+ goto error_out;
+ }
if (nbd_cmd(req) == NBD_CMD_WRITE) {
struct bio *bio;
@@ -232,10 +282,16 @@
flags = 0;
if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
flags = MSG_MORE;
- DEBUG("data, ");
+ dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
+ lo->disk->disk_name, req,
+ bvec->bv_len);
result = sock_send_bvec(sock, bvec, flags);
- if (result <= 0)
- FAIL("Send data failed.");
+ if (result <= 0) {
+ printk(KERN_ERR "%s: Send data failed (result %d)\n",
+ lo->disk->disk_name,
+ result);
+ goto error_out;
+ }
}
}
}
@@ -272,55 +328,71 @@
{
int result;
void *kaddr = kmap(bvec->bv_page);
- result = nbd_xmit(0, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+ result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
MSG_WAITALL);
kunmap(bvec->bv_page);
return result;
}
-#define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; }
+/* NULL returned = something went wrong, inform userspace */
struct request *nbd_read_stat(struct nbd_device *lo)
- /* NULL returned = something went wrong, inform userspace */
{
int result;
struct nbd_reply reply;
struct request *req;
struct socket *sock = lo->sock;
- DEBUG("reading control, ");
reply.magic = 0;
- result = nbd_xmit(0, sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
- if (result <= 0)
- HARDFAIL("Recv control failed.");
+ result = sock_xmit(sock, 0, &reply, sizeof(reply), MSG_WAITALL);
+ if (result <= 0) {
+ printk(KERN_ERR "%s: Receive control failed (result %d)\n",
+ lo->disk->disk_name, result);
+ lo->harderror = result;
+ return NULL;
+ }
req = nbd_find_request(lo, reply.handle);
- if (req == NULL)
- HARDFAIL("Unexpected reply");
-
- DEBUG("ok, ");
- if (ntohl(reply.magic) != NBD_REPLY_MAGIC)
- HARDFAIL("Not enough magic.");
- if (ntohl(reply.error))
- FAIL("Other side returned error.");
+ if (req == NULL) {
+ printk(KERN_ERR "%s: Unexpected reply (%p)\n",
+ lo->disk->disk_name, reply.handle);
+ lo->harderror = result;
+ return NULL;
+ }
+
+ if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+ printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+ lo->disk->disk_name,
+ (unsigned long)ntohl(reply.magic));
+ lo->harderror = result;
+ return NULL;
+ }
+ if (ntohl(reply.error)) {
+ printk(KERN_ERR "%s: Other side returned error (%d)\n",
+ lo->disk->disk_name, ntohl(reply.error));
+ req->errors++;
+ return req;
+ }
+ dprintk(DBG_RX, "%s: request %p: got reply\n",
+ lo->disk->disk_name, req);
if (nbd_cmd(req) == NBD_CMD_READ) {
int i;
struct bio *bio;
- DEBUG("data, ");
rq_for_each_bio(bio, req) {
struct bio_vec *bvec;
bio_for_each_segment(bvec, bio, i) {
result = sock_recv_bvec(sock, bvec);
- if (result <= 0)
- HARDFAIL("Recv data failed.");
+ if (result <= 0) {
+ printk(KERN_ERR "%s: Receive data failed (result %d)\n",
+ lo->disk->disk_name,
+ result);
+ lo->harderror = result;
+ return NULL;
+ }
+ dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
+ lo->disk->disk_name, req, bvec->bv_len);
}
}
}
- DEBUG("done.\n");
- return req;
-
-/* Can we get here? Yes, if other side returns error */
- error_out:
- req->errors++;
return req;
}
@@ -328,17 +400,13 @@
{
struct request *req;
- while (1) {
- req = nbd_read_stat(lo);
-
- if (!req) {
- printk(KERN_ALERT "req should never be null\n" );
- goto out;
- }
- BUG_ON(lo->magic != LO_MAGIC);
+#ifdef PARANOIA
+ BUG_ON(lo->magic != LO_MAGIC);
+#endif
+ while ((req = nbd_read_stat(lo)) != NULL)
nbd_end_request(req);
- }
- out:
+ printk(KERN_NOTICE "%s: req should never be null\n",
+ lo->disk->disk_name);
return;
}
@@ -346,7 +414,9 @@
{
struct request *req;
+#ifdef PARANOIA
BUG_ON(lo->magic != LO_MAGIC);
+#endif
do {
req = NULL;
@@ -360,7 +430,7 @@
req->errors++;
nbd_end_request(req);
}
- } while(req);
+ } while (req);
}
/*
@@ -370,9 +440,6 @@
* { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
*/
-#undef FAIL
-#define FAIL( s ) { printk( KERN_ERR "%s: " s "\n", req->rq_disk->disk_name ); goto error_out; }
-
static void do_nbd_request(request_queue_t * q)
{
struct request *req;
@@ -380,30 +447,44 @@
while ((req = elv_next_request(q)) != NULL) {
struct nbd_device *lo;
+ blkdev_dequeue_request(req);
+ dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
+ req->rq_disk->disk_name, req, req->flags);
+
if (!(req->flags & REQ_CMD))
goto error_out;
lo = req->rq_disk->private_data;
- if (!lo->file)
- FAIL("Request when not-ready.");
+#ifdef PARANOIA
+ BUG_ON(lo->magic != LO_MAGIC);
+#endif
+ if (!lo->file) {
+ printk(KERN_ERR "%s: Request when not-ready\n",
+ lo->disk->disk_name);
+ goto error_out;
+ }
nbd_cmd(req) = NBD_CMD_READ;
if (rq_data_dir(req) == WRITE) {
nbd_cmd(req) = NBD_CMD_WRITE;
- if (lo->flags & NBD_READ_ONLY)
- FAIL("Write on read-only");
+ if (lo->flags & NBD_READ_ONLY) {
+ printk(KERN_ERR "%s: Write on read-only\n",
+ lo->disk->disk_name);
+ goto error_out;
+ }
}
- BUG_ON(lo->magic != LO_MAGIC);
+#ifdef PARANOIA
requests_in++;
+#endif
req->errors = 0;
- blkdev_dequeue_request(req);
spin_unlock_irq(q->queue_lock);
spin_lock(&lo->queue_lock);
if (!lo->file) {
spin_unlock(&lo->queue_lock);
- printk(KERN_ERR "nbd: failed between accept and semaphore, file lost\n");
+ printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
+ lo->disk->disk_name);
req->errors++;
nbd_end_request(req);
spin_lock_irq(q->queue_lock);
@@ -416,7 +497,8 @@
nbd_send_req(lo, req);
if (req->errors) {
- printk(KERN_ERR "nbd: nbd_send_req failed\n");
+ printk(KERN_ERR "%s: Request send failed\n",
+ lo->disk->disk_name);
spin_lock(&lo->queue_lock);
list_del_init(&req->queuelist);
spin_unlock(&lo->queue_lock);
@@ -430,7 +512,6 @@
error_out:
req->errors++;
- blkdev_dequeue_request(req);
spin_unlock(q->queue_lock);
nbd_end_request(req);
spin_lock(q->queue_lock);
@@ -442,18 +523,30 @@
unsigned int cmd, unsigned long arg)
{
struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
- int error, temp;
+ int error;
struct request sreq ;
- /* Anyone capable of this syscall can do *real bad* things */
-
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+#ifdef PARANOIA
+ BUG_ON(lo->magic != LO_MAGIC);
+#endif
+ /* Anyone capable of this syscall can do *real bad* things */
+ dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
+ lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
+
switch (cmd) {
case NBD_DISCONNECT:
- printk(KERN_INFO "NBD_DISCONNECT\n");
+ printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
sreq.flags = REQ_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
+ /*
+ * Set these to sane values in case server implementation
+ * fails to check the request type first and also to keep
+ * debugging output cleaner.
+ */
+ sreq.sector = 0;
+ sreq.nr_sectors = 0;
if (!lo->sock)
return -EINVAL;
nbd_send_req(lo, &sreq);
@@ -464,7 +557,8 @@
spin_lock(&lo->queue_lock);
if (!list_empty(&lo->queue_head)) {
spin_unlock(&lo->queue_lock);
- printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
+ printk(KERN_ERR "%s: Some requests are in progress -> can not turn off.\n",
+ lo->disk->disk_name);
return -EBUSY;
}
file = lo->file;
@@ -494,24 +588,22 @@
}
return error;
case NBD_SET_BLKSIZE:
- if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
- return -EINVAL;
lo->blksize = arg;
- temp = arg >> 9;
- lo->blksize_bits = 9;
- while (temp > 1) {
- lo->blksize_bits++;
- temp >>= 1;
- }
- lo->bytesize &= ~(lo->blksize-1);
+ lo->bytesize &= ~(lo->blksize-1);
+ inode->i_bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(inode->i_bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_SET_SIZE:
- lo->bytesize = arg & ~(lo->blksize-1);
+ lo->bytesize = arg & ~(lo->blksize-1);
+ inode->i_bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(inode->i_bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_SET_SIZE_BLOCKS:
- lo->bytesize = ((u64) arg) << lo->blksize_bits;
+ lo->bytesize = ((u64) arg) * lo->blksize;
+ inode->i_bdev->bd_inode->i_size = lo->bytesize;
+ set_blocksize(inode->i_bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_DO_IT:
@@ -526,7 +618,8 @@
* there should be a more generic interface rather than
* calling socket ops directly here */
down(&lo->tx_lock);
- printk(KERN_WARNING "nbd: shutting down socket\n");
+ printk(KERN_WARNING "%s: shutting down socket\n",
+ lo->disk->disk_name);
lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
lo->sock = NULL;
up(&lo->tx_lock);
@@ -535,39 +628,31 @@
lo->file = NULL;
spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
- printk(KERN_WARNING "nbd: queue cleared\n");
+ printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
if (file)
fput(file);
return lo->harderror;
case NBD_CLEAR_QUE:
nbd_clear_que(lo);
return 0;
-#ifdef PARANOIA
case NBD_PRINT_DEBUG:
+#ifdef PARANOIA
printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n",
- inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
- lo->queue_head.prev, requests_in, requests_out);
- return 0;
+ inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
+ lo->queue_head.prev, requests_in, requests_out);
+#else
+ printk(KERN_INFO "%s: next = %p, prev = %p\n",
+ inode->i_bdev->bd_disk->disk_name,
+ lo->queue_head.next, lo->queue_head.prev);
#endif
+ return 0;
}
return -EINVAL;
}
-static int nbd_release(struct inode *inode, struct file *file)
-{
- struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
- if (lo->refcnt <= 0)
- printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
- lo->refcnt--;
- /* N.B. Doesn't lo->file need an fput?? */
- return 0;
-}
-
static struct block_device_operations nbd_fops =
{
.owner = THIS_MODULE,
- .open = nbd_open,
- .release = nbd_release,
.ioctl = nbd_ioctl,
};
@@ -581,10 +666,12 @@
int err = -ENOMEM;
int i;
+#ifdef PARANOIA
if (sizeof(struct nbd_request) != 28) {
- printk(KERN_CRIT "Sizeof nbd_request needs to be 28 in order to work!\n" );
+ printk(KERN_CRIT "nbd: Sizeof nbd_request needs to be 28 in order to work!\n" );
return -EIO;
}
+#endif
for (i = 0; i < MAX_NBD; i++) {
struct gendisk *disk = alloc_disk(1);
@@ -601,6 +688,7 @@
put_disk(disk);
goto out;
}
+ memset(disk->queue, 0, sizeof(struct request_queue));
blk_init_queue(disk->queue, do_nbd_request, &nbd_lock);
}
@@ -608,21 +696,22 @@
err = -EIO;
goto out;
}
-#ifdef MODULE
- printk("nbd: registered device at major %d\n", NBD_MAJOR);
-#endif
+
+ printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
+ dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
+
devfs_mk_dir("nbd");
for (i = 0; i < MAX_NBD; i++) {
struct gendisk *disk = nbd_dev[i].disk;
- nbd_dev[i].refcnt = 0;
nbd_dev[i].file = NULL;
+#ifdef PARANOIA
nbd_dev[i].magic = LO_MAGIC;
+#endif
nbd_dev[i].flags = 0;
spin_lock_init(&nbd_dev[i].queue_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
init_MUTEX(&nbd_dev[i].tx_lock);
nbd_dev[i].blksize = 1024;
- nbd_dev[i].blksize_bits = 10;
nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */
disk->major = NBD_MAJOR;
disk->first_minor = i;
@@ -660,9 +749,7 @@
}
devfs_remove("nbd");
unregister_blkdev(NBD_MAJOR, "nbd");
-#ifdef MODULE
- printk("nbd: unregistered device at major %d\n", NBD_MAJOR);
-#endif
+ printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
}
module_init(nbd_init);
@@ -671,4 +758,7 @@
MODULE_DESCRIPTION("Network Block Device");
MODULE_LICENSE("GPL");
-
+#ifndef NDEBUG
+MODULE_PARM(debugflags, "i");
+MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
+#endif
diff -Nru a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c
--- a/drivers/char/agp/amd-k8-agp.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/agp/amd-k8-agp.c Sun Jul 13 20:39:56 2003
@@ -23,6 +23,19 @@
/* Will need to be increased if hammer ever goes >8-way. */
#define MAX_HAMMER_GARTS 8
+/* PTE bits. */
+#define GPTE_VALID 1
+#define GPTE_COHERENT 2
+
+/* Aperture control register bits. */
+#define GARTEN 1<<0
+#define DISGARTCPU 1<<4
+#define DISGARTIO 1<<5
+
+/* GART cache control register bits. */
+#define INVGART 1<<0
+#define GARTPTEERR 1<<1
+
static int nr_garts;
static struct pci_dev * hammers[MAX_HAMMER_GARTS];
@@ -34,7 +47,7 @@
u32 tmp;
pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp);
- tmp |= 1<<0;
+ tmp |= INVGART;
pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp);
}
@@ -49,7 +62,6 @@
int i, j, num_entries;
long tmp;
u32 pte;
- u64 addr;
num_entries = agp_num_entries();
@@ -76,13 +88,12 @@
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- addr = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+ tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
- tmp = addr;
BUG_ON(tmp & 0xffffff0000000ffc);
pte = (tmp & 0x000000ff00000000) >> 28;
pte |=(tmp & 0x00000000fffff000);
- pte |= 1<<1|1<<0;
+ pte |= GPTE_VALID | GPTE_COHERENT;
agp_bridge->gatt_table[j] = pte;
}
@@ -164,8 +175,8 @@
/* Enable GART translation for this hammer. */
pci_read_config_dword(hammer, AMD_X86_64_GARTAPERTURECTL, &tmp);
- tmp &= 0x3f;
- tmp |= 1<<0;
+ tmp |= GARTEN;
+ tmp &= ~(DISGARTCPU | DISGARTIO);
pci_write_config_dword(hammer, AMD_X86_64_GARTAPERTURECTL, tmp);
/* keep CPU's coherent. */
@@ -212,11 +223,6 @@
}
-static struct gatt_mask amd_8151_masks[] =
-{
- { .mask = 1, .type = 0 }
-};
-
struct agp_bridge_driver amd_8151_driver = {
.owner = THIS_MODULE,
.aperture_sizes = amd_8151_sizes,
@@ -227,7 +233,7 @@
.cleanup = amd_8151_cleanup,
.tlb_flush = amd_x86_64_tlbflush,
.mask_memory = agp_generic_mask_memory,
- .masks = amd_8151_masks,
+ .masks = NULL,
.agp_enable = agp_generic_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = agp_generic_create_gatt_table,
@@ -240,14 +246,31 @@
.agp_destroy_page = agp_generic_destroy_page,
};
+
+#ifdef CONFIG_SMP
+static int cache_nbs (void)
+{
+ struct pci_dev *loop_dev = NULL;
+ int i = 0;
+
+ /* cache pci_devs of northbridges. */
+ while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) != NULL) {
+ hammers[i++] = loop_dev;
+ nr_garts = i;
+ if (i == MAX_HAMMER_GARTS)
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+
static int __init agp_amdk8_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
- struct pci_dev *loop_dev = NULL;
u8 rev_id;
u8 cap_ptr;
- int i = 0;
char *revstring=" ";
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
@@ -297,24 +320,25 @@
/* Fill in the mode register */
pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
- /* cache pci_devs of northbridges. */
- while ((loop_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, loop_dev)) != NULL) {
- if (loop_dev->bus->number == 0 &&
- PCI_FUNC(loop_dev->devfn) == 3 &&
- PCI_SLOT(loop_dev->devfn) >=24 &&
- PCI_SLOT(loop_dev->devfn) <=31) {
- hammers[i++] = loop_dev;
- nr_garts = i;
- if (i == MAX_HAMMER_GARTS)
- goto out_free;
- }
+#ifdef CONFIG_SMP
+ if (cache_nbs() == -1) {
+ agp_put_bridge(bridge);
+ return -ENOMEM;
+ }
+#else
+ {
+ struct pci_dev *loop_dev = NULL;
+ while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) != NULL) {
+ /* For UP, we only care about the first GART. */
+ hammers[0] = loop_dev;
+ nr_garts = 1;
+ break;
+ }
}
+#endif
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
-out_free:
- agp_put_bridge(bridge);
- return -ENOMEM;
}
static void __devexit agp_amdk8_remove(struct pci_dev *pdev)
diff -Nru a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
--- a/drivers/char/agp/frontend.c Sun Jul 13 20:39:55 2003
+++ b/drivers/char/agp/frontend.c Sun Jul 13 20:39:55 2003
@@ -740,19 +740,19 @@
}
-static ssize_t agp_read(struct file *file, char *buf,
+static ssize_t agp_read(struct file *file, char __user *buf,
size_t count, loff_t * ppos)
{
return -EINVAL;
}
-static ssize_t agp_write(struct file *file, const char *buf,
+static ssize_t agp_write(struct file *file, const char __user *buf,
size_t count, loff_t * ppos)
{
return -EINVAL;
}
-static int agpioc_info_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_info userinfo;
struct agp_kern_info kerninfo;
@@ -769,13 +769,13 @@
userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
userinfo.pg_used = kerninfo.current_memory;
- if (copy_to_user((void *) arg, &userinfo, sizeof(struct agp_info)))
+ if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
return -EFAULT;
return 0;
}
-static int agpioc_acquire_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_acquire_wrap(struct agp_file_private *priv)
{
int ret;
struct agp_controller *controller;
@@ -815,33 +815,33 @@
return 0;
}
-static int agpioc_release_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_release_wrap(struct agp_file_private *priv)
{
DBG("");
agp_controller_release_current(agp_fe.current_controller, priv);
return 0;
}
-static int agpioc_setup_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_setup mode;
DBG("");
- if (copy_from_user(&mode, (void *) arg, sizeof(struct agp_setup)))
+ if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
return -EFAULT;
agp_enable(mode.agp_mode);
return 0;
}
-static int agpioc_reserve_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_region reserve;
struct agp_client *client;
struct agp_file_private *client_priv;
DBG("");
- if (copy_from_user(&reserve, (void *) arg, sizeof(struct agp_region)))
+ if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
return -EFAULT;
if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
@@ -874,7 +874,7 @@
if (segment == NULL)
return -ENOMEM;
- if (copy_from_user(segment, (void *) reserve.seg_list,
+ if (copy_from_user(segment, (void __user *) reserve.seg_list,
sizeof(struct agp_segment) * reserve.seg_count)) {
kfree(segment);
return -EFAULT;
@@ -902,20 +902,20 @@
return -EINVAL;
}
-static int agpioc_protect_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_protect_wrap(struct agp_file_private *priv)
{
DBG("");
/* This function is not currently implemented */
return -EINVAL;
}
-static int agpioc_allocate_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_memory *memory;
struct agp_allocate alloc;
DBG("");
- if (copy_from_user(&alloc, (void *) arg, sizeof(struct agp_allocate)))
+ if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
return -EFAULT;
memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
@@ -926,19 +926,19 @@
alloc.key = memory->key;
alloc.physical = memory->physical;
- if (copy_to_user((void *) arg, &alloc, sizeof(struct agp_allocate))) {
+ if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
agp_free_memory_wrap(memory);
return -EFAULT;
}
return 0;
}
-static int agpioc_deallocate_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
{
struct agp_memory *memory;
DBG("");
- memory = agp_find_mem_by_key((int) arg);
+ memory = agp_find_mem_by_key(arg);
if (memory == NULL)
return -EINVAL;
@@ -947,13 +947,13 @@
return 0;
}
-static int agpioc_bind_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_bind bind_info;
struct agp_memory *memory;
DBG("");
- if (copy_from_user(&bind_info, (void *) arg, sizeof(struct agp_bind)))
+ if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
return -EFAULT;
memory = agp_find_mem_by_key(bind_info.key);
@@ -964,13 +964,13 @@
return agp_bind_memory(memory, bind_info.pg_start);
}
-static int agpioc_unbind_wrap(struct agp_file_private *priv, unsigned long arg)
+static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_memory *memory;
struct agp_unbind unbind;
DBG("");
- if (copy_from_user(&unbind, (void *) arg, sizeof(struct agp_unbind)))
+ if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
return -EFAULT;
memory = agp_find_mem_by_key(unbind.key);
@@ -1016,43 +1016,43 @@
switch (cmd) {
case AGPIOC_INFO:
- ret_val = agpioc_info_wrap(curr_priv, arg);
+ ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
break;
case AGPIOC_ACQUIRE:
- ret_val = agpioc_acquire_wrap(curr_priv, arg);
+ ret_val = agpioc_acquire_wrap(curr_priv);
break;
case AGPIOC_RELEASE:
- ret_val = agpioc_release_wrap(curr_priv, arg);
+ ret_val = agpioc_release_wrap(curr_priv);
break;
case AGPIOC_SETUP:
- ret_val = agpioc_setup_wrap(curr_priv, arg);
+ ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
break;
case AGPIOC_RESERVE:
- ret_val = agpioc_reserve_wrap(curr_priv, arg);
+ ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
break;
case AGPIOC_PROTECT:
- ret_val = agpioc_protect_wrap(curr_priv, arg);
+ ret_val = agpioc_protect_wrap(curr_priv);
break;
case AGPIOC_ALLOCATE:
- ret_val = agpioc_allocate_wrap(curr_priv, arg);
+ ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
break;
case AGPIOC_DEALLOCATE:
- ret_val = agpioc_deallocate_wrap(curr_priv, arg);
+ ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
break;
case AGPIOC_BIND:
- ret_val = agpioc_bind_wrap(curr_priv, arg);
+ ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
break;
case AGPIOC_UNBIND:
- ret_val = agpioc_unbind_wrap(curr_priv, arg);
+ ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
break;
}
diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
--- a/drivers/char/agp/hp-agp.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/agp/hp-agp.c Sun Jul 13 20:39:56 2003
@@ -1,17 +1,36 @@
/*
- * HP AGPGART routines.
+ * HP AGPGART routines.
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
+ * Bjorn Helgaas
*/
+#include
#include
#include
#include
#include
+
+#include
+
#include "agp.h"
#ifndef log2
#define log2(x) ffz(~(x))
#endif
+#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */
+
+/* HP ZX1 IOC registers */
+#define HP_ZX1_IBASE 0x300
+#define HP_ZX1_IMASK 0x308
+#define HP_ZX1_PCOM 0x310
+#define HP_ZX1_TCNFG 0x318
+#define HP_ZX1_PDIR_BASE 0x320
+
+/* HP ZX1 LBA registers */
+#define HP_ZX1_AGP_STATUS 0x64
+#define HP_ZX1_AGP_COMMAND 0x68
+
#define HP_ZX1_IOVA_BASE GB(1UL)
#define HP_ZX1_IOVA_SIZE GB(1UL)
#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2)
@@ -20,6 +39,9 @@
#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL
#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift)
+/* AGP bridge need not be PCI device, but DRM thinks it is. */
+static struct pci_dev fake_bridge_dev;
+
static struct aper_size_info_fixed hp_zx1_sizes[] =
{
{0, 0, 0}, /* filled in by hp_zx1_fetch_size() */
@@ -31,8 +53,8 @@
};
static struct _hp_private {
- struct pci_dev *ioc;
- volatile u8 *registers;
+ volatile u8 *ioc_regs;
+ volatile u8 *lba_regs;
u64 *io_pdir; // PDIR for entire IOVA
u64 *gatt; // PDIR just for GART (subset of above)
u64 gatt_entries;
@@ -59,7 +81,7 @@
* - IOVA space is 1Gb in size
* - first 512Mb is IOMMU, second 512Mb is GART
*/
- hp->io_tlb_ps = INREG64(hp->registers, HP_ZX1_TCNFG);
+ hp->io_tlb_ps = INREG64(hp->ioc_regs, HP_ZX1_TCNFG);
switch (hp->io_tlb_ps) {
case 0: hp->io_tlb_shift = 12; break;
case 1: hp->io_tlb_shift = 13; break;
@@ -75,13 +97,13 @@
hp->io_page_size = 1 << hp->io_tlb_shift;
hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size;
- hp->iova_base = INREG64(hp->registers, HP_ZX1_IBASE) & ~0x1;
+ hp->iova_base = INREG64(hp->ioc_regs, HP_ZX1_IBASE) & ~0x1;
hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE;
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = phys_to_virt(INREG64(hp->registers, HP_ZX1_PDIR_BASE));
+ hp->io_pdir = phys_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -95,7 +117,8 @@
return 0;
}
-static int __init hp_zx1_ioc_owner(u8 ioc_rev)
+static int __init
+hp_zx1_ioc_owner (void)
{
struct _hp_private *hp = &hp_private;
@@ -130,47 +153,28 @@
return 0;
}
-static int __init hp_zx1_ioc_init(void)
+static int __init
+hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa)
{
struct _hp_private *hp = &hp_private;
- struct pci_dev *ioc;
- int i;
- u8 ioc_rev;
-
- ioc = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_IOC, NULL);
- if (!ioc) {
- printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no IOC\n");
- return -ENODEV;
- }
- hp->ioc = ioc;
-
- pci_read_config_byte(ioc, PCI_REVISION_ID, &ioc_rev);
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- if (pci_resource_flags(ioc, i) == IORESOURCE_MEM) {
- hp->registers = (u8 *) ioremap(pci_resource_start(ioc, i),
- pci_resource_len(ioc, i));
- break;
- }
- }
- if (!hp->registers) {
- printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no CSRs\n");
- return -ENODEV;
- }
+ hp->ioc_regs = ioremap(ioc_hpa, 1024);
+ hp->lba_regs = ioremap(lba_hpa, 256);
/*
* If the IOTLB is currently disabled, we can take it over.
* Otherwise, we have to share with sba_iommu.
*/
- hp->io_pdir_owner = (INREG64(hp->registers, HP_ZX1_IBASE) & 0x1) == 0;
+ hp->io_pdir_owner = (INREG64(hp->ioc_regs, HP_ZX1_IBASE) & 0x1) == 0;
if (hp->io_pdir_owner)
- return hp_zx1_ioc_owner(ioc_rev);
+ return hp_zx1_ioc_owner();
return hp_zx1_ioc_shared();
}
-static int hp_zx1_fetch_size(void)
+static int
+hp_zx1_fetch_size(void)
{
int size;
@@ -180,47 +184,53 @@
return size;
}
-static int hp_zx1_configure(void)
+static int
+hp_zx1_configure (void)
{
struct _hp_private *hp = &hp_private;
agp_bridge->gart_bus_addr = hp->gart_base;
+#if 0
+ /* ouch!! can't do that with a non-PCI AGP bridge... */
agp_bridge->capndx = pci_find_capability(agp_bridge->dev, PCI_CAP_ID_AGP);
- pci_read_config_dword(agp_bridge->dev,
- agp_bridge->capndx + PCI_AGP_STATUS, &agp_bridge->mode);
+#else
+ agp_bridge->capndx = 0;
+#endif
+ agp_bridge->mode = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS);
if (hp->io_pdir_owner) {
- OUTREG64(hp->registers, HP_ZX1_PDIR_BASE,
- virt_to_phys(hp->io_pdir));
- OUTREG64(hp->registers, HP_ZX1_TCNFG, hp->io_tlb_ps);
- OUTREG64(hp->registers, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1));
- OUTREG64(hp->registers, HP_ZX1_IBASE, hp->iova_base | 0x1);
- OUTREG64(hp->registers, HP_ZX1_PCOM,
- hp->iova_base | log2(HP_ZX1_IOVA_SIZE));
- INREG64(hp->registers, HP_ZX1_PCOM);
+ OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir));
+ OUTREG64(hp->ioc_regs, HP_ZX1_TCNFG, hp->io_tlb_ps);
+ OUTREG64(hp->ioc_regs, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1));
+ OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, hp->iova_base | 0x1);
+ OUTREG64(hp->ioc_regs, HP_ZX1_PCOM, hp->iova_base | log2(HP_ZX1_IOVA_SIZE));
+ INREG64(hp->ioc_regs, HP_ZX1_PCOM);
}
return 0;
}
-static void hp_zx1_cleanup(void)
+static void
+hp_zx1_cleanup (void)
{
struct _hp_private *hp = &hp_private;
if (hp->io_pdir_owner)
- OUTREG64(hp->registers, HP_ZX1_IBASE, 0);
- iounmap((void *) hp->registers);
+ OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
+ iounmap((void *) hp->ioc_regs);
}
-static void hp_zx1_tlbflush(struct agp_memory *mem)
+static void
+hp_zx1_tlbflush (struct agp_memory *mem)
{
struct _hp_private *hp = &hp_private;
- OUTREG64(hp->registers, HP_ZX1_PCOM, hp->gart_base | log2(hp->gart_size));
- INREG64(hp->registers, HP_ZX1_PCOM);
+ OUTREG64(hp->ioc_regs, HP_ZX1_PCOM, hp->gart_base | log2(hp->gart_size));
+ INREG64(hp->ioc_regs, HP_ZX1_PCOM);
}
-static int hp_zx1_create_gatt_table(void)
+static int
+hp_zx1_create_gatt_table (void)
{
struct _hp_private *hp = &hp_private;
int i;
@@ -247,7 +257,8 @@
return 0;
}
-static int hp_zx1_free_gatt_table(void)
+static int
+hp_zx1_free_gatt_table (void)
{
struct _hp_private *hp = &hp_private;
@@ -259,8 +270,8 @@
return 0;
}
-static int hp_zx1_insert_memory(struct agp_memory *mem, off_t pg_start,
- int type)
+static int
+hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
{
struct _hp_private *hp = &hp_private;
int i, k;
@@ -305,8 +316,8 @@
return 0;
}
-static int hp_zx1_remove_memory(struct agp_memory *mem, off_t pg_start,
- int type)
+static int
+hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
{
struct _hp_private *hp = &hp_private;
int i, io_pg_start, io_pg_count;
@@ -325,11 +336,28 @@
return 0;
}
-static unsigned long hp_zx1_mask_memory(unsigned long addr, int type)
+static unsigned long
+hp_zx1_mask_memory (unsigned long addr, int type)
{
return HP_ZX1_PDIR_VALID_BIT | addr;
}
+static void
+hp_zx1_enable (u32 mode)
+{
+ struct _hp_private *hp = &hp_private;
+ u32 command;
+
+ command = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS);
+
+ command = agp_collect_device_status(mode, command);
+ command |= 0x00000100;
+
+ OUTREG32(hp->lba_regs, HP_ZX1_AGP_COMMAND, command);
+
+ agp_device_command(command, 0);
+}
+
struct agp_bridge_driver hp_zx1_driver = {
.owner = THIS_MODULE,
.size_type = FIXED_APER_SIZE,
@@ -339,7 +367,7 @@
.tlb_flush = hp_zx1_tlbflush,
.mask_memory = hp_zx1_mask_memory,
.masks = hp_zx1_masks,
- .agp_enable = agp_generic_enable,
+ .agp_enable = hp_zx1_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = hp_zx1_create_gatt_table,
.free_gatt_table = hp_zx1_free_gatt_table,
@@ -352,71 +380,93 @@
.cant_use_aperture = 1,
};
-static int __init agp_hp_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __init
+hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa)
{
struct agp_bridge_data *bridge;
int error;
- /* ZX1 LBAs can be either PCI or AGP bridges */
- if (!pci_find_capability(pdev, PCI_CAP_ID_AGP))
- return -ENODEV;
-
- printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n",
- pdev->slot_name);
+ printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset (ioc=%lx, lba=%lx)\n", ioc_hpa, lba_hpa);
- error = hp_zx1_ioc_init();
+ error = hp_zx1_ioc_init(ioc_hpa, lba_hpa);
if (error)
return error;
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
-
bridge->driver = &hp_zx1_driver;
- bridge->dev = pdev;
- pci_set_drvdata(pdev, bridge);
+ fake_bridge_dev.vendor = PCI_VENDOR_ID_HP;
+ fake_bridge_dev.device = PCI_DEVICE_ID_HP_ZX1_LBA;
+ bridge->dev = &fake_bridge_dev;
+
return agp_add_bridge(bridge);
}
-static void __devexit agp_hp_remove(struct pci_dev *pdev)
+static acpi_status __init
+zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
{
- struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
- agp_remove_bridge(bridge);
- agp_put_bridge(bridge);
-}
-
-static struct pci_device_id agp_hp_pci_table[] __initdata = {
- {
- .class = (PCI_CLASS_BRIDGE_HOST << 8),
- .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_HP,
- .device = PCI_DEVICE_ID_HP_ZX1_LBA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- { }
-};
+ acpi_handle handle, parent;
+ acpi_status status;
+ struct acpi_buffer buffer;
+ struct acpi_device_info *info;
+ u64 lba_hpa, sba_hpa, length;
+ int match;
+
+ status = hp_acpi_csr_space(obj, &lba_hpa, &length);
+ if (ACPI_FAILURE(status))
+ return 1;
+
+ /* Look for an enclosing IOC scope and find its CSR space */
+ handle = obj;
+ do {
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ /* TBD check _CID also */
+ info = buffer.pointer;
+ info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0';
+ match = (strcmp(info->hardware_id.value, "HWP0001") == 0);
+ ACPI_MEM_FREE(info);
+ if (match) {
+ status = hp_acpi_csr_space(handle, &sba_hpa, &length);
+ if (ACPI_SUCCESS(status))
+ break;
+ else {
+ printk(KERN_ERR PFX "Detected HP ZX1 "
+ "AGP LBA but no IOC.\n");
+ return status;
+ }
+ }
+ }
-MODULE_DEVICE_TABLE(pci, agp_hp_pci_table);
+ status = acpi_get_parent(handle, &parent);
+ handle = parent;
+ } while (ACPI_SUCCESS(status));
-static struct pci_driver agp_hp_pci_driver = {
- .name = "agpgart-hp",
- .id_table = agp_hp_pci_table,
- .probe = agp_hp_probe,
- .remove = agp_hp_remove,
-};
+ if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
+ return 1;
+ return 0;
+}
-static int __init agp_hp_init(void)
+static int __init
+agp_hp_init (void)
{
- return pci_module_init(&agp_hp_pci_driver);
+ acpi_status status;
+
+ status = acpi_get_devices("HWP0003", zx1_gart_probe, "HWP0003 AGP LBA", NULL);
+ if (!(ACPI_SUCCESS(status))) {
+ agp_bridge->type = NOT_SUPPORTED;
+ printk(KERN_INFO PFX "Failed to initialize zx1 AGP.\n");
+ return -ENODEV;
+ }
+ return 0;
}
-static void __exit agp_hp_cleanup(void)
+static void __exit
+agp_hp_cleanup (void)
{
- pci_unregister_driver(&agp_hp_pci_driver);
}
module_init(agp_hp_init);
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c Sun Jul 13 20:39:54 2003
+++ b/drivers/char/agp/sis-agp.c Sun Jul 13 20:39:54 2003
@@ -100,16 +100,24 @@
struct agp_device_ids sis_agp_device_ids[] __initdata =
{
{
- .device_id = PCI_DEVICE_ID_SI_740,
- .chipset_name = "740",
+ .device_id = PCI_DEVICE_ID_SI_530,
+ .chipset_name = "530",
},
{
- .device_id = PCI_DEVICE_ID_SI_650,
- .chipset_name = "650",
+ .device_id = PCI_DEVICE_ID_SI_540,
+ .chipset_name = "540",
},
{
- .device_id = PCI_DEVICE_ID_SI_651,
- .chipset_name = "651",
+ .device_id = PCI_DEVICE_ID_SI_550,
+ .chipset_name = "550",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_SI_620,
+ .chipset_name = "620",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_SI_630,
+ .chipset_name = "630",
},
{
.device_id = PCI_DEVICE_ID_SI_645,
@@ -120,40 +128,40 @@
.chipset_name = "646",
},
{
- .device_id = PCI_DEVICE_ID_SI_735,
- .chipset_name = "735",
+ .device_id = PCI_DEVICE_ID_SI_648,
+ .chipset_name = "648",
},
{
- .device_id = PCI_DEVICE_ID_SI_745,
- .chipset_name = "745",
+ .device_id = PCI_DEVICE_ID_SI_650,
+ .chipset_name = "650",
},
{
- .device_id = PCI_DEVICE_ID_SI_730,
- .chipset_name = "730",
+ .device_id = PCI_DEVICE_ID_SI_651,
+ .chipset_name = "651",
},
{
- .device_id = PCI_DEVICE_ID_SI_630,
- .chipset_name = "630",
+ .device_id = PCI_DEVICE_ID_SI_655,
+ .chipset_name = "655",
},
{
- .device_id = PCI_DEVICE_ID_SI_540,
- .chipset_name = "540",
+ .device_id = PCI_DEVICE_ID_SI_730,
+ .chipset_name = "730",
},
{
- .device_id = PCI_DEVICE_ID_SI_620,
- .chipset_name = "620",
+ .device_id = PCI_DEVICE_ID_SI_735,
+ .chipset_name = "735",
},
{
- .device_id = PCI_DEVICE_ID_SI_530,
- .chipset_name = "530",
+ .device_id = PCI_DEVICE_ID_SI_740,
+ .chipset_name = "740",
},
{
- .device_id = PCI_DEVICE_ID_SI_550,
- .chipset_name = "550",
+ .device_id = PCI_DEVICE_ID_SI_745,
+ .chipset_name = "745",
},
{
- .device_id = PCI_DEVICE_ID_SI_655,
- .chipset_name = "655",
+ .device_id = PCI_DEVICE_ID_SI_746,
+ .chipset_name = "746",
},
{ }, /* dummy final entry, always present */
};
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/agp/via-agp.c Sun Jul 13 20:39:56 2003
@@ -382,7 +382,7 @@
}
}
- if (agp_try_unsupported) {
+ if (!agp_try_unsupported) {
printk(KERN_ERR PFX
"Unsupported VIA chipset (device id: %04x),"
" you might want to try agp_try_unsupported=1.\n",
diff -Nru a/drivers/char/drm/ati_pcigart.h b/drivers/char/drm/ati_pcigart.h
--- a/drivers/char/drm/ati_pcigart.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/ati_pcigart.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,11 @@
-/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
+/**
+ * \file ati_pcigart.h
+ * ATI PCI GART support
+ *
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
*
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,9 +29,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Gareth Hughes
*/
#include "drmP.h"
@@ -45,8 +49,8 @@
# error - PAGE_SIZE not 64K, 16K, 8K or 4K
#endif
-# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
-# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
+# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
static unsigned long DRM(ati_alloc_pcigart_table)( void )
{
diff -Nru a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
--- a/drivers/char/drm/drm.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm.h Sun Jul 13 20:39:55 2003
@@ -1,6 +1,14 @@
-/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
+/**
+ * \file drm.h
+ * Header for the Direct Rendering Manager
+ *
+ * \author Rickard E. (Rik) Faith
*
+ * \par Acknowledgments:
+ * Dec 1999, Richard Henderson , move to generic \c cmpxchg.
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
@@ -23,15 +31,9 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- *
- * Acknowledgements:
- * Dec 1999, Richard Henderson , move to generic cmpxchg.
- *
*/
+
#ifndef _DRM_H_
#define _DRM_H_
@@ -82,29 +84,33 @@
#define DRM_MAJOR 226
#define DRM_MAX_MINOR 15
#endif
-#define DRM_NAME "drm" /* Name in kernel, /dev, and /proc */
-#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */
-#define DRM_MAX_ORDER 22 /* Up to 2^22 bytes = 4MB */
-#define DRM_RAM_PERCENT 10 /* How much system ram can we lock? */
+#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
-#define _DRM_LOCK_HELD 0x80000000 /* Hardware lock is held */
-#define _DRM_LOCK_CONT 0x40000000 /* Hardware lock is contended */
+#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
typedef unsigned long drm_handle_t;
typedef unsigned int drm_context_t;
typedef unsigned int drm_drawable_t;
typedef unsigned int drm_magic_t;
-/* Warning: If you change this structure, make sure you change
- * XF86DRIClipRectRec in the server as well */
-/* KW: Actually it's illegal to change either for
+/**
+ * Cliprect.
+ *
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
* backwards-compatibility reasons.
*/
-
typedef struct drm_clip_rect {
unsigned short x1;
unsigned short y1;
@@ -112,6 +118,10 @@
unsigned short y2;
} drm_clip_rect_t;
+
+/**
+ * Texture region,
+ */
typedef struct drm_tex_region {
unsigned char next;
unsigned char prev;
@@ -120,32 +130,52 @@
unsigned int age;
} drm_tex_region_t;
+
+/**
+ * DRM_IOCTL_VERSION ioctl argument type.
+ *
+ * \sa drmGetVersion().
+ */
typedef struct drm_version {
- int version_major; /* Major version */
- int version_minor; /* Minor version */
- int version_patchlevel;/* Patch level */
- size_t name_len; /* Length of name buffer */
- char *name; /* Name of driver */
- size_t date_len; /* Length of date buffer */
- char *date; /* User-space buffer to hold date */
- size_t desc_len; /* Length of desc buffer */
- char *desc; /* User-space buffer to hold desc */
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel;/**< Patch level */
+ size_t name_len; /**< Length of name buffer */
+ char *name; /**< Name of driver */
+ size_t date_len; /**< Length of date buffer */
+ char *date; /**< User-space buffer to hold date */
+ size_t desc_len; /**< Length of desc buffer */
+ char *desc; /**< User-space buffer to hold desc */
} drm_version_t;
+
+/**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
typedef struct drm_unique {
- size_t unique_len; /* Length of unique */
- char *unique; /* Unique name for driver instantiation */
+ size_t unique_len; /**< Length of unique */
+ char *unique; /**< Unique name for driver instantiation */
} drm_unique_t;
+
typedef struct drm_list {
- int count; /* Length of user-space structures */
+ int count; /**< Length of user-space structures */
drm_version_t *version;
} drm_list_t;
+
typedef struct drm_block {
int unused;
} drm_block_t;
+
+/**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
typedef struct drm_control {
enum {
DRM_ADD_COMMAND,
@@ -156,49 +186,70 @@
int irq;
} drm_control_t;
+
+/**
+ * Type of memory to map.
+ */
typedef enum drm_map_type {
- _DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
- _DRM_REGISTERS = 1, /* no caching, no core dump */
- _DRM_SHM = 2, /* shared, cached */
- _DRM_AGP = 3, /* AGP/GART */
- _DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
+ _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
+ _DRM_REGISTERS = 1, /**< no caching, no core dump */
+ _DRM_SHM = 2, /**< shared, cached */
+ _DRM_AGP = 3, /**< AGP/GART */
+ _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
} drm_map_type_t;
+
+/**
+ * Memory mapping flags.
+ */
typedef enum drm_map_flags {
- _DRM_RESTRICTED = 0x01, /* Cannot be mapped to user-virtual */
+ _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
_DRM_READ_ONLY = 0x02,
- _DRM_LOCKED = 0x04, /* shared, cached, locked */
- _DRM_KERNEL = 0x08, /* kernel requires access */
- _DRM_WRITE_COMBINING = 0x10, /* use write-combining if available */
- _DRM_CONTAINS_LOCK = 0x20, /* SHM page that contains lock */
- _DRM_REMOVABLE = 0x40 /* Removable mapping */
+ _DRM_LOCKED = 0x04, /**< shared, cached, locked */
+ _DRM_KERNEL = 0x08, /**< kernel requires access */
+ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
+ _DRM_REMOVABLE = 0x40 /**< Removable mapping */
} drm_map_flags_t;
+
typedef struct drm_ctx_priv_map {
- unsigned int ctx_id; /* Context requesting private mapping */
- void *handle; /* Handle of map */
+ unsigned int ctx_id; /**< Context requesting private mapping */
+ void *handle; /**< Handle of map */
} drm_ctx_priv_map_t;
+
+/**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
typedef struct drm_map {
- unsigned long offset; /* Requested physical address (0 for SAREA)*/
- unsigned long size; /* Requested physical size (bytes) */
- drm_map_type_t type; /* Type of memory to map */
- drm_map_flags_t flags; /* Flags */
- void *handle; /* User-space: "Handle" to pass to mmap */
- /* Kernel-space: kernel-virtual address */
- int mtrr; /* MTRR slot used */
- /* Private data */
+ unsigned long offset; /**< Requested physical address (0 for SAREA)*/
+ unsigned long size; /**< Requested physical size (bytes) */
+ drm_map_type_t type; /**< Type of memory to map */
+ drm_map_flags_t flags; /**< Flags */
+ void *handle; /**< User-space: "Handle" to pass to mmap() */
+ /**< Kernel-space: kernel-virtual address */
+ int mtrr; /**< MTRR slot used */
+ /* Private data */
} drm_map_t;
+
+/**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
typedef struct drm_client {
- int idx; /* Which client desired? */
- int auth; /* Is client authenticated? */
- unsigned long pid; /* Process id */
- unsigned long uid; /* User id */
- unsigned long magic; /* Magic */
- unsigned long iocs; /* Ioctl count */
+ int idx; /**< Which client desired? */
+ int auth; /**< Is client authenticated? */
+ unsigned long pid; /**< Process ID */
+ unsigned long uid; /**< User ID */
+ unsigned long magic; /**< Magic */
+ unsigned long iocs; /**< Ioctl count */
} drm_client_t;
+
typedef enum {
_DRM_STAT_LOCK,
_DRM_STAT_OPENS,
@@ -206,20 +257,24 @@
_DRM_STAT_IOCTLS,
_DRM_STAT_LOCKS,
_DRM_STAT_UNLOCKS,
- _DRM_STAT_VALUE, /* Generic value */
- _DRM_STAT_BYTE, /* Generic byte counter (1024bytes/K) */
- _DRM_STAT_COUNT, /* Generic non-byte counter (1000/k) */
-
- _DRM_STAT_IRQ, /* IRQ */
- _DRM_STAT_PRIMARY, /* Primary DMA bytes */
- _DRM_STAT_SECONDARY, /* Secondary DMA bytes */
- _DRM_STAT_DMA, /* DMA */
- _DRM_STAT_SPECIAL, /* Special DMA (e.g., priority or polled) */
- _DRM_STAT_MISSED /* Missed DMA opportunity */
+ _DRM_STAT_VALUE, /**< Generic value */
+ _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
+ _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
+
+ _DRM_STAT_IRQ, /**< IRQ */
+ _DRM_STAT_PRIMARY, /**< Primary DMA bytes */
+ _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
+ _DRM_STAT_DMA, /**< DMA */
+ _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
+ _DRM_STAT_MISSED /**< Missed DMA opportunity */
/* Add to the *END* of the list */
} drm_stat_type_t;
+
+/**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
typedef struct drm_stats {
unsigned long count;
struct {
@@ -228,137 +283,220 @@
} data[15];
} drm_stats_t;
+
+/**
+ * Hardware locking flags.
+ */
typedef enum drm_lock_flags {
- _DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
- _DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
- _DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */
- _DRM_LOCK_FLUSH_ALL = 0x08, /* Flush all DMA queues first */
+ _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
/* These *HALT* flags aren't supported yet
-- they will be used to support the
full-screen DGA-like mode. */
- _DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues */
- _DRM_HALT_CUR_QUEUES = 0x20 /* Halt all current queues */
+ _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+ _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
} drm_lock_flags_t;
+
+/**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ *
+ * \sa drmGetLock() and drmUnlock().
+ */
typedef struct drm_lock {
int context;
drm_lock_flags_t flags;
} drm_lock_t;
-typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
- /* Flags for DMA buffer dispatch */
- _DRM_DMA_BLOCK = 0x01, /* Block until buffer dispatched.
- Note, the buffer may not yet have
- been processed by the hardware --
- getting a hardware lock with the
- hardware quiescent will ensure
- that the buffer has been
- processed. */
- _DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held */
- _DRM_DMA_PRIORITY = 0x04, /* High priority dispatch */
-
- /* Flags for DMA buffer request */
- _DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
- _DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
- _DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
+
+/**
+ * DMA flags
+ *
+ * \warning
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+typedef enum drm_dma_flags {
+ /* Flags for DMA buffer dispatch */
+ _DRM_DMA_BLOCK = 0x01, /**<
+ * Block until buffer dispatched.
+ *
+ * \note The buffer may not yet have
+ * been processed by the hardware --
+ * getting a hardware lock with the
+ * hardware quiescent will ensure
+ * that the buffer has been
+ * processed.
+ */
+ _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+
+ /* Flags for DMA buffer request */
+ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
} drm_dma_flags_t;
+
+/**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
typedef struct drm_buf_desc {
- int count; /* Number of buffers of this size */
- int size; /* Size in bytes */
- int low_mark; /* Low water mark */
- int high_mark; /* High water mark */
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
enum {
- _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
- _DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
- _DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
+ _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+ _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
} flags;
- unsigned long agp_start; /* Start address of where the agp buffers
- * are in the agp aperture */
+ unsigned long agp_start; /**<
+ * Start address of where the AGP buffers are
+ * in the AGP aperture
+ */
} drm_buf_desc_t;
+
+/**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
typedef struct drm_buf_info {
- int count; /* Entries in list */
+ int count; /**< Entries in list */
drm_buf_desc_t *list;
} drm_buf_info_t;
+
+/**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
typedef struct drm_buf_free {
int count;
int *list;
} drm_buf_free_t;
+
+/**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
typedef struct drm_buf_pub {
- int idx; /* Index into master buflist */
- int total; /* Buffer size */
- int used; /* Amount of buffer in use (for DMA) */
- void *address; /* Address of buffer */
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ void *address; /**< Address of buffer */
} drm_buf_pub_t;
+
+/**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
typedef struct drm_buf_map {
- int count; /* Length of buflist */
- void *virtual; /* Mmaped area in user-virtual */
- drm_buf_pub_t *list; /* Buffer information */
+ int count; /**< Length of the buffer list */
+ void *virtual; /**< Mmap'd area in user-virtual */
+ drm_buf_pub_t *list; /**< Buffer information */
} drm_buf_map_t;
+
+/**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
typedef struct drm_dma {
- /* Indices here refer to the offset into
- buflist in drm_buf_get_t. */
- int context; /* Context handle */
- int send_count; /* Number of buffers to send */
- int *send_indices; /* List of handles to buffers */
- int *send_sizes; /* Lengths of data to send */
- drm_dma_flags_t flags; /* Flags */
- int request_count; /* Number of buffers requested */
- int request_size; /* Desired size for buffers */
- int *request_indices; /* Buffer information */
+ int context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ int *send_indices; /**< List of handles to buffers */
+ int *send_sizes; /**< Lengths of data to send */
+ drm_dma_flags_t flags; /**< Flags */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size for buffers */
+ int *request_indices; /**< Buffer information */
int *request_sizes;
- int granted_count; /* Number of buffers granted */
+ int granted_count; /**< Number of buffers granted */
} drm_dma_t;
+
typedef enum {
_DRM_CONTEXT_PRESERVED = 0x01,
_DRM_CONTEXT_2DONLY = 0x02
} drm_ctx_flags_t;
+
+/**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
typedef struct drm_ctx {
drm_context_t handle;
drm_ctx_flags_t flags;
} drm_ctx_t;
+
+/**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
typedef struct drm_ctx_res {
int count;
drm_ctx_t *contexts;
} drm_ctx_res_t;
+
+/**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
typedef struct drm_draw {
drm_drawable_t handle;
} drm_draw_t;
+
+/**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
typedef struct drm_auth {
drm_magic_t magic;
} drm_auth_t;
+
+/**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
typedef struct drm_irq_busid {
- int irq;
- int busnum;
- int devnum;
- int funcnum;
+ int irq; /**< IRQ number */
+ int busnum; /**< bus number */
+ int devnum; /**< device number */
+ int funcnum; /**< function number */
} drm_irq_busid_t;
+
typedef enum {
- _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */
- _DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */
- _DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
+ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
} drm_vblank_seq_type_t;
+
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
struct drm_wait_vblank_request {
drm_vblank_seq_type_t type;
unsigned int sequence;
unsigned long signal;
};
+
struct drm_wait_vblank_reply {
drm_vblank_seq_type_t type;
unsigned int sequence;
@@ -366,29 +504,59 @@
long tval_usec;
};
+
+/**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
typedef union drm_wait_vblank {
struct drm_wait_vblank_request request;
struct drm_wait_vblank_reply reply;
} drm_wait_vblank_t;
+
+/**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
typedef struct drm_agp_mode {
- unsigned long mode;
+ unsigned long mode; /**< AGP mode */
} drm_agp_mode_t;
- /* For drm_agp_alloc -- allocated a buffer */
+
+/**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
typedef struct drm_agp_buffer {
- unsigned long size; /* In bytes -- will round to page boundary */
- unsigned long handle; /* Used for BIND/UNBIND ioctls */
- unsigned long type; /* Type of memory to allocate */
- unsigned long physical; /* Physical used by i810 */
+ unsigned long size; /**< In bytes -- will round to page boundary */
+ unsigned long handle; /**< Used for binding / unbinding */
+ unsigned long type; /**< Type of memory to allocate */
+ unsigned long physical; /**< Physical used by i810 */
} drm_agp_buffer_t;
- /* For drm_agp_bind */
+
+/**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
typedef struct drm_agp_binding {
- unsigned long handle; /* From drm_agp_buffer */
- unsigned long offset; /* In bytes -- will round to page boundary */
+ unsigned long handle; /**< From drm_agp_buffer */
+ unsigned long offset; /**< In bytes -- will round to page boundary */
} drm_agp_binding_t;
+
+/**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
typedef struct drm_agp_info {
int agp_version_major;
int agp_version_minor;
@@ -403,11 +571,16 @@
unsigned short id_device;
} drm_agp_info_t;
+
+/**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
typedef struct drm_scatter_gather {
- unsigned long size; /* In bytes -- will round to page boundary */
- unsigned long handle; /* Used for mapping / unmapping */
+ unsigned long size; /**< In bytes -- will round to page boundary */
+ unsigned long handle; /**< Used for mapping / unmapping */
} drm_scatter_gather_t;
+
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
@@ -467,8 +640,13 @@
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
-/* Device specfic ioctls should only be in their respective headers
- * The device specific ioctl range is 0x40 to 0x79. */
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x79.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
#define DRM_COMMAND_BASE 0x40
#endif
diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
--- a/drivers/char/drm/drmP.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drmP.h Sun Jul 13 20:39:56 2003
@@ -1,6 +1,12 @@
-/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- *
+/**
+ * \file drmP.h
+ * Private header for Direct Rendering Manager
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
@@ -23,15 +29,12 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#ifndef _DRM_P_H_
#define _DRM_P_H_
+
#ifdef __KERNEL__
#ifdef __alpha__
/* add include of current.h so that "current" is defined
@@ -72,8 +75,11 @@
#include "drm_os_linux.h"
-/* DRM template customization defaults
- */
+
+/***********************************************************************/
+/** \name DRM template customization defaults */
+/*@{*/
+
#ifndef __HAVE_AGP
#define __HAVE_AGP 0
#endif
@@ -101,19 +107,23 @@
#define __REALLY_HAVE_MTRR (__HAVE_MTRR && defined(CONFIG_MTRR))
#define __REALLY_HAVE_SG (__HAVE_SG)
-/* Begin the DRM...
- */
+/*@}*/
+
-#define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then
+/***********************************************************************/
+/** \name Begin the DRM... */
+/*@{*/
+
+#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
also include looping detection. */
-#define DRM_HASH_SIZE 16 /* Size of key hash table */
-#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */
-#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */
+#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
#define DRM_LOOPING_LIMIT 5000000
-#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */
-#define DRM_TIME_SLICE (HZ/20) /* Time slice for GLXContexts */
-#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
+#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
+#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
#define DRM_FLAG_DEBUG 0x01
@@ -140,8 +150,14 @@
#define DRM_MEM_SGLISTS 20
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Backward compatibility section */
+/*@{*/
- /* Backward compatibility section */
#ifndef minor
#define minor(x) MINOR((x))
#endif
@@ -191,17 +207,42 @@
#define DRM_RPR_ARG(vma) vma,
#endif
-
#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
- /* Macros to make printk easier */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Macros to make printk easier */
+/*@{*/
+
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
#define DRM_ERROR(fmt, arg...) \
printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
+
+/**
+ * Memory error output.
+ *
+ * \param area memory area where the error occurred.
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
#define DRM_MEM_ERROR(area, fmt, arg...) \
printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
DRM(mem_stats)[area].name , ##arg)
#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+/**
+ * Debug output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
#if DRM_DEBUG_CODE
#define DRM_DEBUG(fmt, arg...) \
do { \
@@ -224,7 +265,13 @@
len += sprintf(&buf[len], fmt , ##arg); \
if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
- /* Mapping helper macros */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Mapping helper macros */
+/*@{*/
+
#define DRM_IOREMAP(map, dev) \
(map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) )
@@ -237,6 +284,15 @@
DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \
} while (0)
+/**
+ * Find mapping.
+ *
+ * \param _map matching mapping if found, untouched otherwise.
+ * \param _o offset.
+ *
+ * Expects the existence of a local variable named \p dev pointing to the
+ * drm_device structure.
+ */
#define DRM_FIND_MAP(_map, _o) \
do { \
struct list_head *_list; \
@@ -249,9 +305,21 @@
} \
} \
} while(0)
+
+/**
+ * Drop mapping.
+ *
+ * \sa #DRM_FIND_MAP.
+ */
#define DRM_DROP_MAP(_map)
- /* Internal types and structures */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Internal types and structures */
+/*@{*/
+
#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
@@ -260,10 +328,23 @@
#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
+/**
+ * Get the private SAREA mapping.
+ *
+ * \param _dev DRM device.
+ * \param _ctx context number.
+ * \param _map output mapping.
+ */
#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
(_map) = (_dev)->context_sareas[_ctx]; \
} while(0)
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
#define LOCK_TEST_WITH_RETURN( dev, filp ) \
do { \
if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
@@ -274,7 +355,14 @@
} \
} while (0)
-
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
@@ -290,8 +378,7 @@
} drm_ioctl_desc_t;
typedef struct drm_devstate {
- pid_t owner; /* X server pid holding x_lock */
-
+ pid_t owner; /**< X server pid holding x_lock */
} drm_devstate_t;
typedef struct drm_magic_entry {
@@ -311,21 +398,24 @@
pid_t pid;
} drm_vma_entry_t;
+/**
+ * DMA buffer.
+ */
typedef struct drm_buf {
- int idx; /* Index into master buflist */
- int total; /* Buffer size */
- int order; /* log-base-2(total) */
- int used; /* Amount of buffer in use (for DMA) */
- unsigned long offset; /* Byte offset (used internally) */
- void *address; /* Address of buffer */
- unsigned long bus_address; /* Bus address of buffer */
- struct drm_buf *next; /* Kernel-only: used for free list */
- __volatile__ int waiting; /* On kernel DMA queue */
- __volatile__ int pending; /* On hardware DMA queue */
- wait_queue_head_t dma_wait; /* Processes waiting */
- struct file *filp; /* Pointer to holding file descr */
- int context; /* Kernel queue for this buffer */
- int while_locked;/* Dispatch this buffer while locked */
+ int idx; /**< Index into master buflist */
+ int total; /**< Buffer size */
+ int order; /**< log-base-2(total) */
+ int used; /**< Amount of buffer in use (for DMA) */
+ unsigned long offset; /**< Byte offset (used internally) */
+ void *address; /**< Address of buffer */
+ unsigned long bus_address; /**< Bus address of buffer */
+ struct drm_buf *next; /**< Kernel-only: used for free list */
+ __volatile__ int waiting; /**< On kernel DMA queue */
+ __volatile__ int pending; /**< On hardware DMA queue */
+ wait_queue_head_t dma_wait; /**< Processes waiting */
+ struct file *filp; /**< Pointer to holding file descr */
+ int context; /**< Kernel queue for this buffer */
+ int while_locked;/**< Dispatch this buffer while locked */
enum {
DRM_LIST_NONE = 0,
DRM_LIST_FREE = 1,
@@ -333,41 +423,43 @@
DRM_LIST_PEND = 3,
DRM_LIST_PRIO = 4,
DRM_LIST_RECLAIM = 5
- } list; /* Which list we're on */
-
+ } list; /**< Which list we're on */
- int dev_priv_size; /* Size of buffer private stoarge */
- void *dev_private; /* Per-buffer private storage */
+ int dev_priv_size; /**< Size of buffer private storage */
+ void *dev_private; /**< Per-buffer private storage */
} drm_buf_t;
- /* bufs is one longer than it has to be */
+/** bufs is one longer than it has to be */
typedef struct drm_waitlist {
- int count; /* Number of possible buffers */
- drm_buf_t **bufs; /* List of pointers to buffers */
- drm_buf_t **rp; /* Read pointer */
- drm_buf_t **wp; /* Write pointer */
- drm_buf_t **end; /* End pointer */
+ int count; /**< Number of possible buffers */
+ drm_buf_t **bufs; /**< List of pointers to buffers */
+ drm_buf_t **rp; /**< Read pointer */
+ drm_buf_t **wp; /**< Write pointer */
+ drm_buf_t **end; /**< End pointer */
spinlock_t read_lock;
spinlock_t write_lock;
} drm_waitlist_t;
typedef struct drm_freelist {
- int initialized; /* Freelist in use */
- atomic_t count; /* Number of free buffers */
- drm_buf_t *next; /* End pointer */
-
- wait_queue_head_t waiting; /* Processes waiting on free bufs */
- int low_mark; /* Low water mark */
- int high_mark; /* High water mark */
- atomic_t wfh; /* If waiting for high mark */
+ int initialized; /**< Freelist in use */
+ atomic_t count; /**< Number of free buffers */
+ drm_buf_t *next; /**< End pointer */
+
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ atomic_t wfh; /**< If waiting for high mark */
spinlock_t lock;
} drm_freelist_t;
+/**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
typedef struct drm_buf_entry {
- int buf_size;
- int buf_count;
- drm_buf_t *buflist;
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ drm_buf_t *buflist; /**< buffer list */
int seg_count;
int page_order;
unsigned long *seglist;
@@ -375,11 +467,19 @@
drm_freelist_t freelist;
} drm_buf_entry_t;
+/**
+ * Hardware lock.
+ *
+ * The lock structure is a simple cache-line aligned integer. To avoid
+ * processor bus contention on a multiprocessor system, there should not be any
+ * other data stored in the same cache line.
+ */
typedef struct drm_hw_lock {
- __volatile__ unsigned int lock;
- char padding[60]; /* Pad to cache line */
+ __volatile__ unsigned int lock; /**< lock variable */
+ char padding[60]; /**< Pad to cache line */
} drm_hw_lock_t;
+/** File private data */
typedef struct drm_file {
int authenticated;
int minor;
@@ -394,69 +494,85 @@
unsigned long lock_count;
} drm_file_t;
-
+/** Wait queue */
typedef struct drm_queue {
- atomic_t use_count; /* Outstanding uses (+1) */
- atomic_t finalization; /* Finalization in progress */
- atomic_t block_count; /* Count of processes waiting */
- atomic_t block_read; /* Queue blocked for reads */
- wait_queue_head_t read_queue; /* Processes waiting on block_read */
- atomic_t block_write; /* Queue blocked for writes */
- wait_queue_head_t write_queue; /* Processes waiting on block_write */
+ atomic_t use_count; /**< Outstanding uses (+1) */
+ atomic_t finalization; /**< Finalization in progress */
+ atomic_t block_count; /**< Count of processes waiting */
+ atomic_t block_read; /**< Queue blocked for reads */
+ wait_queue_head_t read_queue; /**< Processes waiting on block_read */
+ atomic_t block_write; /**< Queue blocked for writes */
+ wait_queue_head_t write_queue; /**< Processes waiting on block_write */
#if 1
- atomic_t total_queued; /* Total queued statistic */
- atomic_t total_flushed;/* Total flushes statistic */
- atomic_t total_locks; /* Total locks statistics */
-#endif
- drm_ctx_flags_t flags; /* Context preserving and 2D-only */
- drm_waitlist_t waitlist; /* Pending buffers */
- wait_queue_head_t flush_queue; /* Processes waiting until flush */
+ atomic_t total_queued; /**< Total queued statistic */
+ atomic_t total_flushed;/**< Total flushes statistic */
+ atomic_t total_locks; /**< Total locks statistics */
+#endif
+ drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
+ drm_waitlist_t waitlist; /**< Pending buffers */
+ wait_queue_head_t flush_queue; /**< Processes waiting until flush */
} drm_queue_t;
+/**
+ * Lock data.
+ */
typedef struct drm_lock_data {
- drm_hw_lock_t *hw_lock; /* Hardware lock */
- struct file *filp; /* File descr of lock holder (0=kernel) */
- wait_queue_head_t lock_queue; /* Queue of blocked processes */
- unsigned long lock_time; /* Time of last lock in jiffies */
+ drm_hw_lock_t *hw_lock; /**< Hardware lock */
+ struct file *filp; /**< File descr of lock holder (0=kernel) */
+ wait_queue_head_t lock_queue; /**< Queue of blocked processes */
+ unsigned long lock_time; /**< Time of last lock in jiffies */
} drm_lock_data_t;
+/**
+ * DMA data.
+ */
typedef struct drm_device_dma {
- drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
- int buf_count;
- drm_buf_t **buflist; /* Vector of pointers info bufs */
+ drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
+ int buf_count; /**< total number of buffers */
+ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
int seg_count;
- int page_count;
- unsigned long *pagelist;
+ int page_count; /**< number of pages */
+ unsigned long *pagelist; /**< page list */
unsigned long byte_count;
enum {
_DRM_DMA_USE_AGP = 0x01,
_DRM_DMA_USE_SG = 0x02
} flags;
- /* DMA support */
- drm_buf_t *this_buffer; /* Buffer being sent */
- drm_buf_t *next_buffer; /* Selected buffer to send */
- drm_queue_t *next_queue; /* Queue from which buffer selected*/
- wait_queue_head_t waiting; /* Processes waiting on free bufs */
+ /** \name DMA support */
+ /*@{*/
+ drm_buf_t *this_buffer; /**< Buffer being sent */
+ drm_buf_t *next_buffer; /**< Selected buffer to send */
+ drm_queue_t *next_queue; /**< Queue from which buffer selected*/
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ /*@}*/
} drm_device_dma_t;
#if __REALLY_HAVE_AGP
+/**
+ * AGP memory entry. Stored as a doubly linked list.
+ */
typedef struct drm_agp_mem {
- unsigned long handle;
- struct agp_memory *memory;
- unsigned long bound; /* address */
+ unsigned long handle; /**< handle */
+ struct agp_memory *memory;
+ unsigned long bound; /**< address */
int pages;
- struct drm_agp_mem *prev;
- struct drm_agp_mem *next;
+ struct drm_agp_mem *prev; /**< previous entry */
+ struct drm_agp_mem *next; /**< next entry */
} drm_agp_mem_t;
+/**
+ * AGP data.
+ *
+ * \sa DRM(agp_init)() and drm_device::agp.
+ */
typedef struct drm_agp_head {
- struct agp_kern_info agp_info;
- drm_agp_mem_t *memory;
- unsigned long mode;
- int enabled;
- int acquired;
+ struct agp_kern_info agp_info; /**< AGP device information */
+ drm_agp_mem_t *memory; /**< memory entries */
+ unsigned long mode; /**< AGP mode */
+ int enabled; /**< whether the AGP bus as been enabled */
+ int acquired; /**< whether the AGP device has been acquired */
unsigned long base;
int agp_mtrr;
int cant_use_aperture;
@@ -464,6 +580,9 @@
} drm_agp_head_t;
#endif
+/**
+ * Scatter-gather memory.
+ */
typedef struct drm_sg_mem {
unsigned long handle;
void *virtual;
@@ -477,9 +596,12 @@
drm_hw_lock_t *lock;
} drm_sigdata_t;
+/**
+ * Mappings list
+ */
typedef struct drm_map_list {
- struct list_head head;
- drm_map_t *map;
+ struct list_head head; /**< list head */
+ drm_map_t *map; /**< mapping */
} drm_map_list_t;
typedef drm_map_t drm_local_map_t;
@@ -495,88 +617,108 @@
#endif
+/**
+ * DRM device structure.
+ */
typedef struct drm_device {
- const char *name; /* Simple driver name */
- char *unique; /* Unique identifier: e.g., busid */
- int unique_len; /* Length of unique field */
- dev_t device; /* Device number for mknod */
- char *devname; /* For /proc/interrupts */
-
- int blocked; /* Blocked due to VC switch? */
- struct proc_dir_entry *root; /* Root for this device's entries */
-
- /* Locks */
- spinlock_t count_lock; /* For inuse, open_count, buf_use */
- struct semaphore struct_sem; /* For others */
-
- /* Usage Counters */
- int open_count; /* Outstanding files open */
- atomic_t ioctl_count; /* Outstanding IOCTLs pending */
- atomic_t vma_count; /* Outstanding vma areas open */
- int buf_use; /* Buffers in use -- cannot alloc */
- atomic_t buf_alloc; /* Buffer allocation in progress */
+ const char *name; /**< Simple driver name */
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ dev_t device; /**< Device number for mknod */
+ char *devname; /**< For /proc/interrupts */
+
+ int blocked; /**< Blocked due to VC switch? */
+ struct proc_dir_entry *root; /**< Root for this device's entries */
+
+ /** \name Locks */
+ /*@{*/
+ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+ struct semaphore struct_sem; /**< For others */
+ /*@}*/
+
+ /** \name Usage Counters */
+ /*@{*/
+ int open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /**< Buffer allocation in progress */
+ /*@}*/
- /* Performance counters */
+ /** \name Performance counters */
+ /*@{*/
unsigned long counters;
drm_stat_type_t types[15];
atomic_t counts[15];
+ /*@}*/
- /* Authentication */
- drm_file_t *file_first;
- drm_file_t *file_last;
- drm_magic_head_t magiclist[DRM_HASH_SIZE];
-
- /* Memory management */
- drm_map_list_t *maplist; /* Linked list of regions */
+ /** \name Authentication */
+ /*@{*/
+ drm_file_t *file_first; /**< file list head */
+ drm_file_t *file_last; /**< file list tail */
+ drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
+ /*@}*/
+
+ /** \name Memory management */
+ /*@{*/
+ drm_map_list_t *maplist; /**< Linked list of regions */
+ int map_count; /**< Number of mappable regions */
- drm_map_t **context_sareas;
+ drm_map_t **context_sareas; /**< per-context SAREA's */
int max_context;
- drm_vma_entry_t *vmalist; /* List of vmas (for debugging) */
- drm_lock_data_t lock; /* Information on hardware lock */
-
- /* DMA queues (contexts) */
- int queue_count; /* Number of active DMA queues */
- int queue_reserved; /* Number of reserved DMA queues */
- int queue_slots; /* Actual length of queuelist */
- drm_queue_t **queuelist; /* Vector of pointers to DMA queues */
- drm_device_dma_t *dma; /* Optional pointer for DMA support */
-
- /* Context support */
- int irq; /* Interrupt used by board */
- __volatile__ long context_flag; /* Context swapping flag */
- __volatile__ long interrupt_flag; /* Interruption handler flag */
- __volatile__ long dma_flag; /* DMA dispatch flag */
- struct timer_list timer; /* Timer for delaying ctx switch */
- wait_queue_head_t context_wait; /* Processes waiting on ctx switch */
- int last_checked; /* Last context checked for DMA */
- int last_context; /* Last current context */
- unsigned long last_switch; /* jiffies at last context switch */
- struct work_struct work;
+ drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+ drm_lock_data_t lock; /**< Information on hardware lock */
+ /*@}*/
+
+ /** \name DMA queues (contexts) */
+ /*@{*/
+ int queue_count; /**< Number of active DMA queues */
+ int queue_reserved; /**< Number of reserved DMA queues */
+ int queue_slots; /**< Actual length of queuelist */
+ drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
+ drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+ /*@}*/
+
+ /** \name Context support */
+ /*@{*/
+ int irq; /**< Interrupt used by board */
+ __volatile__ long context_flag; /**< Context swapping flag */
+ __volatile__ long interrupt_flag; /**< Interruption handler flag */
+ __volatile__ long dma_flag; /**< DMA dispatch flag */
+ struct timer_list timer; /**< Timer for delaying ctx switch */
+ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+ int last_checked; /**< Last context checked for DMA */
+ int last_context; /**< Last current context */
+ unsigned long last_switch; /**< jiffies at last context switch */
+ /*@}*/
+
+ struct work_struct work;
+ /** \name VBLANK IRQ support */
+ /*@{*/
#if __HAVE_VBL_IRQ
- wait_queue_head_t vbl_queue;
+ wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
atomic_t vbl_received;
spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs;
+ drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
unsigned int vbl_pending;
#endif
+ /*@}*/
cycles_t ctx_start;
cycles_t lck_start;
- /* Callback to X server for context switch
- and for heavy-handed reset. */
- char buf[DRM_BSZ]; /* Output buffer */
- char *buf_rp; /* Read pointer */
- char *buf_wp; /* Write pointer */
- char *buf_end; /* End pointer */
- struct fasync_struct *buf_async;/* Processes waiting for SIGIO */
- wait_queue_head_t buf_readers; /* Processes waiting to read */
- wait_queue_head_t buf_writers; /* Processes waiting to ctx switch */
+ char buf[DRM_BSZ]; /**< Output buffer */
+ char *buf_rp; /**< Read pointer */
+ char *buf_wp; /**< Write pointer */
+ char *buf_end; /**< End pointer */
+ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+ wait_queue_head_t buf_readers; /**< Processes waiting to read */
+ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
#if __REALLY_HAVE_AGP
- drm_agp_head_t *agp;
+ drm_agp_head_t *agp; /**< AGP data */
#endif
- struct pci_dev *pdev;
+ struct pci_dev *pdev; /**< PCI device structure */
#ifdef __alpha__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
struct pci_controler *hose;
@@ -584,17 +726,17 @@
struct pci_controller *hose;
#endif
#endif
- drm_sg_mem_t *sg; /* Scatter gather memory */
- unsigned long *ctx_bitmap;
- void *dev_private;
- drm_sigdata_t sigdata; /* For block_all_signals */
+ drm_sg_mem_t *sg; /**< Scatter gather memory */
+ unsigned long *ctx_bitmap; /**< context bitmap */
+ void *dev_private; /**< device private data */
+ drm_sigdata_t sigdata; /**< For block_all_signals */
sigset_t sigmask;
} drm_device_t;
-/* ================================================================
- * Internal function definitions
- */
+/******************************************************************/
+/** \name Internal function definitions */
+/*@{*/
/* Misc. support (drm_init.h) */
extern int DRM(flags);
@@ -653,7 +795,8 @@
extern void DRM(free_pages)(unsigned long address, int order,
int area);
extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
-extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size,
+ drm_device_t *dev);
extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
#if __REALLY_HAVE_AGP
@@ -841,6 +984,8 @@
extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
unsigned long addr,
dma_addr_t bus_addr);
+
+/*@}*/
#endif /* __KERNEL__ */
#endif
diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h
--- a/drivers/char/drm/drm_agpsupport.h Sun Jul 13 20:39:54 2003
+++ b/drivers/char/drm/drm_agpsupport.h Sun Jul 13 20:39:54 2003
@@ -1,6 +1,12 @@
-/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
- * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
- *
+/**
+ * \file drm_agpsupport.h
+ * DRM support for AGP/GART backend
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -23,10 +29,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Author:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
@@ -34,17 +36,33 @@
#if __REALLY_HAVE_AGP
+
#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
#define DRM_AGP_PUT inter_module_put("drm_agp")
+/**
+ * Pointer to the drm_agp_t structure made available by the agpgart module.
+ */
static const drm_agp_t *drm_agp = NULL;
+/**
+ * AGP information ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a (output) drm_agp_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been initialized and acquired and fills in the
+ * drm_agp_info structure with the information in drm_agp_head::agp_info.
+ */
int DRM(agp_info)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
- struct agp_kern_info *kern;
+ struct agp_kern_info *kern;
drm_agp_info_t info;
if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
@@ -66,6 +84,18 @@
return 0;
}
+/**
+ * Acquire the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * drm_agp->acquire().
+ */
int DRM(agp_acquire)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -80,6 +110,17 @@
return 0;
}
+/**
+ * Release the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls drm_agp->release().
+ */
int DRM(agp_release)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -94,11 +135,28 @@
}
+/**
+ * Release the AGP device.
+ *
+ * Calls drm_agp->release().
+ */
void DRM(agp_do_release)(void)
{
if (drm_agp->release) drm_agp->release();
}
+/**
+ * Enable the AGP bus.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_mode structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired but not enabled, and calls
+ * drm_agp->enable().
+ */
int DRM(agp_enable)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -119,6 +177,18 @@
return 0;
}
+/**
+ * Allocate AGP memory.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired, allocates the
+ * memory via alloc_agp() and creates a drm_agp_mem entry for it.
+ */
int DRM(agp_alloc)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -146,7 +216,7 @@
return -ENOMEM;
}
- entry->handle = (unsigned long)memory->key;
+ entry->handle = (unsigned long)memory->key + 1;
entry->memory = memory;
entry->bound = 0;
entry->pages = pages;
@@ -168,6 +238,15 @@
return 0;
}
+/**
+ * Search for the AGP memory entry associated with a handle.
+ *
+ * \param dev DRM device structure.
+ * \param handle AGP memory handle.
+ * \return pointer to the drm_agp_mem structure associated with \p handle.
+ *
+ * Walks through drm_agp_head::memory until finding a matching handle.
+ */
static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev,
unsigned long handle)
{
@@ -179,6 +258,18 @@
return NULL;
}
+/**
+ * Unbind AGP memory from the GATT (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and acquired, looks-up the AGP memory
+ * entry and passes it to the unbind_agp() function.
+ */
int DRM(agp_unbind)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -200,6 +291,19 @@
return ret;
}
+/**
+ * Bind AGP memory into the GATT (ioctl)
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and that no memory
+ * is currently bound into the GATT. Looks-up the AGP memory entry and passes
+ * it to bind_agp() function.
+ */
int DRM(agp_bind)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -225,6 +329,20 @@
return 0;
}
+/**
+ * Free AGP memory (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and looks up the
+ * AGP memory entry. If the memory it's currently bound, unbind it via
+ * unbind_agp(). Frees it via free_agp() as well as the entry itself
+ * and unlinks from the doubly linked list it's inserted in.
+ */
int DRM(agp_free)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -248,6 +366,15 @@
return 0;
}
+/**
+ * Initialize the AGP resources.
+ *
+ * \return pointer to a drm_agp_head structure.
+ *
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
+ */
drm_agp_head_t *DRM(agp_init)(void)
{
drm_agp_head_t *head = NULL;
@@ -274,18 +401,25 @@
return head;
}
+/**
+ * Free the AGP resources.
+ *
+ * Releases the pointer in ::drm_agp.
+ */
void DRM(agp_uninit)(void)
{
DRM_AGP_PUT;
drm_agp = NULL;
}
+/** Calls drm_agp->allocate_memory() */
struct agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type)
{
if (!drm_agp->allocate_memory) return NULL;
return drm_agp->allocate_memory(pages, type);
}
+/** Calls drm_agp->free_memory() */
int DRM(agp_free_memory)(struct agp_memory *handle)
{
if (!handle || !drm_agp->free_memory) return 0;
@@ -293,12 +427,14 @@
return 1;
}
+/** Calls drm_agp->bind_memory() */
int DRM(agp_bind_memory)(struct agp_memory *handle, off_t start)
{
if (!handle || !drm_agp->bind_memory) return -EINVAL;
return drm_agp->bind_memory(handle, start);
}
+/** Calls drm_agp->unbind_memory() */
int DRM(agp_unbind_memory)(struct agp_memory *handle)
{
if (!handle || !drm_agp->unbind_memory) return -EINVAL;
diff -Nru a/drivers/char/drm/drm_auth.h b/drivers/char/drm/drm_auth.h
--- a/drivers/char/drm/drm_auth.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_auth.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,12 @@
-/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
+/**
+ * \file drm_auth.h
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,19 +31,34 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/**
+ * Generate a hash key from a magic.
+ *
+ * \param magic magic.
+ * \return hash key.
+ *
+ * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
+ * a power of 2.
+ */
static int DRM(hash_magic)(drm_magic_t magic)
{
return magic & (DRM_HASH_SIZE-1);
}
+/**
+ * Find the file with the given magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches in drm_device::magiclist within all files with the same hash key
+ * the one with matching magic number, while holding the drm_device::struct_sem
+ * lock.
+ */
static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
{
drm_file_t *retval = NULL;
@@ -53,6 +76,17 @@
return retval;
}
+/**
+ * Adds a magic number.
+ *
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+ *
+ * Creates a drm_magic_entry structure and appends to the linked list
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_sem lock.
+ */
int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
{
int hash;
@@ -81,12 +115,22 @@
return 0;
}
+/**
+ * Remove a magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_sem lock.
+ */
int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
int hash;
+
DRM_DEBUG("%d\n", magic);
hash = DRM(hash_magic)(magic);
@@ -113,6 +157,19 @@
return -EINVAL;
}
+/**
+ * Get a unique magic number (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a resulting drm_auth structure.
+ * \return zero on success, or a negative number on failure.
+ *
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * filp.
+ */
int DRM(getmagic)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -142,6 +199,17 @@
return 0;
}
+/**
+ * Authenticate with a magic.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_auth structure.
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p filp is associated with the magic number passed in \arg.
+ */
int DRM(authmagic)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
--- a/drivers/char/drm/drm_bufs.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_bufs.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,12 @@
-/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
+/**
+ * \file drm_bufs.h
+ * Generic buffer template
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include
@@ -51,8 +55,15 @@
#endif
#endif
-/*
- * Compute order. Can be made faster.
+
+/**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
*/
int DRM(order)( unsigned long size )
{
@@ -67,6 +78,19 @@
return order;
}
+/**
+ * Ioctl to specify a range of memory that is available for mapping by a non-root process.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
int DRM(addmap)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -186,10 +210,22 @@
}
-/* Remove a map private from list and deallocate resources if the mapping
+/**
+ * Remove a map private from list and deallocate resources if the mapping
* isn't in use.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map_t structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa addmap().
*/
-
int DRM(rmmap)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -262,7 +298,13 @@
#if __HAVE_DMA
-
+/**
+ * Cleanup after an error on one of the addbufs() functions.
+ *
+ * \param entry buffer entry where the error occurred.
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
{
int i;
@@ -305,6 +347,19 @@
}
#if __REALLY_HAVE_AGP
+/**
+ * Add AGP buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ *
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -884,6 +939,20 @@
}
#endif /* __HAVE_SG */
+/**
+ * Add buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ *
+ * According with the memory type specified in drm_buf_desc::flags and the
+ * build options, it dispatches the call either to addbufs_agp(),
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
int DRM(addbufs)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -910,6 +979,24 @@
#endif
}
+
+/**
+ * Get information about the buffer mappings.
+ *
+ * This was originally mean for debugging purposes, or by a sophisticated
+ * client library to determine how best to use the available buffers (e.g.,
+ * large buffers can be used for image transfer).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Increments drm_device::buf_use while holding the drm_device::count_lock
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
int DRM(infobufs)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -981,6 +1068,20 @@
return 0;
}
+/**
+ * Specifies a low and high water mark for buffer allocation
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg a pointer to a drm_buf_desc structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies that the size order is bounded between the admissible orders and
+ * updates the respective drm_device_dma::bufs entry low and high water mark.
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
int DRM(markbufs)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -1015,6 +1116,18 @@
return 0;
}
+/**
+ * Unreserve the buffers in list, previously reserved using drmDMA.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
int DRM(freebufs)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -1056,6 +1169,19 @@
return 0;
}
+/**
+ * Maps all of the DMA buffers into client-virtual space (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Maps the AGP or SG buffer region with do_mmap(), and copies information
+ * about each buffer into user space. The PCI buffers are already mapped on the
+ * addbufs_pci() call.
+ */
int DRM(mapbufs)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
diff -Nru a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
--- a/drivers/char/drm/drm_context.h Sun Jul 13 20:39:54 2003
+++ b/drivers/char/drm/drm_context.h Sun Jul 13 20:39:54 2003
@@ -1,4 +1,12 @@
-/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
+/**
+ * \file drm_context.h
+ * IOCTLs for generic contexts
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,9 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
+ */
+
+/*
* ChangeLog:
* 2001-11-16 Torsten Duwe
* added context constructor/destructor hooks,
@@ -40,10 +47,20 @@
#endif
-/* ================================================================
- * Context bitmap support
- */
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
+/**
+ * Free a handle from the context bitmap.
+ *
+ * \param dev DRM device.
+ * \param ctx_handle context handle.
+ *
+ * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
+ * in drm_device::context_sareas, while holding the drm_device::struct_sem
+ * lock.
+ */
void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
{
if ( ctx_handle < 0 ) goto failed;
@@ -62,6 +79,16 @@
return;
}
+/**
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+ * \return (non-negative) context handle on success or a negative number on failure.
+ *
+ * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
+ * drm_device::context_sareas to accommodate the new entry while holding the
+ * drm_device::struct_sem lock.
+ */
int DRM(ctxbitmap_next)( drm_device_t *dev )
{
int bit;
@@ -112,6 +139,14 @@
return -1;
}
+/**
+ * Context bitmap initialization.
+ *
+ * \param dev DRM device.
+ *
+ * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
int DRM(ctxbitmap_init)( drm_device_t *dev )
{
int i;
@@ -137,6 +172,14 @@
return 0;
}
+/**
+ * Context bitmap cleanup.
+ *
+ * \param dev DRM device.
+ *
+ * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
{
down(&dev->struct_sem);
@@ -148,10 +191,24 @@
up(&dev->struct_sem);
}
-/* ================================================================
- * Per Context SAREA Support
- */
+/*@}*/
+/******************************************************************/
+/** \name Per Context SAREA Support */
+/*@{*/
+
+/**
+ * Get per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Gets the map from drm_device::context_sareas with the handle specified and
+ * returns its handle.
+ */
int DRM(getsareactx)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -180,6 +237,18 @@
return 0;
}
+/**
+ * Set per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the mapping specified in \p arg and update the entry in
+ * drm_device::context_sareas with it.
+ */
int DRM(setsareactx)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -218,10 +287,22 @@
return 0;
}
-/* ================================================================
- * The actual DRM context handling routines
- */
+/*@}*/
+/******************************************************************/
+/** \name The actual DRM context handling routines */
+/*@{*/
+
+/**
+ * Switch context.
+ *
+ * \param dev DRM device.
+ * \param old old context handle.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to set drm_device::context_flag.
+ */
int DRM(context_switch)( drm_device_t *dev, int old, int new )
{
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
@@ -240,6 +321,17 @@
return 0;
}
+/**
+ * Complete context switch.
+ *
+ * \param dev DRM device.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Updates drm_device::last_context and drm_device::last_switch. Verifies the
+ * hardware lock is held, clears the drm_device::context_flag and wakes up
+ * drm_device::context_wait.
+ */
int DRM(context_switch_complete)( drm_device_t *dev, int new )
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
@@ -258,6 +350,15 @@
return 0;
}
+/**
+ * Reserve contexts.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
int DRM(resctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -284,6 +385,17 @@
return 0;
}
+/**
+ * Add context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
int DRM(addctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -322,6 +434,15 @@
return 0;
}
+/**
+ * Get context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
int DRM(getctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -338,6 +459,17 @@
return 0;
}
+/**
+ * Switch context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch().
+ */
int DRM(switchctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -352,6 +484,17 @@
return DRM(context_switch)( dev, dev->last_context, ctx.handle );
}
+/**
+ * New context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch_complete().
+ */
int DRM(newctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -368,6 +511,17 @@
return 0;
}
+/**
+ * Remove context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
int DRM(rmctx)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -392,3 +546,4 @@
return 0;
}
+/*@}*/
diff -Nru a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h
--- a/drivers/char/drm/drm_dma.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_dma.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,12 @@
-/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
+/**
+ * \file drm_dma.h
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
@@ -51,6 +55,14 @@
#if __HAVE_DMA
+/**
+ * Initialize the DMA data.
+ *
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
int DRM(dma_setup)( drm_device_t *dev )
{
int i;
@@ -67,6 +79,14 @@
return 0;
}
+/**
+ * Cleanup the DMA resources.
+ *
+ * \param dev DRM device.
+ *
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the the drm_device::dma structure itself.
+ */
void DRM(dma_takedown)(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -128,7 +148,14 @@
}
-
+/**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+ *
+ * Resets the fields of \p buf.
+ */
void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
{
if (!buf) return;
@@ -154,6 +181,13 @@
}
#if !__HAVE_DMA_RECLAIM
+/**
+ * Reclaim the buffers.
+ *
+ * \param filp file pointer.
+ *
+ * Frees each buffer associated with \p filp not already on the hardware.
+ */
void DRM(reclaim_buffers)( struct file *filp )
{
drm_file_t *priv = filp->private_data;
@@ -185,6 +219,16 @@
#if __HAVE_DMA_IRQ
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ * \param irq IRQ number.
+ *
+ * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
+ * before and after the installation.
+ */
int DRM(irq_install)( drm_device_t *dev, int irq )
{
int ret;
@@ -250,6 +294,13 @@
return 0;
}
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
+ */
int DRM(irq_uninstall)( drm_device_t *dev )
{
int irq;
@@ -271,6 +322,17 @@
return 0;
}
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
int DRM(control)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -293,6 +355,25 @@
#if __HAVE_VBL_IRQ
+/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the IRQ is installed.
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+ * that case. If the number of tasks waiting for the interrupt exceeds 100 the
+ * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
+ * task.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
int DRM(wait_vblank)( DRM_IOCTL_ARGS )
{
drm_file_t *priv = filp->private_data;
@@ -381,6 +462,15 @@
return ret;
}
+/**
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
void DRM(vbl_send_signals)( drm_device_t *dev )
{
struct list_head *list, *tmp;
diff -Nru a/drivers/char/drm/drm_drawable.h b/drivers/char/drm/drm_drawable.h
--- a/drivers/char/drm/drm_drawable.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_drawable.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,12 @@
-/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
+/**
+ * \file drm_drawable.h
+ * IOCTLs for drawables
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +31,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/** No-op. */
int DRM(adddraw)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -43,6 +48,7 @@
return 0;
}
+/** No-op. */
int DRM(rmdraw)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
--- a/drivers/char/drm/drm_drv.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_drv.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,31 @@
-/* drm_drv.h -- Generic driver template -*- linux-c -*-
+/**
+ * \file drm_drv.h
+ * Generic driver template
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ *
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * \code
+ * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME "mga"
+ * #define DRIVER_DESC "Matrox G200/G400"
+ * #define DRIVER_DATE "20001127"
+ *
+ * #define DRIVER_MAJOR 2
+ * #define DRIVER_MINOR 0
+ * #define DRIVER_PATCHLEVEL 2
+ *
+ * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
+ *
+ * #define DRM(x) mga_##x
+ * \endcode
+ */
+
+/*
* Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,29 +50,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
- */
-
-/*
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME "mga"
- * #define DRIVER_DESC "Matrox G200/G400"
- * #define DRIVER_DATE "20001127"
- *
- * #define DRIVER_MAJOR 2
- * #define DRIVER_MINOR 0
- * #define DRIVER_PATCHLEVEL 2
- *
- * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
- *
- * #define DRM(x) mga_##x
*/
#ifndef __MUST_HAVE_AGP
@@ -84,6 +88,10 @@
#ifndef __HAVE_SG
#define __HAVE_SG 0
#endif
+/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm modules in
+ * the DRI cvs tree, but it is required by the kernel tree's sparc
+ * driver.
+ */
#ifndef __HAVE_KERNEL_CTX_SWITCH
#define __HAVE_KERNEL_CTX_SWITCH 0
#endif
@@ -134,12 +142,13 @@
#endif
#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO). It calls the insmod option
- * routine, drm_parse_drm.
- */
-/* Use an additional macro to avoid preprocessor troubles */
+/** Use an additional macro to avoid preprocessor troubles */
#define DRM_OPTIONS_FUNC DRM(options)
+/**
+ * Called by the kernel to parse command-line options passed via the
+ * boot-loader (e.g., LILO). It calls the insmod option routine,
+ * parse_options().
+ */
static int __init DRM(options)( char *str )
{
DRM(parse_options)( str );
@@ -150,7 +159,7 @@
#undef DRM_OPTIONS_FUNC
#endif
-/*
+/**
* The default number of instances (minor numbers) to initialize.
*/
#ifndef DRIVER_NUM_CARDS
@@ -163,6 +172,7 @@
DRIVER_FOPS;
+/** Ioctl table */
static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
@@ -348,7 +358,8 @@
DRM_DEBUG( "\n" );
- /* The kernel's context could be created here, but is now created
+ /*
+ * The kernel's context could be created here, but is now created
* in drm_dma_enqueue. This is more resource-efficient for
* hardware that does not do DMA, but may mean that
* drm_select_queue fails between the time the interrupt is
@@ -359,6 +370,15 @@
}
+/**
+ * Take down the DRM device.
+ *
+ * \param dev DRM device structure.
+ *
+ * Frees every resource in \p dev.
+ *
+ * \sa drm_device and setup().
+ */
static int DRM(takedown)( drm_device_t *dev )
{
drm_magic_entry_t *pt, *next;
@@ -516,8 +536,12 @@
return 0;
}
-/*
+/**
* Figure out how many instances to initialize.
+ *
+ * \return number of cards found.
+ *
+ * Searches for every PCI card in \c DRIVER_CARD_LIST with matching vendor and device ids.
*/
static int drm_count_cards(void)
{
@@ -551,8 +575,18 @@
return num;
}
-/* drm_init is called via init_module at module load time, or via
+/**
+ * Module initialization. Called via init_module at module load time, or via
* linux/init/main.c (this is not currently supported).
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Allocates and initialize an array of drm_device structures, and attempts to
+ * initialize all available devices, using consecutive minors, registering the
+ * stubs and initializing the AGP device.
+ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
*/
static int __init drm_init( void )
{
@@ -641,7 +675,12 @@
return 0;
}
-/* drm_cleanup is called via cleanup_module at module unload time.
+/**
+ * Called via cleanup_module() at module unload time.
+ *
+ * Cleans up all DRM device, calling takedown().
+ *
+ * \sa drm_init().
*/
static void __exit drm_cleanup( void )
{
@@ -694,6 +733,17 @@
module_exit( drm_cleanup );
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
int DRM(version)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -729,6 +779,17 @@
return 0;
}
+/**
+ * Open file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the DRM device with the same minor number, calls open_helper(), and
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
+ */
int DRM(open)( struct inode *inode, struct file *filp )
{
drm_device_t *dev = NULL;
@@ -759,6 +820,18 @@
return retcode;
}
+/**
+ * Release file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the hardware lock is held then free it, and take it again for the kernel
+ * context since it's necessary to reclaim buffers. Unlink the file private
+ * data from its list and free it. Decreases the open count and if it reaches
+ * zero calls takedown().
+ */
int DRM(release)( struct inode *inode, struct file *filp )
{
drm_file_t *priv = filp->private_data;
@@ -885,7 +958,17 @@
return retcode;
}
-/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
*/
int DRM(ioctl)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
@@ -926,6 +1009,17 @@
return retcode;
}
+/**
+ * Lock ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Add the current task to the lock wait queue, and attempt to take to lock.
+ */
int DRM(lock)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -1018,6 +1112,10 @@
DRIVER_DMA_QUIESCENT();
}
#endif
+ /* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the
+ * drm modules in the DRI cvs tree, but it is required
+ * by the Sparc driver.
+ */
#if __HAVE_KERNEL_CTX_SWITCH
if ( dev->last_context != lock.context ) {
DRM(context_switch)(dev, dev->last_context,
@@ -1031,7 +1129,17 @@
return ret;
}
-
+/**
+ * Unlock ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Transfer and free the lock.
+ */
int DRM(unlock)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -1050,6 +1158,10 @@
atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
+ /* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm
+ * modules in the DRI cvs tree, but it is required by the
+ * Sparc driver.
+ */
#if __HAVE_KERNEL_CTX_SWITCH
/* We no longer really hold it, but if we are the next
* agent to request it then we should just be able to
@@ -1075,13 +1187,9 @@
DRM(dma_schedule)( dev, 1 );
#endif
- /* FIXME: Do we ever really need to check this???
- */
- if ( 1 /* !dev->context_flag */ ) {
- if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT ) ) {
- DRM_ERROR( "\n" );
- }
+ if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT ) ) {
+ DRM_ERROR( "\n" );
}
#endif /* !__HAVE_KERNEL_CTX_SWITCH */
diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
--- a/drivers/char/drm/drm_fops.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_fops.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,13 @@
-/* drm_fops.h -- File operations for DRM -*- linux-c -*-
+/**
+ * \file drm_fops.h
+ * File operations for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Daryll Strauss
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,18 +32,23 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Daryll Strauss
- * Gareth Hughes
*/
#include "drmP.h"
#include
-/* drm_open is called whenever a process opens /dev/drm. */
+/**
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
{
int minor = minor(inode->i_rdev);
@@ -90,6 +104,7 @@
return 0;
}
+/** No-op. */
int DRM(flush)(struct file *filp)
{
drm_file_t *priv = filp->private_data;
@@ -100,6 +115,7 @@
return 0;
}
+/** No-op. */
int DRM(fasync)(int fd, struct file *filp, int on)
{
drm_file_t *priv = filp->private_data;
@@ -113,6 +129,7 @@
}
#if !__HAVE_DRIVER_FOPS_POLL
+/** No-op. */
unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
{
return 0;
@@ -121,6 +138,7 @@
#if !__HAVE_DRIVER_FOPS_READ
+/** No-op. */
ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
{
return 0;
diff -Nru a/drivers/char/drm/drm_init.h b/drivers/char/drm/drm_init.h
--- a/drivers/char/drm/drm_init.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_init.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,12 @@
-/* drm_init.h -- Setup/Cleanup for DRM -*- linux-c -*-
+/**
+ * \file drm_init.h
+ * Setup/Cleanup for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,22 +31,23 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/** Debug flags. Set by parse_option(). */
#if 0
int DRM(flags) = DRM_FLAG_DEBUG;
#else
int DRM(flags) = 0;
#endif
-/* drm_parse_option parses a single option. See description for
- * drm_parse_options for details.
+/**
+ * Parse a single option.
+ *
+ * \param s option string.
+ *
+ * \sa See parse_options() for details.
*/
static void DRM(parse_option)(char *s)
{
@@ -58,26 +67,33 @@
return;
}
-/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
- * options passed to the kernel via LILO. The grammar of the format is as
+/**
+ * Parse the insmod "drm_opts=" options, or the command-line
+ * options passed to the kernel via LILO.
+ *
+ * \param s contains option_list without the 'drm_opts=' part.
+ *
+ * The grammar of the format is as
* follows:
*
+ * \code
* drm ::= 'drm_opts=' option_list
* option_list ::= option [ ';' option_list ]
* option ::= 'device:' major
* | 'debug'
* | 'noctx'
* major ::= INTEGER
+ * \endcode
*
- * Note that 's' contains option_list without the 'drm_opts=' part.
- *
- * device=major,minor specifies the device number used for /dev/drm
- * if major == 0 then the misc device is used
- * if major == 0 and minor == 0 then dynamic misc allocation is used
- * debug=on specifies that debugging messages will be printk'd
- * debug=trace specifies that each function call will be logged via printk
- * debug=off turns off all debugging options
+ * - device=major,minor specifies the device number used for /dev/drm
+ * - if major == 0 then the misc device is used
+ * - if major == 0 and minor == 0 then dynamic misc allocation is used
+ * - debug=on specifies that debugging messages will be printk'd
+ * - debug=trace specifies that each function call will be logged via printk
+ * - debug=off turns off all debugging options
*
+ * \todo Actually only the \e presence of the 'debug' option is currently
+ * checked.
*/
void DRM(parse_options)(char *s)
@@ -95,8 +111,10 @@
}
}
-/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
- * otherwise.
+/**
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
*/
int DRM(cpu_valid)(void)
{
diff -Nru a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h
--- a/drivers/char/drm/drm_ioctl.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_ioctl.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,12 @@
-/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
+/**
+ * \file drm_ioctl.h
+ * IOCTL processing for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,15 +31,22 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/**
+ * Get interrupt from bus id.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ */
int DRM(irq_busid)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -84,6 +99,17 @@
return 0;
}
+/**
+ * Get the bus id.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from drm_device::unique into user space.
+ */
int DRM(getunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -103,6 +129,18 @@
return 0;
}
+/**
+ * Set the bus id.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from userspace into drm_device::unique, and searches for
+ * the respective PCI device, updating drm_device::pdev.
+ */
int DRM(setunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -180,6 +218,19 @@
}
+/**
+ * Get a mapping information.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
int DRM(getmap)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -226,6 +277,19 @@
return 0;
}
+/**
+ * Get client information.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_client structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the client with the specified index and copies its information
+ * into userspace
+ */
int DRM(getclient)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
@@ -259,6 +323,16 @@
return 0;
}
+/**
+ * Get statistics information.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_stats structure.
+ *
+ * \return zero on success or a negative number on failure.
+ */
int DRM(getstats)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
diff -Nru a/drivers/char/drm/drm_lock.h b/drivers/char/drm/drm_lock.h
--- a/drivers/char/drm/drm_lock.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_lock.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,12 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
+/**
+ * \file drm_lock.h
+ * IOCTLs for locking
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +31,11 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/** No-op ioctl. */
int DRM(noop)(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -38,7 +43,15 @@
return 0;
}
-
+/**
+ * Take the heavyweight lock.
+ *
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return one if the lock is held, or zero otherwise.
+ *
+ * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
+ */
int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
{
unsigned int old, new, prev;
@@ -65,8 +78,18 @@
return 0;
}
-/* This takes a lock forcibly and hands it to context. Should ONLY be used
- inside *_unlock to give lock to kernel before calling *_dma_schedule. */
+/**
+ * This takes a lock forcibly and hands it to context. Should ONLY be used
+ * inside *_unlock to give lock to kernel before calling *_dma_schedule.
+ *
+ * \param dev DRM device.
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return always one.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as held by the given context, via the \p cmpxchg instruction.
+ */
int DRM(lock_transfer)(drm_device_t *dev,
__volatile__ unsigned int *lock, unsigned int context)
{
@@ -81,6 +104,17 @@
return 1;
}
+/**
+ * Free lock.
+ *
+ * \param dev DRM device.
+ * \param lock lock.
+ * \param context context.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
+ * waiting on the lock queue.
+ */
int DRM(lock_free)(drm_device_t *dev,
__volatile__ unsigned int *lock, unsigned int context)
{
@@ -102,18 +136,17 @@
return 0;
}
-/* If we get here, it means that the process has called DRM_IOCTL_LOCK
- without calling DRM_IOCTL_UNLOCK.
-
- If the lock is not held, then let the signal proceed as usual.
-
- If the lock is held, then set the contended flag and keep the signal
- blocked.
-
-
- Return 1 if the signal should be delivered normally.
- Return 0 if the signal should be blocked. */
-
+/**
+ * If we get here, it means that the process has called DRM_IOCTL_LOCK
+ * without calling DRM_IOCTL_UNLOCK.
+ *
+ * If the lock is not held, then let the signal proceed as usual. If the lock
+ * is held, then set the contended flag and keep the signal blocked.
+ *
+ * \param priv pointer to a drm_sigdata structure.
+ * \return one if the signal should be delivered normally, or zero if the
+ * signal should be blocked.
+ */
int DRM(notifier)(void *priv)
{
drm_sigdata_t *s = (drm_sigdata_t *)priv;
diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
--- a/drivers/char/drm/drm_memory.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_memory.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,12 @@
-/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
+/**
+ * \file drm_memory.h
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,17 +31,14 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include
#include
#include "drmP.h"
-/* Cut down version of drm_memory_debug.h, which used to be called
+/**
+ * Cut down version of drm_memory_debug.h, which used to be called
* drm_memory.h. If you want the debug functionality, change 0 to 1
* below.
*/
@@ -188,22 +193,38 @@
#if DEBUG_MEMORY
#include "drm_memory_debug.h"
#else
+
+/** No-op. */
void DRM(mem_init)(void)
{
}
-/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+/**
+ * Called when "/proc/dri/%dev%/mem" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param len requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * No-op.
+ */
int DRM(mem_info)(char *buf, char **start, off_t offset,
int len, int *eof, void *data)
{
return 0;
}
+/** Wrapper around kmalloc() */
void *DRM(alloc)(size_t size, int area)
{
return kmalloc(size, GFP_KERNEL);
}
+/** Wrapper around kmalloc() and kfree() */
void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
{
void *pt;
@@ -216,11 +237,21 @@
return pt;
}
+/** Wrapper around kfree() */
void DRM(free)(void *pt, size_t size, int area)
{
kfree(pt);
}
+/**
+ * Allocate pages.
+ *
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ * \return page address on success, or zero on failure.
+ *
+ * Allocate and reserve free pages.
+ */
unsigned long DRM(alloc_pages)(int order, int area)
{
unsigned long address;
@@ -245,6 +276,15 @@
return address;
}
+/**
+ * Free pages.
+ *
+ * \param address address of the pages to free.
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ *
+ * Unreserve and free pages allocated by alloc_pages().
+ */
void DRM(free_pages)(unsigned long address, int order, int area)
{
unsigned long bytes = PAGE_SIZE << order;
@@ -264,37 +304,44 @@
free_pages(address, order);
}
+/** Wrapper around drm_ioremap() */
void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
{
return drm_ioremap(offset, size, dev);
}
+/** Wrapper around drm_ioremap_nocache() */
void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
{
return drm_ioremap_nocache(offset, size, dev);
}
+/** Wrapper around drm_iounmap() */
void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
{
drm_ioremapfree(pt, size, dev);
}
#if __REALLY_HAVE_AGP
+/** Wrapper around agp_allocate_memory() */
struct agp_memory *DRM(alloc_agp)(int pages, u32 type)
{
return DRM(agp_allocate_memory)(pages, type);
}
+/** Wrapper around agp_free_memory() */
int DRM(free_agp)(struct agp_memory *handle, int pages)
{
return DRM(agp_free_memory)(handle) ? 0 : -EINVAL;
}
+/** Wrapper around agp_bind_memory() */
int DRM(bind_agp)(struct agp_memory *handle, unsigned int start)
{
return DRM(agp_bind_memory)(handle, start);
}
+/** Wrapper around agp_unbind_memory() */
int DRM(unbind_agp)(struct agp_memory *handle)
{
return DRM(agp_unbind_memory)(handle);
diff -Nru a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
--- a/drivers/char/drm/drm_memory_debug.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_memory_debug.h Sun Jul 13 20:39:55 2003
@@ -1,6 +1,12 @@
-/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
- * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
+/**
+ * \file drm_memory.h
+ * Memory management wrappers for DRM.
*
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -23,10 +29,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include
diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
--- a/drivers/char/drm/drm_os_linux.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_os_linux.h Sun Jul 13 20:39:56 2003
@@ -1,35 +1,55 @@
+/**
+ * \file drm_os_linux.h
+ * OS abstraction macros.
+ */
+
#include /* For task queue support */
#include
+/** File pointer type */
#define DRMFILE struct file *
+/** Ioctl arguments */
#define DRM_IOCTL_ARGS struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
#define DRM_ERR(d) -(d)
+/** Current process ID */
#define DRM_CURRENTPID current->pid
#define DRM_UDELAY(d) udelay(d)
+/** Read a byte from a MMIO region */
#define DRM_READ8(map, offset) readb(((unsigned long)(map)->handle) + (offset))
+/** Read a dword from a MMIO region */
#define DRM_READ32(map, offset) readl(((unsigned long)(map)->handle) + (offset))
+/** Write a byte into a MMIO region */
#define DRM_WRITE8(map, offset, val) writeb(val, ((unsigned long)(map)->handle) + (offset))
+/** Write a dword into a MMIO region */
#define DRM_WRITE32(map, offset, val) writel(val, ((unsigned long)(map)->handle) + (offset))
+/** Read memory barrier */
#define DRM_READMEMORYBARRIER() rmb()
+/** Write memory barrier */
#define DRM_WRITEMEMORYBARRIER() wmb()
+/** Read/write memory barrier */
#define DRM_MEMORYBARRIER() mb()
+/** DRM device local declaration */
#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
drm_device_t *dev = priv->dev
-
+
+/** IRQ handler arguments */
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
+/** Task queue handler arguments */
#define DRM_TASKQUEUE_ARGS void *arg
-/* For data going from/to the kernel through the ioctl argument */
+/** For data going into the kernel through the ioctl argument */
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
if ( copy_from_user(&arg1, arg2, arg3) ) \
return -EFAULT
+/** For data going from the kernel through the ioctl argument */
#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
if ( copy_to_user(arg1, &arg2, arg3) ) \
return -EFAULT
-/* Other copying of data from/to kernel space */
+/** Other copying of data to kernel space */
#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
copy_from_user(arg1, arg2, arg3)
+/** Other copying of data from kernel space */
#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
copy_to_user(arg1, arg2, arg3)
/* Macros for copyfrom user, but checking readability only once */
@@ -41,10 +61,16 @@
__get_user(val, uaddr)
-/* malloc/free without the overhead of DRM(alloc) */
+/** 'malloc' without the overhead of DRM(alloc)() */
#define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
+/** 'free' without the overhead of DRM(free)() */
#define DRM_FREE(x,size) kfree(x)
+/**
+ * Get the pointer to the SAREA.
+ *
+ * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
+ */
#define DRM_GETSAREA() \
do { \
drm_map_list_t *entry; \
diff -Nru a/drivers/char/drm/drm_proc.h b/drivers/char/drm/drm_proc.h
--- a/drivers/char/drm/drm_proc.h Sun Jul 13 20:39:54 2003
+++ b/drivers/char/drm/drm_proc.h Sun Jul 13 20:39:54 2003
@@ -1,4 +1,16 @@
-/* drm_proc.h -- /proc support for DRM -*- linux-c -*-
+/**
+ * \file drm_proc.h
+ * /proc support for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ *
+ * \par Acknowledgements:
+ * Matthew J Sottek sent in a patch to fix
+ * the problem with the proc files not outputting all their information.
+ */
+
+/*
* Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +35,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
- *
- * Acknowledgements:
- * Matthew J Sottek sent in a patch to fix
- * the problem with the proc files not outputting all their information.
*/
#include "drmP.h"
@@ -50,9 +54,12 @@
int request, int *eof, void *data);
#endif
+/**
+ * Proc file list.
+ */
struct drm_proc_list {
- const char *name;
- int (*f)(char *, char **, off_t, int, int *, void *);
+ const char *name; /**< file name */
+ int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
} DRM(proc_list)[] = {
{ "name", DRM(name_info) },
{ "mem", DRM(mem_info) },
@@ -66,6 +73,19 @@
};
#define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0]))
+/**
+ * Initialize the DRI proc filesystem for a device.
+ *
+ * \param dev DRM device.
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root resulting DRI device proc dir entry.
+ * \return root entry pointer on success, or NULL on failure.
+ *
+ * Create the DRI proc root entry "/proc/dri", the device proc root entry
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor,
struct proc_dir_entry *root,
struct proc_dir_entry **dev_root)
@@ -83,7 +103,7 @@
sprintf(name, "%d", minor);
*dev_root = create_proc_entry(name, S_IFDIR, root);
if (!*dev_root) {
- DRM_ERROR("Cannot create /proc/%s\n", name);
+ DRM_ERROR("Cannot create /proc/dri/%s\n", name);
return NULL;
}
@@ -108,6 +128,16 @@
}
+/**
+ * Cleanup the proc filesystem resources.
+ *
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root DRI device proc dir entry.
+ * \return always zero.
+ *
+ * Remove all proc entries created by proc_init().
+ */
int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root,
struct proc_dir_entry *dev_root)
{
@@ -125,6 +155,19 @@
return 0;
}
+/**
+ * Called when "/proc/dri/.../name" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints the device name together with the bus id if available.
+ */
static int DRM(name_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -151,6 +194,19 @@
return len - offset;
}
+/**
+ * Called when "/proc/dri/.../vm" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints information about all mappings in drm_device::maplist.
+ */
static int DRM(_vm_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -204,6 +260,9 @@
return len - offset;
}
+/**
+ * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ */
static int DRM(vm_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -216,7 +275,17 @@
return ret;
}
-
+/**
+ * Called when "/proc/dri/.../queues" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
static int DRM(_queues_info)(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
@@ -261,6 +330,9 @@
return len - offset;
}
+/**
+ * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ */
static int DRM(queues_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -273,9 +345,17 @@
return ret;
}
-/* drm_bufs_info is called whenever a process reads
- /dev/dri//bufs. */
-
+/**
+ * Called when "/proc/dri/.../bufs" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
static int DRM(_bufs_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -320,6 +400,9 @@
return len - offset;
}
+/**
+ * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ */
static int DRM(bufs_info)(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
@@ -332,7 +415,17 @@
return ret;
}
-
+/**
+ * Called when "/proc/dri/.../clients" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
static int DRM(_clients_info)(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
@@ -364,6 +457,9 @@
return len - offset;
}
+/**
+ * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ */
static int DRM(clients_info)(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
diff -Nru a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
--- a/drivers/char/drm/drm_sarea.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_sarea.h Sun Jul 13 20:39:56 2003
@@ -1,5 +1,11 @@
-/* sarea.h -- SAREA definitions -*- linux-c -*-
+/**
+ * \file drm_sarea.h
+ * \brief SAREA definitions
*
+ * \author Michel Dänzer
+ */
+
+/*
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -21,22 +27,22 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Michel Dänzer
*/
#ifndef _DRM_SAREA_H_
#define _DRM_SAREA_H_
+/** Maximum number of drawables in the SAREA */
#define SAREA_MAX_DRAWABLES 256
-typedef struct _drm_sarea_drawable_t {
+/** SAREA drawable */
+typedef struct drm_sarea_drawable {
unsigned int stamp;
unsigned int flags;
} drm_sarea_drawable_t;
-typedef struct _dri_sarea_frame_t {
+/** SAREA frame */
+typedef struct drm_sarea_frame {
unsigned int x;
unsigned int y;
unsigned int width;
@@ -44,13 +50,14 @@
unsigned int fullscreen;
} drm_sarea_frame_t;
-typedef struct _drm_sarea_t {
- /* first thing is always the drm locking structure */
+/** SAREA */
+typedef struct drm_sarea {
+ /** first thing is always the DRM locking structure */
drm_hw_lock_t lock;
- /* NOT_DONE: Use readers/writer lock for drawable_lock */
+ /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
drm_hw_lock_t drawable_lock;
- drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES];
- drm_sarea_frame_t frame;
+ drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
+ drm_sarea_frame_t frame; /**< frame */
drm_context_t dummy_context;
} drm_sarea_t;
diff -Nru a/drivers/char/drm/drm_scatter.h b/drivers/char/drm/drm_scatter.h
--- a/drivers/char/drm/drm_scatter.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/drm_scatter.h Sun Jul 13 20:39:55 2003
@@ -1,4 +1,11 @@
-/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
+/**
+ * \file drm_scatter.h
+ * IOCTLs to manage scatter/gather memory
+ *
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
*
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,9 +29,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Gareth Hughes
*/
#include
diff -Nru a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
--- a/drivers/char/drm/drm_stub.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_stub.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,11 @@
-/* drm_stub.h -- -*- linux-c -*-
+/**
+ * \file drm_stub.h
+ * Stub support
+ *
+ * \author Rickard E. (Rik) Faith
+ */
+
+/*
* Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
*
* Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,30 +29,37 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- *
*/
#include "drmP.h"
#define DRM_STUB_MAXCARDS 16 /* Enough for one machine */
+/** Stub list. One for each minor. */
static struct drm_stub_list {
const char *name;
- struct file_operations *fops;
- struct proc_dir_entry *dev_root;
+ struct file_operations *fops; /**< file operations */
+ struct proc_dir_entry *dev_root; /**< proc directory entry */
} *DRM(stub_list);
static struct proc_dir_entry *DRM(stub_root);
+/** Stub information */
static struct drm_stub_info {
int (*info_register)(const char *name, struct file_operations *fops,
drm_device_t *dev);
int (*info_unregister)(int minor);
} DRM(stub_info);
+/**
+ * File \c open operation.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ *
+ * Puts the drm_stub_list::fops corresponding to the device minor number into
+ * \p filp, call the \c open method, and restore the file operations.
+ */
static int DRM(stub_open)(struct inode *inode, struct file *filp)
{
int minor = minor(inode->i_rdev);
@@ -64,11 +78,24 @@
return err;
}
+/** File operations structure */
static struct file_operations DRM(stub_fops) = {
.owner = THIS_MODULE,
.open = DRM(stub_open)
};
+/**
+ * Get a device minor number.
+ *
+ * \param name driver name.
+ * \param fops file operations.
+ * \param dev DRM device.
+ * \return minor number on success, or a negative number on failure.
+ *
+ * Allocate and initialize ::stub_list if one doesn't exist already. Search an
+ * empty entry and initialize it to the given parameters, and create the proc
+ * init entry via proc_init().
+ */
static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
drm_device_t *dev)
{
@@ -96,6 +123,16 @@
return -1;
}
+/**
+ * Put a device minor number.
+ *
+ * \param minor minor number.
+ * \return always zero.
+ *
+ * Cleans up the proc resources. If a minor is zero then release the foreign
+ * "drm" data, otherwise unregisters the "drm" data, frees the stub list and
+ * unregisters the character device.
+ */
static int DRM(stub_putminor)(int minor)
{
if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
@@ -115,7 +152,20 @@
return 0;
}
-
+/**
+ * Register.
+ *
+ * \param name driver name.
+ * \param fops file operations
+ * \param dev DRM device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to register the char device and get the foreign "drm" data. If
+ * successful then another module already registered so gets the stub info,
+ * otherwise use this module stub info and make it available for other modules.
+ *
+ * Finally calls stub_info::info_register.
+ */
int DRM(stub_register)(const char *name, struct file_operations *fops,
drm_device_t *dev)
{
@@ -141,6 +191,13 @@
return -1;
}
+/**
+ * Unregister.
+ *
+ * \param minor
+ *
+ * Calls drm_stub_info::unregister.
+ */
int DRM(stub_unregister)(int minor)
{
DRM_DEBUG("%d\n", minor);
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/drm_vm.h Sun Jul 13 20:39:56 2003
@@ -1,4 +1,12 @@
-/* drm_vm.h -- Memory mapping for DRM -*- linux-c -*-
+/**
+ * \file drm_vm.h
+ * Memory mapping for DRM
+ *
+ * \author Rickard E. (Rik) Faith
+ * \author Gareth Hughes
+ */
+
+/*
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,38 +31,49 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith
- * Gareth Hughes
*/
#include "drmP.h"
+/** AGP virtual memory operations */
struct vm_operations_struct DRM(vm_ops) = {
.nopage = DRM(vm_nopage),
.open = DRM(vm_open),
.close = DRM(vm_close),
};
+/** Shared virtual memory operations */
struct vm_operations_struct DRM(vm_shm_ops) = {
.nopage = DRM(vm_shm_nopage),
.open = DRM(vm_open),
.close = DRM(vm_shm_close),
};
+/** DMA virtual memory operations */
struct vm_operations_struct DRM(vm_dma_ops) = {
.nopage = DRM(vm_dma_nopage),
.open = DRM(vm_open),
.close = DRM(vm_close),
};
+/** Scatter-gather virtual memory operations */
struct vm_operations_struct DRM(vm_sg_ops) = {
.nopage = DRM(vm_sg_nopage),
.open = DRM(vm_open),
.close = DRM(vm_close),
};
+/**
+ * \c nopage method for AGP virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ *
+ * Find the right map and if it's AGP memory find the real physical page to
+ * map, get the page, increment the use count and return it.
+ */
struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
unsigned long address,
int write_access)
@@ -122,6 +141,17 @@
return NOPAGE_SIGBUS; /* Disallow mremap */
}
+/**
+ * \c nopage method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ *
+ * Get the the mapping, find the real physical page to map, get the page, and
+ * return it.
+ */
struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
unsigned long address,
int write_access)
@@ -145,10 +175,15 @@
return page;
}
-/* Special close routine which deletes map information if we are the last
+
+/**
+ * \c close method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ *
+ * Deletes map information if we are the last
* person to close a mapping and it's not in the global maplist.
*/
-
void DRM(vm_shm_close)(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
@@ -221,6 +256,16 @@
up(&dev->struct_sem);
}
+/**
+ * \c nopage method for DMA virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ *
+ * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
+ */
struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
unsigned long address,
int write_access)
@@ -247,6 +292,16 @@
return page;
}
+/**
+ * \c nopage method for scatter-gather virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ *
+ * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
+ */
struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
unsigned long address,
int write_access)
@@ -274,6 +329,14 @@
return page;
}
+/**
+ * \c open method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ *
+ * Create a new drm_vma_entry structure as the \p vma private data entry and
+ * add it to drm_device::vmalist.
+ */
void DRM(vm_open)(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
@@ -295,6 +358,14 @@
}
}
+/**
+ * \c close method for all virtual memory types.
+ *
+ * \param vma virtual memory area.
+ *
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
void DRM(vm_close)(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
@@ -320,6 +391,16 @@
up(&dev->struct_sem);
}
+/**
+ * mmap DMA memory.
+ *
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ *
+ * Sets the virtual memory area operations structure to vm_dma_ops, the file
+ * pointer, and calls vm_open().
+ */
int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
@@ -366,6 +447,19 @@
#endif
#endif
+/**
+ * mmap DMA memory.
+ *
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the virtual memory area has no offset associated with it then it's a DMA
+ * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
+ * checks that the restricted flag is not set, sets the virtual memory operations
+ * according to the mapping type and remaps the pages. Finally sets the file
+ * pointer and calls vm_open().
+ */
int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
diff -Nru a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h
--- a/drivers/char/drm/i810.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/i810.h Sun Jul 13 20:39:55 2003
@@ -45,7 +45,7 @@
#define DRIVER_NAME "i810"
#define DRIVER_DESC "Intel i810"
-#define DRIVER_DATE "20020211"
+#define DRIVER_DATE "20030605"
/* Interface history
*
@@ -54,10 +54,11 @@
* - XFree86 4.2
* 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
* - Remove requirement for interrupt (leave stubs again)
+ * 1.3 - Add page flipping.
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 1
+#define DRIVER_MINOR 3
+#define DRIVER_PATCHLEVEL 0
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, \
@@ -73,8 +74,9 @@
[DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)] = { i810_dma_mc, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 }
-
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] = { i810_flip_bufs, 1, 0 }
+
#define __HAVE_COUNTERS 4
#define __HAVE_COUNTER6 _DRM_STAT_IRQ
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/i810_dma.c Sun Jul 13 20:39:55 2003
@@ -282,10 +282,12 @@
ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
ring->space = ring->head - (ring->tail+8);
if (ring->space < 0) ring->space += ring->Size;
-
- if (ring->head != last_head)
- end = jiffies + (HZ*3);
-
+
+ if (ring->head != last_head) {
+ end = jiffies + (HZ*3);
+ last_head = ring->head;
+ }
+
iters++;
if(time_before(end, jiffies)) {
DRM_ERROR("space: %d wanted %d\n", ring->space, n);
@@ -403,6 +405,7 @@
dev_priv->pitch = init->pitch;
dev_priv->back_offset = init->back_offset;
dev_priv->depth_offset = init->depth_offset;
+ dev_priv->front_offset = init->front_offset;
dev_priv->overlay_offset = init->overlay_offset;
dev_priv->overlay_physical = init->overlay_physical;
@@ -582,6 +585,8 @@
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
if (dirty & I810_UPLOAD_BUFFERS) {
i810EmitDestVerified( dev, sarea_priv->BufferState );
@@ -620,6 +625,14 @@
int cpp = 2;
int i;
RING_LOCALS;
+
+ if ( dev_priv->current_page == 1 ) {
+ unsigned int tmp = flags;
+
+ flags &= ~(I810_FRONT | I810_BACK);
+ if (tmp & I810_FRONT) flags |= I810_BACK;
+ if (tmp & I810_BACK) flags |= I810_FRONT;
+ }
i810_kernel_lost_context(dev);
@@ -685,10 +698,11 @@
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = 2;
- int ofs = dev_priv->back_offset;
int i;
RING_LOCALS;
+ DRM_DEBUG("swapbuffers\n");
+
i810_kernel_lost_context(dev);
if (nbox > I810_NR_SAREA_CLIPRECTS)
@@ -699,7 +713,7 @@
unsigned int w = pbox->x2 - pbox->x1;
unsigned int h = pbox->y2 - pbox->y1;
unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
- unsigned int start = ofs + dst;
+ unsigned int start = dst;
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
@@ -711,9 +725,15 @@
OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
OUT_RING( pitch | (0xCC << 16));
OUT_RING( (h << 16) | (w * cpp));
- OUT_RING( dst );
+ if (dev_priv->current_page == 0)
+ OUT_RING(dev_priv->front_offset + start);
+ else
+ OUT_RING(dev_priv->back_offset + start);
OUT_RING( pitch );
- OUT_RING( start );
+ if (dev_priv->current_page == 0)
+ OUT_RING(dev_priv->back_offset + start);
+ else
+ OUT_RING(dev_priv->front_offset + start);
ADVANCE_LP_RING();
}
}
@@ -800,6 +820,52 @@
}
}
+static void i810_dma_dispatch_flip( drm_device_t *dev )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ int pitch = dev_priv->pitch;
+ RING_LOCALS;
+
+ DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page,
+ dev_priv->sarea_priv->pf_current_page);
+
+ i810_kernel_lost_context(dev);
+
+ BEGIN_LP_RING( 2 );
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+
+ BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+ /* On i815 at least ASYNC is buggy */
+ /* pitch<<5 is from 11.2.8 p158,
+ its the pitch / 8 then left shifted 8,
+ so (pitch >> 3) << 8 */
+ OUT_RING( CMD_OP_FRONTBUFFER_INFO | (pitch<<5) /*| ASYNC_FLIP */ );
+ if ( dev_priv->current_page == 0 ) {
+ OUT_RING( dev_priv->back_offset );
+ dev_priv->current_page = 1;
+ } else {
+ OUT_RING( dev_priv->front_offset );
+ dev_priv->current_page = 0;
+ }
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ BEGIN_LP_RING(2);
+ OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );
+ OUT_RING( 0 );
+ ADVANCE_LP_RING();
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+}
void i810_dma_quiescent(drm_device_t *dev)
{
@@ -1191,3 +1257,47 @@
}
+/* Not sure why this isn't set all the time:
+ */
+static void i810_do_init_pageflip( drm_device_t *dev )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+int i810_do_cleanup_pageflip( drm_device_t *dev )
+{
+ drm_i810_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ if (dev_priv->current_page != 0)
+ i810_dma_dispatch_flip( dev );
+
+ dev_priv->page_flipping = 0;
+ return 0;
+}
+
+int i810_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_flip_buf called without lock held\n");
+ return -EINVAL;
+ }
+
+ if (!dev_priv->page_flipping)
+ i810_do_init_pageflip( dev );
+
+ i810_dma_dispatch_flip( dev );
+ return 0;
+}
diff -Nru a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
--- a/drivers/char/drm/i810_drm.h Sun Jul 13 20:39:54 2003
+++ b/drivers/char/drm/i810_drm.h Sun Jul 13 20:39:54 2003
@@ -166,6 +166,9 @@
int vertex_prim;
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active;
+ int pf_current_page; /* which buffer is being displayed? */
} drm_i810_sarea_t;
/* WARNING: If you change any of these defines, make sure to change the
@@ -189,6 +192,7 @@
#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b)
#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t)
#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d )
+#define DRM_IOCTL_I810_FLIP DRM_IO ( 0x4e )
typedef struct _drm_i810_clear {
int clear_color;
diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
--- a/drivers/char/drm/i810_drv.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/i810_drv.h Sun Jul 13 20:39:56 2003
@@ -75,7 +75,20 @@
int overlay_physical;
int w, h;
int pitch;
+ int back_pitch;
+ int depth_pitch;
+ int do_boxes;
+ int dma_used;
+
+ int current_page;
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+ atomic_t irq_received;
+ atomic_t irq_emitted;
+
+ int front_offset;
} drm_i810_private_t;
/* i810_dma.c */
@@ -124,6 +137,8 @@
int i810_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+int i810_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
#define I810_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
@@ -225,12 +240,15 @@
#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23))
#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23))
#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23))
+#define CMD_OP_WAIT_FOR_EVENT ((0x0<<29)|(0x03<<23))
#define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000
#define BR00_OP_SRC_COPY_BLT 0x10C00000
#define BR13_SOLID_PATTERN 0x80000000
-
+#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define WAIT_FOR_PLANE_A_FLIP (1<<2)
+#define WAIT_FOR_VBLANK (1<<3)
#endif
diff -Nru a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
--- a/drivers/char/drm/r128.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/r128.h Sun Jul 13 20:39:55 2003
@@ -47,13 +47,17 @@
#define DRIVER_NAME "r128"
#define DRIVER_DESC "ATI Rage 128"
-#define DRIVER_DATE "20021029"
+#define DRIVER_DATE "20030526"
#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 3
+#define DRIVER_MINOR 4
#define DRIVER_PATCHLEVEL 0
-
+/* Interface history:
+ *
+ * ?? - ??
+ * 2.4 - Add support for ycbcr textures (no new ioctls)
+ */
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/r128_drv.h Sun Jul 13 20:39:56 2003
@@ -343,13 +343,20 @@
#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
#define R128_CCE_VC_CNTL_NUM_SHIFT 16
+#define R128_DATATYPE_VQ 0
+#define R128_DATATYPE_CI4 1
#define R128_DATATYPE_CI8 2
#define R128_DATATYPE_ARGB1555 3
#define R128_DATATYPE_RGB565 4
#define R128_DATATYPE_RGB888 5
#define R128_DATATYPE_ARGB8888 6
#define R128_DATATYPE_RGB332 7
+#define R128_DATATYPE_Y8 8
#define R128_DATATYPE_RGB8 9
+#define R128_DATATYPE_CI16 10
+#define R128_DATATYPE_YVYU422 11
+#define R128_DATATYPE_VYUY422 12
+#define R128_DATATYPE_AYUV444 14
#define R128_DATATYPE_ARGB4444 15
/* Constants */
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/r128_state.c Sun Jul 13 20:39:55 2003
@@ -802,6 +802,8 @@
case R128_DATATYPE_ARGB1555:
case R128_DATATYPE_RGB565:
case R128_DATATYPE_ARGB4444:
+ case R128_DATATYPE_YVYU422:
+ case R128_DATATYPE_VYUY422:
dword_shift = 1;
break;
case R128_DATATYPE_CI8:
diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
--- a/drivers/char/drm/radeon.h Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/radeon.h Sun Jul 13 20:39:56 2003
@@ -51,7 +51,7 @@
#define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 8
+#define DRIVER_MINOR 9
#define DRIVER_PATCHLEVEL 0
/* Interface history:
diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
--- a/drivers/char/drm/radeon_drm.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/radeon_drm.h Sun Jul 13 20:39:55 2003
@@ -141,7 +141,10 @@
#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
#define R200_EMIT_PP_CUBIC_FACES_5 71
#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
-#define RADEON_MAX_STATE_PACKETS 73
+#define RADEON_EMIT_PP_TEX_SIZE_0 73
+#define RADEON_EMIT_PP_TEX_SIZE_1 74
+#define RADEON_EMIT_PP_TEX_SIZE_2 75
+#define RADEON_MAX_STATE_PACKETS 76
/* Commands understood by cmd_buffer ioctl. More can be added but
diff -Nru a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
--- a/drivers/char/drm/radeon_drv.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/radeon_drv.c Sun Jul 13 20:39:56 2003
@@ -1,6 +1,11 @@
-/* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
- * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
+/**
+ * \file radeon_drv.c
+ * ATI Radeon driver
*
+ * \author Gareth Hughes
+ */
+
+/*
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
@@ -22,10 +27,8 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Gareth Hughes
*/
+
#include
#include "radeon.h"
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h Sun Jul 13 20:39:55 2003
+++ b/drivers/char/drm/radeon_drv.h Sun Jul 13 20:39:55 2003
@@ -669,6 +669,10 @@
#define R200_RE_POINTSIZE 0x2648
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
+#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
+#define RADEON_PP_TEX_SIZE_1 0x1d0c
+#define RADEON_PP_TEX_SIZE_2 0x1d14
+
#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001
#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/drm/radeon_state.c Sun Jul 13 20:39:56 2003
@@ -292,6 +292,9 @@
{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+ { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
+ { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
+ { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" },
};
@@ -885,15 +888,14 @@
static void radeon_cp_dispatch_vertex( drm_device_t *dev,
drm_buf_t *buf,
- drm_radeon_tcl_prim_t *prim,
- drm_clip_rect_t *boxes,
- int nbox )
+ drm_radeon_tcl_prim_t *prim )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t box;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
int numverts = (int)prim->numverts;
+ int nbox = sarea_priv->nbox;
int i = 0;
RING_LOCALS;
@@ -913,10 +915,8 @@
do {
/* Emit the next cliprect */
if ( i < nbox ) {
- if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
- return;
-
- radeon_emit_clip_rect( dev_priv, &box );
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
}
/* Emit the vertex buffer rendering commands */
@@ -995,18 +995,17 @@
static void radeon_cp_dispatch_indices( drm_device_t *dev,
drm_buf_t *elt_buf,
- drm_radeon_tcl_prim_t *prim,
- drm_clip_rect_t *boxes,
- int nbox )
+ drm_radeon_tcl_prim_t *prim )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t box;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int offset = dev_priv->agp_buffers_offset + prim->offset;
u32 *data;
int dwords;
int i = 0;
int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
int count = (prim->finish - start) / sizeof(u16);
+ int nbox = sarea_priv->nbox;
DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
prim->prim,
@@ -1045,12 +1044,9 @@
(count << RADEON_NUM_VERTICES_SHIFT) );
do {
- if ( i < nbox ) {
- if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
- return;
-
- radeon_emit_clip_rect( dev_priv, &box );
- }
+ if ( i < nbox )
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
radeon_cp_dispatch_indirect( dev, elt_buf,
prim->start,
@@ -1450,9 +1446,7 @@
prim.numverts = vertex.count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
- radeon_cp_dispatch_vertex( dev, buf, &prim,
- dev_priv->sarea_priv->boxes,
- dev_priv->sarea_priv->nbox );
+ radeon_cp_dispatch_vertex( dev, buf, &prim );
}
if (vertex.discard) {
@@ -1550,9 +1544,7 @@
prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
prim.vc_format = dev_priv->sarea_priv->vc_format;
- radeon_cp_dispatch_indices( dev, buf, &prim,
- dev_priv->sarea_priv->boxes,
- dev_priv->sarea_priv->nbox );
+ radeon_cp_dispatch_indices( dev, buf, &prim );
if (elts.discard) {
radeon_cp_discard_buffer( dev, buf );
}
@@ -1769,16 +1761,12 @@
tclprim.offset = prim.numverts * 64;
tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
- radeon_cp_dispatch_indices( dev, buf, &tclprim,
- sarea_priv->boxes,
- sarea_priv->nbox);
+ radeon_cp_dispatch_indices( dev, buf, &tclprim );
} else {
tclprim.numverts = prim.numverts;
tclprim.offset = 0; /* not used */
- radeon_cp_dispatch_vertex( dev, buf, &tclprim,
- sarea_priv->boxes,
- sarea_priv->nbox);
+ radeon_cp_dispatch_vertex( dev, buf, &tclprim );
}
if (sarea_priv->nbox == 1)
diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c
--- a/drivers/char/dtlk.c Sun Jul 13 20:39:55 2003
+++ b/drivers/char/dtlk.c Sun Jul 13 20:39:55 2003
@@ -55,7 +55,7 @@
#include
#include /* for verify_area */
#include /* for -EBUSY */
-#include /* for check_region, request_region */
+#include /* for request_region */
#include /* for loops_per_jiffy */
#include /* for inb_p, outb_p, inb, outb, etc. */
#include /* for get_user, etc. */
diff -Nru a/drivers/char/genrtc.c b/drivers/char/genrtc.c
--- a/drivers/char/genrtc.c Sun Jul 13 20:39:56 2003
+++ b/drivers/char/genrtc.c Sun Jul 13 20:39:56 2003
@@ -355,8 +355,6 @@
if (gen_rtc_status & RTC_IS_OPEN)
return -EBUSY;
- MOD_INC_USE_COUNT;
-
gen_rtc_status |= RTC_IS_OPEN;
gen_rtc_irq_data = 0;
irq_active = 0;
@@ -374,8 +372,6 @@
gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
gen_rtc_status &= ~RTC_IS_OPEN;
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig Sun Jul 13 20:39:55 2003
+++ b/drivers/eisa/Kconfig Sun Jul 13 20:39:55 2003
@@ -14,7 +14,7 @@
config EISA_PCI_EISA
bool "Generic PCI/EISA bridge"
- depends on PCI && EISA
+ depends on !PARISC && PCI && EISA
default y
---help---
Activate this option if your system contains a PCI to EISA
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c Sun Jul 13 20:39:55 2003
+++ b/drivers/ide/ide-cd.c Sun Jul 13 20:39:55 2003
@@ -749,12 +749,17 @@
by transferring the semaphore from the packet
command request to the request sense request. */
+ rq->flags |= REQ_FAILED;
if ((stat & ERR_STAT) != 0) {
wait = rq->waiting;
rq->waiting = NULL;
+ if ((rq->flags & REQ_BLOCK_PC) != 0) {
+ cdrom_queue_request_sense(drive, wait,
+ rq->sense, rq);
+ return 1; /* REQ_BLOCK_PC self-cares */
+ }
}
- rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 0);
if ((stat & ERR_STAT) != 0)
@@ -1657,13 +1662,14 @@
dma = info->dma;
if (dma) {
info->dma = 0;
- if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
- printk("ide-cd: dma error\n");
- HWIF(drive)->ide_dma_off(drive);
- }
+ dma_error = HWIF(drive)->ide_dma_end(drive);
}
if (cdrom_decode_status(drive, 0, &stat)) {
+ if ((stat & ERR_STAT) != 0) {
+ end_that_request_chunk(rq, 0, rq->data_len);
+ goto end_request; /* purge the whole thing... */
+ }
end_that_request_chunk(rq, 1, rq->data_len);
return ide_stopped;
}
@@ -1672,8 +1678,11 @@
* using dma, transfer is complete now
*/
if (dma) {
- if (dma_error)
+ if (dma_error) {
+ printk("ide-cd: dma error\n");
+ HWIF(drive)->ide_dma_off(drive);
return DRIVER(drive)->error(drive, "dma error", stat);
+ }
end_that_request_chunk(rq, 1, rq->data_len);
rq->data_len = 0;
diff -Nru a/drivers/input/misc/gsc_ps2.c b/drivers/input/misc/gsc_ps2.c
--- a/drivers/input/misc/gsc_ps2.c Sun Jul 13 20:39:55 2003
+++ b/drivers/input/misc/gsc_ps2.c Sun Jul 13 20:39:55 2003
@@ -56,12 +56,13 @@
#include /* for request_irq/free_irq */
#include
#include
-#include
#include
#include
+#include
#include
#include
+#include
/* Debugging stuff */
#undef KBD_DEBUG
@@ -79,6 +80,7 @@
/* PS/2 keyboard and mouse constants */
#define AUX_RECONNECT 0xAA /* PS/2 Mouse end of test successful */
#define AUX_REPLY_ACK 0xFA
+#define AUX_ENABLE_DEV 0xF4 /* Enables aux device */
/* Order of the mouse bytes coming to the host */
#define PACKET_X 1
@@ -131,6 +133,12 @@
#define MOUSE_XOVFLOW 0x40
#define MOUSE_YOVFLOW 0x80
+/* Remnant of pc_keyb.h */
+#define KBD_CMD_SET_LEDS 0xED /* Sets keyboard leds */
+#define KBD_CMD_SET_RATE 0xF3 /* Sets typematic rate */
+#define KBD_CMD_ENABLE 0xF4 /* Enables scanning */
+#define KBD_CMD_DISABLE 0xF5
+#define KBD_CMD_RESET 0xFF
static unsigned char hpkeyb_keycode[KBD_TBLSIZE] =
{
@@ -341,7 +349,7 @@
default:
hpkeyb.scancode = scancode;
DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released);
- input_regs(regs);
+ /*input_regs(regs);*/
input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released);
input_sync(&hpkeyb.dev);
if (hpkeyb.escaped)
@@ -388,7 +396,7 @@
if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW)))
DPRINTK("Mouse: position overflow\n");
- input_regs(regs);
+ /*input_regs(regs);*/
input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN);
input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN);
@@ -420,7 +428,7 @@
* key value to the system.
*/
-static void gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
{
/* process mouse actions */
while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE)
@@ -429,6 +437,8 @@
/* process keyboard scancode */
while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE)
gscps2_kbd_docode(reg);
+
+ return IRQ_HANDLED;
}
@@ -525,7 +535,7 @@
/* TODO These need some adjustement, are they really useful ? */
hpkeyb.dev.id.bustype = BUS_GSC;
- hpkeyb.dev.id.vendor = 0x0001;
+ hpkeyb.dev.id.vendor = PCI_VENDOR_ID_HP;
hpkeyb.dev.id.product = 0x0001;
hpkeyb.dev.id.version = 0x0010;
hpkeyb.initialized = 1;
@@ -580,7 +590,7 @@
{
u8 id;
char *addr, *name;
- int ret, device_found = 0;
+ int ret = 0, device_found = 0;
unsigned long hpa = dev->hpa;
if (!dev->irq)
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c Sun Jul 13 20:39:55 2003
+++ b/drivers/isdn/hisax/isurf.c Sun Jul 13 20:39:55 2003
@@ -237,7 +237,7 @@
struct pnp_card *pb;
struct pnp_dev *pd;
- cs->subtyp = 0;
+ card->cs->subtyp = 0;
if ((pb = pnp_find_card(
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pnp_surf))) {
diff -Nru a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
--- a/drivers/net/appletalk/cops.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/appletalk/cops.c Sun Jul 13 20:39:55 2003
@@ -424,7 +424,7 @@
init_timer(&cops_timer);
cops_timer.function = cops_poll;
cops_timer.data = (unsigned long)dev;
- cops_timer.expires = jiffies + 5;
+ cops_timer.expires = jiffies + HZ/20;
add_timer(&cops_timer);
}
else
@@ -700,7 +700,8 @@
status = inb(ioaddr+TANG_CARD_STATUS);
} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
- cops_timer.expires = jiffies+5;
+ /* poll 20 times per second */
+ cops_timer.expires = jiffies + HZ/20;
add_timer(&cops_timer);
return;
diff -Nru a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
--- a/drivers/net/appletalk/ltpc.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/appletalk/ltpc.c Sun Jul 13 20:39:55 2003
@@ -926,8 +926,9 @@
if (!dev)
return; /* we've been downed */
+ /* poll 20 times per second */
idle(dev);
- ltpc_timer.expires = jiffies+5;
+ ltpc_timer.expires = jiffies + HZ/20;
add_timer(<pc_timer);
}
@@ -1217,7 +1218,7 @@
ltpc_timer.function=ltpc_poll;
ltpc_timer.data = (unsigned long) dev;
- ltpc_timer.expires = jiffies + 5;
+ ltpc_timer.expires = jiffies + HZ/20;
add_timer(<pc_timer);
}
diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c
--- a/drivers/net/declance.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/declance.c Sun Jul 13 20:39:55 2003
@@ -992,7 +992,7 @@
return;
if (lp->tx_old != lp->tx_new) {
- mod_timer(&lp->multicast_timer, jiffies + 4);
+ mod_timer(&lp->multicast_timer, jiffies + 4 * HZ/100);
netif_wake_queue(dev);
return;
}
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c Sun Jul 13 20:39:54 2003
+++ b/drivers/net/dgrs.c Sun Jul 13 20:39:54 2003
@@ -1252,18 +1252,12 @@
{
DGRS_PRIV *priv;
struct net_device *dev, *aux;
-
- /* Allocate and fill new device structure. */
- int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV);
int i, ret;
- dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
-
+ dev = alloc_etherdev(sizeof(DGRS_PRIV));
if (!dev)
return -ENOMEM;
- memset(dev, 0, dev_size);
- dev->priv = ((void *)dev) + sizeof(struct net_device);
priv = (DGRS_PRIV *)dev->priv;
dev->base_addr = io;
@@ -1279,7 +1273,7 @@
dev->init = dgrs_probe1;
SET_MODULE_OWNER(dev);
- ether_setup(dev);
+
if (register_netdev(dev) != 0) {
kfree(dev);
return -EIO;
@@ -1302,15 +1296,18 @@
struct net_device *devN;
DGRS_PRIV *privN;
/* Allocate new dev and priv structures */
- devN = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
- /* Make it an exact copy of dev[0]... */
+ devN = alloc_etherdev(sizeof(DGRS_PRIV));
ret = -ENOMEM;
if (!devN)
goto fail;
- memcpy(devN, dev, dev_size);
- memset(devN->name, 0, sizeof(devN->name));
- devN->priv = ((void *)devN) + sizeof(struct net_device);
+
+ /* Make it an exact copy of dev[0]... */
+ *devN = *dev;
+
+ /* copy the priv structure of dev[0] */
privN = (DGRS_PRIV *)devN->priv;
+ *privN = *priv;
+
/* ... and zero out VM areas */
privN->vmem = 0;
privN->vplxdma = 0;
@@ -1318,9 +1315,11 @@
devN->irq = 0;
/* ... and base MAC address off address of 1st port */
devN->dev_addr[5] += i;
+ /* ... choose a new name */
+ strncpy(devN->name, "eth%d", IFNAMSIZ);
devN->init = dgrs_initclone;
SET_MODULE_OWNER(devN);
- ether_setup(devN);
+
ret = -EIO;
if (register_netdev(devN)) {
kfree(devN);
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/e100/e100_main.c Sun Jul 13 20:39:55 2003
@@ -46,6 +46,13 @@
/* Change Log
*
+ * 2.3.18 07/08/03
+ * o Bug fix: read skb->len after freeing skb
+ * [Andrew Morton] akpm@zip.com.au
+ * o Bug fix: 82557 (with National PHY) timeout during init
+ * [Adam Kropelin] akropel1@rochester.rr.com
+ * o Feature add: allow to change Wake On LAN when EEPROM disabled
+ *
* 2.3.13 05/08/03
* o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely
* o Feature remove: IDIAG support (use ethtool -t instead)
@@ -65,20 +72,6 @@
* o Bug fix: statistic command failure would stop statistic collection.
*
* 2.2.21 02/11/03
- * o Removed marketing brand strings. Instead, Using generic string
- * "Intel(R) PRO/100 Network Connection" for all adapters.
- * o Implemented ethtool -S option
- * o Strip /proc/net/PRO_LAN_Adapters files for kernel driver
- * o Bug fix: Read wrong byte in EEPROM when offset is odd number
- * o Bug fix: PHY loopback test fails on ICH devices
- * o Bug fix: System panic on e100_close when repeating Hot Remove and
- * Add in a team
- * o Bug fix: Linux Bonding driver claims adapter's link loss because of
- * not updating last_rx field
- * o Bug fix: e100 does not check validity of MAC address
- * o New feature: added ICH5 support
- *
- * 2.1.27 11/20/02
*/
#include
@@ -144,7 +137,7 @@
static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
/* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.3.13-k1";
+char e100_driver_version[]="2.3.18-k1";
const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
char e100_short_driver_name[] = "e100";
static int e100nics = 0;
@@ -689,17 +682,16 @@
bdp->wolsupported = 0;
bdp->wolopts = 0;
+ if (bdp->rev_id >= D101A4_REV_ID)
+ bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
+ if (bdp->rev_id >= D101MA_REV_ID)
+ bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
/* Check if WoL is enabled on EEPROM */
if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) {
/* Magic Packet WoL is enabled on device by default */
/* if EEPROM WoL bit is TRUE */
- bdp->wolsupported = WAKE_MAGIC;
bdp->wolopts = WAKE_MAGIC;
- if (bdp->rev_id >= D101A4_REV_ID)
- bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
- if (bdp->rev_id >= D101MA_REV_ID)
- bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
}
printk(KERN_NOTICE "\n");
diff -Nru a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c
--- a/drivers/net/e100/e100_phy.c Sun Jul 13 20:39:54 2003
+++ b/drivers/net/e100/e100_phy.c Sun Jul 13 20:39:54 2003
@@ -919,6 +919,7 @@
unsigned char __devinit
e100_phy_init(struct e100_private *bdp)
{
+ e100_phy_reset(bdp);
e100_phy_address_detect(bdp);
e100_phy_isolate(bdp);
e100_phy_id_detect(bdp);
@@ -930,7 +931,6 @@
bdp->PhyDelay = 0;
bdp->zlock_state = ZLOCK_INITIAL;
- e100_phy_reset(bdp);
e100_phy_set_speed_duplex(bdp, false);
e100_fix_polarity(bdp);
diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/hamradio/mkiss.c Sun Jul 13 20:39:56 2003
@@ -22,6 +22,8 @@
* Matthias (DG2FEF) Added support for FlexNet CRC (on special request)
* Fixed bug in ax25_close(): dev_lock_wait() was
* called twice, causing a deadlock.
+ * Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
+ * MOD_*_USE_COUNT
*/
#include
@@ -55,15 +57,6 @@
static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
-#define NR_MKISS 4
-#define MKISS_SERIAL_TYPE_NORMAL 1
-
-struct mkiss_channel {
- int magic; /* magic word */
- int init; /* channel exists? */
- struct tty_struct *tty; /* link to tty control structure */
-};
-
typedef struct ax25_ctrl {
struct ax_disp ctrl; /* */
struct net_device dev; /* the device */
@@ -310,19 +303,11 @@
/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
static void ax_bump(struct ax_disp *ax)
{
- struct ax_disp *tmp_ax;
struct sk_buff *skb;
- struct mkiss_channel *mkiss;
int count;
- tmp_ax = ax;
-
if (ax->rbuff[0] > 0x0f) {
- if (ax->mkiss != NULL) {
- mkiss= ax->mkiss->tty->driver_data;
- if (mkiss->magic == MKISS_DRIVER_MAGIC)
- tmp_ax = ax->mkiss;
- } else if (ax->rbuff[0] & 0x20) {
+ if (ax->rbuff[0] & 0x20) {
ax->crcmode = CRC_MODE_FLEX;
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
ax->rx_errors++;
@@ -346,14 +331,14 @@
return;
}
- skb->dev = tmp_ax->dev;
+ skb->dev = ax->dev;
memcpy(skb_put(skb,count), ax->rbuff, count);
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_AX25);
netif_rx(skb);
- tmp_ax->dev->last_rx = jiffies;
- tmp_ax->rx_packets++;
- tmp_ax->rx_bytes+=count;
+ ax->dev->last_rx = jiffies;
+ ax->rx_packets++;
+ ax->rx_bytes+=count;
}
/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
@@ -361,7 +346,6 @@
{
unsigned char *p;
int actual, count;
- struct mkiss_channel *mkiss = ax->tty->driver_data;
if (ax->mtu != ax->dev->mtu + 73) /* Someone has been ifconfigging */
ax_changedmtu(ax);
@@ -376,37 +360,26 @@
p = icp;
- if (mkiss->magic != MKISS_DRIVER_MAGIC) {
- switch (ax->crcmode) {
- unsigned short crc;
-
- case CRC_MODE_FLEX:
- *p |= 0x20;
- crc = calc_crc_flex(p, len);
- count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
- break;
-
- default:
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- break;
- }
- ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
- actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count);
- ax->tx_packets++;
- ax->tx_bytes+=actual;
- ax->dev->trans_start = jiffies;
- ax->xleft = count - actual;
- ax->xhead = ax->xbuff + actual;
- } else {
- count = kiss_esc(p, (unsigned char *) ax->mkiss->xbuff, len);
- ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
- actual = ax->mkiss->tty->driver->write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);
- ax->tx_packets++;
- ax->tx_bytes+=actual;
- ax->mkiss->dev->trans_start = jiffies;
- ax->mkiss->xleft = count - actual;
- ax->mkiss->xhead = ax->mkiss->xbuff + actual;
- }
+ switch (ax->crcmode) {
+ unsigned short crc;
+
+ case CRC_MODE_FLEX:
+ *p |= 0x20;
+ crc = calc_crc_flex(p, len);
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
+
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ break;
+ }
+ ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count);
+ ax->tx_packets++;
+ ax->tx_bytes+=actual;
+ ax->dev->trans_start = jiffies;
+ ax->xleft = count - actual;
+ ax->xhead = ax->xbuff + actual;
}
/*
@@ -417,7 +390,6 @@
{
int actual;
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
- struct mkiss_channel *mkiss;
/* First make sure we're connected. */
if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
@@ -428,12 +400,6 @@
*/
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- if (ax->mkiss != NULL) {
- mkiss= ax->mkiss->tty->driver_data;
- if (mkiss->magic == MKISS_DRIVER_MAGIC)
- ax_unlock(ax->mkiss);
- }
-
netif_wake_queue(ax->dev);
return;
}
@@ -447,32 +413,12 @@
static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ax_disp *ax = (struct ax_disp *) dev->priv;
- struct mkiss_channel *mkiss = ax->tty->driver_data;
- struct ax_disp *tmp_ax;
-
- tmp_ax = NULL;
-
- if (mkiss->magic == MKISS_DRIVER_MAGIC) {
- if (skb->data[0] < 0x10)
- skb->data[0] = skb->data[0] + 0x10;
- tmp_ax = ax->mkiss;
- }
if (!netif_running(dev)) {
printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
return 1;
}
- if (tmp_ax != NULL)
- if (netif_queue_stopped(tmp_ax->dev))
- return 1;
-
- if (tmp_ax != NULL)
- if (netif_queue_stopped(dev)) {
- printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");
- ax_unlock(ax);
- }
-
if (netif_queue_stopped(dev)) {
/*
* May be we must check transmitter timeout here ?
@@ -495,8 +441,6 @@
/* We were not busy, so we are now... :-) */
if (skb != NULL) {
ax_lock(ax);
- if (tmp_ax != NULL)
- ax_lock(tmp_ax);
ax_encaps(ax, skb->data, skb->len);
kfree_skb(skb);
}
@@ -634,9 +578,7 @@
static int ax25_open(struct tty_struct *tty)
{
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
- struct ax_disp *tmp_ax;
- struct mkiss_channel *mkiss;
- int err, cnt;
+ int err;
/* First make sure we're not already connected. */
if (ax && ax->magic == AX25_MAGIC)
@@ -649,9 +591,6 @@
ax->tty = tty;
tty->disc_data = ax;
- ax->mkiss = NULL;
- tmp_ax = NULL;
-
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
if (tty->ldisc.flush_buffer)
@@ -664,29 +603,6 @@
if ((err = ax_open(ax->dev)))
return err;
- mkiss = ax->tty->driver_data;
-
- if (mkiss->magic == MKISS_DRIVER_MAGIC) {
- for (cnt = 1; cnt < ax25_maxdev; cnt++) {
- if (ax25_ctrls[cnt]) {
- if (netif_running(&ax25_ctrls[cnt]->dev)) {
- if (ax == &ax25_ctrls[cnt]->ctrl) {
- cnt--;
- tmp_ax = &ax25_ctrls[cnt]->ctrl;
- break;
- }
- }
- }
- }
- }
-
- if (tmp_ax != NULL) {
- ax->mkiss = tmp_ax;
- tmp_ax->mkiss = ax;
- }
-
- MOD_INC_USE_COUNT;
-
/* Done. We have linked the TTY line to a channel. */
return ax->dev->base_addr;
}
@@ -705,7 +621,6 @@
ax->tty = NULL;
ax_free(ax);
- MOD_DEC_USE_COUNT;
}
diff -Nru a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
--- a/drivers/net/hamradio/mkiss.h Sun Jul 13 20:39:54 2003
+++ b/drivers/net/hamradio/mkiss.h Sun Jul 13 20:39:54 2003
@@ -19,7 +19,6 @@
/* Various fields. */
struct tty_struct *tty; /* ptr to TTY structure */
struct net_device *dev; /* easy for intr handling */
- struct ax_disp *mkiss; /* mkiss txport if mkiss channel*/
/* These are pointers to the malloc()ed frame buffers. */
unsigned char *rbuff; /* receiver buffer */
@@ -60,4 +59,3 @@
};
#define AX25_MAGIC 0x5316
-#define MKISS_DRIVER_MAGIC 1215
diff -Nru a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
--- a/drivers/net/irda/Kconfig Sun Jul 13 20:39:56 2003
+++ b/drivers/net/irda/Kconfig Sun Jul 13 20:39:56 2003
@@ -22,6 +22,7 @@
config DONGLE
bool "Serial dongle support"
+ depends on IRTTY_SIR
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
@@ -69,7 +70,7 @@
config IRTTY_OLD
tristate "Old IrTTY (broken)"
- depends on IRDA
+ depends on IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the IrTTY line
discipline. If you want to compile it as a module (irtty), say M
@@ -102,6 +103,7 @@
config DONGLE_OLD
bool "Old Serial dongle support"
+ depends on IRTTY_OLD || IRPORT_SIR
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
@@ -226,8 +228,8 @@
comment "FIR device drivers"
config USB_IRDA
- tristate "IrDA USB dongles (EXPERIMENTAL)"
- depends on IRDA && USB && EXPERIMENTAL
+ tristate "IrDA USB dongles"
+ depends on IRDA && USB
---help---
Say Y here if you want to build support for the USB IrDA FIR Dongle
device driver. If you want to compile it as a module (irda-usb),
@@ -243,7 +245,7 @@
config NSC_FIR
tristate "NSC PC87108/PC87338"
- depends on IRDA
+ depends on IRDA && ISA
help
Say Y here if you want to build support for the NSC PC87108 and
PC87338 IrDA chipsets. This driver supports SIR,
@@ -255,7 +257,7 @@
config WINBOND_FIR
tristate "Winbond W83977AF (IR)"
- depends on IRDA
+ depends on IRDA && ISA
help
Say Y here if you want to build IrDA support for the Winbond
W83977AF super-io chipset. This driver should be used for the IrDA
@@ -295,7 +297,7 @@
config SMC_IRCC_OLD
tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
- depends on EXPERIMENTAL && IRDA
+ depends on EXPERIMENTAL && IRDA && ISA
help
Say Y here if you want to build support for the SMC Infrared
Communications Controller. It is used in the Fujitsu Lifebook 635t
@@ -307,7 +309,7 @@
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
- depends on EXPERIMENTAL && IRDA
+ depends on EXPERIMENTAL && IRDA && ISA
help
Say Y here if you want to build support for the SMC Infrared
Communications Controller. It is used in a wide variety of
@@ -318,7 +320,7 @@
config ALI_FIR
tristate "ALi M5123 FIR (EXPERIMENTAL)"
- depends on EXPERIMENTAL && IRDA
+ depends on EXPERIMENTAL && IRDA && ISA
help
Say Y here if you want to build support for the ALi M5123 FIR
Controller. The ALi M5123 FIR Controller is embedded in ALi M1543C,
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/irda/irda-usb.c Sun Jul 13 20:39:55 2003
@@ -74,8 +74,10 @@
/* These are the currently known IrDA USB dongles. Add new dongles here */
static struct usb_device_id dongles[] = {
- /* ACTiSYS Corp, ACT-IR2000U FIR-USB Adapter */
+ /* ACTiSYS Corp., ACT-IR2000U FIR-USB Adapter */
{ USB_DEVICE(0x9c4, 0x011), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
+ /* Look like ACTiSYS, Report : IBM Corp., IBM UltraPort IrDA */
+ { USB_DEVICE(0x4428, 0x012), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW },
/* KC Technology Inc., KC-180 USB IrDA Device */
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
@@ -1123,7 +1125,10 @@
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
- self->qos.baud_rate.bits = desc->wBaudRate;
+ /* See spec section 7.2 for meaning.
+ * Values are little endian (as most USB stuff), the IrDA stack
+ * use it in native order (see parameters.c). - Jean II */
+ self->qos.baud_rate.bits = le16_to_cpu(desc->wBaudRate);
self->qos.min_turn_time.bits = desc->bmMinTurnaroundTime;
self->qos.additional_bofs.bits = desc->bmAdditionalBOFs;
self->qos.window_size.bits = desc->bmWindowSize;
@@ -1134,7 +1139,7 @@
/* Don't always trust what the dongle tell us */
if(self->capability & IUC_SIR_ONLY)
- self->qos.baud_rate.bits &= 0xff;
+ self->qos.baud_rate.bits &= 0x00ff;
if(self->capability & IUC_SMALL_PKT)
self->qos.data_size.bits = 0x07;
if(self->capability & IUC_NO_WINDOW)
@@ -1327,13 +1332,14 @@
*/
static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
{
+ /* Values are little endian */
printk("bLength=%x\n", desc->bLength);
printk("bDescriptorType=%x\n", desc->bDescriptorType);
- printk("bcdSpecRevision=%x\n", desc->bcdSpecRevision);
+ printk("bcdSpecRevision=%x\n", le16_to_cpu(desc->bcdSpecRevision));
printk("bmDataSize=%x\n", desc->bmDataSize);
printk("bmWindowSize=%x\n", desc->bmWindowSize);
printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime);
- printk("wBaudRate=%x\n", desc->wBaudRate);
+ printk("wBaudRate=%x\n", le16_to_cpu(desc->wBaudRate));
printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs);
printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff);
printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList);
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c Sun Jul 13 20:39:54 2003
+++ b/drivers/net/irda/nsc-ircc.c Sun Jul 13 20:39:54 2003
@@ -81,8 +81,10 @@
static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
/* These are the known NSC chips */
static nsc_chip_t chips[] = {
@@ -94,6 +96,10 @@
/* Contributed by Kevin Thayer - OmniBook 6100 */
{ "PC87338?", { 0x2e, 0x15c, 0x398 }, 0x08, 0x00, 0xf8,
nsc_ircc_probe_338, nsc_ircc_init_338 },
+ /* Contributed by Jan Frey - IBM A30/A31 */
+ /* Should use nsc_ircc_probe_39x properly */
+ { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ NULL }
};
@@ -426,7 +432,7 @@
outb(0x00, cfg_base+1); /* Disable device */
/* Base Address and Interrupt Control Register (BAIC) */
- outb(0, cfg_base);
+ outb(CFG_108_BAIC, cfg_base);
switch (info->fir_base) {
case 0x3e8: outb(0x14, cfg_base+1); break;
case 0x2e8: outb(0x15, cfg_base+1); break;
@@ -446,7 +452,7 @@
case 15: temp = 0x07; break;
default: ERROR("%s(), invalid irq", __FUNCTION__);
}
- outb(1, cfg_base);
+ outb(CFG_108_CSRT, cfg_base);
switch (info->dma) {
case 0: outb(0x08+temp, cfg_base+1); break;
@@ -455,7 +461,7 @@
default: ERROR("%s(), invalid dma", __FUNCTION__);
}
- outb(2, cfg_base); /* Mode Control Register (MCTL) */
+ outb(CFG_108_MCTL, cfg_base); /* Mode Control Register (MCTL) */
outb(0x03, cfg_base+1); /* Enable device */
return 0;
@@ -473,7 +479,7 @@
int reg;
/* Read address and interrupt control register (BAIC) */
- outb(CFG_BAIC, cfg_base);
+ outb(CFG_108_BAIC, cfg_base);
reg = inb(cfg_base+1);
switch (reg & 0x03) {
@@ -495,7 +501,7 @@
info->fir_base);
/* Read control signals routing register (CSRT) */
- outb(CFG_CSRT, cfg_base);
+ outb(CFG_108_CSRT, cfg_base);
reg = inb(cfg_base+1);
switch (reg & 0x07) {
@@ -544,7 +550,7 @@
IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
/* Read mode control register (MCTL) */
- outb(CFG_MCTL, cfg_base);
+ outb(CFG_108_MCTL, cfg_base);
reg = inb(cfg_base+1);
info->enabled = reg & 0x01;
@@ -581,13 +587,194 @@
int pnp;
/* Read funtion enable register (FER) */
- outb(CFG_FER, cfg_base);
+ outb(CFG_338_FER, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->enabled = (reg >> 2) & 0x01;
+
+ /* Check if we are in Legacy or PnP mode */
+ outb(CFG_338_PNP0, cfg_base);
+ reg = inb(cfg_base+1);
+
+ pnp = (reg >> 3) & 0x01;
+ if (pnp) {
+ IRDA_DEBUG(2, "(), Chip is in PnP mode\n");
+ outb(0x46, cfg_base);
+ reg = (inb(cfg_base+1) & 0xfe) << 2;
+
+ outb(0x47, cfg_base);
+ reg |= ((inb(cfg_base+1) & 0xfc) << 8);
+
+ info->fir_base = reg;
+ } else {
+ /* Read function address register (FAR) */
+ outb(CFG_338_FAR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch ((reg >> 4) & 0x03) {
+ case 0:
+ info->fir_base = 0x3f8;
+ break;
+ case 1:
+ info->fir_base = 0x2f8;
+ break;
+ case 2:
+ com = 3;
+ break;
+ case 3:
+ com = 4;
+ break;
+ }
+
+ if (com) {
+ switch ((reg >> 6) & 0x03) {
+ case 0:
+ if (com == 3)
+ info->fir_base = 0x3e8;
+ else
+ info->fir_base = 0x2e8;
+ break;
+ case 1:
+ if (com == 3)
+ info->fir_base = 0x338;
+ else
+ info->fir_base = 0x238;
+ break;
+ case 2:
+ if (com == 3)
+ info->fir_base = 0x2e8;
+ else
+ info->fir_base = 0x2e0;
+ break;
+ case 3:
+ if (com == 3)
+ info->fir_base = 0x220;
+ else
+ info->fir_base = 0x228;
+ break;
+ }
+ }
+ }
+ info->sir_base = info->fir_base;
+
+ /* Read PnP register 1 (PNP1) */
+ outb(CFG_338_PNP1, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->irq = reg >> 4;
+
+ /* Read PnP register 3 (PNP3) */
+ outb(CFG_338_PNP3, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->dma = (reg & 0x07) - 1;
+
+ /* Read power and test register (PTR) */
+ outb(CFG_338_PTR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->suspended = reg & 0x01;
+
+ return 0;
+}
+
+
+/*
+ * Function nsc_ircc_init_39x (chip, info)
+ *
+ * Now that we know it's a '39x (see probe below), we need to
+ * configure it so we can use it.
+ *
+ * The NSC '338 chip is a Super I/O chip with a "bank" architecture,
+ * the configuration of the different functionality (serial, parallel,
+ * floppy...) are each in a different bank (Logical Device Number).
+ * The base address, irq and dma configuration registers are common
+ * to all functionalities (index 0x30 to 0x7F).
+ * There is only one configuration register specific to the
+ * serial port, CFG_39X_SPC.
+ * JeanII
+ *
+ * Note : this code was written by Jan Frey
+ */
+static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info)
+{
+ int cfg_base = info->cfg_base;
+ int reg1, reg2, irq, irqt, dma1, dma2;
+ int enabled, susp;
+
+ /* This function should be executed with irq off to avoid
+ * another driver messing with the Super I/O bank - Jean II */
+
+ /* Access bank for SP2 */
+ outb(CFG_39X_LDN, cfg_base);
+ outb(0x02, cfg_base+1);
+
+ /* Read infos about SP2 */
+ outb(CFG_39X_BASEH, cfg_base);
+ reg1 = inb(cfg_base+1);
+ outb(CFG_39X_BASEL, cfg_base);
+ reg2 = inb(cfg_base+1);
+ info->fir_base = (reg1 << 8) | reg2;
+
+ outb(CFG_39X_IRQNUM, cfg_base);
+ irq = inb(cfg_base+1);
+ outb(CFG_39X_IRQSEL, cfg_base);
+ irqt = inb(cfg_base+1);
+ info->irq = irq;
+
+ outb(CFG_39X_DMA0, cfg_base);
+ dma1 = inb(cfg_base+1);
+ outb(CFG_39X_DMA1, cfg_base);
+ dma2 = inb(cfg_base+1);
+ info->dma = dma1 -1;
+
+ outb(CFG_39X_ACT, cfg_base);
+ enabled = inb(cfg_base+1) & 0x01;
+
+ outb(CFG_39X_SPC, cfg_base);
+ susp = 1 - ((inb(cfg_base+1) & 0x02) >> 1);
+
+ /* We should store those values in info ? Jean II */
+
+ IRDA_DEBUG(2, "%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", __FUNCTION__, reg1,reg2,irq,irqt,dma1,dma2,enabled,susp);
+
+ /* Configure SP2 */
+
+ /* Do we want to enable the device if not enabled ? */
+
+ /* Enable UART bank switching (bit 7) */
+ outb(CFG_39X_SPC, cfg_base);
+ outb(0x80, cfg_base+1);
+
+ return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_39x (chip, info)
+ *
+ * Test if we really have a '39x chip at the given address
+ *
+ */
+static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info)
+{
+#if 0
+ int cfg_base = info->cfg_base;
+ int reg, com = 0;
+ int pnp;
+#endif
+
+ /* Why are we using the '338 configuration registers in here ?
+ * This probably need to be rewritten...
+ * Jean II */
+#if 0
+ /* Read funtion enable register (FER) */
+ outb(CFG_338_FER, cfg_base);
reg = inb(cfg_base+1);
info->enabled = (reg >> 2) & 0x01;
/* Check if we are in Legacy or PnP mode */
- outb(CFG_PNP0, cfg_base);
+ outb(CFG_338_PNP0, cfg_base);
reg = inb(cfg_base+1);
pnp = (reg >> 3) & 0x01;
@@ -602,7 +789,7 @@
info->fir_base = reg;
} else {
/* Read function address register (FAR) */
- outb(CFG_FAR, cfg_base);
+ outb(CFG_338_FAR, cfg_base);
reg = inb(cfg_base+1);
switch ((reg >> 4) & 0x03) {
@@ -652,22 +839,23 @@
info->sir_base = info->fir_base;
/* Read PnP register 1 (PNP1) */
- outb(CFG_PNP1, cfg_base);
+ outb(CFG_338_PNP1, cfg_base);
reg = inb(cfg_base+1);
info->irq = reg >> 4;
/* Read PnP register 3 (PNP3) */
- outb(CFG_PNP3, cfg_base);
+ outb(CFG_338_PNP3, cfg_base);
reg = inb(cfg_base+1);
info->dma = (reg & 0x07) - 1;
/* Read power and test register (PTR) */
- outb(CFG_PTR, cfg_base);
+ outb(CFG_338_PTR, cfg_base);
reg = inb(cfg_base+1);
info->suspended = reg & 0x01;
+#endif
return 0;
}
diff -Nru a/drivers/net/irda/old_belkin.c b/drivers/net/irda/old_belkin.c
--- a/drivers/net/irda/old_belkin.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/irda/old_belkin.c Sun Jul 13 20:39:56 2003
@@ -32,8 +32,6 @@
#include
#include
#include
-#include
-#include
#include
#include
diff -Nru a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
--- a/drivers/net/pcmcia/3c574_cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/pcmcia/3c574_cs.c Sun Jul 13 20:39:55 2003
@@ -1048,7 +1048,7 @@
}
if (lp->fast_poll) {
lp->fast_poll--;
- lp->media.expires = jiffies + 2;
+ lp->media.expires = jiffies + 2*HZ/100;
add_timer(&lp->media);
return;
}
diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
--- a/drivers/net/pcmcia/3c589_cs.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/pcmcia/3c589_cs.c Sun Jul 13 20:39:56 2003
@@ -921,7 +921,7 @@
}
if (lp->fast_poll) {
lp->fast_poll--;
- lp->media.expires = jiffies + 1;
+ lp->media.expires = jiffies + HZ/100;
add_timer(&lp->media);
return;
}
diff -Nru a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
--- a/drivers/net/pcmcia/axnet_cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/pcmcia/axnet_cs.c Sun Jul 13 20:39:55 2003
@@ -258,7 +258,7 @@
if (*linkp == NULL)
return;
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
axnet_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
@@ -706,7 +706,7 @@
link->open--;
netif_stop_queue(dev);
- del_timer(&info->watchdog);
+ del_timer_sync(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
--- a/drivers/net/pcmcia/ibmtr_cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/pcmcia/ibmtr_cs.c Sun Jul 13 20:39:55 2003
@@ -293,9 +293,9 @@
dev = info->dev;
{
struct tok_info *ti = (struct tok_info *)dev->priv;
- del_timer(&(ti->tr_timer));
+ del_timer_sync(&(ti->tr_timer));
}
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
ibmtr_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
--- a/drivers/net/pcmcia/nmclan_cs.c Sun Jul 13 20:39:54 2003
+++ b/drivers/net/pcmcia/nmclan_cs.c Sun Jul 13 20:39:54 2003
@@ -8,6 +8,7 @@
Written by Roger C. Pao
Copyright 1995 Roger C. Pao
+ Linux 2.5 cleanups Copyright Red Hat 2003
This software may be used and distributed according to the terms of
the GNU General Public License.
@@ -68,6 +69,10 @@
History
-------------------------------------------------------------------------------
Log: nmclan_cs.c,v
+ * 2.5.75-ac1 2003/07/11 Alan Cox
+ * Fixed hang on card eject as we probe it
+ * Cleaned up to use new style locking.
+ *
* Revision 0.16 1995/07/01 06:42:17 rpao
* Bug fix: nmclan_reset() called CardServices incorrectly.
*
@@ -369,6 +374,8 @@
char tx_free_frames; /* Number of free transmit frame buffers */
char tx_irq_disabled; /* MACE TX interrupt disabled */
+
+ spinlock_t bank_lock; /* Must be held if you step off bank 0 */
} mace_private;
/* ----------------------------------------------------------------------------
@@ -482,6 +489,7 @@
link = &lp->link;
link->priv = dev;
+ spin_lock_init(&lp->bank_lock);
init_timer(&link->release);
link->release.function = &nmclan_release;
link->release.data = (u_long)link;
@@ -561,7 +569,7 @@
if (*linkp == NULL)
return;
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
nmclan_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
@@ -588,7 +596,7 @@
assuming that during normal operation, the MACE is always in
bank 0.
---------------------------------------------------------------------------- */
-static int mace_read(ioaddr_t ioaddr, int reg)
+static int mace_read(mace_private *lp, ioaddr_t ioaddr, int reg)
{
int data = 0xFF;
unsigned long flags;
@@ -598,12 +606,11 @@
data = inb(ioaddr + AM2150_MACE_BASE + reg);
break;
case 1: /* register 16-31 */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&lp->bank_lock, flags);
MACEBANK(1);
data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
MACEBANK(0);
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->bank_lock, flags);
break;
}
return (data & 0xFF);
@@ -616,7 +623,7 @@
are assuming that during normal operation, the MACE is always in
bank 0.
---------------------------------------------------------------------------- */
-static void mace_write(ioaddr_t ioaddr, int reg, int data)
+static void mace_write(mace_private *lp, ioaddr_t ioaddr, int reg, int data)
{
unsigned long flags;
@@ -625,12 +632,11 @@
outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg);
break;
case 1: /* register 16-31 */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&lp->bank_lock, flags);
MACEBANK(1);
outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
MACEBANK(0);
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->bank_lock, flags);
break;
}
} /* mace_write */
@@ -639,22 +645,29 @@
mace_init
Resets the MACE chip.
---------------------------------------------------------------------------- */
-static void mace_init(ioaddr_t ioaddr, char *enet_addr)
+static int mace_init(mace_private *lp, ioaddr_t ioaddr, char *enet_addr)
{
int i;
+ int ct = 0;
/* MACE Software reset */
- mace_write(ioaddr, MACE_BIUCC, 1);
- while (mace_read(ioaddr, MACE_BIUCC) & 0x01) {
+ mace_write(lp, ioaddr, MACE_BIUCC, 1);
+ while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) {
/* Wait for reset bit to be cleared automatically after <= 200ns */;
+ if(++ct > 500)
+ {
+ printk(KERN_ERR "mace: reset failed, card removed ?\n");
+ return -1;
+ }
+ udelay(1);
}
- mace_write(ioaddr, MACE_BIUCC, 0);
+ mace_write(lp, ioaddr, MACE_BIUCC, 0);
/* The Am2150 requires that the MACE FIFOs operate in burst mode. */
- mace_write(ioaddr, MACE_FIFOCC, 0x0F);
+ mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F);
- mace_write(ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */
- mace_write(ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */
+ mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */
+ mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */
/*
* Bit 2-1 PORTSEL[1-0] Port Select.
@@ -670,31 +683,39 @@
*/
switch (if_port) {
case 1:
- mace_write(ioaddr, MACE_PLSCC, 0x02);
+ mace_write(lp, ioaddr, MACE_PLSCC, 0x02);
break;
case 2:
- mace_write(ioaddr, MACE_PLSCC, 0x00);
+ mace_write(lp, ioaddr, MACE_PLSCC, 0x00);
break;
default:
- mace_write(ioaddr, MACE_PHYCC, /* ASEL */ 4);
+ mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4);
/* ASEL Auto Select. When set, the PORTSEL[1-0] bits are overridden,
and the MACE device will automatically select the operating media
interface port. */
break;
}
- mace_write(ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR);
+ mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR);
/* Poll ADDRCHG bit */
- while (mace_read(ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
- ;
+ ct = 0;
+ while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
+ {
+ if(++ ct > 500)
+ {
+ printk(KERN_ERR "mace: ADDRCHG timeout, card removed ?\n");
+ return -1;
+ }
+ }
/* Set PADR register */
for (i = 0; i < ETHER_ADDR_LEN; i++)
- mace_write(ioaddr, MACE_PADR, enet_addr[i]);
+ mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]);
/* MAC Configuration Control Register should be written last */
/* Let set_multicast_list set this. */
- /* mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */
- mace_write(ioaddr, MACE_MACCC, 0x00);
+ /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */
+ mace_write(lp, ioaddr, MACE_MACCC, 0x00);
+ return 0;
} /* mace_init */
/* ----------------------------------------------------------------------------
@@ -759,8 +780,8 @@
{
char sig[2];
- sig[0] = mace_read(ioaddr, MACE_CHIPIDL);
- sig[1] = mace_read(ioaddr, MACE_CHIPIDH);
+ sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL);
+ sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH);
if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) {
DEBUG(0, "nmclan_cs configured: mace id=%x %x\n",
sig[0], sig[1]);
@@ -772,7 +793,8 @@
}
}
- mace_init(ioaddr, dev->dev_addr);
+ if(mace_init(lp, ioaddr, dev->dev_addr) == -1)
+ goto failed;
/* The if_port symbol can be set when the module is loaded */
if (if_port <= 2)
@@ -923,8 +945,8 @@
lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
/* Reinitialize the MACE chip for operation. */
- mace_init(dev->base_addr, dev->dev_addr);
- mace_write(dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);
+ mace_init(lp, dev->base_addr, dev->dev_addr);
+ mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);
/* Restore the multicast list and enable TX and RX. */
restore_multicast_list(dev);
@@ -1456,9 +1478,9 @@
{
mace_private *lp = (mace_private *)dev->priv;
- lp->mace_stats.rcvcc += mace_read(ioaddr, MACE_RCVCC);
- lp->mace_stats.rntpc += mace_read(ioaddr, MACE_RNTPC);
- lp->mace_stats.mpc += mace_read(ioaddr, MACE_MPC);
+ lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC);
+ lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC);
+ lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC);
/* At this point, mace_stats is fully updated for this call.
We may now update the linux_stats. */
@@ -1608,30 +1630,30 @@
DEBUG(1, "Attempt to restore multicast list detected.\n");
- mace_write(ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR);
+ mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR);
/* Poll ADDRCHG bit */
- while (mace_read(ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
+ while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
;
/* Set LADRF register */
for (i = 0; i < MACE_LADRF_LEN; i++)
- mace_write(ioaddr, MACE_LADRF, ladrf[i]);
+ mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]);
- mace_write(ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL);
- mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL);
+ mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
} else if (num_addrs < 0) {
/* Promiscuous mode: receive all packets */
- mace_write(ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
- mace_write(ioaddr, MACE_MACCC,
+ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+ mace_write(lp, ioaddr, MACE_MACCC,
MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
);
} else {
/* Normal mode */
- mace_write(ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
- mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+ mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
}
} /* restore_multicast_list */
@@ -1691,20 +1713,21 @@
static void restore_multicast_list(struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
+ mace_private *lp = (mace_private *)dev->priv;
DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name,
((mace_private *)(dev->priv))->multicast_num_addrs);
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode: receive all packets */
- mace_write(ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
- mace_write(ioaddr, MACE_MACCC,
+ mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+ mace_write(lp, ioaddr, MACE_MACCC,
MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
);
} else {
/* Normal mode */
- mace_write(ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
- mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+ mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
}
} /* restore_multicast_list */
diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
--- a/drivers/net/pcmcia/pcnet_cs.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/pcmcia/pcnet_cs.c Sun Jul 13 20:39:56 2003
@@ -357,7 +357,7 @@
if (*linkp == NULL)
return;
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
pcnet_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
@@ -1052,7 +1052,7 @@
link->open--;
netif_stop_queue(dev);
- del_timer(&info->watchdog);
+ del_timer_sync(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
--- a/drivers/net/pcmcia/smc91c92_cs.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/pcmcia/smc91c92_cs.c Sun Jul 13 20:39:56 2003
@@ -433,7 +433,7 @@
if (*linkp == NULL)
return;
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
smc91c92_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
@@ -1330,7 +1330,7 @@
outw(CTL_POWERDOWN, ioaddr + CONTROL );
link->open--;
- del_timer(&smc->media);
+ del_timer_sync(&smc->media);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
@@ -1996,7 +1996,7 @@
}
if (smc->fast_poll) {
smc->fast_poll--;
- smc->media.expires = jiffies + 1;
+ smc->media.expires = jiffies + HZ/100;
add_timer(&smc->media);
SMC_SELECT_BANK(saved_bank);
return;
diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
--- a/drivers/net/pcmcia/xirc2ps_cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/pcmcia/xirc2ps_cs.c Sun Jul 13 20:39:55 2003
@@ -689,7 +689,7 @@
* the release() function is called, that will trigger a proper
* detach().
*/
- del_timer(&link->release);
+ del_timer_sync(&link->release);
if (link->state & DEV_CONFIG) {
xirc2ps_release((unsigned long)link);
if (link->state & DEV_STALE_CONFIG) {
diff -Nru a/drivers/net/plip.c b/drivers/net/plip.c
--- a/drivers/net/plip.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/plip.c Sun Jul 13 20:39:56 2003
@@ -277,27 +277,10 @@
then calls us here.
*/
-int __init
-plip_init_dev(struct net_device *dev, struct parport *pb)
+static int
+plip_init_netdev(struct net_device *dev)
{
- struct net_local *nl;
- struct pardevice *pardev;
-
- SET_MODULE_OWNER(dev);
- dev->irq = pb->irq;
- dev->base_addr = pb->base;
-
- if (pb->irq == -1) {
- printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
- "which is fairly inefficient!\n", pb->name);
- }
-
- pardev = parport_register_device(pb, dev->name, plip_preempt,
- plip_wakeup, plip_interrupt,
- 0, dev);
-
- if (!pardev)
- return -ENODEV;
+ struct net_local *nl = dev->priv;
printk(KERN_INFO "%s", version);
if (dev->irq != -1)
@@ -307,9 +290,6 @@
printk(KERN_INFO "%s: Parallel port at %#3lx, not using IRQ.\n",
dev->name, dev->base_addr);
- /* Fill in the generic fields of the device structure. */
- ether_setup(dev);
-
/* Then, override parts of it */
dev->hard_start_xmit = plip_tx_packet;
dev->open = plip_open;
@@ -322,22 +302,12 @@
memset(dev->dev_addr, 0xfc, ETH_ALEN);
/* Set the private structure */
- dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL);
- if (dev->priv == NULL) {
- printk(KERN_ERR "%s: out of memory\n", dev->name);
- parport_unregister_device(pardev);
- return -ENOMEM;
- }
- memset(dev->priv, 0, sizeof(struct net_local));
- nl = (struct net_local *) dev->priv;
-
nl->orig_hard_header = dev->hard_header;
dev->hard_header = plip_hard_header;
nl->orig_hard_header_cache = dev->hard_header_cache;
dev->hard_header_cache = plip_hard_header_cache;
- nl->pardev = pardev;
nl->port_owner = 0;
@@ -1299,29 +1269,52 @@
* available to use. */
static void plip_attach (struct parport *port)
{
- static int i;
+ static int unit;
+ struct net_device *dev;
+ struct net_local *nl;
+ char name[IFNAMSIZ];
if ((parport[0] == -1 && (!timid || !port->devices)) ||
plip_searchfor(parport, port->number)) {
- if (i == PLIP_MAX) {
+ if (unit == PLIP_MAX) {
printk(KERN_ERR "plip: too many devices\n");
return;
}
- dev_plip[i] = kmalloc(sizeof(struct net_device),
- GFP_KERNEL);
- if (!dev_plip[i]) {
+
+ sprintf(name, "plip%d", unit);
+ dev = alloc_netdev(sizeof(struct net_local), name,
+ ether_setup);
+ if (!dev) {
printk(KERN_ERR "plip: memory squeeze\n");
return;
}
- memset(dev_plip[i], 0, sizeof(struct net_device));
- sprintf(dev_plip[i]->name, "plip%d", i);
- dev_plip[i]->priv = port;
- if (plip_init_dev(dev_plip[i],port) ||
- register_netdev(dev_plip[i])) {
- kfree(dev_plip[i]);
- dev_plip[i] = NULL;
+
+ dev->init = plip_init_netdev;
+
+ SET_MODULE_OWNER(dev);
+ dev->irq = port->irq;
+ dev->base_addr = port->base;
+ if (port->irq == -1) {
+ printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
+ "which is fairly inefficient!\n", port->name);
+ }
+
+ nl = dev->priv;
+ nl->pardev = parport_register_device(port, name, plip_preempt,
+ plip_wakeup, plip_interrupt,
+ 0, dev);
+
+ if (!nl->pardev) {
+ printk(KERN_ERR "%s: parport_register failed\n", name);
+ kfree(dev);
+ return;
+ }
+
+ if (register_netdev(dev)) {
+ printk(KERN_ERR "%s: network register failed\n", name);
+ kfree(dev);
} else {
- i++;
+ dev_plip[unit++] = dev;
}
}
}
@@ -1341,20 +1334,19 @@
static void __exit plip_cleanup_module (void)
{
+ struct net_device *dev;
int i;
parport_unregister_driver (&plip_driver);
for (i=0; i < PLIP_MAX; i++) {
- if (dev_plip[i]) {
- struct net_local *nl =
- (struct net_local *)dev_plip[i]->priv;
- unregister_netdev(dev_plip[i]);
+ if ((dev = dev_plip[i])) {
+ struct net_local *nl = dev->priv;
+ unregister_netdev(dev);
if (nl->port_owner)
parport_release(nl->pardev);
parport_unregister_device(nl->pardev);
- kfree(dev_plip[i]->priv);
- kfree(dev_plip[i]);
+ kfree(dev);
dev_plip[i] = NULL;
}
}
diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
--- a/drivers/net/sb1250-mac.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/sb1250-mac.c Sun Jul 13 20:39:56 2003
@@ -2493,7 +2493,7 @@
/* Set the timer to check for link beat. */
init_timer(&sc->sbm_timer);
- sc->sbm_timer.expires = jiffies + 2;
+ sc->sbm_timer.expires = jiffies + 2 * HZ/100;
sc->sbm_timer.data = (unsigned long)dev;
sc->sbm_timer.function = &sbmac_timer;
add_timer(&sc->sbm_timer);
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/sk_mca.c Sun Jul 13 20:39:55 2003
@@ -537,7 +537,7 @@
ResetBoard(dev);
InitBoard(dev);
- njiffies = jiffies + 100;
+ njiffies = jiffies + HZ;
do {
csr0val = GetLANCE(dev, LANCE_CSR0);
}
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/sundance.c Sun Jul 13 20:39:55 2003
@@ -87,11 +87,15 @@
Version LK1.09 (D-Link):
- Fix the flowctrl bug.
- Set Pause bit in MII ANAR if flow control enabled.
+
+ Version LK1.09a (ICPlus):
+ - Add the delay time in reading the contents of EEPROM
+
*/
#define DRV_NAME "sundance"
#define DRV_VERSION "1.01+LK1.09a"
-#define DRV_RELDATE "16-May-2003"
+#define DRV_RELDATE "10-Jul-2003"
/* The user-configurable values.
@@ -744,12 +748,14 @@
return 0;
}
+#define eeprom_delay(ee_addr) readl(ee_addr)
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
static int __devinit eeprom_read(long ioaddr, int location)
{
- int boguscnt = 1000; /* Typical 190 ticks. */
+ int boguscnt = 10000; /* Typical 1900 ticks. */
writew(0x0200 | (location & 0xff), ioaddr + EECtrl);
do {
+ eeprom_delay(ioaddr + EECtrl);
if (! (readw(ioaddr + EECtrl) & 0x8000)) {
return readw(ioaddr + EEData);
}
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/sunhme.c Sun Jul 13 20:39:55 2003
@@ -1521,12 +1521,6 @@
hme_write32(hp, bregs + BMAC_IGAP1, DEFAULT_IPG1);
hme_write32(hp, bregs + BMAC_IGAP2, DEFAULT_IPG2);
- /* Make sure we can handle VLAN frames. */
- hme_write32(hp, bregs + BMAC_TXMAX,
- ETH_DATA_LEN + ETH_HLEN + 8);
- hme_write32(hp, bregs + BMAC_RXMAX,
- ETH_DATA_LEN + ETH_HLEN + 8);
-
/* Load up the MAC address and random seed. */
HMD(("rseed/macaddr, "));
@@ -2805,8 +2799,8 @@
dev->watchdog_timeo = 5*HZ;
dev->do_ioctl = &happy_meal_ioctl;
- /* Happy Meal can do it all... */
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ /* Happy Meal can do it all... except VLAN. */
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
dev->irq = sdev->irqs[0];
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/tg3.c Sun Jul 13 20:39:55 2003
@@ -6679,10 +6679,9 @@
}
/* Configure DMA attributes. */
- if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
+ if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
pci_using_dac = 1;
- if (pci_set_consistent_dma_mask(pdev,
- (u64) 0xffffffffffffffff)) {
+ if (pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL)) {
printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
"for consistent allocations\n");
goto err_out_free_res;
diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
--- a/drivers/net/tokenring/3c359.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/tokenring/3c359.c Sun Jul 13 20:39:56 2003
@@ -464,7 +464,7 @@
printk(KERN_INFO "3C359: Uploading Microcode: ");
- for (i = start,j=0; (j < mc_size && i <= 0xffff) ; i++,j++) {
+ for (i = start, j = 0; j < mc_size; i++, j++) {
writel(MEM_BYTE_WRITE | 0XD0000 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
writeb(microcode[j],xl_mmio + MMIO_MACDATA) ;
if (j % 1024 == 0)
diff -Nru a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
--- a/drivers/net/tokenring/proteon.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/tokenring/proteon.c Sun Jul 13 20:39:56 2003
@@ -401,7 +401,6 @@
int init_module(void)
{
int i, num;
- struct net_device *dev;
num = 0;
if (io[0]) { /* Only probe addresses from command line */
diff -Nru a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
--- a/drivers/net/tokenring/skisa.c Sun Jul 13 20:39:54 2003
+++ b/drivers/net/tokenring/skisa.c Sun Jul 13 20:39:54 2003
@@ -414,7 +414,6 @@
int init_module(void)
{
int i, num;
- struct net_device *dev;
num = 0;
if (io[0]) { /* Only probe addresses from command line */
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/via-rhine.c Sun Jul 13 20:39:56 2003
@@ -1152,7 +1152,7 @@
/* Set the timer to check for link beat. */
init_timer(&np->timer);
- np->timer.expires = jiffies + 2;
+ np->timer.expires = jiffies + 2 * HZ/100;
np->timer.data = (unsigned long)dev;
np->timer.function = &via_rhine_timer; /* timer handler */
add_timer(&np->timer);
diff -Nru a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
--- a/drivers/net/wireless/atmel_cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/net/wireless/atmel_cs.c Sun Jul 13 20:39:55 2003
@@ -391,7 +391,7 @@
local_info_t *dev;
int last_fn, last_ret;
u_char buf[64];
- int card_index = -1;
+ int card_index = -1, done = 0;
handle = link->handle;
dev = link->priv;
@@ -415,13 +415,13 @@
manfid->manf == card_table[i].manf &&
manfid->card == card_table[i].card) {
card_index = i;
- goto done;
+ done = 1;
}
}
}
tuple.DesiredTuple = CISTPL_VERS_1;
- if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
+ if (!done && (CardServices(GetFirstTuple, handle, &tuple) == 0)) {
int i, j, k;
cistpl_vers_1_t *ver1;
CS_CHECK(GetTupleData, handle, &tuple);
@@ -446,12 +446,11 @@
goto mismatch;
}
card_index = i;
- goto done;
+ break; /* done */
mismatch:
-
+ j = 0; /* dummy stmt to shut up compiler */
}
- done:
}
/*
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c Sun Jul 13 20:39:56 2003
+++ b/drivers/net/wireless/wavelan.c Sun Jul 13 20:39:56 2003
@@ -3730,8 +3730,8 @@
int i; /* Loop counter */
/* Check if the base address if available. */
- if (check_region(ioaddr, sizeof(ha_t)))
- return -EADDRINUSE; /* ioaddr already used */
+ if (!request_region(ioaddr, sizeof(ha_t), "wavelan probe"))
+ return -EBUSY; /* ioaddr already used */
/* Reset host interface */
wv_hacr_reset(ioaddr);
@@ -3739,6 +3739,8 @@
/* Read the MAC address from the parameter storage area. */
psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
mac, 6);
+
+ release_region(ioaddr, sizeof(ha_t));
/*
* Check the first three octets of the address for the manufacturer's code.
diff -Nru a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
--- a/drivers/parisc/Kconfig Sun Jul 13 20:39:55 2003
+++ b/drivers/parisc/Kconfig Sun Jul 13 20:39:55 2003
@@ -57,8 +57,11 @@
source "drivers/eisa/Kconfig"
config ISA
- bool
+ bool "ISA support"
depends on EISA
+ help
+ If you want to plug an ISA card into your EISA bus, say Y here.
+ Most people should say N.
config PCI
bool "PCI support"
diff -Nru a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
--- a/drivers/pcmcia/bulkmem.c Sun Jul 13 20:39:56 2003
+++ b/drivers/pcmcia/bulkmem.c Sun Jul 13 20:39:56 2003
@@ -258,7 +258,7 @@
win->ctl.flags |= MAP_ATTRIB;
win->ctl.speed = req->AccessSpeed;
win->ctl.card_start = req->CardOffset;
- win->sock->ss_entry->set_mem_map(win->sock, &win->ctl);
+ win->sock->ops->set_mem_map(win->sock, &win->ctl);
return CS_SUCCESS;
}
@@ -271,7 +271,7 @@
return CS_BAD_VPP;
s = SOCKET(handle);
s->socket.Vpp = req->Vpp1;
- if (s->ss_entry->set_socket(s, &s->socket))
+ if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
return CS_SUCCESS;
}
@@ -286,7 +286,7 @@
s->socket.csc_mask |= SS_READY;
else
s->socket.csc_mask &= ~SS_READY;
- if (s->ss_entry->set_socket(s, &s->socket))
+ if (s->ops->set_socket(s, &s->socket))
return CS_GENERAL_FAILURE;
return CS_SUCCESS;
}
diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
--- a/drivers/pcmcia/cistpl.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/cistpl.c Sun Jul 13 20:39:55 2003
@@ -86,7 +86,7 @@
{
if (s->cis_mem.sys_start != 0) {
s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ss_entry->set_mem_map(s, &s->cis_mem);
+ s->ops->set_mem_map(s, &s->cis_mem);
if (!(s->features & SS_CAP_STATIC_MAP))
release_mem_region(s->cis_mem.sys_start, s->map_size);
iounmap(s->cis_virt);
@@ -118,7 +118,7 @@
}
mem->card_start = card_offset;
mem->flags = flags;
- s->ss_entry->set_mem_map(s, mem);
+ s->ops->set_mem_map(s, mem);
if (s->features & SS_CAP_STATIC_MAP) {
if (s->cis_virt)
iounmap(s->cis_virt);
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/cs.c Sun Jul 13 20:39:55 2003
@@ -225,43 +225,6 @@
};
#define SERVICE_COUNT (sizeof(service_table)/sizeof(lookup_t))
-/*======================================================================
-
- These functions are just shorthand for the actual low-level drivers
-
-======================================================================*/
-
-static int get_socket_status(struct pcmcia_socket *s, int *val)
-{
- return s->ss_entry->get_status(s, val);
-}
-
-static int set_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- return s->ss_entry->set_socket(s, state);
-}
-
-static int set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
-{
- return s->ss_entry->set_io_map(s, io);
-}
-
-static int set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
-{
- return s->ss_entry->set_mem_map(s, mem);
-}
-
-static int suspend_socket(struct pcmcia_socket *s)
-{
- s->socket = dead_socket;
- return s->ss_entry->suspend(s);
-}
-
-static int init_socket(struct pcmcia_socket *s)
-{
- s->socket = dead_socket;
- return s->ss_entry->init(s);
-}
/*====================================================================
@@ -339,12 +302,14 @@
INIT_LIST_HEAD(&socket->cis_cache);
spin_lock_init(&socket->lock);
- init_socket(socket);
-
init_completion(&socket->thread_done);
init_waitqueue_head(&socket->thread_wait);
init_MUTEX(&socket->skt_sem);
spin_lock_init(&socket->thread_lock);
+
+ socket->socket = dead_socket;
+ socket->ops->init(socket);
+
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
if (ret < 0)
return ret;
@@ -373,7 +338,7 @@
socket->clients = socket->clients->next;
kfree(client);
}
- socket->ss_entry = NULL;
+ socket->ops = NULL;
}
static void pcmcia_release_socket(struct class_device *class_dev)
@@ -388,10 +353,10 @@
*/
int pcmcia_register_socket(struct pcmcia_socket *socket)
{
- if (!socket || !socket->ss_entry || !socket->dev.dev)
+ if (!socket || !socket->ops || !socket->dev.dev)
return -EINVAL;
- DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ss_entry);
+ DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ops);
/* try to obtain a socket number [yes, it gets ugly if we
* register more than 2^sizeof(unsigned int) pcmcia
@@ -443,7 +408,7 @@
if (!socket)
return;
- DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ss_entry);
+ DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops);
init_completion(&socket->socket_released);
@@ -510,7 +475,8 @@
/* Blank out the socket state */
s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
- init_socket(s);
+ s->socket = dead_socket;
+ s->ops->init(s);
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
destroy_cis_cache(s);
@@ -525,7 +491,7 @@
s->socket.Vpp = 0;
s->socket.Vcc = 0;
s->socket.io_irq = 0;
- set_socket(s, &s->socket);
+ s->ops->set_socket(s, &s->socket);
/* */
#ifdef CONFIG_CARDBUS
cb_free(s);
@@ -619,16 +585,16 @@
int status, i;
skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
- set_socket(skt, &skt->socket);
+ skt->ops->set_socket(skt, &skt->socket);
udelay((long)reset_time);
skt->socket.flags &= ~SS_RESET;
- set_socket(skt, &skt->socket);
+ skt->ops->set_socket(skt, &skt->socket);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(unreset_delay));
for (i = 0; i < unreset_limit; i++) {
- get_socket_status(skt, &status);
+ skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
@@ -648,7 +614,7 @@
{
int status, i;
- get_socket_status(skt, &status);
+ skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
@@ -656,7 +622,7 @@
schedule_timeout(cs_to_timeout(initial_delay));
for (i = 0; i < 100; i++) {
- get_socket_status(skt, &status);
+ skt->ops->get_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
@@ -693,7 +659,7 @@
}
skt->state |= SOCKET_PRESENT;
skt->socket.flags = SS_DEBOUNCED;
- set_socket(skt, &skt->socket);
+ skt->ops->set_socket(skt, &skt->socket);
/*
* Wait "vcc_settle" for the supply to stabilise.
@@ -739,7 +705,8 @@
return CS_IN_USE;
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
- suspend_socket(skt);
+ skt->socket = dead_socket;
+ skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND;
return CS_SUCCESS;
@@ -757,7 +724,8 @@
if (!(skt->state & SOCKET_SUSPEND))
return CS_IN_USE;
- init_socket(skt);
+ skt->socket = dead_socket;
+ skt->ops->init(skt);
ret = socket_setup(skt, resume_delay);
if (ret == CS_SUCCESS) {
@@ -811,7 +779,7 @@
schedule_timeout(cs_to_timeout(2));
}
- get_socket_status(skt, &status);
+ skt->ops->get_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_remove(skt);
@@ -868,13 +836,19 @@
complete_and_exit(&skt->thread_done, 0);
}
+/*
+ * Yenta (at least) probes interrupts before registering the socket and
+ * starting the handler thread.
+ */
void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
{
- spin_lock(&s->thread_lock);
- s->thread_events |= events;
- spin_unlock(&s->thread_lock);
+ if (s->thread) {
+ spin_lock(&s->thread_lock);
+ s->thread_events |= events;
+ spin_unlock(&s->thread_lock);
- wake_up(&s->thread_wait);
+ wake_up(&s->thread_wait);
+ }
} /* pcmcia_parse_events */
@@ -1362,7 +1336,7 @@
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
s = SOCKET(handle);
- get_socket_status(s, &val);
+ s->ops->get_status(s, &val);
status->CardState = status->SocketState = 0;
status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
@@ -1441,7 +1415,7 @@
return CS_BAD_PAGE;
s = win->sock;
win->ctl.card_start = req->CardOffset;
- if (set_mem_map(s, &win->ctl) != 0)
+ if (s->ops->set_mem_map(s, &win->ctl) != 0)
return CS_BAD_OFFSET;
return CS_SUCCESS;
} /* map_mem_page */
@@ -1474,7 +1448,7 @@
c->Attributes &= ~CONF_ENABLE_IRQ;
s->socket.io_irq = 0;
}
- set_socket(s, &s->socket);
+ s->ops->set_socket(s, &s->socket);
}
if (mod->Attributes & CONF_VCC_CHANGE_VALID)
@@ -1486,7 +1460,7 @@
if (mod->Vpp1 != mod->Vpp2)
return CS_BAD_VPP;
c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
- if (set_socket(s, &s->socket))
+ if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
(mod->Attributes & CONF_VPP2_CHANGE_VALID))
@@ -1516,7 +1490,7 @@
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
win->ctl.speed = req->AccessSpeed;
- set_mem_map(win->sock, &win->ctl);
+ win->sock->ops->set_mem_map(win->sock, &win->ctl);
return CS_SUCCESS;
} /* modify_window */
@@ -1616,7 +1590,7 @@
s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
s->socket.Vpp = 0;
s->socket.io_irq = 0;
- set_socket(s, &s->socket);
+ s->ops->set_socket(s, &s->socket);
}
if (c->state & CONFIG_IO_REQ)
for (i = 0; i < MAX_IO_WIN; i++) {
@@ -1626,7 +1600,7 @@
if (s->io[i].Config != 0)
continue;
io.map = i;
- set_io_map(s, &io);
+ s->ops->set_io_map(s, &io);
}
c->state &= ~CONFIG_LOCKED;
}
@@ -1727,7 +1701,7 @@
/* Shut down memory window */
win->ctl.flags &= ~MAP_ACTIVE;
- set_mem_map(s, &win->ctl);
+ s->ops->set_mem_map(s, &win->ctl);
s->state &= ~SOCKET_WIN_REQ(win->index);
/* Release system memory */
@@ -1774,7 +1748,7 @@
if (req->Vpp1 != req->Vpp2)
return CS_BAD_VPP;
s->socket.Vpp = req->Vpp1;
- if (set_socket(s, &s->socket))
+ if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
@@ -1792,7 +1766,7 @@
s->socket.io_irq = s->irq.AssignedIRQ;
else
s->socket.io_irq = 0;
- set_socket(s, &s->socket);
+ s->ops->set_socket(s, &s->socket);
s->lock_count++;
/* Set up CIS configuration registers */
@@ -1857,7 +1831,7 @@
}
iomap.start = s->io[i].BasePort;
iomap.stop = iomap.start + s->io[i].NumPorts - 1;
- set_io_map(s, &iomap);
+ s->ops->set_io_map(s, &iomap);
s->io[i].Config++;
}
}
@@ -2078,7 +2052,7 @@
win->ctl.sys_start = win->base;
win->ctl.sys_stop = win->base + win->size-1;
win->ctl.card_start = 0;
- if (set_mem_map(s, &win->ctl) != 0)
+ if (s->ops->set_mem_map(s, &win->ctl) != 0)
return CS_BAD_ARGS;
s->state |= SOCKET_WIN_REQ(w);
diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
--- a/drivers/pcmcia/cs_internal.h Sun Jul 13 20:39:54 2003
+++ b/drivers/pcmcia/cs_internal.h Sun Jul 13 20:39:54 2003
@@ -113,7 +113,7 @@
(((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC))
#define CHECK_SOCKET(s) \
- (((s) >= sockets) || (socket_table[s]->ss_entry == NULL))
+ (((s) >= sockets) || (socket_table[s]->ops == NULL))
#define SOCKET(h) (h->Socket)
#define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
--- a/drivers/pcmcia/i82092.c Sun Jul 13 20:39:56 2003
+++ b/drivers/pcmcia/i82092.c Sun Jul 13 20:39:56 2003
@@ -161,7 +161,7 @@
for (i = 0; idev;
- sockets[i].socket.ss_entry = &i82092aa_operations;
+ sockets[i].socket.ops = &i82092aa_operations;
ret = pcmcia_register_socket(&sockets[i].socket);
if (ret) {
goto err_out_free_sockets;
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c Sun Jul 13 20:39:56 2003
+++ b/drivers/pcmcia/i82365.c Sun Jul 13 20:39:56 2003
@@ -1403,7 +1403,7 @@
/* register sockets with the pcmcia core */
for (i = 0; i < sockets; i++) {
socket[i].socket.dev.dev = &i82365_device.dev;
- socket[i].socket.ss_entry = &pcic_operations;
+ socket[i].socket.ops = &pcic_operations;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff -Nru a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h
--- a/drivers/pcmcia/ricoh.h Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/ricoh.h Sun Jul 13 20:39:55 2003
@@ -161,7 +161,7 @@
rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
}
- socket->socket.ss_entry->init = ricoh_init;
+ socket->socket.ops->init = ricoh_init;
return 0;
}
diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
--- a/drivers/pcmcia/rsrc_mgr.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/rsrc_mgr.c Sun Jul 13 20:39:55 2003
@@ -360,7 +360,7 @@
map.sys_start = res->start;
map.sys_stop = res->end;
map.card_start = 0;
- s->ss_entry->set_mem_map(s, &map);
+ s->ops->set_mem_map(s, &map);
/* Don't bother checking every word... */
for (i = 0; i < s->map_size; i += 44) {
@@ -370,7 +370,7 @@
}
map.flags = 0;
- s->ss_entry->set_mem_map(s, &map);
+ s->ops->set_mem_map(s, &map);
iounmap(virt);
}
diff -Nru a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c
--- a/drivers/pcmcia/sa11xx_core.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/sa11xx_core.c Sun Jul 13 20:39:55 2003
@@ -725,7 +725,7 @@
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
memset(skt, 0, sizeof(*skt));
- skt->socket.ss_entry = &sa11xx_pcmcia_operations;
+ skt->socket.ops = &sa11xx_pcmcia_operations;
skt->socket.owner = ops->owner;
skt->socket.dev.dev = dev;
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/tcic.c Sun Jul 13 20:39:55 2003
@@ -519,7 +519,7 @@
platform_device_register(&tcic_device);
for (i = 0; i < sockets; i++) {
- socket_table[i].socket.ss_entry = &tcic_operations;
+ socket_table[i].socket.ops = &tcic_operations;
socket_table[i].socket.dev.dev = &tcic_device.dev;
ret = pcmcia_register_socket(&socket_table[i].socket);
if (ret && i)
diff -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
--- a/drivers/pcmcia/ti113x.h Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/ti113x.h Sun Jul 13 20:39:55 2003
@@ -176,27 +176,36 @@
if (new != reg)
exca_writeb(socket, I365_INTCTL, new);
+#if 0
+ /* THIS CAUSES HANGS! Disabled for now, do not know why */
+
/*
* If ISA interrupts don't work, then fall back to routing card
* interrupts to the PCI interrupt of the socket.
+ *
+ * Tweaking this when we are using serial PCI IRQs causes hangs
+ * --rmk
*/
if (!socket->socket.irq_mask) {
- int irqmux, devctl;
-
- printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
+ u8 irqmux, devctl;
devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
- devctl &= ~TI113X_DCR_IMODE_MASK;
+ if (devctl & TI113X_DCR_IMODE_MASK != TI12XX_DCR_IMODE_ALL_SERIAL) {
+ printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
- irqmux = config_readl(socket, TI122X_IRQMUX);
- irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */
- irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */
+ devctl &= ~TI113X_DCR_IMODE_MASK;
- config_writel(socket, TI122X_IRQMUX, irqmux);
- config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+ irqmux = config_readl(socket, TI122X_IRQMUX);
+ irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */
+ irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */
+
+ config_writel(socket, TI122X_IRQMUX, irqmux);
+ config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+ }
}
+#endif
- socket->socket.ss_entry->init = ti_init;
+ socket->socket.ops->init = ti_init;
return 0;
}
@@ -229,7 +238,7 @@
if (socket->cb_irq)
ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
ti_override(socket);
- socket->socket.ss_entry->init = ti113x_init;
+ socket->socket.ops->init = ti113x_init;
return 0;
}
@@ -258,7 +267,7 @@
if (socket->cb_irq)
ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
ti113x_override(socket);
- socket->socket.ss_entry->init = ti1250_init;
+ socket->socket.ops->init = ti1250_init;
return 0;
}
diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c Sun Jul 13 20:39:55 2003
+++ b/drivers/pcmcia/yenta_socket.c Sun Jul 13 20:39:55 2003
@@ -828,7 +828,7 @@
memset(socket, 0, sizeof(*socket));
/* prepare pcmcia_socket */
- socket->socket.ss_entry = ¥ta_socket_operations;
+ socket->socket.ops = ¥ta_socket_operations;
socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket;
socket->socket.owner = THIS_MODULE;
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c Sun Jul 13 20:39:55 2003
+++ b/drivers/scsi/g_NCR5380.c Sun Jul 13 20:39:55 2003
@@ -386,14 +386,21 @@
if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
for (i = 0; ports[i]; i++) {
+ if (!request_region(ports[i], 16, "ncr53c80"))
+ continue;
if (overrides[current_override].NCR5380_map_name == ports[i])
break;
+ release_region(ports[i], 16);
} else
for (i = 0; ports[i]; i++) {
- if ((!check_region(ports[i], 16)) && (inb(ports[i]) == 0xff))
+ if (!request_region(ports[i], 16, "ncr53c80"))
+ continue;
+ if (inb(ports[i]) == 0xff)
break;
+ release_region(ports[i], 16);
}
if (ports[i]) {
+ /* At this point we have our region reserved */
outb(0x59, 0x779);
outb(0xb9, 0x379);
outb(0xc5, 0x379);
@@ -408,12 +415,15 @@
} else
continue;
}
-
- request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380");
+ else
+ {
+ /* Not a 53C400A style setup - just grab */
+ if(!(request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380")))
+ continue;
+ }
#else
- if (check_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size))
+ if(!request_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380"))
continue;
- request_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380");
#endif
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL) {
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c Sun Jul 13 20:39:55 2003
+++ b/drivers/usb/class/usblp.c Sun Jul 13 20:39:55 2003
@@ -146,6 +146,7 @@
int rcomplete; /* reading is completed */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
+ unsigned char present; /* True if not disconnected */
unsigned char bidir; /* interface is bidirectional */
unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
/* first 2 bytes are (big-endian) length */
@@ -157,6 +158,7 @@
dbg("usblp=0x%p", usblp);
dbg("dev=0x%p", usblp->dev);
+ dbg("present=%d", usblp->present);
dbg("buf=0x%p", usblp->buf);
dbg("readcount=%d", usblp->readcount);
dbg("ifnum=%d", usblp->ifnum);
@@ -253,7 +255,7 @@
{
struct usblp *usblp = urb->context;
- if (!usblp || !usblp->dev || !usblp->used)
+ if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
return;
if (unlikely(urb->status))
@@ -267,7 +269,7 @@
{
struct usblp *usblp = urb->context;
- if (!usblp || !usblp->dev || !usblp->used)
+ if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
return;
if (unlikely(urb->status))
@@ -332,7 +334,7 @@
goto out;
}
usblp = usb_get_intfdata (intf);
- if (!usblp || !usblp->dev)
+ if (!usblp || !usblp->dev || !usblp->present)
goto out;
retval = -EBUSY;
@@ -404,7 +406,7 @@
down (&usblp->sem);
lock_kernel();
usblp->used = 0;
- if (usblp->dev) {
+ if (usblp->present) {
usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
@@ -432,7 +434,7 @@
int retval = 0;
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
retval = -ENODEV;
goto done;
}
@@ -630,7 +632,7 @@
}
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
up (&usblp->sem);
return -ENODEV;
}
@@ -691,7 +693,7 @@
return -EINVAL;
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
count = -ENODEV;
goto done;
}
@@ -726,7 +728,7 @@
remove_wait_queue(&usblp->wait, &wait);
}
- if (!usblp->dev) {
+ if (!usblp->present) {
count = -ENODEV;
goto done;
}
@@ -916,6 +918,8 @@
usb_set_intfdata (intf, usblp);
+ usblp->present = 1;
+
return 0;
abort_minor:
@@ -1115,14 +1119,14 @@
down (&usblp->sem);
lock_kernel();
- usblp->dev = NULL;
+ usblp->present = 0;
usb_set_intfdata (intf, NULL);
usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
- else /* cleanup later, on close */
+ else /* cleanup later, on release */
up (&usblp->sem);
unlock_kernel();
}
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c Sun Jul 13 20:39:54 2003
+++ b/drivers/usb/core/inode.c Sun Jul 13 20:39:54 2003
@@ -491,10 +491,6 @@
static struct super_block *usb_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
- if (fs_type == &usbdevice_fs_type)
- printk (KERN_INFO "Please use the 'usbfs' filetype instead, "
- "the 'usbdevfs' name is deprecated.\n");
-
return get_sb_single(fs_type, flags, data, usbfs_fill_super);
}
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c Sun Jul 13 20:39:55 2003
+++ b/drivers/usb/core/message.c Sun Jul 13 20:39:55 2003
@@ -986,7 +986,7 @@
if (err < 0) {
err("error getting string descriptor 0 (error=%d)", err);
goto errout;
- } else if (tbuf[0] < 4) {
+ } else if (err < 4 || tbuf[0] < 4) {
err("string descriptor 0 too short");
err = -EINVAL;
goto errout;
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c Sun Jul 13 20:39:55 2003
+++ b/drivers/usb/net/usbnet.c Sun Jul 13 20:39:55 2003
@@ -2391,7 +2391,7 @@
if (retval) {
devdbg (dev, "drop, code %d", retval);
drop:
- retval = NET_XMIT_DROP;
+ retval = NET_XMIT_SUCCESS;
dev->stats.tx_dropped++;
if (skb)
dev_kfree_skb_any (skb);
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c Sun Jul 13 20:39:56 2003
+++ b/drivers/usb/serial/ftdi_sio.c Sun Jul 13 20:39:56 2003
@@ -4,6 +4,8 @@
* Copyright (C) 1999 - 2001
* Greg Kroah-Hartman (greg@kroah.com)
* Bill Ryder (bryder@sgi.com)
+ * Copyright (C) 2002
+ * Kuba Ober (kuba@mareimbrium.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,49 +15,156 @@
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
- * and extra documentation
+ * and extra documentation
+ *
+ * (27/Jun/2003) Ian Abbott
+ * Reworked the urb handling logic. We have no more pool, but dynamically
+ * allocate the urb and the transfer buffer on the fly. In testing this
+ * does not incure any measurable overhead. This also relies on the fact
+ * that we have proper reference counting logic for urbs. I nicked this
+ * from Greg KH's Visor driver.
+ *
+ * (23/Jun/2003) Ian Abbott
+ * Reduced flip buffer pushes and corrected a data length test in
+ * ftdi_read_bulk_callback.
+ * Defererence pointers after any paranoid checks, not before.
+ *
+ * (21/Jun/2003) Erik Nygren
+ * Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip.
+ * See . Only operates properly
+ * at 100000 and RTS-CTS, so set custom divisor mode on startup.
+ * Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
+ *
+ * (18/Jun/2003) Ian Abbott
+ * Added Device ID of the USB relais from Rudolf Gugler (backported from
+ * Philipp Gühring's patch for 2.5.x kernel).
+ * Moved read transfer buffer reallocation into startup function.
+ * Free existing write urb and transfer buffer in startup function.
+ * Only use urbs in write urb pool that were successfully allocated.
+ * Moved some constant macros out of functions.
+ * Minor whitespace and comment changes.
+ *
+ * (12/Jun/2003) David Norwood
+ * Added support for USB-UIRT IR tranceiver using 8U232AM chip.
+ * See . Only
+ * operates properly at 312500, so set custom divisor mode on startup.
+ *
+ * (12/Jun/2003) Ian Abbott
+ * Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang
+ * - I've eliminated some that don't seem to exist!
+ * Added Home Electronics Tira-1 IR transceiver pid from Chris Horn
+ * Some whitespace/coding-style cleanups
+ *
+ * (11/Jun/2003) Ian Abbott
+ * Fixed unsafe spinlock usage in ftdi_write
+ *
+ * (24/Feb/2003) Richard Shooter
+ * Increase read buffer size to improve read speeds at higher baud rates
+ * (specifically tested with up to 1Mb/sec at 1.5M baud)
+ *
+ * (23/Feb/2003) John Wilkins
+ * Added Xon/xoff flow control (activating support in the ftdi device)
+ * Added vid/pid for Videonetworks/Homechoice (UK ISP)
+ *
+ * (23/Feb/2003) Bill Ryder
+ * Added matrix orb device vid/pids from Wayne Wylupski
+ *
+ * (19/Feb/2003) Ian Abbott
+ * For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has
+ * changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI,
+ * ASYNC_SPD_SHI or ASYNC_SPD_WARP. Also, unless ASYNC_SPD_CUST is in
+ * force, don't bother changing baud rate when custom_divisor has changed.
+ *
+ * (18/Feb/2003) Ian Abbott
+ * Fixed TIOCMGET handling to include state of DTR and RTS, the state
+ * of which are now saved by set_dtr() and set_rts().
+ * Fixed improper storage class for buf in set_dtr() and set_rts().
+ * Added FT232BM chip type and support for its extra baud rates (compared
+ * to FT8U232AM).
+ * Took account of special case divisor values for highest baud rates of
+ * FT8U232AM and FT232BM.
+ * For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used,
+ * as previous alt_speed setting is now stale.
+ * Moved startup code common between the startup routines for the
+ * different chip types into a common subroutine.
+ *
+ * (17/Feb/2003) Bill Ryder
+ * Added write urb buffer pool on a per device basis
+ * Added more checking for open file on callbacks (fixed OOPS)
+ * Added CrystalFontz 632 and 634 PIDs
+ * (thanx to CrystalFontz for the sample devices - they flushed out
+ * some driver bugs)
+ * Minor debugging message changes
+ * Added throttle, unthrottle and chars_in_buffer functions
+ * Fixed FTDI_SIO (the original device) bug
+ * Fixed some shutdown handling
+ *
+ *
+ *
*
+ * (07/Jun/2002) Kuba Ober
+ * Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
+ * function. It was getting too complex.
+ * Fix the divisor calculation logic which was setting divisor of 0.125
+ * instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8.
+ * Also make it bump up the divisor to next integer in case of 7/8 - it's
+ * a better approximation.
+ *
+ * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
+ * Not tested by me but it doesn't break anything I use.
+ *
+ * (04/Jan/2002) Kuba Ober
+ * Implemented 38400 baudrate kludge, where it can be substituted with other
+ * values. That's the only way to set custom baudrates.
+ * Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
+ * FIXME: both baudrate things should eventually go to usbserial.c as other
+ * devices may need that functionality too. Actually, it can probably be
+ * merged in serial.c somehow - too many drivers repeat this code over
+ * and over.
+ * Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
+ * Divisors for baudrates are calculated by a macro.
+ * Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
+ *
* (04/Nov/2001) Bill Ryder
- * Fixed bug in read_bulk_callback where incorrect urb buffer was used.
- * cleaned up write offset calculation
- * added write_room since default values can be incorrect for sio
- * changed write_bulk_callback to use same queue_task as other drivers
- * (the previous version caused panics)
- * Removed port iteration code since the device only has one I/O port and it
- * was wrong anyway.
+ * Fixed bug in read_bulk_callback where incorrect urb buffer was used.
+ * Cleaned up write offset calculation
+ * Added write_room since default values can be incorrect for sio
+ * Changed write_bulk_callback to use same queue_task as other drivers
+ * (the previous version caused panics)
+ * Removed port iteration code since the device only has one I/O port and it
+ * was wrong anyway.
*
* (31/May/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * Switched from using spinlock to a semaphore, which fixes lots of problems.
*
* (23/May/2001) Bill Ryder
- * Added runtime debug patch (thanx Tyson D Sawyer).
- * Cleaned up comments for 8U232
- * Added parity, framing and overrun error handling
- * Added receive break handling.
+ * Added runtime debug patch (thanx Tyson D Sawyer).
+ * Cleaned up comments for 8U232
+ * Added parity, framing and overrun error handling
+ * Added receive break handling.
*
* (04/08/2001) gb
* Identify version on module load.
*
* (18/March/2001) Bill Ryder
- * (Not released)
- * Added send break handling. (requires kernel patch too)
- * Fixed 8U232AM hardware RTS/CTS etc status reporting.
- * Added flipbuf fix copied from generic device
+ * (Not released)
+ * Added send break handling. (requires kernel patch too)
+ * Fixed 8U232AM hardware RTS/CTS etc status reporting.
+ * Added flipbuf fix copied from generic device
*
* (12/3/2000) Bill Ryder
- * Added support for 8U232AM device.
- * Moved PID and VIDs into header file only.
- * Turned on low-latency for the tty (device will do high baudrates)
- * Added shutdown routine to close files when device removed.
- * More debug and error message cleanups.
- *
+ * Added support for 8U232AM device.
+ * Moved PID and VIDs into header file only.
+ * Turned on low-latency for the tty (device will do high baudrates)
+ * Added shutdown routine to close files when device removed.
+ * More debug and error message cleanups.
*
* (11/13/2000) Bill Ryder
- * Added spinlock protected open code and close code.
- * Multiple opens work (sort of - see webpage mentioned above).
- * Cleaned up comments. Removed multiple PID/VID definitions.
- * Factorised cts/dtr code
- * Made use of __FUNCTION__ in dbg's
+ * Added spinlock protected open code and close code.
+ * Multiple opens work (sort of - see webpage mentioned above).
+ * Cleaned up comments. Removed multiple PID/VID definitions.
+ * Factorised cts/dtr code
+ * Made use of __FUNCTION__ in dbg's
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
@@ -72,16 +181,16 @@
* driver is a loadable module now.
*
* (04/04/2000) Bill Ryder
- * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
+ * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
* handled elsewhere in the tty io driver chain).
*
* (03/30/2000) Bill Ryder
- * Implemented lots of ioctls
- * Fixed a race condition in write
- * Changed some dbg's to errs
+ * Implemented lots of ioctls
+ * Fixed a race condition in write
+ * Changed some dbg's to errs
*
* (03/26/2000) gkh
- * Split driver up into device specific pieces.
+ * Split driver up into device specific pieces.
*
*/
@@ -90,7 +199,6 @@
/* to talk to the device */
/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
-
#include
#include
#include
@@ -103,6 +211,7 @@
#include
#include
#include
+#include
#ifdef CONFIG_USB_SERIAL_DEBUG
static int debug = 1;
#else
@@ -112,47 +221,244 @@
#include "usb-serial.h"
#include "ftdi_sio.h"
-
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.2.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder "
-#define DRIVER_DESC "USB FTDI RS232 Converters Driver"
+#define DRIVER_VERSION "v1.4.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober "
+#define DRIVER_DESC "USB FTDI Serial Converters Driver"
static struct usb_device_id id_table_sio [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ } /* Terminating entry */
};
-/* THe 8U232AM has the same API as the sio except for:
- - it can support MUCH higher baudrates (921600 at 48MHz/230400
- at 12MHz so .. it's baudrate setting codes are different
- - it has a two byte status code.
- - it returns characters very 16ms (the FTDI does it every 40ms)
- */
+/*
+ * The 8U232AM has the same API as the sio except for:
+ * - it can support MUCH higher baudrates; up to:
+ * o 921600 for RS232 and 2000000 for RS422/485 at 48MHz
+ * o 230400 at 12MHz
+ * so .. 8U232AM's baudrate setting codes are different
+ * - it has a two byte status code.
+ * - it returns characters every 16ms (the FTDI does it every 40ms)
+ *
+ * the bcdDevice value is used to differentiate FT232BM and FT245BM from
+ * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID
+ * combinations in both tables.
+ * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know
+ * if those ever went into mass production. [Ian Abbott]
+ */
+
-
static struct usb_device_id id_table_8U232AM [] = {
- { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
- { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
+ { } /* Terminating entry */
+};
+
+
+static struct usb_device_id id_table_FT232BM [] = {
+ { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
{ } /* Terminating entry */
};
-static struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_USB_UIRT [] = {
+ { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
+ { } /* Terminating entry */
+};
+
+
+static struct usb_device_id id_table_HE_TIRA1 [] = {
+ { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
+ { } /* Terminating entry */
+};
+
+
+static __devinitdata struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID) },
+ { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
+ { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver ftdi_driver = {
- .owner = THIS_MODULE,
.name = "ftdi_sio",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
@@ -160,31 +466,63 @@
};
+/* Constants for read urb and write urb */
+#define BUFSZ 512
+#define PKTSZ 64
+
struct ftdi_private {
- enum ftdi_type ftdi_type;
- __u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */
- int write_offset;
+ ftdi_chip_type_t chip_type;
+ /* type of the device, either SIO or FT8U232AM */
+ int baud_base; /* baud base clock for divisor setting */
+ int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+ __u16 last_set_data_urb_value ;
+ /* the last data state set - needed for doing a break */
+ int write_offset; /* This is the offset in the usb data block to write the serial data -
+ * it is different between devices
+ */
+ int flags; /* some ASYNC_xxxx flags are supported */
+ unsigned long last_dtr_rts; /* saved modem control outputs */
+ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ char prev_status, diff_status; /* Used for TIOCMIWAIT */
+
+ int force_baud; /* if non-zero, force the baud rate to this value */
+ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
};
+
+/* Used for TIOCMIWAIT */
+#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
+#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
+/* End TIOCMIWAIT */
+
+#define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \
+ ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
+
/* function prototypes for a FTDI serial converter */
-static int ftdi_sio_startup (struct usb_serial *serial);
+static int ftdi_SIO_startup (struct usb_serial *serial);
static int ftdi_8U232AM_startup (struct usb_serial *serial);
-static void ftdi_sio_shutdown (struct usb_serial *serial);
-static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp);
-static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp);
-static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
-static int ftdi_sio_write_room (struct usb_serial_port *port);
-static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
-static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file);
-static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state );
-
-/* Should rename most ftdi_sio's to ftdi_ now since there are two devices
- which share common code */
+static int ftdi_FT232BM_startup (struct usb_serial *serial);
+static int ftdi_USB_UIRT_startup (struct usb_serial *serial);
+static int ftdi_HE_TIRA1_startup (struct usb_serial *serial);
+static void ftdi_shutdown (struct usb_serial *serial);
+static int ftdi_open (struct usb_serial_port *port, struct file *filp);
+static void ftdi_close (struct usb_serial_port *port, struct file *filp);
+static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int ftdi_write_room (struct usb_serial_port *port);
+static int ftdi_chars_in_buffer (struct usb_serial_port *port);
+static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
+static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old);
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl (struct usb_serial_port *port, int break_state );
+static void ftdi_throttle (struct usb_serial_port *port);
+static void ftdi_unthrottle (struct usb_serial_port *port);
+
+static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
+static unsigned short int ftdi_232am_baud_to_divisor (int baud);
+static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
+static __u32 ftdi_232bm_baud_to_divisor (int baud);
-static struct usb_serial_device_type ftdi_sio_device = {
+static struct usb_serial_device_type ftdi_SIO_device = {
.owner = THIS_MODULE,
.name = "FTDI SIO",
.id_table = id_table_sio,
@@ -192,77 +530,206 @@
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_ports = 1,
- .open = ftdi_sio_open,
- .close = ftdi_sio_close,
- .write = ftdi_sio_write,
- .write_room = ftdi_sio_write_room,
- .read_bulk_callback = ftdi_sio_read_bulk_callback,
- .write_bulk_callback = ftdi_sio_write_bulk_callback,
- .ioctl = ftdi_sio_ioctl,
- .set_termios = ftdi_sio_set_termios,
- .break_ctl = ftdi_sio_break_ctl,
- .tiocmget = ftdi_sio_tiocmget,
- .tiocmset = ftdi_sio_tiocmset,
- .attach = ftdi_sio_startup,
- .shutdown = ftdi_sio_shutdown,
+ .open = ftdi_open,
+ .close = ftdi_close,
+ .throttle = ftdi_throttle,
+ .unthrottle = ftdi_unthrottle,
+ .write = ftdi_write,
+ .write_room = ftdi_write_room,
+ .chars_in_buffer = ftdi_chars_in_buffer,
+ .read_bulk_callback = ftdi_read_bulk_callback,
+ .write_bulk_callback = ftdi_write_bulk_callback,
+ .ioctl = ftdi_ioctl,
+ .set_termios = ftdi_set_termios,
+ .break_ctl = ftdi_break_ctl,
+ .attach = ftdi_SIO_startup,
+ .shutdown = ftdi_shutdown,
};
static struct usb_serial_device_type ftdi_8U232AM_device = {
.owner = THIS_MODULE,
- .name = "FTDI 8U232AM",
+ .name = "FTDI 8U232AM Compatible",
.id_table = id_table_8U232AM,
.num_interrupt_in = 0,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_ports = 1,
- .open = ftdi_sio_open,
- .close = ftdi_sio_close,
- .write = ftdi_sio_write,
- .write_room = ftdi_sio_write_room,
- .read_bulk_callback = ftdi_sio_read_bulk_callback,
- .write_bulk_callback = ftdi_sio_write_bulk_callback,
- .ioctl = ftdi_sio_ioctl,
- .set_termios = ftdi_sio_set_termios,
- .break_ctl = ftdi_sio_break_ctl,
- .tiocmget = ftdi_sio_tiocmget,
- .tiocmset = ftdi_sio_tiocmset,
+ .open = ftdi_open,
+ .close = ftdi_close,
+ .throttle = ftdi_throttle,
+ .unthrottle = ftdi_unthrottle,
+ .write = ftdi_write,
+ .write_room = ftdi_write_room,
+ .chars_in_buffer = ftdi_chars_in_buffer,
+ .read_bulk_callback = ftdi_read_bulk_callback,
+ .write_bulk_callback = ftdi_write_bulk_callback,
+ .ioctl = ftdi_ioctl,
+ .set_termios = ftdi_set_termios,
+ .break_ctl = ftdi_break_ctl,
.attach = ftdi_8U232AM_startup,
- .shutdown = ftdi_sio_shutdown,
+ .shutdown = ftdi_shutdown,
+};
+
+static struct usb_serial_device_type ftdi_FT232BM_device = {
+ .owner = THIS_MODULE,
+ .name = "FTDI FT232BM Compatible",
+ .id_table = id_table_FT232BM,
+ .num_interrupt_in = 0,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = ftdi_open,
+ .close = ftdi_close,
+ .throttle = ftdi_throttle,
+ .unthrottle = ftdi_unthrottle,
+ .write = ftdi_write,
+ .write_room = ftdi_write_room,
+ .chars_in_buffer = ftdi_chars_in_buffer,
+ .read_bulk_callback = ftdi_read_bulk_callback,
+ .write_bulk_callback = ftdi_write_bulk_callback,
+ .ioctl = ftdi_ioctl,
+ .set_termios = ftdi_set_termios,
+ .break_ctl = ftdi_break_ctl,
+ .attach = ftdi_FT232BM_startup,
+ .shutdown = ftdi_shutdown,
};
+static struct usb_serial_device_type ftdi_USB_UIRT_device = {
+ .owner = THIS_MODULE,
+ .name = "USB-UIRT Infrared Receiver/Transmitter",
+ .id_table = id_table_USB_UIRT,
+ .num_interrupt_in = 0,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = ftdi_open,
+ .close = ftdi_close,
+ .throttle = ftdi_throttle,
+ .unthrottle = ftdi_unthrottle,
+ .write = ftdi_write,
+ .write_room = ftdi_write_room,
+ .chars_in_buffer = ftdi_chars_in_buffer,
+ .read_bulk_callback = ftdi_read_bulk_callback,
+ .write_bulk_callback = ftdi_write_bulk_callback,
+ .ioctl = ftdi_ioctl,
+ .set_termios = ftdi_set_termios,
+ .break_ctl = ftdi_break_ctl,
+ .attach = ftdi_USB_UIRT_startup,
+ .shutdown = ftdi_shutdown,
+};
+
+/* The TIRA1 is based on a FT232BM which requires a fixed baud rate of 100000
+ * and which requires RTS-CTS to be enabled. */
+static struct usb_serial_device_type ftdi_HE_TIRA1_device = {
+ .owner = THIS_MODULE,
+ .name = "Home-Electronics TIRA-1 IR Transceiver",
+ .id_table = id_table_HE_TIRA1,
+ .num_interrupt_in = 0,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = ftdi_open,
+ .close = ftdi_close,
+ .throttle = ftdi_throttle,
+ .unthrottle = ftdi_unthrottle,
+ .write = ftdi_write,
+ .write_room = ftdi_write_room,
+ .chars_in_buffer = ftdi_chars_in_buffer,
+ .read_bulk_callback = ftdi_read_bulk_callback,
+ .write_bulk_callback = ftdi_write_bulk_callback,
+ .ioctl = ftdi_ioctl,
+ .set_termios = ftdi_set_termios,
+ .break_ctl = ftdi_break_ctl,
+ .attach = ftdi_HE_TIRA1_startup,
+ .shutdown = ftdi_shutdown,
+};
+
+
+
+#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+/* High and low are for DTR, RTS etc etc */
+#define HIGH 1
+#define LOW 0
/*
* ***************************************************************************
- * FTDI SIO Serial Converter specific driver functions
+ * Utlity functions
* ***************************************************************************
*/
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
+{
+ unsigned short int divisor;
+ int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+ if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
+ divisor = divisor3 >> 3;
+ divisor3 &= 0x7;
+ if (divisor3 == 1) divisor |= 0xc000; else // 0.125
+ if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
+ if (divisor3 != 0) divisor |= 0x8000; // 0.25
+ if (divisor == 1) divisor = 0; /* special case for maximum baud rate */
+ return divisor;
+}
-/* utility functions to set and unset dtr and rts */
-#define HIGH 1
-#define LOW 0
-static int set_rts(struct usb_device *dev,
- unsigned int pipe,
- int high_or_low)
-{
- static char buf[1];
- unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH :
- FTDI_SIO_SET_RTS_LOW);
- return(usb_control_msg(dev, pipe,
+static unsigned short int ftdi_232am_baud_to_divisor(int baud)
+{
+ return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
+}
+
+static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
+{
+ static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
+ __u32 divisor;
+ int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+ divisor = divisor3 >> 3;
+ divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
+ /* Deal with special cases for highest baud rates. */
+ if (divisor == 1) divisor = 0; else // 1.0
+ if (divisor == 0x4001) divisor = 1; // 1.5
+ return divisor;
+}
+
+static __u32 ftdi_232bm_baud_to_divisor(int baud)
+{
+ return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
+}
+
+static int set_rts(struct usb_serial_port *port, int high_or_low)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char buf[1];
+ unsigned ftdi_high_or_low;
+ if (high_or_low) {
+ ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH;
+ priv->last_dtr_rts |= TIOCM_RTS;
+ } else {
+ ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW;
+ priv->last_dtr_rts &= ~TIOCM_RTS;
+ }
+ return(usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_MODEM_CTRL_REQUEST,
FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
ftdi_high_or_low, 0,
buf, 0, WDR_TIMEOUT));
}
-static int set_dtr(struct usb_device *dev,
- unsigned int pipe,
- int high_or_low)
-{
- static char buf[1];
- unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH :
- FTDI_SIO_SET_DTR_LOW);
- return(usb_control_msg(dev, pipe,
+
+
+static int set_dtr(struct usb_serial_port *port, int high_or_low)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char buf[1];
+ unsigned ftdi_high_or_low;
+ if (high_or_low) {
+ ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH;
+ priv->last_dtr_rts |= TIOCM_DTR;
+ } else {
+ ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW;
+ priv->last_dtr_rts &= ~TIOCM_DTR;
+ }
+ return(usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_MODEM_CTRL_REQUEST,
FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
ftdi_high_or_low, 0,
@@ -270,71 +737,409 @@
}
+static __u32 get_ftdi_divisor(struct usb_serial_port * port);
+
+
+static int change_speed(struct usb_serial_port *port)
+{
+ char buf[1];
+ __u16 urb_value;
+ __u16 urb_index;
+ __u32 urb_index_value;
+
+ urb_index_value = get_ftdi_divisor(port);
+ urb_value = (__u16)urb_index_value;
+ urb_index = (__u16)(urb_index_value >> 16);
+
+ return (usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_BAUDRATE_REQUEST,
+ FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+ urb_value, urb_index,
+ buf, 0, 100) < 0);
+}
+
+
+static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+{ /* get_ftdi_divisor */
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ __u32 div_value = 0;
+ int div_okay = 1;
+ char *chip_name = "";
+ int baud;
+
+ /*
+ * The logic involved in setting the baudrate can be cleanly split in 3 steps.
+ * Obtaining the actual baud rate is a little tricky since unix traditionally
+ * somehow ignored the possibility to set non-standard baud rates.
+ * 1. Standard baud rates are set in tty->termios->c_cflag
+ * 2. If these are not enough, you can set any speed using alt_speed as follows:
+ * - set tty->termios->c_cflag speed to B38400
+ * - set your real speed in tty->alt_speed; it gets ignored when
+ * alt_speed==0, (or)
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+ * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
+ * sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+ * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
+ * 3. You can also set baud rate by setting custom divisor as follows
+ * - set tty->termios->c_cflag speed to B38400
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+ * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
+ * o custom_divisor set to baud_base / your_new_baudrate
+ * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
+ * spend some time and separate+move this common code to serial.c, it is
+ * replicated in nearly every serial driver you see.
+ */
+
+ /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+
+ baud = tty_get_baud_rate(port->tty);
+ dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud);
+
+ /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+
+ if (baud == 38400 &&
+ ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+ (priv->custom_divisor)) {
+ baud = priv->baud_base / priv->custom_divisor;
+ dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud);
+ }
+
+ /* 3. Convert baudrate to device-specific divisor */
+
+ if (!baud) baud = 9600;
+ switch(priv->chip_type) {
+ case SIO: /* SIO chip */
+ chip_name = "SIO";
+ switch(baud) {
+ case 300: div_value = ftdi_sio_b300; break;
+ case 600: div_value = ftdi_sio_b600; break;
+ case 1200: div_value = ftdi_sio_b1200; break;
+ case 2400: div_value = ftdi_sio_b2400; break;
+ case 4800: div_value = ftdi_sio_b4800; break;
+ case 9600: div_value = ftdi_sio_b9600; break;
+ case 19200: div_value = ftdi_sio_b19200; break;
+ case 38400: div_value = ftdi_sio_b38400; break;
+ case 57600: div_value = ftdi_sio_b57600; break;
+ case 115200: div_value = ftdi_sio_b115200; break;
+ } /* baud */
+ if (div_value == 0) {
+ dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud);
+ div_value = ftdi_sio_b9600;
+ div_okay = 0;
+ }
+ break;
+ case FT8U232AM: /* 8U232AM chip */
+ chip_name = "FT8U232AM";
+ if (baud <= 3000000) {
+ div_value = ftdi_232am_baud_to_divisor(baud);
+ } else {
+ dbg("%s - Baud rate too high!", __FUNCTION__);
+ div_value = ftdi_232am_baud_to_divisor(9600);
+ div_okay = 0;
+ }
+ break;
+ case FT232BM: /* FT232BM chip */
+ chip_name = "FT232BM";
+ if (baud <= 3000000) {
+ div_value = ftdi_232bm_baud_to_divisor(baud);
+ } else {
+ dbg("%s - Baud rate too high!", __FUNCTION__);
+ div_value = ftdi_232bm_baud_to_divisor(9600);
+ div_okay = 0;
+ }
+ break;
+ } /* priv->chip_type */
+
+ if (div_okay) {
+ dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+ __FUNCTION__, baud, (unsigned long)div_value, chip_name);
+ }
+
+ return(div_value);
+}
+
-static int ftdi_sio_startup (struct usb_serial *serial)
+static int get_serial_info(struct usb_serial_port * port, struct serial_struct * retinfo)
{
- struct ftdi_private *priv;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.flags = priv->flags;
+ tmp.baud_base = priv->baud_base;
+ tmp.custom_divisor = priv->custom_divisor;
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+} /* get_serial_info */
+
+
+static int set_serial_info(struct usb_serial_port * port, struct serial_struct * newinfo)
+{ /* set_serial_info */
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct serial_struct new_serial;
+ struct ftdi_private old_priv;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+ old_priv = * priv;
+
+ /* Do error checking and permission checking */
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (priv->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ priv->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ if ((new_serial.baud_base != priv->baud_base) ||
+ (new_serial.baud_base < 9600))
+ return -EINVAL;
+
+ /* Make the changes - these are privileged changes! */
+
+ priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
+ priv->custom_divisor = new_serial.custom_divisor;
+
+ port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+check_and_exit:
+ if ((old_priv.flags & ASYNC_SPD_MASK) !=
+ (priv->flags & ASYNC_SPD_MASK)) {
+ if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ port->tty->alt_speed = 57600;
+ else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ port->tty->alt_speed = 115200;
+ else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ port->tty->alt_speed = 230400;
+ else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ port->tty->alt_speed = 460800;
+ else
+ port->tty->alt_speed = 0;
+ }
+ if (((old_priv.flags & ASYNC_SPD_MASK) !=
+ (priv->flags & ASYNC_SPD_MASK)) ||
+ (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+ (old_priv.custom_divisor != priv->custom_divisor))) {
+ change_speed(port);
+ }
+ return (0);
+
+} /* set_serial_info */
+
+/*
+ * ***************************************************************************
+ * FTDI driver specific functions
+ * ***************************************************************************
+ */
+
+/* Common startup subroutine */
+/* Called from ftdi_SIO_startup, etc. */
+static int ftdi_common_startup (struct usb_serial *serial)
+{
+ struct usb_serial_port *port = &serial->port[0];
+ struct ftdi_private *priv;
+ dbg("%s",__FUNCTION__);
+
priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv){
err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
return -ENOMEM;
}
+ memset(priv, 0, sizeof(*priv));
- priv->ftdi_type = sio;
- priv->write_offset = 1;
- usb_set_serial_port_data(serial->port, priv);
+ init_waitqueue_head(&priv->delta_msr_wait);
+ /* This will push the characters through immediately rather
+ than queue a task to deliver them */
+ priv->flags = ASYNC_LOW_LATENCY;
+
+ /* Increase the size of read buffers */
+ if (port->bulk_in_buffer) {
+ kfree (port->bulk_in_buffer);
+ }
+ port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
+ if (!port->bulk_in_buffer) {
+ kfree (priv);
+ return -ENOMEM;
+ }
+ if (port->read_urb) {
+ port->read_urb->transfer_buffer = port->bulk_in_buffer;
+ port->read_urb->transfer_buffer_length = BUFSZ;
+ }
+
+ /* Free port's existing write urb and transfer buffer. */
+ if (port->write_urb) {
+ usb_free_urb (port->write_urb);
+ port->write_urb = NULL;
+ }
+ if (port->bulk_out_buffer) {
+ kfree (port->bulk_out_buffer);
+ port->bulk_out_buffer = NULL;
+ }
+ usb_set_serial_port_data(serial->port, priv);
+
return (0);
}
-static int ftdi_8U232AM_startup (struct usb_serial *serial)
+/* Startup for the SIO chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_SIO_startup (struct usb_serial *serial)
{
struct ftdi_private *priv;
-
+ int err;
- priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
- if (!priv){
- err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
- return -ENOMEM;
- }
+ dbg("%s",__FUNCTION__);
- priv->ftdi_type = F8U232AM;
- priv->write_offset = 0;
- usb_set_serial_port_data(serial->port, priv);
+ err = ftdi_common_startup(serial);
+ if (err){
+ return (err);
+ }
+ priv = usb_get_serial_port_data(serial->port);
+ priv->chip_type = SIO;
+ priv->baud_base = 12000000 / 16;
+ priv->write_offset = 1;
+
return (0);
}
-static void ftdi_sio_shutdown (struct usb_serial *serial)
-{
- void *priv;
+/* Startup for the 8U232AM chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_8U232AM_startup (struct usb_serial *serial)
+{ /* ftdi_8U232AM_startup */
+ struct ftdi_private *priv;
+ int err;
+
+ dbg("%s",__FUNCTION__);
+ err = ftdi_common_startup(serial);
+ if (err){
+ return (err);
+ }
+
+ priv = usb_get_serial_port_data(serial->port);
+ priv->chip_type = FT8U232AM;
+ priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
+
+ return (0);
+} /* ftdi_8U232AM_startup */
+
+/* Startup for the FT232BM chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_FT232BM_startup (struct usb_serial *serial)
+{ /* ftdi_FT232BM_startup */
+ struct ftdi_private *priv;
+ int err;
+
+ dbg("%s",__FUNCTION__);
+ err = ftdi_common_startup(serial);
+ if (err){
+ return (err);
+ }
+
+ priv = usb_get_serial_port_data(serial->port);
+ priv->chip_type = FT232BM;
+ priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */
+
+ return (0);
+} /* ftdi_FT232BM_startup */
+
+/* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
+/* Called from usbserial:serial_probe */
+static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
+{ /* ftdi_USB_UIRT_startup */
+ struct ftdi_private *priv;
+ int err;
+
+ dbg("%s",__FUNCTION__);
+ err = ftdi_8U232AM_startup(serial);
+ if (err){
+ return (err);
+ }
+
+ priv = usb_get_serial_port_data(serial->port);
+ priv->flags |= ASYNC_SPD_CUST;
+ priv->custom_divisor = 77;
+ priv->force_baud = B38400;
+
+ return (0);
+} /* ftdi_USB_UIRT_startup */
+
+/* Startup for the HE-TIRA1 device, which requires hardwired
+ * baudrate (38400 gets mapped to 100000) */
+static int ftdi_HE_TIRA1_startup (struct usb_serial *serial)
+{ /* ftdi_HE_TIRA1_startup */
+ struct ftdi_private *priv;
+ int err;
+
+ dbg("%s",__FUNCTION__);
+ err = ftdi_FT232BM_startup(serial);
+ if (err){
+ return (err);
+ }
+
+ priv = usb_get_serial_port_data(serial->port);
+ priv->flags |= ASYNC_SPD_CUST;
+ priv->custom_divisor = 240;
+ priv->force_baud = B38400;
+ priv->force_rtscts = 1;
+
+ return (0);
+} /* ftdi_HE_TIRA1_startup */
+
+
+/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
+ * it is called when the usb device is disconnected
+ *
+ * usbserial:usb_serial_disconnect
+ * calls __serial_close for each open of the port
+ * shutdown is called then (ie ftdi_shutdown)
+ */
+
+
+static void ftdi_shutdown (struct usb_serial *serial)
+{ /* ftdi_shutdown */
+
+ struct usb_serial_port *port = serial->port;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s", __FUNCTION__);
- priv = usb_get_serial_port_data(&serial->port[0]);
- if (priv){
+ /* all open ports are closed at this point
+ * (by usbserial.c:__serial_close, which calls ftdi_close)
+ */
+
+ if (priv) {
kfree(priv);
- usb_set_serial_port_data(&serial->port[0], NULL);
+ usb_set_serial_port_data(port, NULL);
}
-}
-
+} /* ftdi_shutdown */
-static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
-{ /* ftdi_sio_open */
+static int ftdi_open (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_open */
struct termios tmp_termios;
struct usb_serial *serial = port->serial;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+
int result = 0;
char buf[1]; /* Needed for the usb_control_msg I think */
dbg("%s", __FUNCTION__);
- /* This will push the characters through immediately rather
- than queue a task to deliver them */
- port->tty->low_latency = 1;
+
+ port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
@@ -343,19 +1148,20 @@
FTDI_SIO_RESET_SIO,
0, buf, 0, WDR_TIMEOUT);
- /* Setup termios defaults. According to tty_io.c the
- settings are driver specific */
- port->tty->termios->c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ /* Termios defaults are set by usb_serial_init. We don't change
+ port->tty->termios - this would loose speed settings, etc.
+ This is same behaviour as serial.c/rs_open() - Kuba */
- /* ftdi_sio_set_termios will send usb control messages */
- ftdi_sio_set_termios(port, &tmp_termios);
+ /* ftdi_set_termios will send usb control messages */
+ ftdi_set_termios(port, &tmp_termios);
+ /* FIXME: Flow control might be enabled, so it should be checked -
+ we have no control of defaults! */
/* Turn on RTS and DTR since we are not flow controlling by default */
- if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
+ if (set_dtr(port, HIGH) < 0) {
err("%s Error from DTR HIGH urb", __FUNCTION__);
}
- if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
+ if (set_rts(port, HIGH) < 0){
err("%s Error from RTS HIGH urb", __FUNCTION__);
}
@@ -363,23 +1169,37 @@
usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ftdi_sio_read_bulk_callback, port);
+ ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+
return result;
-} /* ftdi_sio_open */
+} /* ftdi_open */
+
-static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
-{ /* ftdi_sio_close */
- struct usb_serial *serial = port->serial; /* Checked in usbserial.c */
+/*
+ * usbserial:__serial_close only calls ftdi_close if the point is open
+ *
+ * This only gets called when it is the last close
+ *
+ *
+ */
+
+static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_close */
+ struct usb_serial *serial;
unsigned int c_cflag = port->tty->termios->c_cflag;
char buf[1];
dbg("%s", __FUNCTION__);
+ serial = get_usb_serial ( port, __FUNCTION__);
+ if (!serial)
+ return;
+
if (serial->dev) {
if (c_cflag & HUPCL){
/* Disable flow control */
@@ -392,38 +1212,46 @@
}
/* drop DTR */
- if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
+ if (set_dtr(port, LOW) < 0){
err("Error from DTR LOW urb");
}
/* drop RTS */
- if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
+ if (set_rts(port, LOW) < 0) {
err("Error from RTS LOW urb");
}
+ /* shutdown our bulk read */
+ if (port->read_urb) {
+ usb_unlink_urb (port->read_urb);
+ }
+ /* unlink the running write urbs */
+
+
} /* Note change no line is hupcl is off */
+ } /* if (serial->dev) */
- /* shutdown our bulk reads and writes */
- /* ***CHECK*** behaviour when there is nothing queued */
- usb_unlink_urb (port->write_urb);
- usb_unlink_urb (port->read_urb);
- }
-} /* ftdi_sio_close */
+
+} /* ftdi_close */
-/* The ftdi_sio requires the first byte to have:
+/* The SIO requires the first byte to have:
* B0 1
* B1 0
* B2..7 length of message excluding byte 0
+ *
+ * The new devices do not require this byte
*/
-static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
+static int ftdi_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
-{ /* ftdi_sio_write */
- struct usb_serial *serial = port->serial;
+{ /* ftdi_write */
+ struct usb_serial *serial = get_usb_serial ( port, __FUNCTION__);
struct ftdi_private *priv = usb_get_serial_port_data(port);
- unsigned char *first_byte = port->write_urb->transfer_buffer;
- int data_offset ;
- int result;
-
+ struct urb *urb;
+ unsigned char *buffer;
+ int data_offset ; /* will be 1 for the SIO and 0 otherwise */
+ int status;
+ int transfer_size;
+
dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
if (count == 0) {
@@ -434,123 +1262,209 @@
data_offset = priv->write_offset;
dbg("data_offset set to %d",data_offset);
- if (port->write_urb->status == -EINPROGRESS) {
- dbg("%s - already writing", __FUNCTION__);
- return (0);
- }
-
- count += data_offset;
- count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
- /* Copy in the data to send */
- if (from_user) {
- if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
- buf, count - data_offset )){
- return -EFAULT;
+ /* Determine total transfer size */
+ transfer_size = count;
+ if (data_offset > 0) {
+ /* Original sio needs control bytes too... */
+ transfer_size += (data_offset *
+ ((count + (PKTSZ - 1 - data_offset)) /
+ (PKTSZ - data_offset)));
+ }
+
+ buffer = kmalloc (transfer_size, GFP_ATOMIC);
+ if (!buffer) {
+ err("%s ran out of kernel memory for urb ...", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ err("%s - no more free urbs", __FUNCTION__);
+ kfree (buffer);
+ return -ENOMEM;
+ }
+
+ /* Copy data */
+ if (data_offset > 0) {
+ /* Original sio requires control byte at start of each packet. */
+ int user_pktsz = PKTSZ - data_offset;
+ int todo = count;
+ unsigned char *first_byte = buffer;
+ const unsigned char *current_position = buf;
+
+ while (todo > 0) {
+ if (user_pktsz > todo) {
+ user_pktsz = todo;
+ }
+ /* Write the control byte at the front of the packet*/
+ *first_byte = 1 | ((user_pktsz) << 2);
+ /* Copy data for packet */
+ if (from_user) {
+ if (copy_from_user (first_byte + data_offset,
+ current_position, user_pktsz)){
+ kfree (buffer);
+ usb_free_urb (urb);
+ return -EFAULT;
+ }
+ } else {
+ memcpy (first_byte + data_offset,
+ current_position, user_pktsz);
+ }
+ first_byte += user_pktsz + data_offset;
+ current_position += user_pktsz;
+ todo -= user_pktsz;
}
} else {
- memcpy(port->write_urb->transfer_buffer + data_offset,
- buf, count - data_offset );
- }
-
- first_byte = port->write_urb->transfer_buffer;
- if (data_offset > 0){
- /* Write the control byte at the front of the packet*/
- *first_byte = 1 | ((count-data_offset) << 2) ;
+ /* No control byte required. */
+ /* Copy in the data to send */
+ if (from_user) {
+ if (copy_from_user (buffer, buf, count)) {
+ kfree (buffer);
+ usb_free_urb (urb);
+ return -EFAULT;
+ }
+ } else {
+ memcpy (buffer, buf, count);
+ }
}
- dbg("%s Bytes: %d, First Byte: 0x%02x", __FUNCTION__,count, first_byte[0]);
- usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
-
- /* send the data out the bulk port */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, buffer);
+
+ /* fill the buffer and send it */
+ usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count,
- ftdi_sio_write_bulk_callback, port);
-
- result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
- return 0;
+ buffer, transfer_size,
+ ftdi_write_bulk_callback, port);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
+ count = status;
}
- dbg("%s write returning: %d", __FUNCTION__, count - data_offset);
- return (count - data_offset);
-} /* ftdi_sio_write */
+ /* we are done with this urb, so let the host driver
+ * really free it when it is finished with it */
+ usb_free_urb (urb);
+
+ dbg("%s write returning: %d", __FUNCTION__, count);
+ return count;
+} /* ftdi_write */
-static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+
+/* This function may get called when the device is closed */
+
+static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial;
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg("%s", __FUNCTION__);
- if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) {
+ if (port_paranoia_check (port, __FUNCTION__))
return;
- }
-
- serial = port->serial;
- if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) {
- return;
- }
if (urb->status) {
dbg("nonzero write bulk status received: %d", urb->status);
return;
}
- schedule_work(&port->work);
-} /* ftdi_sio_write_bulk_callback */
+ if (!serial) {
+ dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+ return;
+ }
+
+ /* Have to check for validity of queueing up the tasks */
+ dbg("%s - port->open_count = %d", __FUNCTION__, port->open_count);
+
+ if (port->open_count > 0){
+ schedule_work(&port->work);
+ }
+ return;
+} /* ftdi_write_bulk_callback */
-static int ftdi_sio_write_room( struct usb_serial_port *port )
+
+static int ftdi_write_room( struct usb_serial_port *port )
{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- int room;
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /*
+ * We really can take anything the user throws at us
+ * but let's pick a nice big number to tell the tty
+ * layer that we have lots of free space
+ */
+ return 2048;
+} /* ftdi_write_room */
- if ( port->write_urb->status == -EINPROGRESS) {
- /* There is a race here with the _write routines but it won't hurt */
- room = 0;
- } else {
- room = port->bulk_out_size - priv->write_offset;
- }
- return(room);
-} /* ftdi_sio_write_room */
+static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+{ /* ftdi_chars_in_buffer */
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /*
+ * We can't really account for how much data we
+ * have sent out, but hasn't made it through to the
+ * device, so just tell the tty layer that everything
+ * is flushed.
+ */
+ return 0;
+} /* ftdi_chars_in_buffer */
-static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{ /* ftdi_sio_serial_buld_callback */
+
+
+static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{ /* ftdi_read_bulk_callback */
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial;
- struct tty_struct *tty = port->tty ;
+ struct tty_struct *tty;
+ struct ftdi_private *priv;
char error_flag;
unsigned char *data = urb->transfer_buffer;
- const int data_offset = 2;
int i;
int result;
+ int need_flip;
+ int packet_offset;
- dbg("%s - port %d", __FUNCTION__, port->number);
+ if (urb->number_of_packets > 0) {
+ err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
+ urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
+ err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags );
+ }
+
+ dbg("%s", __FUNCTION__);
- if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
+ if (port_paranoia_check (port, __FUNCTION__)) {
return;
}
+ if (port->open_count <= 0)
+ return;
- serial = port->serial;
- if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) {
+ serial = get_usb_serial(port,__FUNCTION__);
+ if (!serial){
+ dbg("%s - bad serial pointer - exiting",__FUNCTION__);
+ return;
+ }
+
+ tty = port->tty;
+ if (!tty) {
+ dbg("%s - bad tty pointer - exiting",__FUNCTION__);
return;
}
+ priv = usb_get_serial_port_data(port);
+
if (urb->status) {
/* This will happen at close every time so it is a dbg not an err */
- dbg("nonzero read bulk status received: %d", urb->status);
+ dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status);
return;
}
+ /* The first two bytes of every read packet are status */
if (urb->actual_length > 2) {
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
} else {
- dbg("Just status 0o%03o0o%03o",data[0],data[1]);
+ dbg("Status only: %03oo %03oo",data[0],data[1]);
}
@@ -559,129 +1473,101 @@
/* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
/* if CD is dropped and the line is not CLOCAL then we should hangup */
- /* Handle errors and break */
- error_flag = TTY_NORMAL;
- /* Although the device uses a bitmask and hence can have multiple */
- /* errors on a packet - the order here sets the priority the */
- /* error is returned to the tty layer */
-
- if ( data[1] & FTDI_RS_OE ) {
- error_flag = TTY_OVERRUN;
- dbg("OVERRRUN error");
- }
- if ( data[1] & FTDI_RS_BI ) {
- error_flag = TTY_BREAK;
- dbg("BREAK received");
- }
- if ( data[1] & FTDI_RS_PE ) {
- error_flag = TTY_PARITY;
- dbg("PARITY error");
- }
- if ( data[1] & FTDI_RS_FE ) {
- error_flag = TTY_FRAME;
- dbg("FRAMING error");
- }
- if (urb->actual_length > data_offset) {
-
- for (i = data_offset ; i < urb->actual_length ; ++i) {
- /* have to make sure we don't overflow the buffer
- with tty_insert_flip_char's */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* Note that the error flag is duplicated for
- every character received since we don't know
- which character it applied to */
- tty_insert_flip_char(tty, data[i], error_flag);
+ need_flip = 0;
+ for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ /* Compare new line status to the old one, signal if different */
+ if (priv != NULL) {
+ char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
+ if (new_status != priv->prev_status) {
+ priv->diff_status |= new_status ^ priv->prev_status;
+ wake_up_interruptible(&priv->delta_msr_wait);
+ priv->prev_status = new_status;
+ }
}
- tty_flip_buffer_push(tty);
-
- }
+ /* Handle errors and break */
+ error_flag = TTY_NORMAL;
+ /* Although the device uses a bitmask and hence can have multiple */
+ /* errors on a packet - the order here sets the priority the */
+ /* error is returned to the tty layer */
+
+ if ( data[packet_offset+1] & FTDI_RS_OE ) {
+ error_flag = TTY_OVERRUN;
+ dbg("OVERRRUN error");
+ }
+ if ( data[packet_offset+1] & FTDI_RS_BI ) {
+ error_flag = TTY_BREAK;
+ dbg("BREAK received");
+ }
+ if ( data[packet_offset+1] & FTDI_RS_PE ) {
+ error_flag = TTY_PARITY;
+ dbg("PARITY error");
+ }
+ if ( data[packet_offset+1] & FTDI_RS_FE ) {
+ error_flag = TTY_FRAME;
+ dbg("FRAMING error");
+ }
+ if (urb->actual_length > packet_offset + 2) {
+ for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) {
+ /* have to make sure we don't overflow the buffer
+ with tty_insert_flip_char's */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* Note that the error flag is duplicated for
+ every character received since we don't know
+ which character it applied to */
+ tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
+ }
+ need_flip = 1;
+ }
#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
- /* if a parity error is detected you get status packets forever
- until a character is sent without a parity error.
- This doesn't work well since the application receives a never
- ending stream of bad data - even though new data hasn't been sent.
- Therefore I (bill) have taken this out.
- However - this might make sense for framing errors and so on
- so I am leaving the code in for now.
- */
- else {
- if (error_flag != TTY_NORMAL){
- dbg("error_flag is not normal");
+ /* if a parity error is detected you get status packets forever
+ until a character is sent without a parity error.
+ This doesn't work well since the application receives a never
+ ending stream of bad data - even though new data hasn't been sent.
+ Therefore I (bill) have taken this out.
+ However - this might make sense for framing errors and so on
+ so I am leaving the code in for now.
+ */
+ else {
+ if (error_flag != TTY_NORMAL){
+ dbg("error_flag is not normal");
/* In this case it is just status - if that is an error send a bad character */
if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
tty_insert_flip_char(tty, 0xff, error_flag);
- tty_flip_buffer_push(tty);
+ need_flip = 1;
+ }
}
- }
#endif
+ } /* "for(packet_offset=0..." */
- /* Continue trying to always read */
- usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ftdi_sio_read_bulk_callback, port);
-
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ /* Low latency */
+ if (need_flip) {
+ tty_flip_buffer_push(tty);
+ }
+
+ /* if the port is closed stop trying to read */
+ if (port->open_count > 0){
+ /* Continue trying to always read */
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
+
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ }
return;
-} /* ftdi_sio_serial_read_bulk_callback */
-
+} /* ftdi_read_bulk_callback */
-static __u16 translate_baudrate_to_ftdi(unsigned int cflag, enum ftdi_type ftdi_type)
-{ /* translate_baudrate_to_ftdi */
-
- __u16 urb_value = ftdi_sio_b9600;
- if (ftdi_type == sio){
- switch(cflag & CBAUD){
- case B0: break; /* ignored by this */
- case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
- case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
- case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
- case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
- case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
- case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
- case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
- case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
- case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
- case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
- default: dbg("%s - FTDI_SIO does not support the baudrate (%d) requested",
- __FUNCTION__, (cflag & CBAUD));
- break;
- }
- } else { /* it is 8U232AM */
- switch(cflag & CBAUD){
- case B0: break; /* ignored by this */
- case B300: urb_value = ftdi_8U232AM_48MHz_b300; dbg("Set to 300"); break;
- case B600: urb_value = ftdi_8U232AM_48MHz_b600; dbg("Set to 600") ; break;
- case B1200: urb_value = ftdi_8U232AM_48MHz_b1200; dbg("Set to 1200") ; break;
- case B2400: urb_value = ftdi_8U232AM_48MHz_b2400; dbg("Set to 2400") ; break;
- case B4800: urb_value = ftdi_8U232AM_48MHz_b4800; dbg("Set to 4800") ; break;
- case B9600: urb_value = ftdi_8U232AM_48MHz_b9600; dbg("Set to 9600") ; break;
- case B19200: urb_value = ftdi_8U232AM_48MHz_b19200; dbg("Set to 19200") ; break;
- case B38400: urb_value = ftdi_8U232AM_48MHz_b38400; dbg("Set to 38400") ; break;
- case B57600: urb_value = ftdi_8U232AM_48MHz_b57600; dbg("Set to 57600") ; break;
- case B115200: urb_value = ftdi_8U232AM_48MHz_b115200; dbg("Set to 115200") ; break;
- case B230400: urb_value = ftdi_8U232AM_48MHz_b230400; dbg("Set to 230400") ; break;
- case B460800: urb_value = ftdi_8U232AM_48MHz_b460800; dbg("Set to 460800") ; break;
- case B921600: urb_value = ftdi_8U232AM_48MHz_b921600; dbg("Set to 921600") ; break;
- default: dbg("%s - The baudrate (%d) requested is not implemented",
- __FUNCTION__, (cflag & CBAUD));
- break;
- }
- }
- return(urb_value);
-}
-
-static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state )
+static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
{
struct usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -704,32 +1590,48 @@
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , 0,
buf, 0, WDR_TIMEOUT) < 0) {
- err("%s - FAILED to enable/disable break state (state was %d)",
- __FUNCTION__, break_state);
+ err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
}
- dbg("%s - break state is %d - urb is %d", __FUNCTION__, break_state, urb_value);
+ dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
}
+/* old_termios contains the original termios settings and tty->termios contains
+ * the new setting to be used
+ * WARNING: set_termios calls this with old_termios in kernel space
+ */
-/* As I understand this - old_termios contains the original termios settings */
-/* and tty->termios contains the new setting to be used */
-/* */
-/* WARNING: set_termios calls this with old_termios in kernel space */
-
-static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios)
-{ /* ftdi_sio_set_termios */
+static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{ /* ftdi_termios */
struct usb_serial *serial = port->serial;
unsigned int cflag = port->tty->termios->c_cflag;
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
+ // Added for xon/xoff support
+ unsigned int iflag = port->tty->termios->c_iflag;
+ unsigned char vstop;
+ unsigned char vstart;
dbg("%s", __FUNCTION__);
+ /* Force baud rate if this device requires it, unless it is set to B0. */
+ if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) {
+ dbg("%s: forcing baud rate for this device", __FUNCTION__);
+ port->tty->termios->c_cflag &= ~CBAUD;
+ port->tty->termios->c_cflag |= priv->force_baud;
+ }
+
+ /* Force RTS-CTS if this device requires it. */
+ if (priv->force_rtscts) {
+ dbg("%s: forcing rtscts for this device", __FUNCTION__);
+ port->tty->termios->c_cflag |= CRTSCTS;
+ }
+
+ cflag = port->tty->termios->c_cflag;
/* FIXME -For this cut I don't care if the line is really changing or
not - so just do the change regardless - should be able to
@@ -771,8 +1673,6 @@
}
/* Now do the baudrate */
- urb_value = translate_baudrate_to_ftdi((cflag & CBAUD), priv->ftdi_type);
-
if ((cflag & CBAUD) == B0 ) {
/* Disable flow control */
if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -783,24 +1683,20 @@
err("%s error from disable flowcontrol urb", __FUNCTION__);
}
/* Drop RTS and DTR */
- if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+ if (set_dtr(port, LOW) < 0){
err("%s Error from DTR LOW urb", __FUNCTION__);
}
- if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+ if (set_rts(port, LOW) < 0){
err("%s Error from RTS LOW urb", __FUNCTION__);
}
} else {
/* set the baudrate determined before */
- if (usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- FTDI_SIO_SET_BAUDRATE_REQUEST,
- FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
- urb_value, 0,
- buf, 0, 100) < 0) {
+ if (change_speed(port)) {
err("%s urb failed to set baurdrate", __FUNCTION__);
}
}
+
/* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
if (cflag & CRTSCTS) {
@@ -815,146 +1711,290 @@
}
} else {
- /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
- dbg("%s Turning off hardware flow control", __FUNCTION__);
- if (usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- FTDI_SIO_SET_FLOW_CTRL_REQUEST,
- FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
- 0, 0,
- buf, 0, WDR_TIMEOUT) < 0) {
- err("urb failed to clear flow control");
- }
+ /*
+ * Xon/Xoff code
+ *
+ * Check the IXOFF status in the iflag component of the termios structure
+ * if IXOFF is not set, the pre-xon/xoff code is executed.
+ */
+ if (iflag & IXOFF) {
+ dbg("%s request to enable xonxoff iflag=%04x",__FUNCTION__,iflag);
+ // Try to enable the XON/XOFF on the ftdi_sio
+ // Set the vstart and vstop -- could have been done up above where
+ // a lot of other dereferencing is done but that would be very
+ // inefficient as vstart and vstop are not always needed
+ vstart=port->tty->termios->c_cc[VSTART];
+ vstop=port->tty->termios->c_cc[VSTOP];
+ urb_value=(vstop << 8) | (vstart);
+
+ if (usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+ urb_value , FTDI_SIO_XON_XOFF_HS,
+ buf, 0, WDR_TIMEOUT) < 0) {
+ err("urb failed to set to xon/xoff flow control");
+ }
+ } else {
+ /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
+ /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+ dbg("%s Turning off hardware flow control", __FUNCTION__);
+ if (usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+ 0, 0,
+ buf, 0, WDR_TIMEOUT) < 0) {
+ err("urb failed to clear flow control");
+ }
+ }
}
return;
-} /* ftdi_sio_set_termios */
+} /* ftdi_termios */
-static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file)
+
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- char *buf = NULL;
- int ret = -EINVAL;
- int size;
+
+ __u16 urb_value=0; /* Will hold the new flags */
+ char buf[2];
+ int ret, mask;
- dbg("%s", __FUNCTION__);
+ dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
- buf = kmalloc(2, GFP_KERNEL);
- if (!buf)
- goto exit;
+ /* Based on code from acm.c and others */
+ switch (cmd) {
- if (priv->ftdi_type == sio) {
- size = 1;
- } else {
- /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
- format as the data returned from the in point */
- size = 2;
- }
- ret = usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0, buf, size, WDR_TIMEOUT);
- if (ret < 0) {
- err("%s Could not get modem status of device - err: %d",
- __FUNCTION__, ret);
- goto exit;
- }
-
- ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
- (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
- (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
- (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0);
-
-exit:
- kfree(buf);
- return ret;
-}
+ case TIOCMGET:
+ dbg("%s TIOCMGET", __FUNCTION__);
+ switch (priv->chip_type) {
+ case SIO:
+ /* Request the status from the device */
+ if ((ret = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT)) < 0 ) {
+ err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+ ret);
+ return(ret);
+ }
+ break;
+ case FT8U232AM:
+ case FT232BM:
+ /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
+ format as the data returned from the in point */
+ if ((ret = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 2, WDR_TIMEOUT)) < 0 ) {
+ err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+ ret);
+ return(ret);
+ }
+ break;
+ default:
+ return -EFAULT;
+ break;
+ }
-static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct usb_serial *serial = port->serial;
- int ret = 0;
-
- dbg("%s", __FUNCTION__);
+ return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+ (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+ (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
+ (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
+ priv->last_dtr_rts,
+ (unsigned long *) arg);
+ break;
- if (set & TIOCM_RTS)
- if ((ret = set_rts(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- HIGH)) < 0) {
- err("Urb to set RTS failed");
- goto exit;
+ case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+ dbg("%s TIOCMSET", __FUNCTION__);
+ if (get_user(mask, (unsigned long *) arg))
+ return -EFAULT;
+ urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
+ if ((ret = set_dtr(port, urb_value)) < 0){
+ err("Error from DTR set urb (TIOCMSET)");
+ return(ret);
}
-
- if (set & TIOCM_DTR)
- if ((ret = set_dtr(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- HIGH)) < 0) {
- err("Urb to set DTR failed");
- goto exit;
+ urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
+ if ((ret = set_rts(port, urb_value)) < 0){
+ err("Error from RTS set urb (TIOCMSET)");
+ return(ret);
}
-
- if (clear & TIOCM_RTS)
- if ((ret = set_rts(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- LOW)) < 0) {
- err("Urb to unset RTS failed");
- goto exit;
+ return(0);
+ break;
+
+ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
+ dbg("%s TIOCMBIS", __FUNCTION__);
+ if (get_user(mask, (unsigned long *) arg))
+ return -EFAULT;
+ if (mask & TIOCM_DTR){
+ if ((ret = set_dtr(port, HIGH)) < 0) {
+ err("Urb to set DTR failed");
+ return(ret);
+ }
}
+ if (mask & TIOCM_RTS) {
+ if ((ret = set_rts(port, HIGH)) < 0){
+ err("Urb to set RTS failed");
+ return(ret);
+ }
+ }
+ return(0);
+ break;
- if (clear & TIOCM_DTR)
- if ((ret = set_dtr(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- LOW)) < 0) {
- err("Urb to unset DTR failed");
- goto exit;
+ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
+ dbg("%s TIOCMBIC", __FUNCTION__);
+ if (get_user(mask, (unsigned long *) arg))
+ return -EFAULT;
+ if (mask & TIOCM_DTR){
+ if ((ret = set_dtr(port, LOW)) < 0){
+ err("Urb to unset DTR failed");
+ return(ret);
+ }
+ }
+ if (mask & TIOCM_RTS) {
+ if ((ret = set_rts(port, LOW)) < 0){
+ err("Urb to unset RTS failed");
+ return(ret);
+ }
}
+ return(0);
+ break;
-exit:
- return ret;
-}
+ /*
+ * I had originally implemented TCSET{A,S}{,F,W} and
+ * TCGET{A,S} here separately, however when testing I
+ * found that the higher layers actually do the termios
+ * conversions themselves and pass the call onto
+ * ftdi_sio_set_termios.
+ *
+ */
+
+ case TIOCGSERIAL: /* gets serial port data */
+ return get_serial_info(port, (struct serial_struct *) arg);
+
+ case TIOCSSERIAL: /* sets serial port data */
+ return set_serial_info(port, (struct serial_struct *) arg);
+
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was.
+ *
+ * This code is borrowed from linux/drivers/char/serial.c
+ */
+ case TIOCMIWAIT:
+ while (priv != NULL) {
+ interruptible_sleep_on(&priv->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ else {
+ char diff = priv->diff_status;
-static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
+ if (diff == 0) {
+ return -EIO; /* no change => error */
+ }
- switch (cmd) {
+ /* Consume all events */
+ priv->diff_status = 0;
+
+ /* Return 0 if caller wanted to know about these bits */
+ if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
+ ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+ return 0;
+ }
+ /*
+ * Otherwise caller can't care less about what happened,
+ * and so we continue to wait for more events.
+ */
+ }
+ }
+ return(0);
+ break;
default:
- /* This is not an error - turns out the higher layers will do
- * some ioctls itself
- */
- dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd);
- return(-ENOIOCTLCMD);
break;
+
}
- return 0;
-} /* ftdi_sio_ioctl */
-static int __init ftdi_sio_init (void)
+ /* This is not necessarily an error - turns out the higher layers will do
+ * some ioctls itself (see comment above)
+ */
+ dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
+
+ return(-ENOIOCTLCMD);
+} /* ftdi_ioctl */
+
+
+static void ftdi_throttle (struct usb_serial_port *port)
{
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ usb_unlink_urb (port->read_urb);
+}
+
+
+static void ftdi_unthrottle (struct usb_serial_port *port)
+{
+ int result;
+ struct usb_serial *serial = port->serial;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ port->read_urb->dev = serial->dev;
+
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
+
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+}
+
+static int __init ftdi_init (void)
+{
+
dbg("%s", __FUNCTION__);
- usb_serial_register (&ftdi_sio_device);
+ usb_serial_register (&ftdi_SIO_device);
usb_serial_register (&ftdi_8U232AM_device);
+ usb_serial_register (&ftdi_FT232BM_device);
+ usb_serial_register (&ftdi_USB_UIRT_device);
+ usb_serial_register (&ftdi_HE_TIRA1_device);
usb_register (&ftdi_driver);
+
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
-static void __exit ftdi_sio_exit (void)
+static void __exit ftdi_exit (void)
{
+
dbg("%s", __FUNCTION__);
+
usb_deregister (&ftdi_driver);
- usb_serial_deregister (&ftdi_sio_device);
+ usb_serial_deregister (&ftdi_HE_TIRA1_device);
+ usb_serial_deregister (&ftdi_USB_UIRT_device);
+ usb_serial_deregister (&ftdi_FT232BM_device);
usb_serial_deregister (&ftdi_8U232AM_device);
+ usb_serial_deregister (&ftdi_SIO_device);
+
}
-module_init(ftdi_sio_init);
-module_exit(ftdi_sio_exit);
+module_init(ftdi_init);
+module_exit(ftdi_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h Sun Jul 13 20:39:56 2003
+++ b/drivers/usb/serial/ftdi_sio.h Sun Jul 13 20:39:56 2003
@@ -14,11 +14,12 @@
* of the protocol required to talk to the device and ongoing assistence
* during development.
*
- * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the
+ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
* FTDI_SIO implementation.
*
* Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
* from Rudolf Gugler
+ *
*/
#define FTDI_VID 0x0403 /* Vendor Id */
@@ -28,6 +29,93 @@
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
+
+/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
+/* they use the ftdi chipset for the USB interface and the vendor id is the same */
+#define FTDI_XF_634_PID 0xFC09 /* Four line device */
+#define FTDI_XF_632_PID 0xFC08 /* Two line device */
+
+/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */
+/* broadband internet service. The following PID is exhibited by the usb device supplied */
+/* (the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
+
+/*
+ * The following are the values for the Matrix Orbital LCD displays,
+ * which are the FT232BM ( similar to the 8U232AM )
+ */
+#define FTDI_MTXORB_VID FTDI_VID /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */
+
+/*
+ * The following are the values for the Sealevel SeaLINK+ adapters.
+ * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and
+ * removed some PIDs that don't seem to match any existing products.)
+ */
+#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */
+#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */
+#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */
+#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */
+#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */
+#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */
+#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */
+#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */
+#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */
+#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */
+#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */
+#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */
+#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */
+#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */
+#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */
+#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */
+#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */
+#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */
+#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */
+#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */
+#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */
+#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */
+#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */
+#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */
+#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */
+#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */
+#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */
+#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */
+#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */
+#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */
+#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */
+#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */
+#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */
+#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */
+#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */
+#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */
+#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */
+#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */
+#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */
+#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */
+#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */
+#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */
+#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */
+#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */
+#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
+#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
+#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
+
+/*
+ * Home Electronics (www.home-electro.com) USB gadgets
+ */
+#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR tranceiver */
+
+/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
+/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
+#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */
+
+/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
@@ -84,19 +172,61 @@
/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_SET_BAUDRATE
- * wValue: BaudRate value - see below
+ * wValue: BaudDivisor value - see below
* wIndex: Port
* wLength: 0
* Data: None
+ * The BaudDivisor values are calculated as follows:
+ * - BaseClock is either 12000000 or 48000000 depending on the device. FIXME: I wish
+ * I knew how to detect old chips to select proper base clock!
+ * - BaudDivisor is a fixed point number encoded in a funny way.
+ * (--WRONG WAY OF THINKING--)
+ * BaudDivisor is a fixed point number encoded with following bit weighs:
+ * (-2)(-1)(13..0). It is a radical with a denominator of 4, so values
+ * end with 0.0 (00...), 0.25 (10...), 0.5 (01...), and 0.75 (11...).
+ * (--THE REALITY--)
+ * The both-bits-set has quite different meaning from 0.75 - the chip designers
+ * have decided it to mean 0.125 instead of 0.75.
+ * This info looked up in FTDI application note "FT8U232 DEVICES \ Data Rates
+ * and Flow Control Consideration for USB to RS232".
+ * - BaudDivisor = (BaseClock / 16) / BaudRate, where the (=) operation should
+ * automagically re-encode the resulting value to take fractions into consideration.
+ * As all values are integers, some bit twiddling is in order:
+ * BaudDivisor = (BaseClock / 16 / BaudRate) |
+ * (((BaseClock / 2 / BaudRate) & 4) ? 0x4000 // 0.5
+ * : ((BaseClock / 2 / BaudRate) & 2) ? 0x8000 // 0.25
+ * : ((BaseClock / 2 / BaudRate) & 1) ? 0xc000 // 0.125
+ * : 0)
+ *
+ * For the FT232BM, a 17th divisor bit was introduced to encode the multiples
+ * of 0.125 missing from the FT8U232AM. Bits 16 to 14 are coded as follows
+ * (the first four codes are the same as for the FT8U232AM, where bit 16 is
+ * always 0):
+ * 000 - add .000 to divisor
+ * 001 - add .500 to divisor
+ * 010 - add .250 to divisor
+ * 011 - add .125 to divisor
+ * 100 - add .375 to divisor
+ * 101 - add .625 to divisor
+ * 110 - add .750 to divisor
+ * 111 - add .875 to divisor
+ * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is
+ * placed in bit 0 of the urb index.
+ *
+ * Note that there are a couple of special cases to support the highest baud
+ * rates. If the calculated divisor value is 1, this needs to be replaced with
+ * 0. Additionally for the FT232BM, if the calculated divisor value is 0x4001
+ * (1.5), this needs to be replaced with 0x0001 (1) (but this divisor value is
+ * not supported by the FT8U232AM).
*/
-enum ftdi_type {
- sio = 1,
- F8U232AM = 2,
-};
+typedef enum {
+ SIO = 1,
+ FT8U232AM = 2,
+ FT232BM = 3,
+} ftdi_chip_type_t;
-
-enum {
+typedef enum {
ftdi_sio_b300 = 0,
ftdi_sio_b600 = 1,
ftdi_sio_b1200 = 2,
@@ -107,39 +237,12 @@
ftdi_sio_b38400 = 7,
ftdi_sio_b57600 = 8,
ftdi_sio_b115200 = 9
-};
-
+} FTDI_SIO_baudrate_t ;
-enum {
- ftdi_8U232AM_12MHz_b300 = 0x09c4,
- ftdi_8U232AM_12MHz_b600 = 0x04E2,
- ftdi_8U232AM_12MHz_b1200 = 0x0271,
- ftdi_8U232AM_12MHz_b2400 = 0x4138,
- ftdi_8U232AM_12MHz_b4800 = 0x809c,
- ftdi_8U232AM_12MHz_b9600 = 0xc04e,
- ftdi_8U232AM_12MHz_b19200 = 0x0027,
- ftdi_8U232AM_12MHz_b38400 = 0x4013,
- ftdi_8U232AM_12MHz_b57600 = 0x000d,
- ftdi_8U232AM_12MHz_b115200 = 0x4006,
- ftdi_8U232AM_12MHz_b230400 = 0x8003,
-};
-/* Apparently all devices are 48MHz */
-enum {
- ftdi_8U232AM_48MHz_b300 = 0x2710,
- ftdi_8U232AM_48MHz_b600 = 0x1388,
- ftdi_8U232AM_48MHz_b1200 = 0x09c4,
- ftdi_8U232AM_48MHz_b2400 = 0x04e2,
- ftdi_8U232AM_48MHz_b4800 = 0x0271,
- ftdi_8U232AM_48MHz_b9600 = 0x4138,
- ftdi_8U232AM_48MHz_b19200 = 0x809c,
- ftdi_8U232AM_48MHz_b38400 = 0xc04e,
- ftdi_8U232AM_48MHz_b57600 = 0x0034,
- ftdi_8U232AM_48MHz_b115200 = 0x001a,
- ftdi_8U232AM_48MHz_b230400 = 0x000d,
- ftdi_8U232AM_48MHz_b460800 = 0x4006,
- ftdi_8U232AM_48MHz_b921600 = 0x8003,
-
-};
+/*
+ * The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values
+ * are calculated internally.
+ */
#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
@@ -443,6 +546,11 @@
* B7 Error in RCVR FIFO
*
*/
+#define FTDI_RS0_CTS (1 << 4)
+#define FTDI_RS0_DSR (1 << 5)
+#define FTDI_RS0_RI (1 << 6)
+#define FTDI_RS0_RLSD (1 << 7)
+
#define FTDI_RS_DR 1
#define FTDI_RS_OE (1<<1)
#define FTDI_RS_PE (1<<2)
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c Sun Jul 13 20:39:56 2003
+++ b/drivers/usb/storage/datafab.c Sun Jul 13 20:39:56 2003
@@ -94,7 +94,7 @@
unsigned char *dest,
int use_sg)
{
- unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 };
+ unsigned char *command = us->iobuf;
unsigned char *buffer = NULL;
unsigned char *ptr;
unsigned char thistime;
@@ -116,8 +116,6 @@
return rc;
}
- command[5] += (info->lun << 4);
-
totallen = sectors * info->ssize;
do {
@@ -138,10 +136,13 @@
command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF;
+ command[5] = 0xE0 + (info->lun << 4);
command[5] |= (sector >> 24) & 0x0F;
+ command[6] = 0x20;
+ command[7] = 0x01;
// send the read command
- result = datafab_bulk_write(us, command, sizeof(command));
+ result = datafab_bulk_write(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
goto leave;
@@ -180,8 +181,8 @@
unsigned char *src,
int use_sg)
{
- unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 };
- unsigned char reply[2] = { 0, 0 };
+ unsigned char *command = us->iobuf;
+ unsigned char *reply = us->iobuf;
unsigned char *buffer = NULL;
unsigned char *ptr;
unsigned char thistime;
@@ -202,8 +203,6 @@
return rc;
}
- command[5] += (info->lun << 4);
-
// If we're using scatter-gather, we have to create a new
// buffer to read all of the data in first, since a
// scatter-gather buffer could in theory start in the middle
@@ -237,10 +236,13 @@
command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF;
+ command[5] = 0xE0 + (info->lun << 4);
command[5] |= (sector >> 24) & 0x0F;
+ command[6] = 0x30;
+ command[7] = 0x02;
// send the command
- result = datafab_bulk_write(us, command, sizeof(command));
+ result = datafab_bulk_write(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
goto leave;
@@ -250,7 +252,7 @@
goto leave;
// read the result
- result = datafab_bulk_read(us, reply, sizeof(reply));
+ result = datafab_bulk_read(us, reply, 2);
if (result != USB_STOR_XFER_GOOD)
goto leave;
@@ -291,13 +293,19 @@
//
// There might be a better way of doing this?
- unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
- unsigned char buf[512];
+ static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
+ unsigned char *command = us->iobuf;
+ unsigned char *buf;
int count = 0, rc;
if (!us || !info)
return USB_STOR_TRANSPORT_ERROR;
+ memcpy(command, scommand, 8);
+ buf = kmalloc(512, GFP_NOIO);
+ if (!buf)
+ return USB_STOR_TRANSPORT_ERROR;
+
US_DEBUGP("datafab_determine_lun: locating...\n");
// we'll try 3 times before giving up...
@@ -306,31 +314,41 @@
command[5] = 0xa0;
rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ if (rc != USB_STOR_XFER_GOOD) {
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
- rc = datafab_bulk_read(us, buf, sizeof(buf));
+ rc = datafab_bulk_read(us, buf, 512);
if (rc == USB_STOR_XFER_GOOD) {
info->lun = 0;
- return USB_STOR_TRANSPORT_GOOD;
+ rc = USB_STOR_TRANSPORT_GOOD;
+ goto leave;
}
command[5] = 0xb0;
rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ if (rc != USB_STOR_XFER_GOOD) {
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
- rc = datafab_bulk_read(us, buf, sizeof(buf));
+ rc = datafab_bulk_read(us, buf, 512);
if (rc == USB_STOR_XFER_GOOD) {
info->lun = 1;
- return USB_STOR_TRANSPORT_GOOD;
+ rc = USB_STOR_TRANSPORT_GOOD;
+ goto leave;
}
wait_ms(20);
}
- return USB_STOR_TRANSPORT_ERROR;
+ rc = USB_STOR_TRANSPORT_ERROR;
+
+ leave:
+ kfree(buf);
+ return rc;
}
static int datafab_id_device(struct us_data *us,
@@ -340,8 +358,9 @@
// to the ATA spec, 'Sector Count' isn't used but the Windows driver
// sets this bit so we do too...
//
- unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
- unsigned char reply[512];
+ static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
+ unsigned char *command = us->iobuf;
+ unsigned char *reply;
int rc;
if (!us || !info)
@@ -353,11 +372,18 @@
return rc;
}
+ memcpy(command, scommand, 8);
+ reply = kmalloc(512, GFP_NOIO);
+ if (!reply)
+ return USB_STOR_TRANSPORT_ERROR;
+
command[5] += (info->lun << 4);
rc = datafab_bulk_write(us, command, 8);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ if (rc != USB_STOR_XFER_GOOD) {
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
// we'll go ahead and extract the media capacity while we're here...
//
@@ -369,10 +395,15 @@
((u32)(reply[116]) << 16) |
((u32)(reply[115]) << 8) |
((u32)(reply[114]) );
- return USB_STOR_TRANSPORT_GOOD;
+ rc = USB_STOR_TRANSPORT_GOOD;
+ goto leave;
}
-
- return USB_STOR_TRANSPORT_ERROR;
+
+ rc = USB_STOR_TRANSPORT_ERROR;
+
+ leave:
+ kfree(reply);
+ return rc;
}
@@ -571,8 +602,7 @@
return USB_STOR_TRANSPORT_ERROR;
}
- // don't bother implementing READ_6 or WRITE_6. Just set MODE_XLATE and
- // let the usb storage code convert to READ_10/WRITE_10
+ // don't bother implementing READ_6 or WRITE_6.
//
if (srb->cmnd[0] == READ_10) {
block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c Sun Jul 13 20:39:56 2003
+++ b/drivers/usb/storage/freecom.c Sun Jul 13 20:39:56 2003
@@ -44,11 +44,6 @@
#define ERR_STAT 0x01
#define DRQ_STAT 0x08
-struct freecom_udata {
- u8 buffer[64]; /* Common command block. */
-};
-typedef struct freecom_udata *freecom_udata_t;
-
/* All of the outgoing packets are 64 bytes long. */
struct freecom_cb_wrap {
u8 Type; /* Command type. */
@@ -112,9 +107,8 @@
freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
unsigned int ipipe, unsigned int opipe, int count)
{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
- (struct freecom_xfer_wrap *) extra->buffer;
+ (struct freecom_xfer_wrap *) us->iobuf;
int result;
fxfr->Type = FCM_PACKET_INPUT | 0x00;
@@ -147,9 +141,8 @@
freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
int unsigned ipipe, unsigned int opipe, int count)
{
- freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
- (struct freecom_xfer_wrap *) extra->buffer;
+ (struct freecom_xfer_wrap *) us->iobuf;
int result;
fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
@@ -190,12 +183,9 @@
int result;
unsigned int partial;
int length;
- freecom_udata_t extra;
- extra = (freecom_udata_t) us->extra;
-
- fcb = (struct freecom_cb_wrap *) extra->buffer;
- fst = (struct freecom_status *) extra->buffer;
+ fcb = (struct freecom_cb_wrap *) us->iobuf;
+ fst = (struct freecom_status *) us->iobuf;
US_DEBUGP("Freecom TRANSPORT STARTED\n");
@@ -386,18 +376,11 @@
freecom_init (struct us_data *us)
{
int result;
- char buffer[33];
+ char *buffer = us->iobuf;
- /* Allocate a buffer for us. The upper usb transport code will
- * free this for us when cleaning up. */
- if (us->extra == NULL) {
- us->extra = kmalloc (sizeof (struct freecom_udata),
- GFP_KERNEL);
- if (us->extra == NULL) {
- US_DEBUGP("Out of memory\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
- }
+ /* The DMA-mapped I/O buffer is 64 bytes long, just right for
+ * all our packets. No need to allocate any extra buffer space.
+ */
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
diff -Nru a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
--- a/drivers/usb/storage/initializers.c Sun Jul 13 20:39:55 2003
+++ b/drivers/usb/storage/initializers.c Sun Jul 13 20:39:55 2003
@@ -47,38 +47,27 @@
* mode */
int usb_stor_euscsi_init(struct us_data *us)
{
- unsigned char data = 0x1;
int result;
US_DEBUGP("Attempting to init eUSCSI bridge...\n");
+ us->iobuf[0] = 0x1;
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
- 0x01, 0x0, &data, 0x1, 5*HZ);
+ 0x01, 0x0, us->iobuf, 0x1, 5*HZ);
US_DEBUGP("-- result is %d\n", result);
- US_DEBUGP("-- data afterwards is %d\n", data);
+ US_DEBUGP("-- data afterwards is %d\n", us->iobuf[0]);
return 0;
}
/* This function is required to activate all four slots on the UCR-61S2B
* flash reader */
-
int usb_stor_ucr61s2b_init(struct us_data *us)
{
- struct bulk_cb_wrap *bcb;
- struct bulk_cs_wrap *bcs;
+ struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap*) us->iobuf;
+ struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap*) us->iobuf;
int res, partial;
- bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
- if (!bcb) {
- return(-1);
- }
- bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
- if (!bcs) {
- kfree(bcb);
- return(-1);
- }
-
US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -91,19 +80,12 @@
res = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb,
US_BULK_CB_WRAP_LEN, &partial);
- US_DEBUGP("-- result is %d\n", res);
- kfree(bcb);
-
- if(res) {
- kfree(bcs);
- return(res);
- }
+ if(res)
+ return res;
+ US_DEBUGP("Getting status packet...\n");
res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
US_BULK_CS_WRAP_LEN, &partial);
- US_DEBUGP("-- result of status read is %d\n", res);
-
- kfree(bcs);
- return(res ? -1 : 0);
+ return (res ? -1 : 0);
}
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h Sun Jul 13 20:39:56 2003
+++ b/drivers/usb/storage/unusual_devs.h Sun Jul 13 20:39:56 2003
@@ -90,12 +90,6 @@
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
-/* Made with the help of Edd Dumbill */
-UNUSUAL_DEV( 0x0451, 0x5409, 0x0001, 0x0001,
- "Frontier Labs",
- "Nex II Digital",
- US_SC_SCSI, US_PR_BULK, NULL, 0),
-
/* Patch submitted by Philipp Friedrich */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
@@ -276,7 +270,7 @@
UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
"Sony",
"Memorystick MSC-U01N",
- US_SC_UFI, US_PR_CB, NULL,
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999,
@@ -301,7 +295,7 @@
UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
"Y-E Data",
"Flashbuster-U",
- US_SC_UFI, US_PR_CBI, NULL,
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN),
UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c Sun Jul 13 20:39:55 2003
+++ b/drivers/usb/usb-skeleton.c Sun Jul 13 20:39:55 2003
@@ -646,9 +646,6 @@
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
- if (!dev)
- return;
-
down (&dev->sem);
/* disable open() */
diff -Nru a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
--- a/drivers/video/sis/init301.c Sun Jul 13 20:39:54 2003
+++ b/drivers/video/sis/init301.c Sun Jul 13 20:39:54 2003
@@ -5282,7 +5282,7 @@
#ifdef SIS315H /* 310/325 series */
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- temp = temp = SiS_GetCH701x(SiS_Pr,0x61);
+ temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 1) {
SiS_SetCH701x(SiS_Pr,0xac76);
SiS_SetCH701x(SiS_Pr,0x0066);
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c Sun Jul 13 20:39:55 2003
+++ b/fs/aio.c Sun Jul 13 20:39:55 2003
@@ -679,12 +679,11 @@
/* after flagging the request as done, we
* must never even look at it again
*/
- barrier();
+ smp_wmb(); /* make event visible before updating tail */
info->tail = tail;
ring->tail = tail;
- wmb();
put_aio_ring_event(event, KM_IRQ0);
kunmap_atomic(ring, KM_IRQ1);
@@ -721,7 +720,7 @@
dprintk("in aio_read_evt h%lu t%lu m%lu\n",
(unsigned long)ring->head, (unsigned long)ring->tail,
(unsigned long)ring->nr);
- barrier();
+
if (ring->head == ring->tail)
goto out;
@@ -732,7 +731,7 @@
struct io_event *evp = aio_ring_event(info, head, KM_USER1);
*ent = *evp;
head = (head + 1) % info->nr;
- barrier();
+ smp_mb(); /* finish reading the event before updatng the head */
ring->head = head;
ret = 1;
put_aio_ring_event(evp, KM_USER1);
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c Sun Jul 13 20:39:54 2003
+++ b/fs/attr.c Sun Jul 13 20:39:54 2003
@@ -65,7 +65,7 @@
int error = 0;
if (ia_valid & ATTR_SIZE) {
- if (attr->ia_size != inode->i_size) {
+ if (attr->ia_size != i_size_read(inode)) {
error = vmtruncate(inode, attr->ia_size);
if (error || (ia_valid == ATTR_SIZE))
goto out;
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c Sun Jul 13 20:39:55 2003
+++ b/fs/binfmt_aout.c Sun Jul 13 20:39:55 2003
@@ -269,7 +269,7 @@
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
@@ -454,7 +454,7 @@
/* We come in here for the regular a.out style of shared libraries */
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
- inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
goto out;
}
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c Sun Jul 13 20:39:55 2003
+++ b/fs/binfmt_elf.c Sun Jul 13 20:39:55 2003
@@ -114,7 +114,7 @@
#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) + (items))
#define STACK_ROUND(sp, items) \
((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
-#define STACK_ALLOC(sp, len) ({ elf_addr_t *old_sp = sp; sp += len; old_sp; })
+#define STACK_ALLOC(sp, len) ({ elf_addr_t *old_sp = (elf_addr_t *)sp; sp += len; old_sp; })
#else
#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) - (items))
#define STACK_ROUND(sp, items) \
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c Sun Jul 13 20:39:56 2003
+++ b/fs/block_dev.c Sun Jul 13 20:39:56 2003
@@ -29,7 +29,7 @@
static sector_t max_block(struct block_device *bdev)
{
sector_t retval = ~((sector_t)0);
- loff_t sz = bdev->bd_inode->i_size;
+ loff_t sz = i_size_read(bdev->bd_inode);
if (sz) {
unsigned int size = block_size(bdev);
@@ -161,7 +161,7 @@
bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
down(&bd_inode->i_sem);
- size = bd_inode->i_size;
+ size = i_size_read(bd_inode);
switch (origin) {
case 2:
@@ -487,7 +487,7 @@
static void bd_set_size(struct block_device *bdev, loff_t size)
{
unsigned bsize = bdev_hardsect_size(bdev);
- bdev->bd_inode->i_size = size;
+ i_size_write(bdev->bd_inode, size);
while (bsize < PAGE_CACHE_SIZE) {
if (size & bsize)
break;
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c Sun Jul 13 20:39:55 2003
+++ b/fs/buffer.c Sun Jul 13 20:39:55 2003
@@ -1721,7 +1721,7 @@
BUG_ON(!PageLocked(page));
- last_block = (inode->i_size - 1) >> inode->i_blkbits;
+ last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
if (!page_has_buffers(page)) {
if (!PageUptodate(page))
@@ -2057,7 +2057,7 @@
head = page_buffers(page);
iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- lblock = (inode->i_size+blocksize-1) >> inode->i_blkbits;
+ lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits;
bh = head;
nr = 0;
i = 0;
@@ -2282,8 +2282,12 @@
struct inode *inode = page->mapping->host;
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
__block_commit_write(inode,page,from,to);
+ /*
+ * No need to use i_size_read() here, the i_size
+ * cannot change under us because we hold i_sem.
+ */
if (pos > inode->i_size) {
- inode->i_size = pos;
+ i_size_write(inode, pos);
mark_inode_dirty(inode);
}
return 0;
@@ -2435,7 +2439,7 @@
set_page_dirty(page);
if (pos > inode->i_size) {
- inode->i_size = pos;
+ i_size_write(inode, pos);
mark_inode_dirty(inode);
}
return 0;
@@ -2565,7 +2569,8 @@
struct writeback_control *wbc)
{
struct inode * const inode = page->mapping->host;
- const unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ loff_t i_size = i_size_read(inode);
+ const unsigned long end_index = i_size >> PAGE_CACHE_SHIFT;
unsigned offset;
void *kaddr;
@@ -2574,7 +2579,7 @@
return __block_write_full_page(inode, page, get_block, wbc);
/* Is the page fully outside i_size? (truncate in progress) */
- offset = inode->i_size & (PAGE_CACHE_SIZE-1);
+ offset = i_size & (PAGE_CACHE_SIZE-1);
if (page->index >= end_index+1 || !offset) {
/*
* The page may have dirty, unmapped buffers. For example,
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES Sun Jul 13 20:39:56 2003
+++ b/fs/cifs/CHANGES Sun Jul 13 20:39:56 2003
@@ -1,3 +1,9 @@
+Version 0.82
+------------
+Add support for mknod of block or character devices. Fix oplock
+code (distributed caching) to properly send response to oplock
+break from server.
+
Version 0.81
------------
Finish up CIFS packet digital signing for the default
diff -Nru a/fs/cifs/README b/fs/cifs/README
--- a/fs/cifs/README Sun Jul 13 20:39:56 2003
+++ b/fs/cifs/README Sun Jul 13 20:39:56 2003
@@ -76,8 +76,9 @@
case sensitive = yes
delete readonly = yes
Some administrators also change the "map archive" and the "create mask" parameters
-from their defaults. For more information on these see the manual pages
-("man smb.conf") on the Samba server system. Note that the cifs vfs, unlike the
+from their default values. Creating special devices (mknod) remotely may require
+specifying a mkdev function to Samba. For more information on these see the manual
+pages ("man smb.conf") on the Samba server system. Note that the cifs vfs, unlike the
smbfs vfs, does not read the smb.conf on the client system (the few optional settings
are passed in on mount via -o parameters instead). Note that Samba 2.2.7 or later
includes a fix that allows the CIFS VFS to delete open files (required for strict
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/cifs_debug.c Sun Jul 13 20:39:55 2003
@@ -89,8 +89,8 @@
ses->serverOS, ses->serverNOS, ses->capabilities);
buf += length;
if(ses->server)
- buf += sprintf(buf, "\tLocal Users To Same Server: %d ",
- atomic_read(&ses->server->socketUseCount));
+ buf += sprintf(buf, "\tLocal Users To Same Server: %d SecMode: 0x%x",
+ atomic_read(&ses->server->socketUseCount),ses->server->secMode);
}
read_unlock(&GlobalSMBSeslock);
sprintf(buf, "\n");
@@ -590,6 +590,8 @@
sign_CIFS_PDUs = 0;
else if (c == '1' || c == 'y' || c == 'Y')
sign_CIFS_PDUs = 1;
+ else if (c == '2')
+ sign_CIFS_PDUs = 2;
return count;
}
diff -Nru a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
--- a/fs/cifs/cifsencrypt.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/cifsencrypt.c Sun Jul 13 20:39:55 2003
@@ -24,6 +24,7 @@
#include "cifsglob.h"
#include "cifs_debug.h"
#include "md5.h"
+#include "cifs_unicode.h"
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
/* the 16 byte signature must be allocated by the caller */
@@ -133,8 +134,68 @@
if ((key == NULL) || (rn == NULL) || (password == NULL))
return -EINVAL;
- E_md4hash(password, temp_key); /* BB may have to do another md4 of it */
+ E_md4hash(password, temp_key);
mdfour(key,temp_key,16);
memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
return 0;
-}
+}
+
+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
+{
+ char temp_hash[16];
+ struct HMACMD5Context ctx;
+ char * ucase_buf;
+ wchar_t * unicode_buf;
+ unsigned int i,user_name_len,dom_name_len;
+
+ if(ses)
+ return -EINVAL;
+
+ E_md4hash(ses->password_with_pad, temp_hash);
+
+ hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
+ user_name_len = strlen(ses->userName);
+ if(user_name_len > MAX_USERNAME_SIZE)
+ return -EINVAL;
+ dom_name_len = strlen(ses->domainName);
+ if(dom_name_len > MAX_USERNAME_SIZE)
+ return -EINVAL;
+
+
+ ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+ unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+
+ for(i=0;icharset2upper[(int)ses->userName[i]];
+ ucase_buf[i] = 0;
+ user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+ unicode_buf[user_name_len] = 0;
+ user_name_len++;
+
+ for(i=0;icharset2upper[(int)ses->domainName[i]];
+ ucase_buf[i] = 0;
+ dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+
+ unicode_buf[user_name_len + dom_name_len] = 0;
+ hmac_md5_update((const unsigned char *) unicode_buf,
+ (user_name_len+dom_name_len)*2,&ctx);
+
+ hmac_md5_final(ses->mac_signing_key,&ctx);
+ kfree(ucase_buf);
+ kfree(unicode_buf);
+ return 0;
+}
+void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
+{
+ struct HMACMD5Context context;
+ memcpy(v2_session_response + 8, ses->server->cryptKey,8);
+ /* gen_blob(v2_session_response + 16); */
+ hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
+
+ hmac_md5_update(ses->server->cryptKey,8,&context);
+/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
+
+
+ hmac_md5_final(v2_session_response,&context);
+}
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/cifsfs.c Sun Jul 13 20:39:55 2003
@@ -301,6 +301,7 @@
/* revalidate:cifs_revalidate, */
.setattr = cifs_setattr,
.symlink = cifs_symlink,
+ .mknod = cifs_mknod,
};
struct inode_operations cifs_file_inode_ops = {
@@ -465,7 +466,14 @@
CIFS_I(pfile->f_dentry->d_inode)->write_behind_rc
= rc;
cFYI(1,("Oplock flush file %p rc %d",pfile,rc));
- /* send oplock break */
+ if(pfile->private_data) {
+ rc = CIFSSMBLock(0, pTcon,
+ ((struct cifsFileInfo *) pfile->private_data)->netfid,
+ 0 /* len */ , 0 /* offset */, 0,
+ 0, LOCKING_ANDX_OPLOCK_RELEASE,
+ 0 /* wait flag */);
+ cFYI(1,("Oplock release rc = %d ",rc));
+ }
write_lock(&GlobalMid_Lock);
} else
break;
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/cifsfs.h Sun Jul 13 20:39:55 2003
@@ -50,6 +50,7 @@
extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
+extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
extern int cifs_mkdir(struct inode *, struct dentry *, int);
extern int cifs_rmdir(struct inode *, struct dentry *);
extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h Sun Jul 13 20:39:54 2003
+++ b/fs/cifs/cifsproto.h Sun Jul 13 20:39:54 2003
@@ -88,8 +88,7 @@
const struct nls_table *);
extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid,
struct cifsSesInfo *ses, char *ntlm_session_key,
- char *lanman_session_key,int ntlmv2_flag,
- const struct nls_table *);
+ int ntlmv2_flag, const struct nls_table *);
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const char *tree, struct cifsTconInfo *tcon,
@@ -156,7 +155,7 @@
__u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid,
- __u64 gid, const struct nls_table *nls_codepage);
+ __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
const char *newName,
@@ -229,8 +228,8 @@
extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
-
-/* BB routines below not implemented yet BB */
+extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
+extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
extern int CIFSBuildServerList(int xid, char *serverBufferList,
int recordlength, int *entries,
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/cifssmb.c Sun Jul 13 20:39:55 2003
@@ -618,6 +618,7 @@
LOCK_REQ *pSMB = NULL;
LOCK_RSP *pSMBr = NULL;
int bytes_returned;
+ int timeout = 0;
cFYI(1, ("In CIFSSMBLock"));
@@ -626,6 +627,9 @@
if (rc)
return rc;
+ if(lockType == LOCKING_ANDX_OPLOCK_RELEASE)
+ timeout = -1; /* no response expected */
+
pSMB->NumberOfLocks = cpu_to_le32(numLock);
pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
pSMB->LockType = lockType;
@@ -640,7 +644,7 @@
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
if (rc) {
cERROR(1, ("Send error in Lock = %d", rc));
@@ -2299,7 +2303,7 @@
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 mode, __u64 uid, __u64 gid,
- const struct nls_table *nls_codepage)
+ dev_t device, const struct nls_table *nls_codepage)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -2358,6 +2362,9 @@
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
data_offset->Uid = cpu_to_le64(uid);
data_offset->Gid = cpu_to_le64(gid);
+ /* better to leave device as zero when it is */
+ data_offset->DevMajor = cpu_to_le64(MAJOR(device));
+ data_offset->DevMinor = cpu_to_le64(MINOR(device));
data_offset->Permissions = cpu_to_le64(mode);
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c Sun Jul 13 20:39:56 2003
+++ b/fs/cifs/connect.c Sun Jul 13 20:39:56 2003
@@ -634,7 +634,6 @@
int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info)
{
int rc = 0;
- char session_key[CIFS_SESSION_KEY_SIZE];
char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
int ntlmv2_flag = FALSE;
@@ -666,35 +665,44 @@
nls_info);
if (!rc) {
if(ntlmv2_flag) {
- cFYI(1,("Able to use the more secure NTLM version 2 password hash"));
- /* SMBNTv2encrypt( ...); */ /* BB fix this up -
- and note that Samba client equivalent looks wrong */
- } else
- SMBNTencrypt(pSesInfo->password_with_pad,
- pSesInfo->server->cryptKey,ntlm_session_key);
+ char * v2_response;
+ cFYI(1,("Can use more secure NTLM version 2 password hash"));
+ CalcNTLMv2_partial_mac_key(pSesInfo,
+ nls_info);
+ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
+ if(v2_response) {
+ CalcNTLMv2_response(pSesInfo,v2_response);
+/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
+ kfree(v2_response);
+ /* BB Put dummy sig in SessSetup PDU? */
+ } else
+ rc = -ENOMEM;
- /* BB add call to save MAC key here BB */
+ } else {
+ SMBNTencrypt(pSesInfo->password_with_pad,
+ pSesInfo->server->cryptKey,
+ ntlm_session_key);
- /* for better security the weaker lanman hash not sent
- in AuthSessSetup so why bother calculating it */
- /* toUpper(nls_info,
- password_with_pad);
- SMBencrypt(password_with_pad,
- pSesInfo->server->cryptKey, session_key); */
+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
+ ntlm_session_key,
+ pSesInfo->password_with_pad);
+ }
+ /* for better security the weaker lanman hash not sent
+ in AuthSessSetup so we no longer calculate it */
rc = CIFSNTLMSSPAuthSessSetup(xid,
- pSesInfo,
- ntlm_session_key,
- session_key,
- ntlmv2_flag,
- nls_info);
+ pSesInfo,
+ ntlm_session_key,
+ ntlmv2_flag,
+ nls_info);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,
ntlm_session_key);
- cifs_calculate_mac_key(pSesInfo->mac_signing_key, ntlm_session_key, pSesInfo->password_with_pad);
+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
+ ntlm_session_key, pSesInfo->password_with_pad);
rc = CIFSSessSetup(xid, pSesInfo,
ntlm_session_key, nls_info);
}
@@ -1297,7 +1305,7 @@
int bytes_returned = 0;
int len;
- cFYI(1, ("In v2 sesssetup "));
+ cFYI(1, ("In spnego sesssetup "));
smb_buffer = buf_get();
if (smb_buffer == 0) {
@@ -1605,7 +1613,9 @@
SecurityBlob->NegotiateFlags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
- NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_128;
+ /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
+ if(sign_CIFS_PDUs)
+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
if(ntlmv2_support)
SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
/* setup pointers to domain name and workstation name */
@@ -1725,6 +1735,17 @@
CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
*pNTLMv2_flag = TRUE;
+
+ if((SecurityBlob2->NegotiateFlags &
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
+ || (sign_CIFS_PDUs > 1))
+ ses->server->secMode |=
+ SECMODE_SIGN_REQUIRED;
+ if ((SecurityBlob2->NegotiateFlags &
+ NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
+ ses->server->secMode |=
+ SECMODE_SIGN_ENABLED;
+
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
@@ -1868,7 +1889,7 @@
int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char *ntlm_session_key, char *lanman_session_key, int ntlmv2_flag,
+ char *ntlm_session_key, int ntlmv2_flag,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
@@ -1934,7 +1955,9 @@
SecurityBlob->NegotiateFlags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
- 0x80000000 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_128;
+ 0x80000000 | NTLMSSP_NEGOTIATE_128;
+ if(sign_CIFS_PDUs)
+ SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
if(ntlmv2_flag)
SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c
--- a/fs/cifs/dir.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/dir.c Sun Jul 13 20:39:55 2003
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
@@ -125,6 +126,7 @@
int rc = -ENOENT;
int xid;
int oplock = REQ_OPLOCK;
+ int desiredAccess = GENERIC_ALL;
__u16 fileHandle;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
@@ -138,10 +140,23 @@
full_path = build_path_from_dentry(direntry);
+
+ if(nd) {
+ cFYI(1,("In create nd flags = 0x%x for %s",nd->flags,full_path));
+ cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
+ if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
+ desiredAccess = GENERIC_READ;
+ else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
+ desiredAccess = GENERIC_WRITE;
+ else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR)
+ desiredAccess = GENERIC_ALL;
+ }
+
+
/* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, GENERIC_ALL
- /* 0x20197 was used previously */ , CREATE_NOT_DIR,
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
+ desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc));
@@ -178,6 +193,43 @@
return rc;
}
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number)
+{
+ int rc = -EPERM;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct inode * newinode = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ full_path = build_path_from_dentry(direntry);
+
+ if (pTcon->ses->capabilities & CAP_UNIX) {
+ rc = CIFSSMBUnixSetPerms(xid, pTcon,
+ full_path, mode, current->euid, current->egid,
+ device_number, cifs_sb->local_nls);
+ if(!rc) {
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb);
+ direntry->d_op = &cifs_dentry_ops;
+ if(rc == 0)
+ d_instantiate(direntry, newinode);
+ }
+ }
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+
+
struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
{
@@ -208,6 +260,13 @@
}
cFYI(1,
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
+
+ if(nd) { /* BB remove begin */
+ cFYI(1,("In lookup nd flags = 0x%x",nd->flags));
+ cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
+ }
+/* BB remove end BB */
+
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb);
@@ -268,6 +327,12 @@
int isValid = 1;
/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
+
+ if(nd) { /* BB remove begin */
+ cFYI(1,("In d_revalidate nd flags = 0x%x",nd->flags));
+ cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
+ }
+/* BB remove end BB */
if (direntry->d_inode) {
if (cifs_revalidate(direntry)) {
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c Sun Jul 13 20:39:54 2003
+++ b/fs/cifs/file.c Sun Jul 13 20:39:54 2003
@@ -52,12 +52,12 @@
xid = GetXid();
- cFYI(1, (" inode = 0x%p file flags are %x", inode, file->f_flags));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry);
+ cFYI(1, (" inode = 0x%p file flags are %x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ;
else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
@@ -125,6 +125,7 @@
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
(__u64)-1,
(__u64)-1,
+ 0 /* dev */,
cifs_sb->local_nls);
else {/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c Sun Jul 13 20:39:54 2003
+++ b/fs/cifs/inode.c Sun Jul 13 20:39:54 2003
@@ -397,6 +397,7 @@
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
+ 0 /* dev_t */,
cifs_sb->local_nls);
else { /* BB to be implemented via Windows secrty descriptors*/
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
@@ -702,7 +703,7 @@
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
- cifs_sb->local_nls);
+ 0 /* dev_t */, cifs_sb->local_nls);
else if (attrs->ia_valid & ATTR_MODE) {
if((mode & S_IWUGO) == 0) /* not writeable */ {
if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c Sun Jul 13 20:39:56 2003
+++ b/fs/cifs/misc.c Sun Jul 13 20:39:56 2003
@@ -338,13 +338,8 @@
netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
if(pSMB->Fid == netfile->netfid) {
struct cifsInodeInfo *pCifsInode;
- /* BB Add following logic:
- 2) look up inode from tcon->openFileList->file->f_dentry->d_inode
- 3) flush dirty pages and cached byte range locks and mark inode
- 4) depending on break type change to r/o caching or no caching
- cifsinode->clientCanCacheAll = 0
- 5) inode->i_data.a_ops = &cifs_addr_ops_writethrough;
- 6) send oplock break response to server */
+ /* BB Add following logic to mark inode for write through
+ inode->i_data.a_ops = &cifs_addr_ops_writethrough; */
read_unlock(&GlobalSMBSeslock);
cFYI(1,("Matching file id, processing oplock break"));
pCifsInode =
@@ -354,7 +349,7 @@
pCifsInode->clientCanCacheRead = FALSE;
pCifsInode->oplockPending = TRUE;
AllocOplockQEntry(netfile->pfile, tcon);
- cFYI(1,("about to wake up oplock thd"));
+ cFYI(1,("about to wake up oplock thd"));
wake_up_process(oplockThread);
return TRUE;
}
diff -Nru a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
--- a/fs/cifs/smbencrypt.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/smbencrypt.c Sun Jul 13 20:39:55 2003
@@ -470,58 +470,3 @@
return TRUE;
}
-
-
-/***********************************************************
- SMB signing - setup the MAC key.
-************************************************************/
-
-void
-cli_calculate_mac_key(__u8 * mac_key, int *pmac_key_len,
- const char *ntpasswd, const unsigned char resp[24])
-{
- /* Get first 16 bytes. */
- E_md4hash(ntpasswd, mac_key);
- memcpy(mac_key + 16, resp, 24);
- *pmac_key_len = 40;
-
- /* Reset the sequence number in case we had a previous (aborted) attempt */
-/* cli->sign_info.send_seq_num = 0; */
-}
-
-/***********************************************************
- SMB signing - calculate a MAC to send.
-************************************************************/
-
-void
-cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key,
- int mac_key_len, __u32 * send_seq_num,
- __u32 * reply_seq_num)
-{
- unsigned char calc_md5_mac[16];
- struct MD5Context md5_ctx;
-
-/* if (!cli->sign_info.use_smb_signing) {
- return;
- } */
-
- /*
- * Firstly put the sequence number into the first 4 bytes.
- * and zero out the next 4 bytes.
- */
-/*
- SIVAL(outbuf, smb_ss_field, *send_seq_num);
- SIVAL(outbuf, smb_ss_field + 4, 0); */
-
- /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
- MD5Init(&md5_ctx);
- MD5Update(&md5_ctx, mac_key, mac_key_len);
- MD5Update(&md5_ctx, outbuf->Protocol,
- be32_to_cpu(outbuf->smb_buf_length));
- MD5Final(calc_md5_mac, &md5_ctx);
-
- memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
- (*send_seq_num)++;
- *reply_seq_num = *send_seq_num;
- (*send_seq_num)++;
-}
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c Sun Jul 13 20:39:55 2003
+++ b/fs/cifs/transport.c Sun Jul 13 20:39:55 2003
@@ -199,13 +199,15 @@
if (in_buf->smb_buf_length > 12)
in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
-
+
rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->sockAddr));
+ if (long_op == -1)
+ goto cifs_no_response_exit;
if (long_op > 1) /* writes past end of file can take looooong time */
timeout = 300 * HZ;
else if (long_op == 1)
@@ -283,7 +285,7 @@
} else
rc = -EIO;
}
-
+cifs_no_response_exit:
DeleteMidQEntry(midQ); /* BB what if process is killed?
- BB add background daemon to clean up Mid entries from
killed processes & test killing process with active mid */
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c Sun Jul 13 20:39:54 2003
+++ b/fs/dcache.c Sun Jul 13 20:39:54 2003
@@ -1451,19 +1451,24 @@
int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)
{
int result;
+ unsigned long seq;
result = 0;
- for (;;) {
- if (new_dentry != old_dentry) {
- struct dentry * parent = new_dentry->d_parent;
- if (parent == new_dentry)
- break;
- new_dentry = parent;
- continue;
+ do {
+ seq = read_seqbegin(&rename_lock);
+ for (;;) {
+ if (new_dentry != old_dentry) {
+ struct dentry * parent = new_dentry->d_parent;
+ if (parent == new_dentry)
+ break;
+ new_dentry = parent;
+ continue;
+ }
+ result = 1;
+ break;
}
- result = 1;
- break;
- }
+ } while (read_seqretry(&rename_lock, seq));
+
return result;
}
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c Sun Jul 13 20:39:55 2003
+++ b/fs/devfs/base.c Sun Jul 13 20:39:55 2003
@@ -2208,8 +2208,46 @@
{
devfs_handle_t de;
wait_queue_head_t wait_queue;
+ atomic_t count;
};
+static struct devfs_lookup_struct *
+new_devfs_lookup_struct(void)
+{
+ struct devfs_lookup_struct *p = kmalloc(sizeof(*p), GFP_KERNEL);
+
+ if (!p)
+ return NULL;
+
+ init_waitqueue_head (&p->wait_queue);
+ atomic_set(&p->count, 1);
+ return p;
+}
+
+static void
+get_devfs_lookup_struct(struct devfs_lookup_struct *info)
+{
+ if (info)
+ atomic_inc(&info->count);
+ else {
+ printk(KERN_ERR "null devfs_lookup_struct pointer\n");
+ dump_stack();
+ }
+}
+
+static void
+put_devfs_lookup_struct(struct devfs_lookup_struct *info)
+{
+ if (info) {
+ if (!atomic_dec_and_test(&info->count))
+ return;
+ kfree(info);
+ } else {
+ printk(KERN_ERR "null devfs_lookup_struct pointer\n");
+ dump_stack();
+ }
+}
+
/* XXX: this doesn't handle the case where we got a negative dentry
but a devfs entry has been registered in the meanwhile */
static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
@@ -2252,11 +2290,13 @@
read_lock (&parent->u.dir.lock);
if (dentry->d_fsdata)
{
+ get_devfs_lookup_struct(lookup_info);
set_current_state (TASK_UNINTERRUPTIBLE);
add_wait_queue (&lookup_info->wait_queue, &wait);
read_unlock (&parent->u.dir.lock);
schedule ();
remove_wait_queue (&lookup_info->wait_queue, &wait);
+ put_devfs_lookup_struct(lookup_info);
}
else read_unlock (&parent->u.dir.lock);
return 1;
@@ -2268,7 +2308,7 @@
static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */
- struct devfs_lookup_struct lookup_info;
+ struct devfs_lookup_struct *lookup_info;
struct fs_info *fs_info = dir->i_sb->s_fs_info;
struct devfs_entry *parent, *de;
struct inode *inode;
@@ -2285,9 +2325,10 @@
read_lock (&parent->u.dir.lock);
de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
read_unlock (&parent->u.dir.lock);
- lookup_info.de = de;
- init_waitqueue_head (&lookup_info.wait_queue);
- dentry->d_fsdata = &lookup_info;
+ lookup_info = new_devfs_lookup_struct();
+ if (!lookup_info) return ERR_PTR(-ENOMEM);
+ lookup_info->de = de;
+ dentry->d_fsdata = lookup_info;
if (de == NULL)
{ /* Try with devfsd. For any kind of failure, leave a negative dentry
so someone else can deal with it (in the case where the sysadmin
@@ -2297,6 +2338,7 @@
if (try_modload (parent, fs_info,
dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
{ /* Lookup event was not queued to devfsd */
+ put_devfs_lookup_struct(lookup_info);
d_add (dentry, NULL);
return NULL;
}
@@ -2308,8 +2350,7 @@
revalidation */
up (&dir->i_sem);
wait_for_devfsd_finished (fs_info); /* If I'm not devfsd, must wait */
- down (&dir->i_sem); /* Grab it again because them's the rules */
- de = lookup_info.de;
+ de = lookup_info->de;
/* If someone else has been so kind as to make the inode, we go home
early */
if (dentry->d_inode) goto out;
@@ -2333,11 +2374,13 @@
de->name, de->inode.ino, inode, de, current->comm);
d_instantiate (dentry, inode);
out:
+ write_lock (&parent->u.dir.lock);
dentry->d_op = &devfs_dops;
dentry->d_fsdata = NULL;
- write_lock (&parent->u.dir.lock);
- wake_up (&lookup_info.wait_queue);
+ wake_up (&lookup_info->wait_queue);
+ put_devfs_lookup_struct(lookup_info);
write_unlock (&parent->u.dir.lock);
+ down (&dir->i_sem); /* Grab it again because them's the rules */
devfs_put (de);
return retval;
} /* End Function devfs_lookup */
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c Sun Jul 13 20:39:55 2003
+++ b/fs/direct-io.c Sun Jul 13 20:39:55 2003
@@ -757,7 +757,7 @@
char *kaddr;
if (dio->block_in_file >=
- dio->inode->i_size>>blkbits) {
+ i_size_read(dio->inode)>>blkbits) {
/* We hit eof */
page_cache_release(page);
goto out;
@@ -943,13 +943,15 @@
if (ret == 0)
ret = dio->page_errors;
if (ret == 0 && dio->result) {
+ loff_t i_size = i_size_read(inode);
+
ret = dio->result;
/*
* Adjust the return value if the read crossed a
* non-block-aligned EOF.
*/
- if (rw == READ && (offset + ret > inode->i_size))
- ret = inode->i_size - offset;
+ if (rw == READ && (offset + ret > i_size))
+ ret = i_size - offset;
}
kfree(dio);
}
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c Sun Jul 13 20:39:55 2003
+++ b/fs/eventpoll.c Sun Jul 13 20:39:55 2003
@@ -245,6 +245,9 @@
/* The "container" of this item */
struct eventpoll *ep;
+ /* The file descriptor this item refers to */
+ int fd;
+
/* The file this item refers to */
struct file *file;
@@ -285,15 +288,17 @@
static int ep_alloc_pages(char **pages, int numpages);
static int ep_free_pages(char **pages, int numpages);
static int ep_file_init(struct file *file, unsigned int hashbits);
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file);
+static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd);
static struct list_head *ep_hash_entry(struct eventpoll *ep, unsigned int index);
static int ep_init(struct eventpoll *ep, unsigned int hashbits);
static void ep_free(struct eventpoll *ep);
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
+static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
static void ep_use_epitem(struct epitem *epi);
static void ep_release_epitem(struct epitem *epi);
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt);
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile);
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
+ poll_table *pt);
+static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
+ struct file *tfile, int fd);
static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event);
static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi);
static int ep_unlink(struct eventpoll *ep, struct epitem *epi);
@@ -580,7 +585,7 @@
down_write(&ep->sem);
/* Try to lookup the file inside our hash table */
- epi = ep_find(ep, tfile);
+ epi = ep_find(ep, tfile, fd);
error = -EINVAL;
switch (op) {
@@ -588,7 +593,7 @@
if (!epi) {
epds.events |= POLLERR | POLLHUP;
- error = ep_insert(ep, &epds, tfile);
+ error = ep_insert(ep, &epds, tfile, fd);
} else
error = -EEXIST;
break;
@@ -814,10 +819,11 @@
/*
* Calculate the index of the hash relative to "file".
*/
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file)
+static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd)
{
+ unsigned long ptr = (unsigned long) file ^ (fd << ep->hashbits);
- return (unsigned int) hash_ptr(file, ep->hashbits);
+ return (unsigned int) hash_ptr((void *) ptr, ep->hashbits);
}
@@ -920,7 +926,7 @@
* the returned item, so the caller must call ep_release_epitem()
* after finished using the "struct epitem".
*/
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file)
+static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
{
unsigned long flags;
struct list_head *lsthead, *lnk;
@@ -928,11 +934,11 @@
read_lock_irqsave(&ep->lock, flags);
- lsthead = ep_hash_entry(ep, ep_hash_index(ep, file));
+ lsthead = ep_hash_entry(ep, ep_hash_index(ep, file, fd));
list_for_each(lnk, lsthead) {
epi = list_entry(lnk, struct epitem, llink);
- if (epi->file == file) {
+ if (epi->file == file && epi->fd == fd) {
ep_use_epitem(epi);
break;
}
@@ -976,7 +982,8 @@
* This is the callback that is used to add our wait queue to the
* target file wakeup lists.
*/
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt)
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
+ poll_table *pt)
{
struct epitem *epi = EP_ITEM_FROM_EPQUEUE(pt);
struct eppoll_entry *pwq;
@@ -995,7 +1002,8 @@
}
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile)
+static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
+ struct file *tfile, int fd)
{
int error, revents, pwake = 0;
unsigned long flags;
@@ -1014,6 +1022,7 @@
INIT_LIST_HEAD(&epi->pwqlist);
epi->ep = ep;
epi->file = tfile;
+ epi->fd = fd;
epi->event = *event;
atomic_set(&epi->usecnt, 1);
epi->nwait = 0;
@@ -1046,7 +1055,7 @@
write_lock_irqsave(&ep->lock, flags);
/* Add the current item to the hash table */
- list_add(&epi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile)));
+ list_add(&epi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile, fd)));
/* If the file is already "ready" we drop it inside the ready list */
if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) {
@@ -1065,8 +1074,8 @@
if (pwake)
ep_poll_safewake(&psw, &ep->poll_wait);
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %p)\n",
- current, ep, tfile));
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %p, %d)\n",
+ current, ep, tfile, fd));
return 0;
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c Sun Jul 13 20:39:55 2003
+++ b/fs/exec.c Sun Jul 13 20:39:55 2003
@@ -923,12 +923,12 @@
if (offset != PAGE_SIZE)
continue;
offset = 0;
- kunmap(page);
+ kunmap_atomic(kaddr, KM_USER0);
inside:
page = bprm->page[bprm->p/PAGE_SIZE];
- kaddr = kmap(page);
+ kaddr = kmap_atomic(page, KM_USER0);
}
- kunmap(page);
+ kunmap_atomic(kaddr, KM_USER0);
bprm->argc--;
}
}
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c Sun Jul 13 20:39:55 2003
+++ b/fs/ext2/ialloc.c Sun Jul 13 20:39:55 2003
@@ -235,10 +235,7 @@
EXT2_INODE_SIZE(inode->i_sb);
block = le32_to_cpu(gdp->bg_inode_table) +
(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
- bh = sb_getblk(inode->i_sb, block);
- if (!buffer_uptodate(bh) && !buffer_locked(bh))
- ll_rw_block(READA, 1, &bh);
- __brelse(bh);
+ sb_breadahead(inode->i_sb, block);
}
/*
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c Sun Jul 13 20:39:56 2003
+++ b/fs/ext3/inode.c Sun Jul 13 20:39:56 2003
@@ -1200,7 +1200,7 @@
if (!partial)
SetPageUptodate(page);
if (pos > inode->i_size)
- inode->i_size = pos;
+ i_size_write(inode, pos);
EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
if (inode->i_size > EXT3_I(inode)->i_disksize) {
EXT3_I(inode)->i_disksize = inode->i_size;
@@ -1574,7 +1574,7 @@
loff_t end = offset + ret;
if (end > inode->i_size) {
ei->i_disksize = end;
- inode->i_size = end;
+ i_size_write(inode, end);
err = ext3_mark_inode_dirty(handle, inode);
if (!ret)
ret = err;
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c Sun Jul 13 20:39:56 2003
+++ b/fs/inode.c Sun Jul 13 20:39:56 2003
@@ -189,6 +189,7 @@
INIT_LIST_HEAD(&inode->i_data.i_mmap);
INIT_LIST_HEAD(&inode->i_data.i_mmap_shared);
spin_lock_init(&inode->i_lock);
+ i_size_ordered_init(inode);
}
static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c Sun Jul 13 20:39:55 2003
+++ b/fs/ioctl.c Sun Jul 13 20:39:55 2003
@@ -40,7 +40,7 @@
return -EBADF;
return put_user(inode->i_sb->s_blocksize, (int *) arg);
case FIONREAD:
- return put_user(inode->i_size - filp->f_pos, (int *) arg);
+ return put_user(i_size_read(inode) - filp->f_pos, (int *) arg);
}
if (filp->f_op && filp->f_op->ioctl)
return filp->f_op->ioctl(inode, filp, cmd, arg);
diff -Nru a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
--- a/fs/jbd/checkpoint.c Sun Jul 13 20:39:55 2003
+++ b/fs/jbd/checkpoint.c Sun Jul 13 20:39:55 2003
@@ -75,11 +75,12 @@
* Called under j-state_lock *only*. It will be unlocked if we have to wait
* for a checkpoint to free up some space in the log.
*/
-
-void __log_wait_for_space(journal_t *journal, int nblocks)
+void __log_wait_for_space(journal_t *journal)
{
+ int nblocks;
assert_spin_locked(&journal->j_state_lock);
+ nblocks = jbd_space_needed(journal);
while (__log_space_left(journal) < nblocks) {
if (journal->j_flags & JFS_ABORT)
return;
@@ -91,9 +92,10 @@
* were waiting for the checkpoint lock
*/
spin_lock(&journal->j_state_lock);
+ nblocks = jbd_space_needed(journal);
if (__log_space_left(journal) < nblocks) {
spin_unlock(&journal->j_state_lock);
- log_do_checkpoint(journal, nblocks);
+ log_do_checkpoint(journal);
spin_lock(&journal->j_state_lock);
}
up(&journal->j_checkpoint_sem);
@@ -279,9 +281,7 @@
*
* The journal should be locked before calling this function.
*/
-
-/* @@@ `nblocks' is unused. Should it be used? */
-int log_do_checkpoint(journal_t *journal, int nblocks)
+int log_do_checkpoint(journal_t *journal)
{
int result;
int batch_count = 0;
@@ -315,7 +315,7 @@
int cleanup_ret, retry = 0;
tid_t this_tid;
- transaction = journal->j_checkpoint_transactions->t_cpnext;
+ transaction = journal->j_checkpoint_transactions;
this_tid = transaction->t_tid;
jh = transaction->t_checkpoint_list;
last_jh = jh->b_cpprev;
@@ -332,27 +332,19 @@
retry = 1;
break;
}
- retry = __flush_buffer(journal, jh, bhs, &batch_count,
- &drop_count);
+ retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count);
} while (jh != last_jh && !retry);
- if (batch_count) {
+
+ if (batch_count)
__flush_batch(journal, bhs, &batch_count);
- continue;
- }
- if (retry)
- continue;
/*
- * If someone emptied the checkpoint list while we slept, we're
- * done.
- */
- if (!journal->j_checkpoint_transactions)
- break;
- /*
* If someone cleaned up this transaction while we slept, we're
* done
*/
- if (journal->j_checkpoint_transactions->t_cpnext != transaction)
+ if (journal->j_checkpoint_transactions != transaction)
+ break;
+ if (retry)
continue;
/*
* Maybe it's a new transaction, but it fell at the same
@@ -367,6 +359,8 @@
*/
cleanup_ret = __cleanup_transaction(journal, transaction);
J_ASSERT(drop_count != 0 || cleanup_ret != 0);
+ if (journal->j_checkpoint_transactions != transaction)
+ break;
}
spin_unlock(&journal->j_list_lock);
result = cleanup_journal_tail(journal);
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c Sun Jul 13 20:39:56 2003
+++ b/fs/jbd/commit.c Sun Jul 13 20:39:56 2003
@@ -169,23 +169,10 @@
* that multiple journal_get_write_access() calls to the same
* buffer are perfectly permissable.
*/
- {
- int nr = 0;
- while (commit_transaction->t_reserved_list) {
- jh = commit_transaction->t_reserved_list;
- JBUFFER_TRACE(jh, "reserved, unused: refile");
- journal_refile_buffer(journal, jh);
- nr++;
- }
- if (nr) {
- static int noisy;
-
- if (noisy < 10) {
- noisy++;
- printk("%s: freed %d reserved buffers\n",
- __FUNCTION__, nr);
- }
- }
+ while (commit_transaction->t_reserved_list) {
+ jh = commit_transaction->t_reserved_list;
+ JBUFFER_TRACE(jh, "reserved, unused: refile");
+ journal_refile_buffer(journal, jh);
}
/*
@@ -413,6 +400,13 @@
__journal_abort_hard(journal);
continue;
}
+
+ /*
+ * start_this_handle() uses t_outstanding_credits to determine
+ * the free space in the log, but this counter is changed
+ * by journal_next_log_block() also.
+ */
+ commit_transaction->t_outstanding_credits--;
/* Bump b_count to prevent truncate from stumbling over
the shadowed buffer! @@@ This can go if we ever get
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c Sun Jul 13 20:39:55 2003
+++ b/fs/jbd/journal.c Sun Jul 13 20:39:55 2003
@@ -484,6 +484,13 @@
ret = __log_start_commit(journal, tid);
if (ret && ptid)
*ptid = tid;
+ } else if (journal->j_committing_transaction && ptid) {
+ /*
+ * If ext3_write_super() recently started a commit, then we
+ * have to wait for completion of that transaction
+ */
+ *ptid = journal->j_committing_transaction->t_tid;
+ ret = 1;
}
spin_unlock(&journal->j_state_lock);
return ret;
@@ -1076,7 +1083,7 @@
spin_lock(&journal->j_list_lock);
while (journal->j_checkpoint_transactions != NULL) {
spin_unlock(&journal->j_list_lock);
- log_do_checkpoint(journal, 1);
+ log_do_checkpoint(journal);
spin_lock(&journal->j_list_lock);
}
@@ -1284,7 +1291,7 @@
spin_lock(&journal->j_list_lock);
while (!err && journal->j_checkpoint_transactions != NULL) {
spin_unlock(&journal->j_list_lock);
- err = log_do_checkpoint(journal, journal->j_maxlen);
+ err = log_do_checkpoint(journal);
spin_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c Sun Jul 13 20:39:55 2003
+++ b/fs/jbd/transaction.c Sun Jul 13 20:39:55 2003
@@ -206,15 +206,10 @@
* Also, this test is inconsitent with the matching one in
* journal_extend().
*/
- needed = journal->j_max_transaction_buffers;
- if (journal->j_committing_transaction)
- needed += journal->j_committing_transaction->
- t_outstanding_credits;
-
- if (__log_space_left(journal) < needed) {
+ if (__log_space_left(journal) < jbd_space_needed(journal)) {
jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
spin_unlock(&transaction->t_handle_lock);
- __log_wait_for_space(journal, needed);
+ __log_wait_for_space(journal);
goto repeat_locked;
}
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c Sun Jul 13 20:39:54 2003
+++ b/fs/libfs.c Sun Jul 13 20:39:54 2003
@@ -328,8 +328,12 @@
struct inode *inode = page->mapping->host;
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ /*
+ * No need to use i_size_read() here, the i_size
+ * cannot change under us because we hold the i_sem.
+ */
if (pos > inode->i_size)
- inode->i_size = pos;
+ i_size_write(inode, pos);
set_page_dirty(page);
return 0;
}
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c Sun Jul 13 20:39:56 2003
+++ b/fs/locks.c Sun Jul 13 20:39:56 2003
@@ -285,7 +285,7 @@
start = filp->f_pos;
break;
case 2: /*SEEK_END*/
- start = filp->f_dentry->d_inode->i_size;
+ start = i_size_read(filp->f_dentry->d_inode);
break;
default:
return -EINVAL;
@@ -335,7 +335,7 @@
start = filp->f_pos;
break;
case 2: /*SEEK_END*/
- start = filp->f_dentry->d_inode->i_size;
+ start = i_size_read(filp->f_dentry->d_inode);
break;
default:
return -EINVAL;
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c Sun Jul 13 20:39:55 2003
+++ b/fs/mpage.c Sun Jul 13 20:39:55 2003
@@ -227,7 +227,7 @@
goto confused;
block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
- last_block = (inode->i_size + blocksize - 1) >> blkbits;
+ last_block = (i_size_read(inode) + blocksize - 1) >> blkbits;
bh.b_page = page;
for (page_block = 0; page_block < blocks_per_page;
@@ -459,7 +459,7 @@
*/
BUG_ON(!PageUptodate(page));
block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
- last_block = (inode->i_size - 1) >> blkbits;
+ last_block = (i_size_read(inode) - 1) >> blkbits;
map_bh.b_page = page;
for (page_block = 0; page_block < blocks_per_page; ) {
@@ -489,9 +489,9 @@
first_unmapped = page_block;
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
if (page->index >= end_index) {
- unsigned offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+ unsigned offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
char *kaddr;
if (page->index > end_index || !offset)
@@ -614,7 +614,6 @@
sector_t last_block_in_bio = 0;
int ret = 0;
int done = 0;
- struct pagevec pvec;
int (*writepage)(struct page *page, struct writeback_control *wbc);
if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -626,7 +625,6 @@
if (get_block == NULL)
writepage = mapping->a_ops->writepage;
- pagevec_init(&pvec, 0);
spin_lock(&mapping->page_lock);
while (!list_empty(&mapping->io_pages) && !done) {
struct page *page = list_entry(mapping->io_pages.prev,
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c Sun Jul 13 20:39:55 2003
+++ b/fs/namei.c Sun Jul 13 20:39:55 2003
@@ -434,19 +434,17 @@
return 1;
}
+/* no need for dcache_lock, as serialization is taken care in
+ * namespace.c
+ */
static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
{
int res = 0;
while (d_mountpoint(*dentry)) {
- struct vfsmount *mounted;
- spin_lock(&dcache_lock);
- mounted = lookup_mnt(*mnt, *dentry);
- if (!mounted) {
- spin_unlock(&dcache_lock);
+ struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
+ if (!mounted)
break;
- }
- *mnt = mntget(mounted);
- spin_unlock(&dcache_lock);
+ *mnt = mounted;
dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root);
@@ -455,21 +453,21 @@
return res;
}
+/* no need for dcache_lock, as serialization is taken care in
+ * namespace.c
+ */
static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
{
struct vfsmount *mounted;
- spin_lock(&dcache_lock);
mounted = lookup_mnt(*mnt, *dentry);
if (mounted) {
- *mnt = mntget(mounted);
- spin_unlock(&dcache_lock);
+ *mnt = mounted;
dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root);
return 1;
}
- spin_unlock(&dcache_lock);
return 0;
}
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c Sun Jul 13 20:39:55 2003
+++ b/fs/namespace.c Sun Jul 13 20:39:55 2003
@@ -26,6 +26,8 @@
extern int __init init_rootfs(void);
extern int __init sysfs_init(void);
+/* spinlock for vfsmount related operations, inplace of dcache_lock */
+spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
static kmem_cache_t *mnt_cache;
@@ -66,30 +68,38 @@
kmem_cache_free(mnt_cache, mnt);
}
+/*
+ * Now, lookup_mnt increments the ref count before returning
+ * the vfsmount struct.
+ */
struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
{
struct list_head * head = mount_hashtable + hash(mnt, dentry);
struct list_head * tmp = head;
- struct vfsmount *p;
+ struct vfsmount *p, *found = NULL;
+ spin_lock(&vfsmount_lock);
for (;;) {
tmp = tmp->next;
p = NULL;
if (tmp == head)
break;
p = list_entry(tmp, struct vfsmount, mnt_hash);
- if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry)
+ if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
+ found = mntget(p);
break;
+ }
}
- return p;
+ spin_unlock(&vfsmount_lock);
+ return found;
}
static int check_mnt(struct vfsmount *mnt)
{
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
while (mnt->mnt_parent != mnt)
mnt = mnt->mnt_parent;
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
return mnt == current->namespace->root;
}
@@ -263,15 +273,15 @@
mnt = list_entry(kill.next, struct vfsmount, mnt_list);
list_del_init(&mnt->mnt_list);
if (mnt->mnt_parent == mnt) {
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
} else {
struct nameidata old_nd;
detach_mnt(mnt, &old_nd);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
path_release(&old_nd);
}
mntput(mnt);
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
}
}
@@ -324,17 +334,17 @@
}
down_write(¤t->namespace->sem);
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
if (atomic_read(&sb->s_active) == 1) {
/* last instance - try to be smart */
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
lock_kernel();
DQUOT_OFF(sb);
acct_auto_close(sb);
unlock_kernel();
security_sb_umount_close(mnt);
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
}
retval = -EBUSY;
if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
@@ -342,7 +352,7 @@
umount_tree(mnt);
retval = 0;
}
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
if (retval)
security_sb_umount_busy(mnt);
up_write(¤t->namespace->sem);
@@ -449,18 +459,18 @@
q = clone_mnt(p, p->mnt_root);
if (!q)
goto Enomem;
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, &nd);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
}
}
return res;
Enomem:
if (res) {
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
umount_tree(res);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
}
return NULL;
}
@@ -485,7 +495,7 @@
goto out_unlock;
err = -ENOENT;
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) {
struct list_head head;
@@ -495,7 +505,7 @@
mntget(mnt);
err = 0;
}
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
out_unlock:
up(&nd->dentry->d_inode->i_sem);
if (!err)
@@ -532,9 +542,9 @@
if (mnt) {
err = graft_tree(mnt, nd);
if (err) {
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
umount_tree(mnt);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
} else
mntput(mnt);
}
@@ -599,7 +609,7 @@
if (IS_DEADDIR(nd->dentry->d_inode))
goto out1;
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
goto out2;
@@ -623,7 +633,7 @@
detach_mnt(old_nd.mnt, &parent_nd);
attach_mnt(old_nd.mnt, nd);
out2:
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
out1:
up(&nd->dentry->d_inode->i_sem);
out:
@@ -804,9 +814,9 @@
down_write(&tsk->namespace->sem);
/* First pass: copy the tree topology */
new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
/* Second pass: switch the tsk->fs->* elements */
if (fs) {
@@ -1027,7 +1037,7 @@
if (new_nd.mnt->mnt_root != new_nd.dentry)
goto out2; /* not a mountpoint */
tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
if (tmp != new_nd.mnt) {
for (;;) {
if (tmp->mnt_parent == tmp)
@@ -1044,7 +1054,7 @@
detach_mnt(user_nd.mnt, &root_parent);
attach_mnt(user_nd.mnt, &old_nd);
attach_mnt(new_nd.mnt, &root_parent);
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
chroot_fs_refs(&user_nd, &new_nd);
security_sb_post_pivotroot(&user_nd, &new_nd);
error = 0;
@@ -1061,7 +1071,7 @@
unlock_kernel();
return error;
out3:
- spin_unlock(&dcache_lock);
+ spin_unlock(&vfsmount_lock);
goto out2;
}
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c Sun Jul 13 20:39:56 2003
+++ b/fs/nfs/inode.c Sun Jul 13 20:39:56 2003
@@ -1001,6 +1001,7 @@
loff_t new_isize;
int invalid = 0;
int mtime_update = 0;
+ loff_t cur_isize;
dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n",
inode->i_sb->s_id, inode->i_ino,
@@ -1087,8 +1088,9 @@
* If we have pending writebacks, things can get
* messy.
*/
- if (nfs_have_writebacks(inode) && new_isize < inode->i_size)
- new_isize = inode->i_size;
+ cur_isize = i_size_read(inode);
+ if (nfs_have_writebacks(inode) && new_isize < cur_isize)
+ new_isize = cur_isize;
nfsi->read_cache_ctime = fattr->ctime;
inode->i_ctime = fattr->ctime;
@@ -1102,7 +1104,7 @@
}
nfsi->read_cache_isize = new_size;
- inode->i_size = new_isize;
+ i_size_write(inode, new_isize);
if (inode->i_mode != fattr->mode ||
inode->i_uid != fattr->uid ||
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c Sun Jul 13 20:39:56 2003
+++ b/fs/nfs/write.c Sun Jul 13 20:39:56 2003
@@ -180,8 +180,8 @@
* If we've extended the file, update the inode
* now so we don't invalidate the cache.
*/
- if (base > inode->i_size)
- inode->i_size = base;
+ if (base > i_size_read(inode))
+ i_size_write(inode, base);
} while (count);
if (PageError(page))
@@ -211,8 +211,8 @@
nfs_unlock_request(req);
nfs_strategy(inode);
end = ((loff_t)page->index<i_size < end)
- inode->i_size = end;
+ if (i_size_read(inode) < end)
+ i_size_write(inode, end);
out:
return status;
@@ -227,9 +227,10 @@
struct inode *inode = page->mapping->host;
unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE;
+ loff_t i_size = i_size_read(inode);
int err;
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ end_index = i_size >> PAGE_CACHE_SHIFT;
/* Ensure we've flushed out any previous writes */
nfs_wb_page(inode,page);
@@ -238,7 +239,7 @@
if (page->index < end_index)
goto do_it;
/* things got complicated... */
- offset = inode->i_size & (PAGE_CACHE_SIZE-1);
+ offset = i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */
err = -EIO;
@@ -701,8 +702,8 @@
status = 0;
end = ((loff_t)page->index<i_size < end)
- inode->i_size = end;
+ if (i_size_read(inode) < end)
+ i_size_write(inode, end);
/* If we wrote past the end of the page.
* Call the strategy routine so it can send out a bunch
@@ -716,7 +717,7 @@
nfs_unlock_request(req);
done:
dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n",
- status, (long long)inode->i_size);
+ status, (long long)i_size_read(inode));
if (status < 0)
ClearPageUptodate(page);
return status;
@@ -951,7 +952,7 @@
end = req_offset(last) + last->wb_bytes;
len = end - start;
/* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
- if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1))
+ if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
len = 0;
data->inode = inode;
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c Sun Jul 13 20:39:55 2003
+++ b/fs/nfsd/nfssvc.c Sun Jul 13 20:39:55 2003
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
#include
@@ -168,6 +169,7 @@
nfsd(struct svc_rqst *rqstp)
{
struct svc_serv *serv = rqstp->rq_server;
+ struct fs_struct *fsp;
int err;
struct nfsd_list me;
sigset_t shutdown_mask, allowed_mask;
@@ -178,6 +180,18 @@
daemonize("nfsd");
current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
+ /* After daemonize() this kernel thread shares current->fs
+ * with the init process. We need to create files with a
+ * umask of 0 instead of init's umask. */
+ fsp = copy_fs_struct(current->fs);
+ if (!fsp) {
+ printk("Unable to start nfsd thread: out of memory\n");
+ goto out;
+ }
+ exit_fs(current);
+ current->fs = fsp;
+ current->fs->umask = 0;
+
siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS);
siginitsetinv(&allowed_mask, ALLOWED_SIGS);
@@ -262,6 +276,7 @@
list_del(&me.list);
nfsdstats.th_cnt --;
+out:
/* Release the thread */
svc_exit_thread(rqstp);
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c Sun Jul 13 20:39:54 2003
+++ b/fs/open.c Sun Jul 13 20:39:54 2003
@@ -1008,7 +1008,7 @@
*/
int generic_file_open(struct inode * inode, struct file * filp)
{
- if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
+ if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
return 0;
}
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c Sun Jul 13 20:39:55 2003
+++ b/fs/proc/base.c Sun Jul 13 20:39:55 2003
@@ -307,20 +307,22 @@
base = dget(current->fs->root);
read_unlock(¤t->fs->lock);
- spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
de = root;
mnt = vfsmnt;
while (vfsmnt != our_vfsmnt) {
- if (vfsmnt == vfsmnt->mnt_parent)
+ if (vfsmnt == vfsmnt->mnt_parent) {
+ spin_unlock(&vfsmount_lock);
goto out;
+ }
de = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
}
+ spin_unlock(&vfsmount_lock);
if (!is_subdir(de, base))
goto out;
- spin_unlock(&dcache_lock);
exit:
dput(base);
@@ -329,7 +331,6 @@
mntput(mnt);
return res;
out:
- spin_unlock(&dcache_lock);
res = -EACCES;
goto exit;
}
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c Sun Jul 13 20:39:56 2003
+++ b/fs/proc/generic.c Sun Jul 13 20:39:56 2003
@@ -566,22 +566,6 @@
return ent;
}
-struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
- struct proc_dir_entry *parent, kdev_t rdev)
-{
- struct proc_dir_entry *ent;
-
- ent = proc_create(&parent,name,mode,1);
- if (ent) {
- ent->rdev = rdev;
- if (proc_register(parent, ent) < 0) {
- kfree(ent);
- ent = NULL;
- }
- }
- return ent;
-}
-
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
{
struct proc_dir_entry *ent;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c Sun Jul 13 20:39:56 2003
+++ b/fs/proc/inode.c Sun Jul 13 20:39:56 2003
@@ -204,8 +204,6 @@
inode->i_op = de->proc_iops;
if (de->proc_fops)
inode->i_fop = de->proc_fops;
- else if (S_ISBLK(de->mode)||S_ISCHR(de->mode)||S_ISFIFO(de->mode))
- init_special_inode(inode,de->mode,kdev_t_to_nr(de->rdev));
}
out:
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c Sun Jul 13 20:39:56 2003
+++ b/fs/proc/root.c Sun Jul 13 20:39:56 2003
@@ -153,7 +153,6 @@
EXPORT_SYMBOL(proc_sys_root);
#endif
EXPORT_SYMBOL(proc_symlink);
-EXPORT_SYMBOL(proc_mknod);
EXPORT_SYMBOL(proc_mkdir);
EXPORT_SYMBOL(create_proc_entry);
EXPORT_SYMBOL(remove_proc_entry);
diff -Nru a/fs/quota_v1.c b/fs/quota_v1.c
--- a/fs/quota_v1.c Sun Jul 13 20:39:56 2003
+++ b/fs/quota_v1.c Sun Jul 13 20:39:56 2003
@@ -132,12 +132,14 @@
mm_segment_t fs;
ssize_t size;
loff_t offset = 0;
+ loff_t isize;
static const uint quota_magics[] = V2_INITQMAGICS;
- if (!inode->i_size)
+ isize = i_size_read(inode);
+ if (!isize)
return 0;
- blocks = inode->i_size >> BLOCK_SIZE_BITS;
- off = inode->i_size & (BLOCK_SIZE - 1);
+ blocks = isize >> BLOCK_SIZE_BITS;
+ off = isize & (BLOCK_SIZE - 1);
if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
return 0;
/* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c Sun Jul 13 20:39:55 2003
+++ b/fs/read_write.c Sun Jul 13 20:39:55 2003
@@ -55,7 +55,7 @@
lock_kernel();
switch (origin) {
case 2:
- offset += file->f_dentry->d_inode->i_size;
+ offset += i_size_read(file->f_dentry->d_inode);
break;
case 1:
offset += file->f_pos;
@@ -84,7 +84,7 @@
lock_kernel();
switch (origin) {
case 2:
- offset += file->f_dentry->d_inode->i_size;
+ offset += i_size_read(file->f_dentry->d_inode);
break;
case 1:
offset += file->f_pos;
diff -Nru a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
--- a/fs/reiserfs/bitmap.c Sun Jul 13 20:39:55 2003
+++ b/fs/reiserfs/bitmap.c Sun Jul 13 20:39:55 2003
@@ -43,7 +43,7 @@
test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
static inline void get_bit_address (struct super_block * s,
- unsigned long block, int * bmap_nr, int * offset)
+ b_blocknr_t block, int * bmap_nr, int * offset)
{
/* It is in the bitmap block number equal to the block
* number divided by the number of bits in a block. */
@@ -54,7 +54,7 @@
}
#ifdef CONFIG_REISERFS_CHECK
-int is_reusable (struct super_block * s, unsigned long block, int bit_value)
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
{
int i, j;
@@ -107,7 +107,7 @@
static inline int is_block_in_journal (struct super_block * s, int bmap, int
off, int *next)
{
- unsigned long tmp;
+ b_blocknr_t tmp;
if (reiserfs_in_journal (s, bmap, off, 1, &tmp)) {
if (tmp) { /* hint supplied */
@@ -235,7 +235,7 @@
/* Tries to find contiguous zero bit window (given size) in given region of
* bitmap and place new blocks there. Returns number of allocated blocks. */
static int scan_bitmap (struct reiserfs_transaction_handle *th,
- unsigned long *start, unsigned long finish,
+ b_blocknr_t *start, b_blocknr_t finish,
int min, int max, int unfm, unsigned long file_block)
{
int nr_allocated=0;
@@ -281,7 +281,7 @@
}
static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
- unsigned long block)
+ b_blocknr_t block)
{
struct super_block * s = th->t_super;
struct reiserfs_super_block * rs;
@@ -327,7 +327,7 @@
}
void reiserfs_free_block (struct reiserfs_transaction_handle *th,
- unsigned long block)
+ b_blocknr_t block)
{
struct super_block * s = th->t_super;
@@ -340,7 +340,7 @@
/* preallocated blocks don't need to be run through journal_mark_freed */
void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th,
- unsigned long block) {
+ b_blocknr_t block) {
RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device");
RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block");
_reiserfs_free_block(th, block) ;
@@ -589,15 +589,15 @@
static inline int old_hashed_relocation (reiserfs_blocknr_hint_t * hint)
{
- unsigned long border;
- unsigned long hash_in;
+ b_blocknr_t border;
+ u32 hash_in;
if (hint->formatted_node || hint->inode == NULL) {
return 0;
}
hash_in = le32_to_cpu((INODE_PKEY(hint->inode))->k_dir_id);
- border = hint->beg + (unsigned long) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
+ border = hint->beg + (u32) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
if (border > hint->search_start)
hint->search_start = border;
@@ -606,7 +606,7 @@
static inline int old_way (reiserfs_blocknr_hint_t * hint)
{
- unsigned long border;
+ b_blocknr_t border;
if (hint->formatted_node || hint->inode == NULL) {
return 0;
@@ -622,7 +622,7 @@
static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint)
{
struct key * key = &hint->key;
- unsigned long slice_start;
+ b_blocknr_t slice_start;
slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100);
if ( slice_start > hint->search_start || slice_start + (hint->end / 100) <= hint->search_start) {
@@ -910,7 +910,7 @@
int reiserfs_can_fit_pages ( struct super_block *sb /* superblock of filesystem
to estimate space */ )
{
- unsigned long space;
+ b_blocknr_t space;
spin_lock(&REISERFS_SB(sb)->bitmap_lock);
space = (SB_FREE_BLOCKS(sb) - REISERFS_SB(sb)->reserved_blocks) >> ( PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
diff -Nru a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
--- a/fs/reiserfs/do_balan.c Sun Jul 13 20:39:55 2003
+++ b/fs/reiserfs/do_balan.c Sun Jul 13 20:39:55 2003
@@ -1250,12 +1250,12 @@
static void free_thrown(struct tree_balance *tb) {
int i ;
- unsigned long blocknr ;
+ b_blocknr_t blocknr ;
for (i = 0; i < sizeof (tb->thrown)/sizeof (tb->thrown[0]); i++) {
if (tb->thrown[i]) {
blocknr = tb->thrown[i]->b_blocknr ;
if (buffer_dirty (tb->thrown[i]))
- printk ("free_thrown deals with dirty buffer %ld\n", blocknr);
+ printk ("free_thrown deals with dirty buffer %d\n", blocknr);
brelse(tb->thrown[i]) ; /* incremented in store_thrown */
reiserfs_free_block (tb->transaction_handle, blocknr);
}
@@ -1339,7 +1339,7 @@
#ifdef CONFIG_REISERFS_CHECK
-int is_reusable (struct super_block * s, unsigned long block, int bit_value);
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
static void check_internal_node (struct super_block * s, struct buffer_head * bh, char * mes)
{
struct disk_child * dc;
diff -Nru a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
--- a/fs/reiserfs/fix_node.c Sun Jul 13 20:39:55 2003
+++ b/fs/reiserfs/fix_node.c Sun Jul 13 20:39:55 2003
@@ -758,7 +758,7 @@
) {
struct buffer_head * p_s_new_bh,
* p_s_Sh = PATH_H_PBUFFER (p_s_tb->tb_path, n_h);
- unsigned long * p_n_blocknr,
+ b_blocknr_t * p_n_blocknr,
a_n_blocknrs[MAX_AMOUNT_NEEDED] = {0, };
int n_counter,
n_number_of_freeblk,
@@ -879,7 +879,7 @@
) {
struct buffer_head * p_s_father, * left;
struct super_block * p_s_sb = p_s_tb->tb_sb;
- unsigned long n_left_neighbor_blocknr;
+ b_blocknr_t n_left_neighbor_blocknr;
int n_left_neighbor_position;
if ( ! p_s_tb->FL[n_h] ) /* Father of the left neighbor does not exist. */
@@ -2501,7 +2501,7 @@
/* deal with list of allocated (used and unused) nodes */
for ( i = 0; i < MAX_FEB_SIZE; i++ ) {
if ( tb->FEB[i] ) {
- unsigned long blocknr = tb->FEB[i]->b_blocknr ;
+ b_blocknr_t blocknr = tb->FEB[i]->b_blocknr ;
/* de-allocated block which was not used by balancing and
bforget about buffer for it */
brelse (tb->FEB[i]);
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c Sun Jul 13 20:39:55 2003
+++ b/fs/reiserfs/inode.c Sun Jul 13 20:39:55 2003
@@ -506,7 +506,7 @@
struct buffer_head * bh_result, int create)
{
int repeat, retval;
- b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is unsigned long
+ b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int
INITIALIZE_PATH(path);
int pos_in_item;
struct cpu_key key;
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c Sun Jul 13 20:39:55 2003
+++ b/fs/reiserfs/journal.c Sun Jul 13 20:39:55 2003
@@ -507,7 +507,7 @@
*/
int reiserfs_in_journal(struct super_block *p_s_sb,
int bmap_nr, int bit_nr, int search_all,
- unsigned long *next_zero_bit) {
+ b_blocknr_t *next_zero_bit) {
struct reiserfs_journal_cnode *cn ;
struct reiserfs_list_bitmap *jb ;
int i ;
@@ -761,7 +761,7 @@
*/
static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journal_cnode *cn) {
struct super_block *sb = cn->sb;
- unsigned long blocknr = cn->blocknr ;
+ b_blocknr_t blocknr = cn->blocknr ;
cn = cn->hprev ;
while(cn) {
@@ -791,7 +791,7 @@
while(cn) {
if (cn->blocknr != 0) {
if (debug) {
- printk("block %lu, bh is %d, state %ld\n", cn->blocknr, cn->bh ? 1: 0,
+ printk("block %u, bh is %d, state %ld\n", cn->blocknr, cn->bh ? 1: 0,
cn->state) ;
}
cn->state = 0 ;
@@ -1105,7 +1105,7 @@
{
struct reiserfs_journal_list *pjl ; /* previous list for this cn */
struct reiserfs_journal_cnode *cn, *walk_cn ;
- unsigned long blocknr ;
+ b_blocknr_t blocknr ;
int run = 0 ;
int orig_trans_id = jl->j_trans_id ;
struct buffer_head *saved_bh ;
@@ -2421,7 +2421,7 @@
**
** returns 1 if it cleaned and relsed the buffer. 0 otherwise
*/
-static int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, int already_cleaned) {
+static int remove_from_transaction(struct super_block *p_s_sb, b_blocknr_t blocknr, int already_cleaned) {
struct buffer_head *bh ;
struct reiserfs_journal_cnode *cn ;
int ret = 0;
@@ -2474,7 +2474,7 @@
*/
static int can_dirty(struct reiserfs_journal_cnode *cn) {
struct super_block *sb = cn->sb;
- unsigned long blocknr = cn->blocknr ;
+ b_blocknr_t blocknr = cn->blocknr ;
struct reiserfs_journal_cnode *cur = cn->hprev ;
int can_dirty = 1 ;
@@ -2710,7 +2710,7 @@
**
** Then remove it from the current transaction, decrementing any counters and filing it on the clean list.
*/
-int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long blocknr) {
+int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, b_blocknr_t blocknr) {
struct reiserfs_journal_cnode *cn = NULL ;
struct buffer_head *bh = NULL ;
struct reiserfs_list_bitmap *jb = NULL ;
@@ -2719,7 +2719,7 @@
if (reiserfs_dont_log(th->t_super)) {
bh = sb_find_get_block(p_s_sb, blocknr) ;
if (bh && buffer_dirty (bh)) {
- printk ("journal_mark_freed(dont_log): dirty buffer on hash list: %lx %ld\n", bh->b_state, blocknr);
+ printk ("journal_mark_freed(dont_log): dirty buffer on hash list: %lx %d\n", bh->b_state, blocknr);
BUG ();
}
brelse (bh);
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c Sun Jul 13 20:39:56 2003
+++ b/fs/reiserfs/stree.c Sun Jul 13 20:39:56 2003
@@ -102,7 +102,7 @@
int n_key_length = REISERFS_SHORT_KEY_LEN;
p_s_le_u32 = (__u32 *)le_key;
- p_s_cpu_u32 = (__u32 *)cpu_key;
+ p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key;
for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) {
if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 )
return -1;
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c Sun Jul 13 20:39:56 2003
+++ b/fs/reiserfs/tail_conversion.c Sun Jul 13 20:39:56 2003
@@ -191,7 +191,7 @@
bh = next ;
} while (bh != head) ;
if ( PAGE_SIZE == bh->b_size ) {
- ClearPageDirty(page);
+ clear_page_dirty(page);
}
}
}
diff -Nru a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c Sun Jul 13 20:39:55 2003
+++ b/fs/stat.c Sun Jul 13 20:39:55 2003
@@ -28,7 +28,7 @@
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
stat->ctime = inode->i_ctime;
- stat->size = inode->i_size;
+ stat->size = i_size_read(inode);
stat->blocks = inode->i_blocks;
stat->blksize = inode->i_blksize;
}
diff -Nru a/include/asm-alpha/timex.h b/include/asm-alpha/timex.h
--- a/include/asm-alpha/timex.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-alpha/timex.h Sun Jul 13 20:39:55 2003
@@ -6,7 +6,9 @@
#ifndef _ASMALPHA_TIMEX_H
#define _ASMALPHA_TIMEX_H
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+/* With only one or two oddballs, we use the RTC as the ticker, selecting
+ the 32.768kHz reference clock, which nicely divides down to our HZ. */
+#define CLOCK_TICK_RATE 32768
/*
* Standard way to access the cycle counter.
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-alpha/unistd.h Sun Jul 13 20:39:55 2003
@@ -359,7 +359,8 @@
#define __NR_clock_getres 421
#define __NR_clock_nanosleep 422
#define __NR_semtimedop 423
-#define NR_SYSCALLS 424
+#define __NR_tgkill 424
+#define NR_SYSCALLS 425
#if defined(__GNUC__)
diff -Nru a/include/asm-generic/div64.h b/include/asm-generic/div64.h
--- a/include/asm-generic/div64.h Sun Jul 13 20:39:56 2003
+++ b/include/asm-generic/div64.h Sun Jul 13 20:39:56 2003
@@ -32,11 +32,15 @@
#elif BITS_PER_LONG == 32
-extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor) __attribute_pure__;
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
# define do_div(n,base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
+ (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
if (likely(((n) >> 32) == 0)) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-i386/unistd.h Sun Jul 13 20:39:55 2003
@@ -276,8 +276,9 @@
#define __NR_statfs64 268
#define __NR_fstatfs64 269
#define __NR_tgkill 270
+#define __NR_utimes 271
-#define NR_syscalls 271
+#define NR_syscalls 272
/* user-visible error numbers are in the range -1 - -124: see */
diff -Nru a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h
--- a/include/asm-parisc/byteorder.h Sun Jul 13 20:39:56 2003
+++ b/include/asm-parisc/byteorder.h Sun Jul 13 20:39:56 2003
@@ -30,9 +30,9 @@
*/
static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
__u64 temp;
- __asm__("permh 3210, %0, %0\n\t"
+ __asm__("permh,3210 %0, %0\n\t"
"hshl %0, 8, %1\n\t"
- "hshr u, %0, 8, %0\n\t"
+ "hshr,u %0, 8, %0\n\t"
"or %1, %0, %0"
: "=r" (x), "=&r" (temp)
: "0" (x));
diff -Nru a/include/asm-parisc/parisc-device.h b/include/asm-parisc/parisc-device.h
--- a/include/asm-parisc/parisc-device.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-parisc/parisc-device.h Sun Jul 13 20:39:55 2003
@@ -33,6 +33,7 @@
char *name;
const struct parisc_device_id *id_table;
int (*probe) (struct parisc_device *dev); /* New device discovered */
+ int (*remove) (struct parisc_device *dev);
struct device_driver drv;
};
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h Sun Jul 13 20:39:56 2003
+++ b/include/asm-parisc/pgtable.h Sun Jul 13 20:39:56 2003
@@ -368,11 +368,11 @@
/* Encode and de-code a swap entry */
#define __swp_type(x) ((x).val & 0x1f)
-#define __swp_offset(x) ( (((x).val >> 5) & 0xf) | \
- (((x).val >> 7) & ~0xf) )
+#define __swp_offset(x) ( (((x).val >> 6) & 0x7) | \
+ (((x).val >> 8) & ~0x7) )
#define __swp_entry(type, offset) ((swp_entry_t) { (type) | \
- ((offset & 0xf) << 5) | \
- ((offset & ~0xf) << 7) })
+ ((offset & 0x7) << 6) | \
+ ((offset & ~0x7) << 8) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
--- a/include/asm-parisc/processor.h Sun Jul 13 20:39:56 2003
+++ b/include/asm-parisc/processor.h Sun Jul 13 20:39:56 2003
@@ -142,6 +142,7 @@
*/
unsigned long thread_saved_pc(struct task_struct *t);
+void show_trace(struct task_struct *task, unsigned long *stack);
/*
* Start user thread in another space.
diff -Nru a/include/asm-sparc/ipc.h b/include/asm-sparc/ipc.h
--- a/include/asm-sparc/ipc.h Sun Jul 13 20:39:54 2003
+++ b/include/asm-sparc/ipc.h Sun Jul 13 20:39:54 2003
@@ -14,6 +14,7 @@
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
+#define SEMTIMEDOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
diff -Nru a/include/asm-sparc/pgtsrmmu.h b/include/asm-sparc/pgtsrmmu.h
--- a/include/asm-sparc/pgtsrmmu.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-sparc/pgtsrmmu.h Sun Jul 13 20:39:55 2003
@@ -13,6 +13,9 @@
#include /* TI_UWINMASK for WINDOW_FLUSH */
#endif
+/* Number of contexts is implementation-dependent; 64k is the most we support */
+#define SRMMU_MAX_CONTEXTS 65536
+
/* PMD_SHIFT determines the size of the area a second-level page table entry can map */
#define SRMMU_PMD_SHIFT 18
#define SRMMU_PMD_SIZE (1UL << SRMMU_PMD_SHIFT)
diff -Nru a/include/asm-sparc64/ipc.h b/include/asm-sparc64/ipc.h
--- a/include/asm-sparc64/ipc.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-sparc64/ipc.h Sun Jul 13 20:39:55 2003
@@ -14,6 +14,7 @@
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
+#define SEMTIMEDOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
diff -Nru a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
--- a/include/asm-sparc64/ptrace.h Sun Jul 13 20:39:55 2003
+++ b/include/asm-sparc64/ptrace.h Sun Jul 13 20:39:55 2003
@@ -94,6 +94,8 @@
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
#ifdef __KERNEL__
+#define force_successful_syscall_return() \
+ set_thread_flag(TIF_SYSCALL_SUCCESS)
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
extern void show_regs(struct pt_regs *);
diff -Nru a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
--- a/include/asm-sparc64/thread_info.h Sun Jul 13 20:39:56 2003
+++ b/include/asm-sparc64/thread_info.h Sun Jul 13 20:39:56 2003
@@ -205,7 +205,12 @@
#define TIF_BLKCOMMIT 9 /* use ASI_BLK_COMMIT_* in copy_user_page */
#define TIF_POLLING_NRFLAG 10
-#define TIF_ABI_PENDING 11
+#define TIF_SYSCALL_SUCCESS 11
+/* NOTE: Thread flags >= 12 should be ones we have no interest
+ * in using in assembly, else we can't use the mask as
+ * an immediate value in instructions such as andcc.
+ */
+#define TIF_ABI_PENDING 12
#define _TIF_SYSCALL_TRACE (1<
-
-typedef __kernel_fsid_t fsid_t;
-
-#endif
-
-struct statfs {
- long f_type;
- long f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
- __kernel_fsid_t f_fsid;
- long f_namelen;
- long f_spare[6];
-};
+#include
#endif /* __V850_STATFS_H__ */
diff -Nru a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
--- a/include/linux/ac97_codec.h Sun Jul 13 20:39:54 2003
+++ b/include/linux/ac97_codec.h Sun Jul 13 20:39:54 2003
@@ -214,6 +214,9 @@
(CODEC)->supported_mixers & (1<
+#define __NEED_I_SIZE_ORDERED
+#define i_size_ordered_init(inode) seqcount_init(&inode->i_size_seqcount)
+#else
+#define i_size_ordered_init(inode) do { } while (0)
+#endif
+
struct inode {
struct hlist_node i_hash;
struct list_head i_list;
@@ -399,7 +410,59 @@
union {
void *generic_ip;
} u;
+#ifdef __NEED_I_SIZE_ORDERED
+ seqcount_t i_size_seqcount;
+#endif
};
+
+/*
+ * NOTE: in a 32bit arch with a preemptable kernel and
+ * an UP compile the i_size_read/write must be atomic
+ * with respect to the local cpu (unlike with preempt disabled),
+ * but they don't need to be atomic with respect to other cpus like in
+ * true SMP (so they need either to either locally disable irq around
+ * the read or for example on x86 they can be still implemented as a
+ * cmpxchg8b without the need of the lock prefix). For SMP compiles
+ * and 64bit archs it makes no difference if preempt is enabled or not.
+ */
+static inline loff_t i_size_read(struct inode *inode)
+{
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+ loff_t i_size;
+ unsigned int seq;
+
+ do {
+ seq = read_seqcount_begin(&inode->i_size_seqcount);
+ i_size = inode->i_size;
+ } while (read_seqcount_retry(&inode->i_size_seqcount, seq));
+ return i_size;
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+ loff_t i_size;
+
+ preempt_disable();
+ i_size = inode->i_size;
+ preempt_enable();
+ return i_size;
+#else
+ return inode->i_size;
+#endif
+}
+
+
+static inline void i_size_write(struct inode *inode, loff_t i_size)
+{
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+ write_seqcount_begin(&inode->i_size_seqcount);
+ inode->i_size = i_size;
+ write_seqcount_end(&inode->i_size_seqcount);
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+ preempt_disable();
+ inode->i_size = i_size;
+ preempt_enable();
+#else
+ inode->i_size = i_size;
+#endif
+}
struct fown_struct {
rwlock_t lock; /* protects pid, uid, euid fields */
diff -Nru a/include/linux/irda.h b/include/linux/irda.h
--- a/include/linux/irda.h Sun Jul 13 20:39:54 2003
+++ b/include/linux/irda.h Sun Jul 13 20:39:54 2003
@@ -25,7 +25,11 @@
#ifndef KERNEL_IRDA_H
#define KERNEL_IRDA_H
-#include /* only for sa_family_t */
+/* Please do *not* add any #include in this file, this file is
+ * included as-is in user space.
+ * Please fix the calling file to properly included needed files before
+ * this one, or preferably to include instead.
+ * Jean II */
/* Hint bit positions for first hint byte */
#define HINT_PNP 0x01
diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h
--- a/include/linux/jbd.h Sun Jul 13 20:39:56 2003
+++ b/include/linux/jbd.h Sun Jul 13 20:39:56 2003
@@ -992,9 +992,9 @@
int __log_start_commit(journal_t *journal, tid_t tid);
int journal_start_commit(journal_t *journal, tid_t *tid);
int log_wait_commit(journal_t *journal, tid_t tid);
-int log_do_checkpoint(journal_t *journal, int nblocks);
+int log_do_checkpoint(journal_t *journal);
-void __log_wait_for_space(journal_t *journal, int nblocks);
+void __log_wait_for_space(journal_t *journal);
extern void __journal_drop_transaction(journal_t *, transaction_t *);
extern int cleanup_journal_tail(journal_t *);
@@ -1052,6 +1052,19 @@
}
extern int journal_blocks_per_page(struct inode *inode);
+
+/*
+ * Return the minimum number of blocks which must be free in the journal
+ * before a new transaction may be started. Must be called under j_state_lock.
+ */
+static inline int jbd_space_needed(journal_t *journal)
+{
+ int nblocks = journal->j_max_transaction_buffers;
+ if (journal->j_committing_transaction)
+ nblocks += journal->j_committing_transaction->
+ t_outstanding_credits;
+ return nblocks;
+}
/*
* Definitions which augment the buffer_head layer
diff -Nru a/include/linux/loop.h b/include/linux/loop.h
--- a/include/linux/loop.h Sun Jul 13 20:39:56 2003
+++ b/include/linux/loop.h Sun Jul 13 20:39:56 2003
@@ -36,7 +36,8 @@
int (*transfer)(struct loop_device *, int cmd,
char *raw_buf, char *loop_buf, int size,
sector_t real_block);
- char lo_name[LO_NAME_SIZE];
+ char lo_file_name[LO_NAME_SIZE];
+ char lo_crypt_name[LO_NAME_SIZE];
char lo_encrypt_key[LO_KEY_SIZE];
int lo_encrypt_key_size;
struct loop_func_table *lo_encryption;
@@ -49,7 +50,6 @@
struct block_device *lo_device;
unsigned lo_blocksize;
void *key_data;
- char key_reserved[48]; /* for use by the filter modules */
int old_gfp_mask;
@@ -102,7 +102,8 @@
__u32 lo_encrypt_type;
__u32 lo_encrypt_key_size; /* ioctl w/o */
__u32 lo_flags; /* ioctl r/o */
- __u8 lo_name[LO_NAME_SIZE];
+ __u8 lo_file_name[LO_NAME_SIZE];
+ __u8 lo_crypt_name[LO_NAME_SIZE];
__u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
__u64 lo_init[2];
};
diff -Nru a/include/linux/mount.h b/include/linux/mount.h
--- a/include/linux/mount.h Sun Jul 13 20:39:54 2003
+++ b/include/linux/mount.h Sun Jul 13 20:39:54 2003
@@ -54,6 +54,7 @@
extern struct vfsmount *alloc_vfsmnt(const char *name);
extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
const char *name, void *data);
+extern spinlock_t vfsmount_lock;
#endif
#endif /* _LINUX_MOUNT_H */
diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h
--- a/include/linux/nbd.h Sun Jul 13 20:39:56 2003
+++ b/include/linux/nbd.h Sun Jul 13 20:39:56 2003
@@ -5,6 +5,9 @@
* 2001 Copyright (C) Steven Whitehouse
* New nbd_end_request() for compatibility with new linux block
* layer code.
+ * 2003/06/24 Louis D. Langholtz
+ * Removed unneeded blksize_bits field from nbd_device struct.
+ * Cleanup PARANOIA usage & code.
*/
#ifndef LINUX_NBD_H
@@ -26,31 +29,27 @@
NBD_CMD_DISC = 2
};
-
-#ifdef PARANOIA
-extern int requests_in;
-extern int requests_out;
-#endif
-
#define nbd_cmd(req) ((req)->cmd[0])
-
#define MAX_NBD 128
+/* Define PARANOIA to include extra sanity checking code in here & driver */
+#define PARANOIA
+
struct nbd_device {
- int refcnt;
int flags;
int harderror; /* Code of hard error */
#define NBD_READ_ONLY 0x0001
#define NBD_WRITE_NOCHK 0x0002
struct socket * sock;
struct file * file; /* If == NULL, device is not ready, yet */
+#ifdef PARANOIA
int magic; /* FIXME: not if debugging is off */
+#endif
spinlock_t queue_lock;
struct list_head queue_head;/* Requests are added here... */
struct semaphore tx_lock;
struct gendisk *disk;
int blksize;
- int blksize_bits;
u64 bytesize;
};
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h Sun Jul 13 20:39:54 2003
+++ b/include/linux/proc_fs.h Sun Jul 13 20:39:54 2003
@@ -71,7 +71,6 @@
write_proc_t *write_proc;
atomic_t count; /* use count */
int deleted; /* delete flag */
- kdev_t rdev;
};
struct kcore_list {
@@ -141,8 +140,6 @@
extern struct proc_dir_entry *proc_symlink(const char *,
struct proc_dir_entry *, const char *);
-extern struct proc_dir_entry *proc_mknod(const char *,mode_t,
- struct proc_dir_entry *,kdev_t);
extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
@@ -209,8 +206,6 @@
static inline struct proc_dir_entry *proc_symlink(const char *name,
struct proc_dir_entry *parent,char *dest) {return NULL;}
-static inline struct proc_dir_entry *proc_mknod(const char *name,mode_t mode,
- struct proc_dir_entry *parent,kdev_t rdev) {return NULL;}
static inline struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent) {return NULL;}
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h Sun Jul 13 20:39:56 2003
+++ b/include/linux/reiserfs_fs.h Sun Jul 13 20:39:56 2003
@@ -269,7 +269,7 @@
#define NO_BALANCING_NEEDED (-4)
#define NO_MORE_UNUSED_CONTIGUOUS_BLOCKS (-5)
-typedef unsigned long b_blocknr_t;
+typedef __u32 b_blocknr_t;
typedef __u32 unp_t;
struct unfm_nodeinfo {
@@ -570,7 +570,7 @@
static inline int uniqueness2type (__u32 uniqueness) CONSTF;
static inline int uniqueness2type (__u32 uniqueness)
{
- switch (uniqueness) {
+ switch ((int)uniqueness) {
case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
@@ -1730,11 +1730,11 @@
int journal_end(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
int journal_end_sync(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
int journal_mark_dirty_nolog(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
-int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, unsigned long blocknr) ;
+int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, b_blocknr_t blocknr) ;
int push_journal_writer(char *w) ;
int pop_journal_writer(int windex) ;
int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ;
-int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, unsigned long *next) ;
+int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, b_blocknr_t *next) ;
int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_sb, unsigned long) ;
void flush_async_commits(struct super_block *p_s_sb) ;
@@ -2105,8 +2105,8 @@
typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
int reiserfs_parse_alloc_options (struct super_block *, char *);
-int is_reusable (struct super_block * s, unsigned long block, int bit_value);
-void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long);
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
+void reiserfs_free_block (struct reiserfs_transaction_handle *th, b_blocknr_t);
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t * , int, int);
extern inline int reiserfs_new_form_blocknrs (struct tree_balance * tb,
b_blocknr_t *new_blocknrs, int amount_needed)
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h Sun Jul 13 20:39:55 2003
+++ b/include/linux/reiserfs_fs_sb.h Sun Jul 13 20:39:55 2003
@@ -133,7 +133,7 @@
struct reiserfs_journal_cnode {
struct buffer_head *bh ; /* real buffer head */
struct super_block *sb ; /* dev of real buffer head */
- unsigned long blocknr ; /* block number of real buffer head, == 0 when buffer on disk */
+ __u32 blocknr ; /* block number of real buffer head, == 0 when buffer on disk */
long state ;
struct reiserfs_journal_list *jlist ; /* journal list this cnode lives in */
struct reiserfs_journal_cnode *next ; /* next in transaction list */
diff -Nru a/include/linux/seqlock.h b/include/linux/seqlock.h
--- a/include/linux/seqlock.h Sun Jul 13 20:39:55 2003
+++ b/include/linux/seqlock.h Sun Jul 13 20:39:55 2003
@@ -94,6 +94,57 @@
return (iv & 1) | (sl->sequence ^ iv);
}
+
+/*
+ * Version using sequence counter only.
+ * This can be used when code has its own mutex protecting the
+ * updating starting before the write_seqcountbeqin() and ending
+ * after the write_seqcount_end().
+ */
+
+typedef struct seqcount {
+ unsigned sequence;
+} seqcount_t;
+
+#define SEQCNT_ZERO { 0 }
+#define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0)
+
+/* Start of read using pointer to a sequence counter only. */
+static inline unsigned read_seqcount_begin(const seqcount_t *s)
+{
+ unsigned ret = s->sequence;
+ smp_rmb();
+ return ret;
+}
+
+/* Test if reader processed invalid data.
+ * Equivalent to: iv is odd or sequence number has changed.
+ * (iv & 1) || (*s != iv)
+ * Using xor saves one conditional branch.
+ */
+static inline int read_seqcount_retry(const seqcount_t *s, unsigned iv)
+{
+ smp_rmb();
+ return (iv & 1) | (s->sequence ^ iv);
+}
+
+
+/*
+ * Sequence counter only version assumes that callers are using their
+ * own mutexing.
+ */
+static inline void write_seqcount_begin(seqcount_t *s)
+{
+ s->sequence++;
+ smp_wmb();
+}
+
+static inline void write_seqcount_end(seqcount_t *s)
+{
+ smp_wmb();
+ s->sequence++;
+}
+
/*
* Possible sw/hw IRQ protected versions of the interfaces.
*/
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h Sun Jul 13 20:39:55 2003
+++ b/include/linux/sysctl.h Sun Jul 13 20:39:55 2003
@@ -6,16 +6,10 @@
****************************************************************
****************************************************************
**
- ** WARNING:
** The values in this file are exported to user space via
- ** the sysctl() binary interface. Do *NOT* change the
- ** numbering of any existing values here, and do not change
- ** any numbers within any one set of values. If you have
- ** to redefine an existing interface, use a new number for it.
- ** The kernel will then return ENOTDIR to any application using
- ** the old binary interface.
- **
- ** --sct
+ ** the sysctl() binary interface. However this interface
+ ** is unstable and deprecated and will be removed in the future.
+ ** For a stable interface use /proc/sys.
**
****************************************************************
****************************************************************
@@ -130,6 +124,8 @@
KERN_PIDMAX=55, /* int: PID # limit */
KERN_CORE_PATTERN=56, /* string: pattern for core-file names */
KERN_PANIC_ON_OOPS=57, /* int: whether we will panic on an oops */
+ KERN_HPPA_PWRSW=58, /* int: hppa soft-power enable */
+ KERN_HPPA_UNALIGNED=59, /* int: hppa unaligned-trap enable */
};
diff -Nru a/include/linux/time.h b/include/linux/time.h
--- a/include/linux/time.h Sun Jul 13 20:39:55 2003
+++ b/include/linux/time.h Sun Jul 13 20:39:55 2003
@@ -217,6 +217,21 @@
extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
extern long do_nanosleep(struct timespec *t);
extern long do_utimes(char __user * filename, struct timeval * times);
+
+static inline void
+set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
+{
+ while (nsec > NSEC_PER_SEC) {
+ nsec -= NSEC_PER_SEC;
+ ++sec;
+ }
+ while (nsec < 0) {
+ nsec += NSEC_PER_SEC;
+ --sec;
+ }
+ ts->tv_sec = sec;
+ ts->tv_nsec = nsec;
+}
#endif
#define FD_SETSIZE __FD_SETSIZE
diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h
--- a/include/net/ip6_route.h Sun Jul 13 20:39:55 2003
+++ b/include/net/ip6_route.h Sun Jul 13 20:39:55 2003
@@ -61,7 +61,11 @@
struct in6_addr *saddr,
int oif, int flags);
-extern struct rt6_info *ip6_dst_alloc(void);
+extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+ struct neighbour *neigh,
+ int (*output)(struct sk_buff *));
+extern int ndisc_dst_gc(int *more);
+extern void fib6_force_start_gc(void);
/*
* support functions for ND
diff -Nru a/include/net/ip_vs.h b/include/net/ip_vs.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/net/ip_vs.h Sun Jul 13 20:39:56 2003
@@ -0,0 +1,1002 @@
+/*
+ * IP Virtual Server
+ * data structure and functionality definitions
+ */
+
+#ifndef _IP_VS_H
+#define _IP_VS_H
+
+#include /* For __uXX types */
+
+#define IP_VS_VERSION_CODE 0x010107
+#define NVERSION(version) \
+ (version >> 16) & 0xFF, \
+ (version >> 8) & 0xFF, \
+ version & 0xFF
+
+/*
+ * Virtual Service Flags
+ */
+#define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */
+#define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */
+
+/*
+ * Destination Server Flags
+ */
+#define IP_VS_DEST_F_AVAILABLE 0x0001 /* server is available */
+#define IP_VS_DEST_F_OVERLOAD 0x0002 /* server is overloaded */
+
+/*
+ * IPVS sync daemon states
+ */
+#define IP_VS_STATE_NONE 0x0000 /* daemon is stopped */
+#define IP_VS_STATE_MASTER 0x0001 /* started as master */
+#define IP_VS_STATE_BACKUP 0x0002 /* started as backup */
+
+/*
+ * IPVS socket options
+ */
+#define IP_VS_BASE_CTL (64+1024+64) /* base */
+
+#define IP_VS_SO_SET_NONE IP_VS_BASE_CTL /* just peek */
+#define IP_VS_SO_SET_INSERT (IP_VS_BASE_CTL+1)
+#define IP_VS_SO_SET_ADD (IP_VS_BASE_CTL+2)
+#define IP_VS_SO_SET_EDIT (IP_VS_BASE_CTL+3)
+#define IP_VS_SO_SET_DEL (IP_VS_BASE_CTL+4)
+#define IP_VS_SO_SET_FLUSH (IP_VS_BASE_CTL+5)
+#define IP_VS_SO_SET_LIST (IP_VS_BASE_CTL+6)
+#define IP_VS_SO_SET_ADDDEST (IP_VS_BASE_CTL+7)
+#define IP_VS_SO_SET_DELDEST (IP_VS_BASE_CTL+8)
+#define IP_VS_SO_SET_EDITDEST (IP_VS_BASE_CTL+9)
+#define IP_VS_SO_SET_TIMEOUT (IP_VS_BASE_CTL+10)
+#define IP_VS_SO_SET_STARTDAEMON (IP_VS_BASE_CTL+11)
+#define IP_VS_SO_SET_STOPDAEMON (IP_VS_BASE_CTL+12)
+#define IP_VS_SO_SET_RESTORE (IP_VS_BASE_CTL+13)
+#define IP_VS_SO_SET_SAVE (IP_VS_BASE_CTL+14)
+#define IP_VS_SO_SET_ZERO (IP_VS_BASE_CTL+15)
+#define IP_VS_SO_SET_MAX IP_VS_SO_SET_ZERO
+
+#define IP_VS_SO_GET_VERSION IP_VS_BASE_CTL
+#define IP_VS_SO_GET_INFO (IP_VS_BASE_CTL+1)
+#define IP_VS_SO_GET_SERVICES (IP_VS_BASE_CTL+2)
+#define IP_VS_SO_GET_SERVICE (IP_VS_BASE_CTL+3)
+#define IP_VS_SO_GET_DESTS (IP_VS_BASE_CTL+4)
+#define IP_VS_SO_GET_DEST (IP_VS_BASE_CTL+5) /* not used now */
+#define IP_VS_SO_GET_TIMEOUT (IP_VS_BASE_CTL+6)
+#define IP_VS_SO_GET_DAEMON (IP_VS_BASE_CTL+7)
+#define IP_VS_SO_GET_MAX IP_VS_SO_GET_DAEMON
+
+
+/*
+ * IPVS Connection Flags
+ */
+#define IP_VS_CONN_F_FWD_MASK 0x0007 /* mask for the fwd methods */
+#define IP_VS_CONN_F_MASQ 0x0000 /* masquerading/NAT */
+#define IP_VS_CONN_F_LOCALNODE 0x0001 /* local node */
+#define IP_VS_CONN_F_TUNNEL 0x0002 /* tunneling */
+#define IP_VS_CONN_F_DROUTE 0x0003 /* direct routing */
+#define IP_VS_CONN_F_BYPASS 0x0004 /* cache bypass */
+#define IP_VS_CONN_F_SYNC 0x0020 /* entry created by sync */
+#define IP_VS_CONN_F_HASHED 0x0040 /* hashed entry */
+#define IP_VS_CONN_F_NOOUTPUT 0x0080 /* no output packets */
+#define IP_VS_CONN_F_INACTIVE 0x0100 /* not established */
+#define IP_VS_CONN_F_OUT_SEQ 0x0200 /* must do output seq adjust */
+#define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */
+#define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */
+#define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */
+
+/* Move it to better place one day, for now keep it unique */
+#define NFC_IPVS_PROPERTY 0x10000
+
+#define IP_VS_SCHEDNAME_MAXLEN 16
+#define IP_VS_IFNAME_MAXLEN 16
+
+
+/*
+ * The struct ip_vs_service_user and struct ip_vs_dest_user are
+ * used to set IPVS rules through setsockopt.
+ */
+struct ip_vs_service_user {
+ /* virtual service addresses */
+ u_int16_t protocol;
+ u_int32_t addr; /* virtual ip address */
+ u_int16_t port;
+ u_int32_t fwmark; /* firwall mark of service */
+
+ /* virtual service options */
+ char sched_name[IP_VS_SCHEDNAME_MAXLEN];
+ unsigned flags; /* virtual service flags */
+ unsigned timeout; /* persistent timeout in sec */
+ u_int32_t netmask; /* persistent netmask */
+};
+
+
+struct ip_vs_dest_user {
+ /* destination server address */
+ u_int32_t addr;
+ u_int16_t port;
+
+ /* real server options */
+ unsigned conn_flags; /* connection flags */
+ int weight; /* destination weight */
+
+ /* thresholds for active connections */
+ u_int32_t u_threshold; /* upper threshold */
+ u_int32_t l_threshold; /* lower threshold */
+};
+
+
+/*
+ * IPVS statistics object (for user space)
+ */
+struct ip_vs_stats_user
+{
+ __u32 conns; /* connections scheduled */
+ __u32 inpkts; /* incoming packets */
+ __u32 outpkts; /* outgoing packets */
+ __u64 inbytes; /* incoming bytes */
+ __u64 outbytes; /* outgoing bytes */
+
+ __u32 cps; /* current connection rate */
+ __u32 inpps; /* current in packet rate */
+ __u32 outpps; /* current out packet rate */
+ __u32 inbps; /* current in byte rate */
+ __u32 outbps; /* current out byte rate */
+};
+
+
+/* The argument to IP_VS_SO_GET_INFO */
+struct ip_vs_getinfo {
+ /* version number */
+ unsigned int version;
+
+ /* size of connection hash table */
+ unsigned int size;
+
+ /* number of virtual services */
+ unsigned int num_services;
+};
+
+
+/* The argument to IP_VS_SO_GET_SERVICE */
+struct ip_vs_service_entry {
+ /* which service: user fills in these */
+ u_int16_t protocol;
+ u_int32_t addr; /* virtual address */
+ u_int16_t port;
+ u_int32_t fwmark; /* firwall mark of service */
+
+ /* service options */
+ char sched_name[IP_VS_SCHEDNAME_MAXLEN];
+ unsigned flags; /* virtual service flags */
+ unsigned timeout; /* persistent timeout */
+ u_int32_t netmask; /* persistent netmask */
+
+ /* number of real servers */
+ unsigned int num_dests;
+
+ /* statistics */
+ struct ip_vs_stats_user stats;
+};
+
+
+struct ip_vs_dest_entry {
+ u_int32_t addr; /* destination address */
+ u_int16_t port;
+ unsigned conn_flags; /* connection flags */
+ int weight; /* destination weight */
+
+ u_int32_t u_threshold; /* upper threshold */
+ u_int32_t l_threshold; /* lower threshold */
+
+ u_int32_t activeconns; /* active connections */
+ u_int32_t inactconns; /* inactive connections */
+ u_int32_t persistconns; /* persistent connections */
+
+ /* statistics */
+ struct ip_vs_stats_user stats;
+};
+
+
+/* The argument to IP_VS_SO_GET_DESTS */
+struct ip_vs_get_dests {
+ /* which service: user fills in these */
+ u_int16_t protocol;
+ u_int32_t addr; /* virtual address */
+ u_int16_t port;
+ u_int32_t fwmark; /* firwall mark of service */
+
+ /* number of real servers */
+ unsigned int num_dests;
+
+ /* the real servers */
+ struct ip_vs_dest_entry entrytable[0];
+};
+
+
+/* The argument to IP_VS_SO_GET_SERVICES */
+struct ip_vs_get_services {
+ /* number of virtual services */
+ unsigned int num_services;
+
+ /* service table */
+ struct ip_vs_service_entry entrytable[0];
+};
+
+
+/* The argument to IP_VS_SO_GET_TIMEOUT */
+struct ip_vs_timeout_user {
+ int tcp_timeout;
+ int tcp_fin_timeout;
+ int udp_timeout;
+};
+
+
+/* The argument to IP_VS_SO_GET_DAEMON */
+struct ip_vs_daemon_user {
+ /* sync daemon state (master/backup) */
+ int state;
+
+ /* multicast interface name */
+ char mcast_ifn[IP_VS_IFNAME_MAXLEN];
+
+ /* SyncID we belong to */
+ int syncid;
+};
+
+
+#ifdef __KERNEL__
+
+#include
+#include /* for struct list_head */
+#include /* for struct rwlock_t */
+#include /* for struct sk_buff */
+#include /* for struct iphdr */
+#include /* for struct atomic_t */
+#include /* for struct neighbour */
+#include /* for struct dst_entry */
+#include
+#include
+#include
+
+
+#ifdef CONFIG_IP_VS_DEBUG
+extern int ip_vs_get_debug_level(void);
+#define IP_VS_DBG(level, msg...) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG "IPVS: " msg); \
+ } while (0)
+#define IP_VS_DBG_RL(msg...) \
+ do { \
+ if (net_ratelimit()) \
+ printk(KERN_DEBUG "IPVS: " msg); \
+ } while (0)
+#define IP_VS_DBG_PKT(level, pp, iph, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ pp->debug_packet(pp, iph, msg); \
+ } while (0)
+#define IP_VS_DBG_RL_PKT(level, pp, iph, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level() && \
+ net_ratelimit()) \
+ pp->debug_packet(pp, iph, msg); \
+ } while (0)
+#else /* NO DEBUGGING at ALL */
+#define IP_VS_DBG(level, msg...) do {} while (0)
+#define IP_VS_DBG_RL(msg...) do {} while (0)
+#define IP_VS_DBG_PKT(level, pp, iph, msg) do {} while (0)
+#define IP_VS_DBG_RL_PKT(level, pp, iph, msg) do {} while (0)
+#endif
+
+#define IP_VS_BUG() BUG()
+#define IP_VS_ERR(msg...) printk(KERN_ERR "IPVS: " msg)
+#define IP_VS_INFO(msg...) printk(KERN_INFO "IPVS: " msg)
+#define IP_VS_WARNING(msg...) \
+ printk(KERN_WARNING "IPVS: " msg)
+#define IP_VS_ERR_RL(msg...) \
+ do { \
+ if (net_ratelimit()) \
+ printk(KERN_ERR "IPVS: " msg); \
+ } while (0)
+
+#ifdef CONFIG_IP_VS_DEBUG
+#define EnterFunction(level) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG "Enter: %s, %s line %i\n", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ } while (0)
+#define LeaveFunction(level) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG "Leave: %s, %s line %i\n", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ } while (0)
+#else
+#define EnterFunction(level) do {} while (0)
+#define LeaveFunction(level) do {} while (0)
+#endif
+
+#define IP_VS_WAIT_WHILE(expr) while (expr) { cpu_relax(); }
+
+
+/*
+ * The port number of FTP service (in network order).
+ */
+#define FTPPORT __constant_htons(21)
+#define FTPDATA __constant_htons(20)
+
+/*
+ * IPVS sysctl variables under the /proc/sys/net/ipv4/vs/
+ */
+#define NET_IPV4_VS 21
+
+enum {
+ NET_IPV4_VS_DEBUG_LEVEL=1,
+ NET_IPV4_VS_AMEMTHRESH=2,
+ NET_IPV4_VS_AMDROPRATE=3,
+ NET_IPV4_VS_DROP_ENTRY=4,
+ NET_IPV4_VS_DROP_PACKET=5,
+ NET_IPV4_VS_SECURE_TCP=6,
+ NET_IPV4_VS_TO_ES=7,
+ NET_IPV4_VS_TO_SS=8,
+ NET_IPV4_VS_TO_SR=9,
+ NET_IPV4_VS_TO_FW=10,
+ NET_IPV4_VS_TO_TW=11,
+ NET_IPV4_VS_TO_CL=12,
+ NET_IPV4_VS_TO_CW=13,
+ NET_IPV4_VS_TO_LA=14,
+ NET_IPV4_VS_TO_LI=15,
+ NET_IPV4_VS_TO_SA=16,
+ NET_IPV4_VS_TO_UDP=17,
+ NET_IPV4_VS_TO_ICMP=18,
+ NET_IPV4_VS_LBLC_EXPIRE=19,
+ NET_IPV4_VS_LBLCR_EXPIRE=20,
+ NET_IPV4_VS_CACHE_BYPASS=22,
+ NET_IPV4_VS_EXPIRE_NODEST_CONN=23,
+ NET_IPV4_VS_SYNC_THRESHOLD=24,
+ NET_IPV4_VS_NAT_ICMP_SEND=25,
+ NET_IPV4_VS_LAST
+};
+
+/*
+ * TCP State Values
+ */
+enum {
+ IP_VS_TCP_S_NONE = 0,
+ IP_VS_TCP_S_ESTABLISHED,
+ IP_VS_TCP_S_SYN_SENT,
+ IP_VS_TCP_S_SYN_RECV,
+ IP_VS_TCP_S_FIN_WAIT,
+ IP_VS_TCP_S_TIME_WAIT,
+ IP_VS_TCP_S_CLOSE,
+ IP_VS_TCP_S_CLOSE_WAIT,
+ IP_VS_TCP_S_LAST_ACK,
+ IP_VS_TCP_S_LISTEN,
+ IP_VS_TCP_S_SYNACK,
+ IP_VS_TCP_S_LAST
+};
+
+/*
+ * UDP State Values
+ */
+enum {
+ IP_VS_UDP_S_NORMAL,
+ IP_VS_UDP_S_LAST,
+};
+
+/*
+ * ICMP State Values
+ */
+enum {
+ IP_VS_ICMP_S_NORMAL,
+ IP_VS_ICMP_S_LAST,
+};
+
+/*
+ * Transport protocol header
+ */
+union ip_vs_tphdr {
+ unsigned char *raw;
+ struct udphdr *uh;
+ struct tcphdr *th;
+ struct icmphdr *icmph;
+ __u16 *portp;
+};
+
+
+/*
+ * Delta sequence info structure
+ * Each ip_vs_conn has 2 (output AND input seq. changes).
+ * Only used in the VS/NAT.
+ */
+struct ip_vs_seq {
+ __u32 init_seq; /* Add delta from this seq */
+ __u32 delta; /* Delta in sequence numbers */
+ __u32 previous_delta; /* Delta in sequence numbers
+ before last resized pkt */
+};
+
+
+/*
+ * IPVS statistics object
+ */
+struct ip_vs_stats
+{
+ __u32 conns; /* connections scheduled */
+ __u32 inpkts; /* incoming packets */
+ __u32 outpkts; /* outgoing packets */
+ __u64 inbytes; /* incoming bytes */
+ __u64 outbytes; /* outgoing bytes */
+
+ __u32 cps; /* current connection rate */
+ __u32 inpps; /* current in packet rate */
+ __u32 outpps; /* current out packet rate */
+ __u32 inbps; /* current in byte rate */
+ __u32 outbps; /* current out byte rate */
+
+ spinlock_t lock; /* spin lock */
+};
+
+struct ip_vs_conn;
+struct ip_vs_app;
+
+struct ip_vs_protocol {
+ struct ip_vs_protocol *next;
+ char *name;
+ __u16 protocol;
+ int minhlen;
+ int minhlen_icmp;
+ int dont_defrag;
+ int skip_nonexisting;
+ int slave; /* if controlled by others */
+ atomic_t appcnt; /* counter of proto app incs */
+ int *timeout_table; /* protocol timeout table */
+
+ void (*init)(struct ip_vs_protocol *pp);
+
+ void (*exit)(struct ip_vs_protocol *pp);
+
+ int (*conn_schedule)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct iphdr *iph, union ip_vs_tphdr h,
+ int *verdict, struct ip_vs_conn **cpp);
+
+ struct ip_vs_conn *
+ (*conn_in_get)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct iphdr *iph,
+ union ip_vs_tphdr h, int inverse);
+
+ struct ip_vs_conn *
+ (*conn_out_get)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct iphdr *iph,
+ union ip_vs_tphdr h, int inverse);
+
+ int (*snat_handler)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
+ struct iphdr *iph, union ip_vs_tphdr h, int size);
+
+ int (*dnat_handler)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
+ struct iphdr *iph, union ip_vs_tphdr h, int size);
+
+ int (*csum_check)(struct sk_buff *skb,
+ struct ip_vs_protocol *pp, struct iphdr *iph,
+ union ip_vs_tphdr h, int size);
+
+ const char *(*state_name)(int state);
+
+ int (*state_transition)(struct ip_vs_conn *cp, int direction,
+ struct iphdr *iph, union ip_vs_tphdr h,
+ struct ip_vs_protocol *pp);
+
+ int (*register_app)(struct ip_vs_app *inc);
+
+ void (*unregister_app)(struct ip_vs_app *inc);
+
+ int (*app_conn_bind)(struct ip_vs_conn *cp);
+
+ void (*debug_packet)(struct ip_vs_protocol *pp, struct iphdr *iph,
+ char *msg);
+
+ void (*timeout_change)(struct ip_vs_protocol *pp, int flags);
+
+ int (*set_state_timeout)(struct ip_vs_protocol *pp, char *sname, int to);
+};
+
+extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);
+
+/*
+ * IP_VS structure allocated for each dynamically scheduled connection
+ */
+struct ip_vs_conn {
+ struct list_head c_list; /* hashed list heads */
+
+ /* Protocol, addresses and port numbers */
+ __u32 caddr; /* client address */
+ __u32 vaddr; /* virtual address */
+ __u32 daddr; /* destination address */
+ __u16 cport;
+ __u16 vport;
+ __u16 dport;
+ __u16 protocol; /* Which protocol (TCP/UDP) */
+
+ /* counter and timer */
+ atomic_t refcnt; /* reference count */
+ struct timer_list timer; /* Expiration timer */
+ volatile unsigned long timeout; /* timeout */
+
+ /* Flags and state transition */
+ spinlock_t lock; /* lock for state transition */
+ volatile __u16 flags; /* status flags */
+ volatile __u16 state; /* state info */
+
+ /* Control members */
+ struct ip_vs_conn *control; /* Master control connection */
+ atomic_t n_control; /* Number of controlled ones */
+ struct ip_vs_dest *dest; /* real server */
+ atomic_t in_pkts; /* incoming packet counter */
+
+ /* packet transmitter for different forwarding methods */
+ int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp);
+
+ /* Note: we can group the following members into a structure,
+ in order to save more space, and the following members are
+ only used in VS/NAT anyway */
+ struct ip_vs_app *app; /* bound ip_vs_app object */
+ void *app_data; /* Application private data */
+ struct ip_vs_seq in_seq; /* incoming seq. struct */
+ struct ip_vs_seq out_seq; /* outgoing seq. struct */
+};
+
+
+/*
+ * The information about the virtual service offered to the net
+ * and the forwarding entries
+ */
+struct ip_vs_service {
+ struct list_head s_list; /* for normal service table */
+ struct list_head f_list; /* for fwmark-based service table */
+ atomic_t refcnt; /* reference counter */
+ atomic_t usecnt; /* use counter */
+
+ __u16 protocol; /* which protocol (TCP/UDP) */
+ __u32 addr; /* IP address for virtual service */
+ __u16 port; /* port number for the service */
+ __u32 fwmark; /* firewall mark of the service */
+ unsigned flags; /* service status flags */
+ unsigned timeout; /* persistent timeout in ticks */
+ __u32 netmask; /* grouping granularity */
+
+ struct list_head destinations; /* real server d-linked list */
+ __u32 num_dests; /* number of servers */
+ struct ip_vs_stats stats; /* statistics for the service */
+ struct ip_vs_app *inc; /* bind conns to this app inc */
+
+ /* for scheduling */
+ struct ip_vs_scheduler *scheduler; /* bound scheduler object */
+ rwlock_t sched_lock; /* lock sched_data */
+ void *sched_data; /* scheduler application data */
+};
+
+
+/*
+ * The real server destination forwarding entry
+ * with ip address, port number, and so on.
+ */
+struct ip_vs_dest {
+ struct list_head n_list; /* for the dests in the service */
+ struct list_head d_list; /* for table with all the dests */
+
+ __u32 addr; /* IP address of the server */
+ __u16 port; /* port number of the server */
+ volatile unsigned flags; /* dest status flags */
+ atomic_t conn_flags; /* flags to copy to conn */
+ atomic_t weight; /* server weight */
+
+ atomic_t refcnt; /* reference counter */
+ struct ip_vs_stats stats; /* statistics */
+
+ /* connection counters and thresholds */
+ atomic_t activeconns; /* active connections */
+ atomic_t inactconns; /* inactive connections */
+ atomic_t persistconns; /* persistent connections */
+ __u32 u_threshold; /* upper threshold */
+ __u32 l_threshold; /* lower threshold */
+
+ /* for destination cache */
+ spinlock_t dst_lock; /* lock of dst_cache */
+ struct dst_entry *dst_cache; /* destination cache entry */
+ u32 dst_rtos; /* RT_TOS(tos) for dst */
+
+ /* for virtual service */
+ struct ip_vs_service *svc; /* service it belongs to */
+ __u16 protocol; /* which protocol (TCP/UDP) */
+ __u32 vaddr; /* virtual IP address */
+ __u16 vport; /* virtual port number */
+ __u32 vfwmark; /* firewall mark of service */
+};
+
+
+/*
+ * The scheduler object
+ */
+struct ip_vs_scheduler {
+ struct list_head n_list; /* d-linked list head */
+ char *name; /* scheduler name */
+ atomic_t refcnt; /* reference counter */
+ struct module *module; /* THIS_MODULE/NULL */
+
+ /* scheduler initializing service */
+ int (*init_service)(struct ip_vs_service *svc);
+ /* scheduling service finish */
+ int (*done_service)(struct ip_vs_service *svc);
+ /* scheduler updating service */
+ int (*update_service)(struct ip_vs_service *svc);
+
+ /* selecting a server from the given service */
+ struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc,
+ struct iphdr *iph);
+};
+
+
+/*
+ * The application module object (a.k.a. app incarnation)
+ */
+struct ip_vs_app
+{
+ struct list_head a_list; /* member in app list */
+ int type; /* IP_VS_APP_TYPE_xxx */
+ char *name; /* application module name */
+ __u16 protocol;
+ struct module *module; /* THIS_MODULE/NULL */
+ struct list_head incs_list; /* list of incarnations */
+
+ /* members for application incarnations */
+ struct list_head p_list; /* member in proto app list */
+ struct ip_vs_app *app; /* its real application */
+ __u16 port; /* port number in net order */
+ atomic_t usecnt; /* usage counter */
+
+ /* output hook */
+ int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct sk_buff *);
+
+ /* input hook */
+ int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct sk_buff *);
+
+ /* ip_vs_app initializer */
+ int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+ /* ip_vs_app finish */
+ int (*done_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+
+ /* not used now */
+ int (*bind_conn)(struct ip_vs_app *, struct ip_vs_conn *,
+ struct ip_vs_protocol *);
+
+ void (*unbind_conn)(struct ip_vs_app *, struct ip_vs_conn *);
+
+ int * timeout_table;
+ int * timeouts;
+ int timeouts_size;
+
+ int (*conn_schedule)(struct sk_buff *skb, struct ip_vs_app *app,
+ struct iphdr *iph, union ip_vs_tphdr h,
+ int *verdict, struct ip_vs_conn **cpp);
+
+ struct ip_vs_conn *
+ (*conn_in_get)(struct sk_buff *skb, struct ip_vs_app *app,
+ struct iphdr *iph, union ip_vs_tphdr h, int inverse);
+
+ struct ip_vs_conn *
+ (*conn_out_get)(struct sk_buff *skb, struct ip_vs_app *app,
+ struct iphdr *iph, union ip_vs_tphdr h, int inverse);
+
+ int (*state_transition)(struct ip_vs_conn *cp, int direction,
+ struct iphdr *iph,
+ union ip_vs_tphdr h, struct ip_vs_app *app);
+
+ void (*timeout_change)(struct ip_vs_app *app, int flags);
+};
+
+
+/*
+ * IPVS core functions
+ * (from ip_vs_core.c)
+ */
+extern const char *ip_vs_proto_name(unsigned proto);
+extern unsigned int check_for_ip_vs_out(struct sk_buff **skb_p,
+ int (*okfn)(struct sk_buff *));
+extern void ip_vs_init_hash_table(struct list_head *table, int rows);
+#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table(t, sizeof(t)/sizeof(t[0]))
+
+#define IP_VS_APP_TYPE_UNSPEC 0
+#define IP_VS_APP_TYPE_FTP 1
+
+/*
+ * ip_vs_conn handling functions
+ * (from ip_vs_conn.c)
+ */
+
+/*
+ * IPVS connection entry hash table
+ */
+#ifndef CONFIG_IP_VS_TAB_BITS
+#define CONFIG_IP_VS_TAB_BITS 12
+#endif
+/* make sure that IP_VS_CONN_TAB_BITS is located in [8, 20] */
+#if CONFIG_IP_VS_TAB_BITS < 8
+#define IP_VS_CONN_TAB_BITS 8
+#endif
+#if CONFIG_IP_VS_TAB_BITS > 20
+#define IP_VS_CONN_TAB_BITS 20
+#endif
+#if 8 <= CONFIG_IP_VS_TAB_BITS && CONFIG_IP_VS_TAB_BITS <= 20
+#define IP_VS_CONN_TAB_BITS CONFIG_IP_VS_TAB_BITS
+#endif
+#define IP_VS_CONN_TAB_SIZE (1 << IP_VS_CONN_TAB_BITS)
+#define IP_VS_CONN_TAB_MASK (IP_VS_CONN_TAB_SIZE - 1)
+
+enum {
+ IP_VS_DIR_INPUT = 0,
+ IP_VS_DIR_OUTPUT,
+ IP_VS_DIR_INPUT_ONLY,
+ IP_VS_DIR_LAST,
+};
+
+extern struct ip_vs_conn *ip_vs_conn_in_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+extern struct ip_vs_conn *ip_vs_conn_out_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+
+/* put back the conn without restarting its timer */
+static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
+{
+ atomic_dec(&cp->refcnt);
+}
+extern void ip_vs_conn_put(struct ip_vs_conn *cp);
+extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport);
+
+extern struct ip_vs_conn *
+ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
+ __u32 daddr, __u16 dport, unsigned flags,
+ struct ip_vs_dest *dest);
+extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
+
+extern const char * ip_vs_state_name(__u16 proto, int state);
+
+extern void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
+extern int ip_vs_check_template(struct ip_vs_conn *ct);
+extern void ip_vs_secure_tcp_set(int on);
+extern void ip_vs_random_dropentry(void);
+extern int ip_vs_conn_init(void);
+extern void ip_vs_conn_cleanup(void);
+
+static inline void ip_vs_control_del(struct ip_vs_conn *cp)
+{
+ struct ip_vs_conn *ctl_cp = cp->control;
+ if (!ctl_cp) {
+ IP_VS_ERR("request control DEL for uncontrolled: "
+ "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(cp->caddr),ntohs(cp->cport),
+ NIPQUAD(cp->vaddr),ntohs(cp->vport));
+ return;
+ }
+
+ IP_VS_DBG(7, "DELeting control for: "
+ "cp.dst=%d.%d.%d.%d:%d ctl_cp.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(cp->caddr),ntohs(cp->cport),
+ NIPQUAD(ctl_cp->caddr),ntohs(ctl_cp->cport));
+
+ cp->control = NULL;
+ if (atomic_read(&ctl_cp->n_control) == 0) {
+ IP_VS_ERR("BUG control DEL with n=0 : "
+ "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(cp->caddr),ntohs(cp->cport),
+ NIPQUAD(cp->vaddr),ntohs(cp->vport));
+ return;
+ }
+ atomic_dec(&ctl_cp->n_control);
+}
+
+static inline void
+ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
+{
+ if (cp->control) {
+ IP_VS_ERR("request control ADD for already controlled: "
+ "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(cp->caddr),ntohs(cp->cport),
+ NIPQUAD(cp->vaddr),ntohs(cp->vport));
+ ip_vs_control_del(cp);
+ }
+
+ IP_VS_DBG(7, "ADDing control for: "
+ "cp.dst=%d.%d.%d.%d:%d ctl_cp.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(cp->caddr),ntohs(cp->cport),
+ NIPQUAD(ctl_cp->caddr),ntohs(ctl_cp->cport));
+
+ cp->control = ctl_cp;
+ atomic_inc(&ctl_cp->n_control);
+}
+
+
+/*
+ * IPVS application functions
+ * (from ip_vs_app.c)
+ */
+#define IP_VS_APP_MAX_PORTS 8
+extern int register_ip_vs_app(struct ip_vs_app *app);
+extern void unregister_ip_vs_app(struct ip_vs_app *app);
+extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern void ip_vs_unbind_app(struct ip_vs_conn *cp);
+extern int
+register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port);
+extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
+extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
+
+extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
+extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
+extern int ip_vs_skb_replace(struct sk_buff *skb, int pri,
+ char *o_buf, int o_len, char *n_buf, int n_len);
+extern int ip_vs_app_init(void);
+extern void ip_vs_app_cleanup(void);
+
+
+/*
+ * IPVS protocol functions (from ip_vs_proto.c)
+ */
+extern int ip_vs_protocol_init(void);
+extern void ip_vs_protocol_cleanup(void);
+extern void ip_vs_protocol_timeout_change(int flags);
+extern int *ip_vs_create_timeout_table(int *table, int size);
+extern int
+ip_vs_set_state_timeout(int *table, int num, char **names, char *name, int to);
+extern struct ip_vs_protocol ip_vs_protocol_tcp;
+extern struct ip_vs_protocol ip_vs_protocol_udp;
+extern struct ip_vs_protocol ip_vs_protocol_icmp;
+extern struct ip_vs_protocol ip_vs_protocol_esp;
+extern struct ip_vs_protocol ip_vs_protocol_ah;
+
+
+/*
+ * Registering/unregistering scheduler functions
+ * (from ip_vs_sched.c)
+ */
+extern int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+extern int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+extern int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ struct ip_vs_scheduler *scheduler);
+extern int ip_vs_unbind_scheduler(struct ip_vs_service *svc);
+extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+extern struct ip_vs_conn *
+ip_vs_schedule(struct ip_vs_service *svc, struct iphdr *iph);
+extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
+ struct ip_vs_protocol *pp, union ip_vs_tphdr h);
+
+
+/*
+ * IPVS control data and functions (from ip_vs_ctl.c)
+ */
+extern int sysctl_ip_vs_cache_bypass;
+extern int sysctl_ip_vs_expire_nodest_conn;
+extern int sysctl_ip_vs_sync_threshold[2];
+extern int sysctl_ip_vs_nat_icmp_send;
+extern atomic_t ip_vs_dropentry;
+extern struct ip_vs_stats ip_vs_stats;
+
+extern struct ip_vs_service *
+ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport);
+
+static inline void ip_vs_service_put(struct ip_vs_service *svc)
+{
+ atomic_dec(&svc->usecnt);
+}
+
+extern struct ip_vs_dest *
+ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport);
+extern int ip_vs_use_count_inc(void);
+extern void ip_vs_use_count_dec(void);
+extern void update_defense_level(void);
+extern int ip_vs_control_init(void);
+extern void ip_vs_control_cleanup(void);
+
+
+/*
+ * IPVS sync daemon data and function prototypes
+ * (from ip_vs_sync.c)
+ */
+extern volatile int ip_vs_sync_state;
+extern volatile int ip_vs_master_syncid;
+extern volatile int ip_vs_backup_syncid;
+extern char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
+extern int stop_sync_thread(int state);
+extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
+
+
+/*
+ * IPVS rate estimator prototypes (from ip_vs_est.c)
+ */
+extern int ip_vs_new_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_kill_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
+
+/*
+ * Various IPVS packet transmitters (from ip_vs_xmit.c)
+ */
+extern int ip_vs_null_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_bypass_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_nat_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_tunnel_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_dr_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern int ip_vs_icmp_xmit
+(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
+
+
+/*
+ * This is a simple mechanism to ignore packets when
+ * we are loaded. Just set ip_vs_drop_rate to 'n' and
+ * we start to drop 1/rate of the packets
+ */
+extern int ip_vs_drop_rate;
+extern int ip_vs_drop_counter;
+
+static __inline__ int ip_vs_todrop(void)
+{
+ if (!ip_vs_drop_rate) return 0;
+ if (--ip_vs_drop_counter > 0) return 0;
+ ip_vs_drop_counter = ip_vs_drop_rate;
+ return 1;
+}
+
+/*
+ * ip_vs_fwd_tag returns the forwarding tag of the connection
+ */
+#define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
+
+extern __inline__ char ip_vs_fwd_tag(struct ip_vs_conn *cp)
+{
+ char fwd;
+
+ switch (IP_VS_FWD_METHOD(cp)) {
+ case IP_VS_CONN_F_MASQ:
+ fwd = 'M'; break;
+ case IP_VS_CONN_F_LOCALNODE:
+ fwd = 'L'; break;
+ case IP_VS_CONN_F_TUNNEL:
+ fwd = 'T'; break;
+ case IP_VS_CONN_F_DROUTE:
+ fwd = 'R'; break;
+ case IP_VS_CONN_F_BYPASS:
+ fwd = 'B'; break;
+ default:
+ fwd = '?'; break;
+ }
+ return fwd;
+}
+
+
+static inline u16 ip_vs_check_diff(u32 old, u32 new, u16 oldsum)
+{
+ u32 diff[2] = { old, new };
+
+ return csum_fold(csum_partial((char *) diff, sizeof(diff),
+ oldsum ^ 0xFFFF));
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _IP_VS_H */
diff -Nru a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
--- a/include/net/irda/irda_device.h Sun Jul 13 20:39:56 2003
+++ b/include/net/irda/irda_device.h Sun Jul 13 20:39:56 2003
@@ -230,7 +230,9 @@
dongle_t *irda_device_dongle_init(struct net_device *dev, int type);
int irda_device_dongle_cleanup(dongle_t *dongle);
+#ifdef CONFIG_ISA
void setup_dma(int channel, char *buffer, int count, int mode);
+#endif
void irda_task_delete(struct irda_task *task);
int irda_task_kick(struct irda_task *task);
diff -Nru a/include/net/irda/nsc-ircc.h b/include/net/irda/nsc-ircc.h
--- a/include/net/irda/nsc-ircc.h Sun Jul 13 20:39:55 2003
+++ b/include/net/irda/nsc-ircc.h Sun Jul 13 20:39:55 2003
@@ -39,17 +39,28 @@
#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
/* Config registers for the '108 */
-#define CFG_BAIC 0x00
-#define CFG_CSRT 0x01
-#define CFG_MCTL 0x02
+#define CFG_108_BAIC 0x00
+#define CFG_108_CSRT 0x01
+#define CFG_108_MCTL 0x02
/* Config registers for the '338 */
-#define CFG_FER 0x00
-#define CFG_FAR 0x01
-#define CFG_PTR 0x02
-#define CFG_PNP0 0x1b
-#define CFG_PNP1 0x1c
-#define CFG_PNP3 0x4f
+#define CFG_338_FER 0x00
+#define CFG_338_FAR 0x01
+#define CFG_338_PTR 0x02
+#define CFG_338_PNP0 0x1b
+#define CFG_338_PNP1 0x1c
+#define CFG_338_PNP3 0x4f
+
+/* Config registers for the '39x (in the logical device bank) */
+#define CFG_39X_LDN 0x07 /* Logical device number (Super I/O bank) */
+#define CFG_39X_ACT 0x30 /* Device activation */
+#define CFG_39X_BASEH 0x60 /* Device base address (high bits) */
+#define CFG_39X_BASEL 0x61 /* Device base address (low bits) */
+#define CFG_39X_IRQNUM 0x70 /* Interrupt number & wake up enable */
+#define CFG_39X_IRQSEL 0x71 /* Interrupt select (edge/level + polarity) */
+#define CFG_39X_DMA0 0x74 /* DMA 0 configuration */
+#define CFG_39X_DMA1 0x75 /* DMA 1 configuration */
+#define CFG_39X_SPC 0xF0 /* Serial port configuration register */
/* Flags for configuration register CRF0 */
#define APEDCRC 0x02
diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h Sun Jul 13 20:39:56 2003
+++ b/include/pcmcia/ss.h Sun Jul 13 20:39:56 2003
@@ -170,7 +170,6 @@
struct pcmcia_socket {
struct module *owner;
spinlock_t lock;
- struct pccard_operations * ss_entry;
socket_state_t socket;
u_int state;
u_short functions;
@@ -206,6 +205,9 @@
ioaddr_t io_offset;
u_char pci_irq;
struct pci_dev * cb_dev;
+
+ /* socket operations */
+ struct pccard_operations * ops;
/* state thread */
struct semaphore skt_sem; /* protects socket h/w state */
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig Sun Jul 13 20:39:56 2003
+++ b/init/Kconfig Sun Jul 13 20:39:56 2003
@@ -118,6 +118,14 @@
a "non-standard" kernel. Only use this if you really know what you
are doing.
+config KALLSYMS
+ bool "Load all symbols for debugging/kksymoops" if EMBEDDED
+ default y
+ help
+ Say Y here to let the kernel print out symbolic crash information and
+ symbolic stack backtraces. This increases the size of the kernel
+ somewhat, as all symbols have to be loaded into the kernel image.
+
config FUTEX
bool "Enable futex support" if EMBEDDED
default y
diff -Nru a/init/version.c b/init/version.c
--- a/init/version.c Sun Jul 13 20:39:55 2003
+++ b/init/version.c Sun Jul 13 20:39:55 2003
@@ -17,8 +17,12 @@
int version_string(LINUX_VERSION_CODE);
struct new_utsname system_utsname = {
- UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
- UTS_MACHINE, UTS_DOMAINNAME
+ .sysname = UTS_SYSNAME,
+ .nodename = UTS_NODENAME,
+ .release = UTS_RELEASE,
+ .version = UTS_VERSION,
+ .machine = UTS_MACHINE,
+ .domainname = UTS_DOMAINNAME,
};
const char *linux_banner =
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c Sun Jul 13 20:39:55 2003
+++ b/ipc/shm.c Sun Jul 13 20:39:55 2003
@@ -703,7 +703,7 @@
}
file = shp->shm_file;
- size = file->f_dentry->d_inode->i_size;
+ size = i_size_read(file->f_dentry->d_inode);
shp->shm_nattch++;
shm_unlock(shp);
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c Sun Jul 13 20:39:55 2003
+++ b/kernel/compat.c Sun Jul 13 20:39:55 2003
@@ -425,11 +425,9 @@
&kernel_mask);
set_fs(old_fs);
- if (ret > 0) {
+ if (ret > 0)
if (put_user(kernel_mask, user_mask_ptr))
- ret = -EFAULT;
- ret = sizeof(compat_ulong_t);
- }
+ return -EFAULT;
return ret;
}
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c Sun Jul 13 20:39:54 2003
+++ b/kernel/fork.c Sun Jul 13 20:39:54 2003
@@ -375,6 +375,7 @@
mm->core_waiters = 0;
mm->page_table_lock = SPIN_LOCK_UNLOCKED;
mm->ioctx_list_lock = RW_LOCK_UNLOCKED;
+ mm->ioctx_list = NULL;
mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
mm->free_area_cache = TASK_UNMAPPED_BASE;
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c Sun Jul 13 20:39:54 2003
+++ b/kernel/ksyms.c Sun Jul 13 20:39:54 2003
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -76,6 +77,8 @@
EXPORT_SYMBOL(do_munmap);
EXPORT_SYMBOL(do_brk);
EXPORT_SYMBOL(exit_mm);
+EXPORT_SYMBOL_GPL(exit_fs);
+EXPORT_SYMBOL_GPL(copy_fs_struct);
/* internal kernel memory management */
EXPORT_SYMBOL(__alloc_pages);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c Sun Jul 13 20:39:56 2003
+++ b/kernel/sched.c Sun Jul 13 20:39:56 2003
@@ -1047,7 +1047,7 @@
*/
#define CAN_MIGRATE_TASK(p,rq,this_cpu) \
- ((jiffies - (p)->last_run > cache_decay_ticks) && \
+ ((!idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \
!task_running(rq, p) && \
((p)->cpus_allowed & (1UL << (this_cpu))))
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c Sun Jul 13 20:39:54 2003
+++ b/kernel/sys.c Sun Jul 13 20:39:54 2003
@@ -233,6 +233,8 @@
cond_syscall(sys_epoll_create)
cond_syscall(sys_epoll_ctl)
cond_syscall(sys_epoll_wait)
+cond_syscall(sys_pciconfig_read)
+cond_syscall(sys_pciconfig_write)
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c Sun Jul 13 20:39:54 2003
+++ b/kernel/sysctl.c Sun Jul 13 20:39:54 2003
@@ -87,6 +87,11 @@
extern int stop_a_enabled;
#endif
+#ifdef __hppa__
+extern int pwrsw_enabled;
+extern int unaligned_enabled;
+#endif
+
#ifdef CONFIG_ARCH_S390
#ifdef CONFIG_MATHEMU
extern int sysctl_ieee_emulation_warnings;
@@ -313,6 +318,30 @@
.proc_handler = &proc_dointvec,
},
#endif
+#ifdef __hppa__
+ {
+ .ctl_name = KERN_HPPA_PWRSW,
+ .procname = "soft-power",
+ .data = &pwrsw_enabled,
+ .maxlen = sizeof (int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = KERN_HPPA_UNALIGNED,
+ .procname = "unaligned-trap",
+ .data = &unaligned_enabled,
+ .maxlen = sizeof (int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
+#ifdef __hppa__
+ {KERN_HPPA_PWRSW, "soft-power", &pwrsw_enabled, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+ {KERN_HPPA_UNALIGNED, "unaligned-trap", &unaligned_enabled, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+#endif
#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
{
.ctl_name = KERN_PPC_POWERSAVE_NAP,
@@ -819,11 +848,28 @@
asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
{
struct __sysctl_args tmp;
+ int name[2];
int error;
if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
-
+
+ if (tmp.nlen != 2 || copy_from_user(name, tmp.name, sizeof(name)) ||
+ name[0] != CTL_KERN || name[1] != KERN_VERSION) {
+ int i;
+ printk(KERN_INFO "%s: numerical sysctl ", current->comm);
+ for (i = 0; i < tmp.nlen; i++) {
+ int n;
+
+ if (get_user(n, tmp.name+i)) {
+ printk("? ");
+ } else {
+ printk("%d ", n);
+ }
+ }
+ printk("is obsolete.\n");
+ }
+
lock_kernel();
error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
tmp.newval, tmp.newlen);
diff -Nru a/lib/vsprintf.c b/lib/vsprintf.c
--- a/lib/vsprintf.c Sun Jul 13 20:39:56 2003
+++ b/lib/vsprintf.c Sun Jul 13 20:39:56 2003
@@ -127,7 +127,7 @@
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
+static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
const char *digits;
@@ -143,9 +143,9 @@
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
- if (num < 0) {
+ if ((signed long long) num < 0) {
sign = '-';
- num = -num;
+ num = - (signed long long) num;
size--;
} else if (type & PLUS) {
sign = '+';
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c Sun Jul 13 20:39:55 2003
+++ b/mm/filemap.c Sun Jul 13 20:39:55 2003
@@ -555,14 +555,15 @@
for (;;) {
struct page *page;
unsigned long end_index, nr, ret;
+ loff_t isize = i_size_read(inode);
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ end_index = isize >> PAGE_CACHE_SHIFT;
if (index > end_index)
break;
nr = PAGE_CACHE_SIZE;
if (index == end_index) {
- nr = inode->i_size & ~PAGE_CACHE_MASK;
+ nr = isize & ~PAGE_CACHE_MASK;
if (nr <= offset)
break;
}
@@ -763,7 +764,7 @@
retval = 0;
if (!count)
goto out; /* skip atime */
- size = inode->i_size;
+ size = i_size_read(inode);
if (pos < size) {
retval = generic_file_direct_IO(READ, iocb,
iov, pos, nr_segs);
@@ -951,7 +952,7 @@
endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
retry_all:
- size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (pgoff >= size)
goto outside_data_content;
@@ -1233,7 +1234,7 @@
pgoff, len >> PAGE_CACHE_SHIFT);
repeat:
- size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (pgoff + (len >> PAGE_CACHE_SHIFT) > size)
return -EINVAL;
@@ -1544,7 +1545,7 @@
if (!isblk) {
/* FIXME: this is for backwards compatibility with 2.4 */
if (file->f_flags & O_APPEND)
- *pos = inode->i_size;
+ *pos = i_size_read(inode);
if (limit != RLIM_INFINITY) {
if (*pos >= limit) {
@@ -1590,15 +1591,17 @@
if (unlikely(*pos + *count > inode->i_sb->s_maxbytes))
*count = inode->i_sb->s_maxbytes - *pos;
} else {
+ loff_t isize;
if (bdev_read_only(inode->i_bdev))
return -EPERM;
- if (*pos >= inode->i_size) {
- if (*count || *pos > inode->i_size)
+ isize = i_size_read(inode);
+ if (*pos >= isize) {
+ if (*count || *pos > isize)
return -ENOSPC;
}
- if (*pos + *count > inode->i_size)
- *count = inode->i_size - *pos;
+ if (*pos + *count > isize)
+ *count = isize - *pos;
}
return 0;
}
@@ -1685,8 +1688,8 @@
iov, pos, nr_segs);
if (written > 0) {
loff_t end = pos + written;
- if (end > inode->i_size && !isblk) {
- inode->i_size = end;
+ if (end > i_size_read(inode) && !isblk) {
+ i_size_write(inode, end);
mark_inode_dirty(inode);
}
*ppos = end;
@@ -1730,14 +1733,15 @@
status = a_ops->prepare_write(file, page, offset, offset+bytes);
if (unlikely(status)) {
+ loff_t isize = i_size_read(inode);
/*
* prepare_write() may have instantiated a few blocks
* outside i_size. Trim these off again.
*/
unlock_page(page);
page_cache_release(page);
- if (pos + bytes > inode->i_size)
- vmtruncate(inode, inode->i_size);
+ if (pos + bytes > isize)
+ vmtruncate(inode, isize);
break;
}
if (likely(nr_segs == 1))
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c Sun Jul 13 20:39:55 2003
+++ b/mm/memory.c Sun Jul 13 20:39:55 2003
@@ -1109,7 +1109,7 @@
if (inode->i_size < offset)
goto do_expand;
- inode->i_size = offset;
+ i_size_write(inode, offset);
pgoff = (offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
down(&mapping->i_shared_sem);
if (unlikely(!list_empty(&mapping->i_mmap)))
@@ -1126,7 +1126,7 @@
goto out_sig;
if (offset > inode->i_sb->s_maxbytes)
goto out;
- inode->i_size = offset;
+ i_size_write(inode, offset);
out_truncate:
if (inode->i_op && inode->i_op->truncate)
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c Sun Jul 13 20:39:55 2003
+++ b/mm/mmap.c Sun Jul 13 20:39:55 2003
@@ -476,10 +476,10 @@
if (!len)
return addr;
- if (len > TASK_SIZE)
- return -EINVAL;
-
+ /* Careful about overflows.. */
len = PAGE_ALIGN(len);
+ if (!len || len > TASK_SIZE)
+ return -EINVAL;
/* offset overflow? */
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c Sun Jul 13 20:39:56 2003
+++ b/mm/nommu.c Sun Jul 13 20:39:56 2003
@@ -48,7 +48,7 @@
if (inode->i_size < offset)
goto do_expand;
- inode->i_size = offset;
+ i_size_write(inode, offset);
truncate_inode_pages(mapping, offset);
goto out_truncate;
@@ -59,7 +59,7 @@
goto out_sig;
if (offset > inode->i_sb->s_maxbytes)
goto out;
- inode->i_size = offset;
+ i_size_write(inode, offset);
out_truncate:
if (inode->i_op && inode->i_op->truncate)
diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c Sun Jul 13 20:39:55 2003
+++ b/mm/oom_kill.c Sun Jul 13 20:39:55 2003
@@ -141,8 +141,16 @@
* CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
* we select a process with CAP_SYS_RAW_IO set).
*/
-void oom_kill_task(struct task_struct *p)
+static void __oom_kill_task(task_t *p)
{
+ task_lock(p);
+ if (!p->mm || p->mm == &init_mm) {
+ WARN_ON(1);
+ printk(KERN_WARNING "tried to kill an mm-less task!\n");
+ task_unlock(p);
+ return;
+ }
+ task_unlock(p);
printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
/*
@@ -161,6 +169,16 @@
}
}
+static struct mm_struct *oom_kill_task(task_t *p)
+{
+ struct mm_struct *mm = get_task_mm(p);
+ if (!mm || mm == &init_mm)
+ return NULL;
+ __oom_kill_task(p);
+ return mm;
+}
+
+
/**
* oom_kill - kill the "best" process when we run out of memory
*
@@ -171,9 +189,11 @@
*/
static void oom_kill(void)
{
+ struct mm_struct *mm;
struct task_struct *g, *p, *q;
read_lock(&tasklist_lock);
+retry:
p = select_bad_process();
/* Found nothing?!?! Either we hang forever, or we panic. */
@@ -182,17 +202,21 @@
panic("Out of memory and no killable processes...\n");
}
- oom_kill_task(p);
+ mm = oom_kill_task(p);
+ if (!mm)
+ goto retry;
/*
* kill all processes that share the ->mm (i.e. all threads),
* but are in a different thread group
*/
do_each_thread(g, q)
- if (q->mm == p->mm && q->tgid != p->tgid)
- oom_kill_task(q);
+ if (q->mm == mm && q->tgid != p->tgid)
+ __oom_kill_task(q);
while_each_thread(g, q);
-
+ if (!p->mm)
+ printk(KERN_INFO "Fixed up OOM kill of mm-less task\n");
read_unlock(&tasklist_lock);
+ mmput(mm);
/*
* Make kswapd go out of the way, so "p" has a good chance of
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c Sun Jul 13 20:39:54 2003
+++ b/mm/readahead.c Sun Jul 13 20:39:54 2003
@@ -208,11 +208,12 @@
LIST_HEAD(page_pool);
int page_idx;
int ret = 0;
+ loff_t isize = i_size_read(inode);
- if (inode->i_size == 0)
+ if (isize == 0)
goto out;
- end_index = ((inode->i_size - 1) >> PAGE_CACHE_SHIFT);
+ end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
/*
* Preallocate as many pages as we will need.
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c Sun Jul 13 20:39:55 2003
+++ b/mm/shmem.c Sun Jul 13 20:39:55 2003
@@ -299,7 +299,7 @@
static const swp_entry_t unswapped = {0};
if (sgp != SGP_WRITE &&
- ((loff_t) index << PAGE_CACHE_SHIFT) >= inode->i_size)
+ ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
return ERR_PTR(-EINVAL);
while (!(entry = shmem_swp_entry(info, index, &page))) {
@@ -332,7 +332,7 @@
return ERR_PTR(-ENOMEM);
}
if (sgp != SGP_WRITE &&
- ((loff_t) index << PAGE_CACHE_SHIFT) >= inode->i_size) {
+ ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
entry = ERR_PTR(-EINVAL);
break;
}
@@ -641,7 +641,7 @@
/* Racing against delete or truncate? Must leave out of page cache */
limit = (inode->i_state & I_FREEING)? 0:
- (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (idx >= limit ||
move_from_swap_cache(page, idx, inode->i_mapping) == 0)
@@ -964,7 +964,7 @@
enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
unsigned long size;
- size = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
return -EINVAL;
@@ -1239,12 +1239,13 @@
for (;;) {
struct page *page = NULL;
unsigned long end_index, nr, ret;
+ loff_t i_size = i_size_read(inode);
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ end_index = i_size >> PAGE_CACHE_SHIFT;
if (index > end_index)
break;
if (index == end_index) {
- nr = inode->i_size & ~PAGE_CACHE_MASK;
+ nr = i_size & ~PAGE_CACHE_MASK;
if (nr <= offset)
break;
}
@@ -1261,9 +1262,10 @@
* are called without i_sem protection against truncate
*/
nr = PAGE_CACHE_SIZE;
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ i_size = i_size_read(inode);
+ end_index = i_size >> PAGE_CACHE_SHIFT;
if (index == end_index) {
- nr = inode->i_size & ~PAGE_CACHE_MASK;
+ nr = i_size & ~PAGE_CACHE_MASK;
if (nr <= offset) {
page_cache_release(page);
break;
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c Sun Jul 13 20:39:55 2003
+++ b/mm/swapfile.c Sun Jul 13 20:39:55 2003
@@ -926,7 +926,7 @@
*/
probe_block = 0;
page_no = 0;
- last_block = inode->i_size >> blkbits;
+ last_block = i_size_read(inode) >> blkbits;
while ((probe_block + blocks_per_page) <= last_block &&
page_no < sis->max) {
unsigned block_in_page;
@@ -1312,7 +1312,7 @@
goto bad_swap;
}
- swapfilesize = mapping->host->i_size >> PAGE_SHIFT;
+ swapfilesize = i_size_read(mapping->host) >> PAGE_SHIFT;
/*
* Read the swap header.
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c Sun Jul 13 20:39:54 2003
+++ b/mm/vmscan.c Sun Jul 13 20:39:54 2003
@@ -147,7 +147,7 @@
pages = nr_used_zone_pages();
list_for_each_entry(shrinker, &shrinker_list, list) {
- long long delta;
+ unsigned long long delta;
delta = scanned * shrinker->seeks;
delta *= (*shrinker->shrinker)(0, gfp_mask);
diff -Nru a/net/compat.c b/net/compat.c
--- a/net/compat.c Sun Jul 13 20:39:55 2003
+++ b/net/compat.c Sun Jul 13 20:39:55 2003
@@ -405,34 +405,6 @@
sizeof(struct sock_fprog));
}
-static int do_set_icmpv6_filter(int fd, int level, int optname,
- char *optval, int optlen)
-{
- struct icmp6_filter kfilter;
- mm_segment_t old_fs;
- int ret, i;
-
- if (optlen < sizeof(kfilter))
- return -EINVAL;
- if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
- return -EFAULT;
-
- for (i = 0; i < 8; i += 2) {
- u32 tmp = kfilter.data[i];
-
- kfilter.data[i] = kfilter.data[i + 1];
- kfilter.data[i + 1] = tmp;
- }
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_setsockopt(fd, level, optname,
- (char *) &kfilter, sizeof(kfilter));
- set_fs(old_fs);
-
- return ret;
-}
-
static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
{
struct compat_timeval *up = (struct compat_timeval *) optval;
@@ -465,9 +437,6 @@
optval, optlen);
if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
return do_set_sock_timeout(fd, level, optname, optval, optlen);
- if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
- return do_set_icmpv6_filter(fd, level, optname,
- optval, optlen);
return sys_setsockopt(fd, level, optname, optval, optlen);
}
diff -Nru a/net/core/net-sysfs.c b/net/core/net-sysfs.c
--- a/net/core/net-sysfs.c Sun Jul 13 20:39:56 2003
+++ b/net/core/net-sysfs.c Sun Jul 13 20:39:56 2003
@@ -1,7 +1,7 @@
/*
* net-sysfs.c - network device class and attributes
*
- * Copyright (c) 2003 Stephen Hemminber
+ * Copyright (c) 2003 Stephen Hemminger
*
*/
diff -Nru a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig Sun Jul 13 20:39:56 2003
+++ b/net/ipv4/Kconfig Sun Jul 13 20:39:56 2003
@@ -375,4 +375,5 @@
If unsure, say Y.
source "net/ipv4/netfilter/Kconfig"
+source "net/ipv4/ipvs/Kconfig"
diff -Nru a/net/ipv4/Makefile b/net/ipv4/Makefile
--- a/net/ipv4/Makefile Sun Jul 13 20:39:55 2003
+++ b/net/ipv4/Makefile Sun Jul 13 20:39:55 2003
@@ -21,5 +21,6 @@
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_NETFILTER) += netfilter/
+obj-$(CONFIG_IP_VS) += ipvs/
obj-y += xfrm4_policy.o xfrm4_state.o xfrm4_input.o xfrm4_tunnel.o
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c Sun Jul 13 20:39:56 2003
+++ b/net/ipv4/igmp.c Sun Jul 13 20:39:56 2003
@@ -1060,17 +1060,19 @@
reporter = im->reporter;
igmp_stop_timer(im);
- if (IGMP_V1_SEEN(in_dev))
- goto done;
- if (IGMP_V2_SEEN(in_dev)) {
- if (reporter)
- igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
- goto done;
- }
- /* IGMPv3 */
- igmpv3_add_delrec(in_dev, im);
+ if (in_dev->dev->flags & IFF_UP) {
+ if (IGMP_V1_SEEN(in_dev))
+ goto done;
+ if (IGMP_V2_SEEN(in_dev)) {
+ if (reporter)
+ igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
+ goto done;
+ }
+ /* IGMPv3 */
+ igmpv3_add_delrec(in_dev, im);
- igmp_ifc_event(in_dev);
+ igmp_ifc_event(in_dev);
+ }
done:
#endif
ip_mc_clear_src(im);
diff -Nru a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/net/ipv4/ipvs/Kconfig Sun Jul 13 20:39:56 2003
@@ -0,0 +1,257 @@
+#
+# IP Virtual Server configuration
+#
+menu "IP: Virtual Server Configuration"
+ depends on INET && NETFILTER
+
+config IP_VS
+ tristate "IP virtual server support (EXPERIMENTAL)"
+ depends on INET && NETFILTER
+ ---help---
+ IP Virtual Server support will let you build a high-performance
+ virtual server based on cluster of two or more real servers. This
+ option must be enabled for at least one of the clustered computers
+ that will take care of intercepting incomming connections to a
+ single IP address and scheduling them to real servers.
+
+ Three request dispatching techniques are implemented, they are
+ virtual server via NAT, virtual server via tunneling and virtual
+ server via direct routing. The several scheduling algorithms can
+ be used to choose which server the connection is directed to,
+ thus load balancing can be achieved among the servers. For more
+ information and its administration program, please visit the
+ following URL:
+ http://www.linuxvirtualserver.org/
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_DEBUG
+ bool "IP virtual server debugging"
+ depends on IP_VS
+ ---help---
+ Say Y here if you want to get additional messages useful in
+ debugging the IP virtual server code. You can change the debug
+ level in /proc/sys/net/ipv4/vs/debug_level
+
+config IP_VS_TAB_BITS
+ int "IPVS connection table size (the Nth power of 2)"
+ depends on IP_VS
+ default "12"
+ ---help---
+ The IPVS connection hash table uses the chaining scheme to handle
+ hash collisions. Using a big IPVS connection hash table will greatly
+ reduce conflicts when there are hundreds of thousands of connections
+ in the hash table.
+
+ Note the table size must be power of 2. The table size will be the
+ value of 2 to the your input number power. The number to choose is
+ from 8 to 20, the default number is 12, which means the table size
+ is 4096. Don't input the number too small, otherwise you will lose
+ performance on it. You can adapt the table size yourself, according
+ to your virtual server application. It is good to set the table size
+ not far less than the number of connections per second multiplying
+ average lasting time of connection in the table. For example, your
+ virtual server gets 200 connections per second, the connection lasts
+ for 200 seconds in average in the connection table, the table size
+ should be not far less than 200x200, it is good to set the table
+ size 32768 (2**15).
+
+ Another note that each connection occupies 128 bytes effectively and
+ each hash entry uses 8 bytes, so you can estimate how much memory is
+ needed for your box.
+
+comment "IPVS transport protocol load balancing support"
+ depends on IP_VS
+
+config IP_VS_PROTO_TCP
+ bool "TCP load balancing support"
+ depends on IP_VS
+ ---help---
+ This option enables support for load balancing TCP transport
+ protocol. Say Y if unsure.
+
+config IP_VS_PROTO_UDP
+ bool "UDP load balancing support"
+ depends on IP_VS
+ ---help---
+ This option enables support for load balancing UDP transport
+ protocol. Say Y if unsure.
+
+config IP_VS_PROTO_ESP
+ bool "ESP load balancing support"
+ depends on IP_VS
+ ---help---
+ This option enables support for load balancing ESP (Encapsultion
+ Security Payload) transport protocol. Say Y if unsure.
+
+config IP_VS_PROTO_AH
+ bool "AH load balancing support"
+ depends on IP_VS
+ ---help---
+ This option enables support for load balancing AH (Authentication
+ Header) transport protocol. Say Y if unsure.
+
+comment "IPVS scheduler"
+ depends on IP_VS
+
+config IP_VS_RR
+ tristate "round-robin scheduling"
+ depends on IP_VS
+ ---help---
+ The robin-robin scheduling algorithm simply directs network
+ connections to different real servers in a round-robin manner.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_WRR
+ tristate "weighted round-robin scheduling"
+ depends on IP_VS
+ ---help---
+ The weighted robin-robin scheduling algorithm directs network
+ connections to different real servers based on server weights
+ in a round-robin manner. Servers with higher weights receive
+ new connections first than those with less weights, and servers
+ with higher weights get more connections than those with less
+ weights and servers with equal weights get equal connections.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_LC
+ tristate "least-connection scheduling scheduling"
+ depends on IP_VS
+ ---help---
+ The least-connection scheduling algorithm directs network
+ connections to the server with the least number of active
+ connections.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_WLC
+ tristate "weighted least-connection scheduling"
+ depends on IP_VS
+ ---help---
+ The weighted least-connection scheduling algorithm directs network
+ connections to the server with the least active connections
+ normalized by the server weight.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_LBLC
+ tristate "locality-based least-connection with replication scheduling"
+ depends on IP_VS
+ ---help---
+ The locality-based least-connection scheduling algorithm is for
+ destination IP load balancing. It is usually used in cache cluster.
+ This algorithm usually directs packet destined for an IP address to
+ its server if the server is alive and under load. If the server is
+ overloaded (its active connection numbers is larger than its weight)
+ and there is a server in its half load, then allocate the weighted
+ least-connection server to this IP address.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_LBLCR
+ tristate "locality-based least-connection with replication schedulin"
+ depends on IP_VS
+ ---help---
+ The locality-based least-connection with replication scheduling
+ algorithm is also for destination IP load balancing. It is
+ usually used in cache cluster. It differs from the LBLC scheduling
+ as follows: the load balancer maintains mappings from a target
+ to a set of server nodes that can serve the target. Requests for
+ a target are assigned to the least-connection node in the target's
+ server set. If all the node in the server set are over loaded,
+ it picks up a least-connection node in the cluster and adds it
+ in the sever set for the target. If the server set has not been
+ modified for the specified time, the most loaded node is removed
+ from the server set, in order to avoid high degree of replication.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_DH
+ tristate "destination hashing scheduling"
+ depends on IP_VS
+ ---help---
+ The destination hashing scheduling algorithm assigns network
+ connections to the servers through looking up a statically assigned
+ hash table by their destination IP addresses.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_SH
+ tristate "source hashing scheduling"
+ depends on IP_VS
+ ---help---
+ The source hashing scheduling algorithm assigns network
+ connections to the servers through looking up a statically assigned
+ hash table by their source IP addresses.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_SED
+ tristate "shortest expected delay scheduling"
+ depends on IP_VS
+ ---help---
+ The shortest expected delay scheduling algorithm assigns network
+ connections to the server with the shortest expected delay. The
+ expected delay that the job will experience is (Ci + 1) / Ui if
+ sent to the ith server, in which Ci is the number of connections
+ on the the ith server and Ui is the fixed service rate (weight)
+ of the ith server.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+config IP_VS_NQ
+ tristate "never queue scheduling"
+ depends on IP_VS
+ ---help---
+ The never queue scheduling algorithm adopts a two-speed model.
+ When there is an idle server available, the job will be sent to
+ the idle server, instead of waiting for a fast one. When there
+ is no idle server available, the job will be sent to the server
+ that minimize its expected delay (The Shortest Expected Delay
+ scheduling algorithm).
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+comment 'IPVS application helper'
+ depends on IP_VS
+
+config IP_VS_FTP
+ tristate "FTP protocol helper"
+ depends on IP_VS
+ ---help---
+ FTP is a protocol that transfers IP address and/or port number in
+ the payload. In the virtual server via Network Address Translation,
+ the IP address and port number of real servers cannot be sent to
+ clients in ftp connections directly, so FTP protocol helper is
+ required for tracking the connection and mangling it back to that of
+ virtual service.
+
+ If you want to compile it in kernel, say Y. If you want to compile
+ it as a module, say M here and read Documentation/modules.txt. If
+ unsure, say N.
+
+endmenu
diff -Nru a/net/ipv4/ipvs/Makefile b/net/ipv4/ipvs/Makefile
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/net/ipv4/ipvs/Makefile Sun Jul 13 20:39:56 2003
@@ -0,0 +1,40 @@
+#
+# Makefile for the IPVS modules on top of IPv4.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+
+# IPVS transport protocol load balancing support
+ip_vs_proto-objs-y :=
+ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o
+ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o
+ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_ESP) += ip_vs_proto_esp.o
+ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH) += ip_vs_proto_ah.o
+
+ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \
+ ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
+ ip_vs_est.o ip_vs_proto.o ip_vs_proto_icmp.o \
+ $(ip_vs_proto-objs-y)
+
+
+# IPVS core
+obj-$(CONFIG_IP_VS) += ip_vs.o
+
+# IPVS schedulers
+obj-$(CONFIG_IP_VS_RR) += ip_vs_rr.o
+obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o
+obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o
+obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o
+obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o
+obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o
+obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o
+obj-$(CONFIG_IP_VS_SH) += ip_vs_sh.o
+obj-$(CONFIG_IP_VS_SED) += ip_vs_sed.o
+obj-$(CONFIG_IP_VS_NQ) += ip_vs_nq.o
+
+# IPVS application helpers
+obj-$(CONFIG_IP_VS_FTP) += ip_vs_ftp.o
diff -Nru a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/net/ipv4/ipvs/ip_vs_app.c Sun Jul 13 20:39:56 2003
@@ -0,0 +1,588 @@
+/*
+ * ip_vs_app.c: Application module support for IPVS
+ *
+ * Version: $Id: ip_vs_app.c,v 1.17 2003/03/22 06:31:21 wensong Exp $
+ *
+ * Authors: Wensong Zhang
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Most code here is taken from ip_masq_app.c in kernel 2.2. The difference
+ * is that ip_vs_app module handles the reverse direction (incoming requests
+ * and outgoing responses).
+ *
+ * IP_MASQ_APP application masquerading module
+ *
+ * Author: Juan Jose Ciarlante,
+ *
+ */
+
+#include