diff -Nru a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
--- a/Documentation/DocBook/procfs-guide.tmpl Mon Oct 28 21:14:41 2002
+++ b/Documentation/DocBook/procfs-guide.tmpl Thu Jul 10 22:22:53 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 Sat Nov 16 15:02:15 2002
+++ b/Documentation/DocBook/procfs_example.c Thu Jul 10 22:22:53 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/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt Thu Jun 5 23:37:53 2003
+++ b/Documentation/kernel-parameters.txt Thu Jul 10 22:23:36 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 Thu May 2 20:49:06 2002
+++ b/Documentation/nbd.txt Thu Jul 10 22:23:52 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 Tue Jul 8 05:00:18 2003
+++ b/MAINTAINERS Wed Jul 9 14:04:13 2003
@@ -1910,7 +1910,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 Thu Jul 10 12:13:30 2003
+++ b/Makefile Fri Jul 11 04:40:19 2003
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 75
-EXTRAVERSION =
+EXTRAVERSION = -bk1
# *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/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c Sat Jun 28 08:50:41 2003
+++ b/arch/alpha/kernel/time.c Thu Jul 10 22:22:57 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 Tue Jun 24 22:21:45 2003
+++ b/arch/arm/Kconfig Thu Jul 10 22:23:10 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 6 16:40:01 2003
+++ b/arch/arm26/Kconfig Thu Jul 10 22:23:10 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 Wed Jul 2 21:19:42 2003
+++ b/arch/i386/Kconfig Thu Jul 10 22:23:10 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/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c Wed Jul 2 21:21:32 2003
+++ b/arch/i386/kernel/time.c Thu Jul 10 22:22:57 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 Wed Jul 9 14:23:16 2003
+++ b/arch/ia64/Kconfig Thu Jul 10 22:23:10 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 Wed Jun 18 00:37:28 2003
+++ b/arch/ia64/kernel/time.c Thu Jul 10 22:22:57 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 Sat Jun 14 16:16:05 2003
+++ b/arch/m68k/kernel/time.c Thu Jul 10 22:22:57 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 Wed Jul 9 16:13:07 2003
+++ b/arch/m68knommu/kernel/time.c Thu Jul 10 22:22:57 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 Jun 22 16:31:20 2003
+++ b/arch/mips/kernel/time.c Thu Jul 10 22:22:57 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 Mon Jun 23 12:08:34 2003
+++ b/arch/mips64/kernel/time.c Thu Jul 10 22:22:57 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 Tue Jun 24 22:21:45 2003
+++ b/arch/parisc/Kconfig Thu Jul 10 22:23:32 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 Tue Dec 31 17:34:28 2002
+++ b/arch/parisc/hpux/sys_hpux.c Thu Jul 10 07:21:18 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 May 25 17:00:00 2003
+++ b/arch/parisc/kernel/drivers.c Wed Jul 2 08:57:46 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 Tue May 27 04:21:38 2003
+++ b/arch/parisc/kernel/ioctl32.c Sun Jun 22 14:25:47 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 Thu Jun 12 08:18:06 2003
+++ b/arch/parisc/kernel/module.c Wed Jul 2 08:57:46 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 Mon Mar 17 09:56:45 2003
+++ b/arch/parisc/kernel/pci.c Sun Jun 22 14:25:47 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 Mon May 5 04:05:48 2003
+++ b/arch/parisc/kernel/sys_parisc32.c Sun Jun 22 14:25:47 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 Mon May 5 08:34:24 2003
+++ b/arch/parisc/kernel/time.c Thu Jul 10 22:22:57 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 Jun 8 13:25:47 2003
+++ b/arch/parisc/kernel/traps.c Wed Jul 2 08:57:46 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 Sat Jan 11 21:50:25 2003
+++ b/arch/parisc/kernel/unaligned.c Thu Jul 10 07:21:18 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 Wed Jul 2 17:44:13 2003
+++ b/arch/ppc/Kconfig Thu Jul 10 22:23:14 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 Sat Jun 14 16:16:05 2003
+++ b/arch/ppc/kernel/time.c Thu Jul 10 22:22:57 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 Sat Jun 14 16:15:59 2003
+++ b/arch/ppc64/kernel/time.c Thu Jul 10 22:22:57 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 Sat Jun 14 16:16:02 2003
+++ b/arch/s390/kernel/time.c Thu Jul 10 22:22:57 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 Sat Jun 28 05:01:28 2003
+++ b/arch/sh/kernel/time.c Thu Jul 10 22:22:57 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/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c Tue Jun 17 15:46:44 2003
+++ b/arch/sparc/kernel/time.c Thu Jul 10 22:22:57 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/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c Tue Jun 17 14:51:27 2003
+++ b/arch/sparc64/kernel/time.c Thu Jul 10 22:22:57 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 Mon Feb 17 18:41:09 2003
+++ b/arch/v850/kernel/bug.c Thu Jul 10 18:06:18 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 Thu Apr 3 15:01:04 2003
+++ b/arch/v850/kernel/gbus_int.c Thu Jul 10 18:06:18 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 Wed Jun 11 12:33:09 2003
+++ b/arch/v850/kernel/simcons.c Thu Jul 10 18:06:18 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 Sat Jun 14 16:16:08 2003
+++ b/arch/v850/kernel/time.c Thu Jul 10 18:06:18 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 Tue Jun 24 22:21:45 2003
+++ b/arch/x86_64/Kconfig Thu Jul 10 22:23:14 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/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c Tue Jun 24 06:31:58 2003
+++ b/arch/x86_64/kernel/time.c Thu Jul 10 22:22:57 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/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig Sun Apr 20 16:21:17 2003
+++ b/drivers/block/Kconfig Thu Jul 10 17:46:23 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 Fri Jul 4 23:52:37 2003
+++ b/drivers/block/Makefile Thu Jul 10 17:46:23 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/cryptoloop.c b/drivers/block/cryptoloop.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/block/cryptoloop.c Thu Jul 10 17:46:23 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/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c Fri Jul 4 23:52:53 2003
+++ b/drivers/block/ll_rw_blk.c Fri Jul 11 01:27:41 2003
@@ -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 Tue Jun 24 13:10:43 2003
+++ b/drivers/block/loop.c Thu Jul 10 22:22:59 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 Jun 22 18:13:08 2003
+++ b/drivers/block/nbd.c Thu Jul 10 22:23:53 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/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c Thu Jul 3 09:01:42 2003
+++ b/drivers/char/agp/via-agp.c Thu Jul 10 15:17:58 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 Thu Mar 13 16:52:15 2003
+++ b/drivers/char/drm/ati_pcigart.h Thu Jul 10 23:18:01 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 Wed Dec 18 09:56:28 2002
+++ b/drivers/char/drm/drm.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drmP.h Thu Jul 10 23:18:01 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 Wed May 21 02:15:24 2003
+++ b/drivers/char/drm/drm_agpsupport.h Thu Jul 10 23:40:39 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 Thu Mar 13 16:52:15 2003
+++ b/drivers/char/drm/drm_auth.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drm_bufs.h Thu Jul 10 23:18:01 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 Fri Apr 25 15:57:57 2003
+++ b/drivers/char/drm/drm_context.h Thu Jul 10 23:18:01 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 Mon Apr 28 20:00:59 2003
+++ b/drivers/char/drm/drm_dma.h Thu Jul 10 23:18:01 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 Thu Mar 13 16:52:15 2003
+++ b/drivers/char/drm/drm_drawable.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drm_drv.h Thu Jul 10 23:18:01 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
@@ -134,12 +138,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 +155,7 @@
#undef DRM_OPTIONS_FUNC
#endif
-/*
+/**
* The default number of instances (minor numbers) to initialize.
*/
#ifndef DRIVER_NUM_CARDS
@@ -163,6 +168,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 +354,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 +366,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 +532,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 +571,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 +671,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 +729,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 +775,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 +816,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 +954,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 +1005,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 )
{
@@ -1031,7 +1121,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 )
{
diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
--- a/drivers/char/drm/drm_fops.h Fri Apr 25 15:57:57 2003
+++ b/drivers/char/drm/drm_fops.h Thu Jul 10 23:18:01 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 Fri Apr 25 15:57:57 2003
+++ b/drivers/char/drm/drm_init.h Thu Jul 10 23:18:01 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 Fri Apr 25 15:57:57 2003
+++ b/drivers/char/drm/drm_ioctl.h Thu Jul 10 23:18:01 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 Fri Apr 25 15:57:57 2003
+++ b/drivers/char/drm/drm_lock.h Thu Jul 10 23:18:01 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 Mon May 26 12:57:49 2003
+++ b/drivers/char/drm/drm_memory.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drm_memory_debug.h Thu Jul 10 23:18:01 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 Mon Apr 28 20:01:25 2003
+++ b/drivers/char/drm/drm_os_linux.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drm_proc.h Thu Jul 10 23:18:01 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 Thu Nov 14 18:19:43 2002
+++ b/drivers/char/drm/drm_sarea.h Thu Jul 10 23:18:01 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 Thu Mar 13 16:52:15 2003
+++ b/drivers/char/drm/drm_scatter.h Thu Jul 10 23:18:01 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 Thu Mar 13 16:52:15 2003
+++ b/drivers/char/drm/drm_stub.h Thu Jul 10 23:18:01 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/drm_vm.h Thu Jul 10 23:18:01 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 Mon Apr 28 19:59:49 2003
+++ b/drivers/char/drm/i810.h Thu Jul 10 23:26:02 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/i810_dma.c Thu Jul 10 23:26:02 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 Mar 2 23:30:02 2003
+++ b/drivers/char/drm/i810_drm.h Thu Jul 10 23:26:02 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 Mon Apr 28 19:59:49 2003
+++ b/drivers/char/drm/i810_drv.h Thu Jul 10 23:26:02 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 Mon Apr 28 19:59:49 2003
+++ b/drivers/char/drm/r128.h Thu Jul 10 23:30:21 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 Mon Apr 28 20:01:25 2003
+++ b/drivers/char/drm/r128_drv.h Thu Jul 10 23:30:21 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 Sat Mar 29 22:34:33 2003
+++ b/drivers/char/drm/r128_state.c Thu Jul 10 23:30:21 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/radeon.h Thu Jul 10 23:33:48 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/radeon_drm.h Thu Jul 10 23:33:48 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 Tue Oct 29 14:29:22 2002
+++ b/drivers/char/drm/radeon_drv.c Thu Jul 10 23:33:48 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 Sat May 24 12:57:42 2003
+++ b/drivers/char/drm/radeon_drv.h Thu Jul 10 23:33:48 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 Fri Apr 25 15:57:58 2003
+++ b/drivers/char/drm/radeon_state.c Thu Jul 10 23:33:48 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/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig Mon Apr 21 09:20:23 2003
+++ b/drivers/eisa/Kconfig Sat Jun 14 08:40:13 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/input/misc/gsc_ps2.c b/drivers/input/misc/gsc_ps2.c
--- a/drivers/input/misc/gsc_ps2.c Wed Feb 12 01:41:01 2003
+++ b/drivers/input/misc/gsc_ps2.c Thu May 29 04:21:53 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/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
--- a/drivers/net/appletalk/cops.c Sun Apr 27 20:36:18 2003
+++ b/drivers/net/appletalk/cops.c Tue Jul 1 16:09:19 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 Apr 27 20:36:18 2003
+++ b/drivers/net/appletalk/ltpc.c Tue Jul 1 16:10:07 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 Wed Jun 25 14:05:16 2003
+++ b/drivers/net/declance.c Tue Jul 1 16:16:27 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 Mon Jun 9 15:48:16 2003
+++ b/drivers/net/dgrs.c Thu Jul 10 16:14:45 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 Thu Jun 26 17:35:25 2003
+++ b/drivers/net/e100/e100_main.c Tue Jul 8 17:18:07 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 Thu May 8 19:16:27 2003
+++ b/drivers/net/e100/e100_phy.c Tue Jul 8 17:18:07 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 Wed Jun 4 04:17:01 2003
+++ b/drivers/net/hamradio/mkiss.c Mon Jul 7 12:55:58 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 Mon Mar 17 15:42:28 2003
+++ b/drivers/net/hamradio/mkiss.h Mon Jul 7 12:50:28 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 Wed Jun 25 13:52:00 2003
+++ b/drivers/net/irda/Kconfig Wed Jul 9 05:02:24 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 Fri May 30 10:45:57 2003
+++ b/drivers/net/irda/irda-usb.c Wed Jul 9 08:40:39 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 Thu May 29 23:50:31 2003
+++ b/drivers/net/irda/nsc-ircc.c Wed Jul 9 08:47:24 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 Thu Nov 21 14:06:11 2002
+++ b/drivers/net/irda/old_belkin.c Wed Jun 4 06:42:08 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 Mon Jun 23 14:45:40 2003
+++ b/drivers/net/pcmcia/3c574_cs.c Mon Jun 30 14:42:46 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 Mon Jun 23 16:24:48 2003
+++ b/drivers/net/pcmcia/3c589_cs.c Mon Jun 30 14:43:04 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/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
--- a/drivers/net/pcmcia/smc91c92_cs.c Tue Jun 24 15:07:31 2003
+++ b/drivers/net/pcmcia/smc91c92_cs.c Mon Jun 30 14:43:26 2003
@@ -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/plip.c b/drivers/net/plip.c
--- a/drivers/net/plip.c Thu Jun 19 14:25:16 2003
+++ b/drivers/net/plip.c Tue Jul 8 08:07:44 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 Wed Jun 25 14:09:38 2003
+++ b/drivers/net/sb1250-mac.c Tue Jul 1 16:24:20 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 Apr 27 20:36:20 2003
+++ b/drivers/net/sk_mca.c Tue Jul 1 16:26:16 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 Thu Jun 19 17:11:29 2003
+++ b/drivers/net/sundance.c Thu Jul 10 16:05:31 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 Wed Jul 9 21:01:34 2003
+++ b/drivers/net/sunhme.c Thu Jul 10 17:42:03 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 Wed Jun 11 23:56:33 2003
+++ b/drivers/net/tg3.c Thu Jul 10 16:25:44 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 Mon Jun 2 20:31:22 2003
+++ b/drivers/net/tokenring/3c359.c Thu Jul 10 16:38:47 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 Mon Jun 2 20:31:22 2003
+++ b/drivers/net/tokenring/proteon.c Thu Jul 10 16:38:47 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 Mon Jun 2 20:31:22 2003
+++ b/drivers/net/tokenring/skisa.c Thu Jul 10 16:38:47 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 Fri Jul 4 06:02:36 2003
+++ b/drivers/net/via-rhine.c Tue Jul 1 16:28:53 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 Thu Jun 5 21:54:48 2003
+++ b/drivers/net/wireless/atmel_cs.c Thu Jul 10 16:47:29 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 Fri Dec 6 10:10:13 2002
+++ b/drivers/net/wireless/wavelan.c Thu Jul 10 16:46:33 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 Sat Jun 14 11:39:40 2003
+++ b/drivers/parisc/Kconfig Sun Jun 22 14:25:53 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/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c Mon Jun 30 13:22:30 2003
+++ b/drivers/pcmcia/cs.c Thu Jul 10 22:23:58 2003
@@ -338,13 +338,13 @@
socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
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);
+
+ init_socket(socket);
+
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
if (ret < 0)
return ret;
@@ -868,13 +868,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 */
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c Tue Jun 17 07:52:28 2003
+++ b/drivers/usb/class/usblp.c Mon Jul 7 12:33:32 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 Tue Jun 10 09:36:21 2003
+++ b/drivers/usb/core/inode.c Thu Jul 10 06:17:51 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 Thu Jun 12 07:28:01 2003
+++ b/drivers/usb/core/message.c Mon Jul 7 08:24:11 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 Wed Jun 25 11:30:59 2003
+++ b/drivers/usb/net/usbnet.c Mon Jul 7 08:53:04 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 Thu May 29 13:51:36 2003
+++ b/drivers/usb/serial/ftdi_sio.c Fri Jun 27 07:43:37 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 Tue Feb 4 05:46:17 2003
+++ b/drivers/usb/serial/ftdi_sio.h Fri Jun 27 04:25:33 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 Jun 1 12:24:07 2003
+++ b/drivers/usb/storage/datafab.c Fri Jul 4 06:23:54 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 Jun 1 12:09:08 2003
+++ b/drivers/usb/storage/freecom.c Fri Jul 4 06:23:54 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 Thu Jun 19 21:23:33 2003
+++ b/drivers/usb/storage/initializers.c Fri Jul 4 06:10:48 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 Tue Jul 1 06:26:58 2003
+++ b/drivers/usb/storage/unusual_devs.h Wed Jul 2 05:27:36 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 Wed Jun 25 03:10:46 2003
+++ b/drivers/usb/usb-skeleton.c Mon Jul 7 03:13:30 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/fs/aio.c b/fs/aio.c
--- a/fs/aio.c Sun Jul 6 18:51:59 2003
+++ b/fs/aio.c Thu Jul 10 22:23:44 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 Wed Jul 2 21:21:22 2003
+++ b/fs/attr.c Thu Jul 10 22:22:59 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 Sat Feb 15 19:30:17 2003
+++ b/fs/binfmt_aout.c Thu Jul 10 22:22:59 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 Wed Jun 25 16:30:52 2003
+++ b/fs/binfmt_elf.c Wed Jul 2 09:01:11 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 Wed Jul 2 21:21:28 2003
+++ b/fs/block_dev.c Thu Jul 10 22:22:59 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 6 18:06:47 2003
+++ b/fs/buffer.c Thu Jul 10 22:22:59 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/dcache.c b/fs/dcache.c
--- a/fs/dcache.c Wed Jun 25 16:30:53 2003
+++ b/fs/dcache.c Thu Jul 10 22:23:45 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 Thu Jul 3 06:36:44 2003
+++ b/fs/devfs/base.c Thu Jul 10 22:24:00 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 Tue Feb 25 09:50:46 2003
+++ b/fs/direct-io.c Thu Jul 10 22:22:59 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 Fri Jul 4 23:52:56 2003
+++ b/fs/eventpoll.c Thu Jul 10 22:24:01 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 Tue Jul 8 12:15:23 2003
+++ b/fs/exec.c Thu Jul 10 22:23:01 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 Wed Jul 2 21:22:40 2003
+++ b/fs/ext2/ialloc.c Thu Jul 10 22:23:36 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 Thu Jul 3 19:20:48 2003
+++ b/fs/ext3/inode.c Thu Jul 10 22:22:59 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 Sat Jun 14 16:16:09 2003
+++ b/fs/inode.c Thu Jul 10 22:22:59 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 Tue May 13 13:42:27 2003
+++ b/fs/ioctl.c Thu Jul 10 22:22:59 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 Fri Jun 20 13:16:31 2003
+++ b/fs/jbd/checkpoint.c Thu Jul 10 22:23:54 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 Wed Jul 2 21:23:09 2003
+++ b/fs/jbd/commit.c Thu Jul 10 22:23:55 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 Fri Jun 20 13:16:31 2003
+++ b/fs/jbd/journal.c Thu Jul 10 22:23:56 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 Wed Jul 2 21:23:09 2003
+++ b/fs/jbd/transaction.c Thu Jul 10 22:23:54 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 Thu Jul 3 06:36:44 2003
+++ b/fs/libfs.c Thu Jul 10 22:22:59 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 Tue May 13 13:42:28 2003
+++ b/fs/locks.c Thu Jul 10 22:22:59 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 Tue Apr 8 03:16:30 2003
+++ b/fs/mpage.c Thu Jul 10 22:23:36 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 Mon Jul 7 12:25:00 2003
+++ b/fs/namei.c Thu Jul 10 22:23:45 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 Jun 29 23:49:25 2003
+++ b/fs/namespace.c Thu Jul 10 22:23:45 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 Fri Jun 20 13:16:06 2003
+++ b/fs/nfs/inode.c Thu Jul 10 22:22:59 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 Wed May 7 03:31:18 2003
+++ b/fs/nfs/write.c Thu Jul 10 22:22:59 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 Mon Jun 23 22:50:30 2003
+++ b/fs/nfsd/nfssvc.c Thu Jul 10 22:23:39 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 Jun 29 23:49:26 2003
+++ b/fs/open.c Thu Jul 10 22:22:59 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 6 18:06:49 2003
+++ b/fs/proc/base.c Thu Jul 10 22:23:45 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 Thu Jul 3 06:36:44 2003
+++ b/fs/proc/generic.c Thu Jul 10 22:22:53 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 Tue May 27 13:07:01 2003
+++ b/fs/proc/inode.c Thu Jul 10 22:22:53 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 Thu Jul 3 06:36:44 2003
+++ b/fs/proc/root.c Thu Jul 10 22:22:53 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 Mar 30 14:25:12 2003
+++ b/fs/quota_v1.c Thu Jul 10 22:22:59 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 Wed May 7 21:20:23 2003
+++ b/fs/read_write.c Thu Jul 10 22:22:59 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 Sat May 17 14:09:36 2003
+++ b/fs/reiserfs/bitmap.c Thu Jul 10 22:22: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 Sat May 17 14:09:35 2003
+++ b/fs/reiserfs/do_balan.c Thu Jul 10 22:22: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 Mon Sep 2 23:28:56 2002
+++ b/fs/reiserfs/fix_node.c Thu Jul 10 22:22: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 Wed Jun 4 00:50:34 2003
+++ b/fs/reiserfs/inode.c Thu Jul 10 22:22: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 Wed Jun 4 00:50:34 2003
+++ b/fs/reiserfs/journal.c Thu Jul 10 22:22: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 Mon Feb 24 10:10:17 2003
+++ b/fs/reiserfs/stree.c Thu Jul 10 22:22:55 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 Fri Jun 27 23:20:15 2003
+++ b/fs/reiserfs/tail_conversion.c Thu Jul 10 22:22:54 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 May 4 22:49:54 2003
+++ b/fs/stat.c Thu Jul 10 22:22:59 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-parisc/byteorder.h b/include/asm-parisc/byteorder.h
--- a/include/asm-parisc/byteorder.h Tue Feb 5 09:39:57 2002
+++ b/include/asm-parisc/byteorder.h Thu Jul 10 07:21:28 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 Tue Dec 24 09:39:09 2002
+++ b/include/asm-parisc/parisc-device.h Wed Jul 2 08:57:59 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 Mon May 5 08:34:24 2003
+++ b/include/asm-parisc/pgtable.h Thu Jul 10 07:21:28 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 Mar 23 05:14:52 2003
+++ b/include/asm-parisc/processor.h Wed Jul 2 08:57:59 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-v850/statfs.h b/include/asm-v850/statfs.h
--- a/include/asm-v850/statfs.h Fri Nov 1 08:38:12 2002
+++ b/include/asm-v850/statfs.h Thu Jul 10 18:06:18 2003
@@ -1,25 +1,6 @@
#ifndef __V850_STATFS_H__
#define __V850_STATFS_H__
-#ifndef __KERNEL_STRICT_NAMES
-
-#include
-
-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/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h Sun Jul 6 13:23:51 2003
+++ b/include/linux/fs.h Thu Jul 10 22:22:59 2003
@@ -349,6 +349,17 @@
struct gendisk * bd_disk;
};
+/*
+ * Use sequence counter to get consistent i_size on 32-bit processors.
+ */
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+#include
+#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 Apr 6 06:03:54 2003
+++ b/include/linux/irda.h Wed Jun 4 07:16:33 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 Tue Jun 17 23:04:25 2003
+++ b/include/linux/jbd.h Thu Jul 10 22:23:54 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 Tue Jun 24 12:15:44 2003
+++ b/include/linux/loop.h Thu Jul 10 17:46:23 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 May 25 17:57:20 2003
+++ b/include/linux/mount.h Thu Jul 10 22:23:45 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 Dec 8 17:58:04 2002
+++ b/include/linux/nbd.h Thu Jul 10 22:23:53 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 Thu Jul 3 06:36:45 2003
+++ b/include/linux/proc_fs.h Thu Jul 10 22:22:53 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 Wed Jun 4 00:50:34 2003
+++ b/include/linux/reiserfs_fs.h Thu Jul 10 22:22:55 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 Wed Jun 4 00:50:34 2003
+++ b/include/linux/reiserfs_fs_sb.h Thu Jul 10 22:22: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 Wed Feb 5 08:05:33 2003
+++ b/include/linux/seqlock.h Thu Jul 10 22:22:58 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 Thu Jun 5 23:37:53 2003
+++ b/include/linux/sysctl.h Sat Jun 14 09:07:18 2003
@@ -130,6 +130,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 Fri Jun 20 13:16:13 2003
+++ b/include/linux/time.h Thu Jul 10 22:22:57 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/irda/irda_device.h b/include/net/irda/irda_device.h
--- a/include/net/irda/irda_device.h Mon Feb 24 12:51:23 2003
+++ b/include/net/irda/irda_device.h Wed Jul 9 04:58:28 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 Tue Feb 5 09:39:49 2002
+++ b/include/net/irda/nsc-ircc.h Wed Jul 9 08:47:24 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/init/Kconfig b/init/Kconfig
--- a/init/Kconfig Wed Jul 2 21:23:11 2003
+++ b/init/Kconfig Thu Jul 10 22:23:14 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/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c Fri May 9 14:23:37 2003
+++ b/ipc/shm.c Thu Jul 10 22:22:59 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 Tue Jun 17 05:37:03 2003
+++ b/kernel/compat.c Thu Jul 10 22:22:52 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 Fri Jul 4 23:52:49 2003
+++ b/kernel/fork.c Thu Jul 10 22:23:43 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 Thu Jul 3 00:32:44 2003
+++ b/kernel/ksyms.c Thu Jul 10 22:23:39 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 Mon Jul 7 13:01:46 2003
+++ b/kernel/sched.c Thu Jul 10 22:23:46 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/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c Sun Jun 29 23:49:26 2003
+++ b/kernel/sysctl.c Thu Jul 10 08:52:17 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;
@@ -312,6 +317,30 @@
.mode = 0644,
.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)
{
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c Sun Jul 6 13:23:51 2003
+++ b/mm/filemap.c Thu Jul 10 22:22:59 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 Thu Jun 12 16:41:04 2003
+++ b/mm/memory.c Thu Jul 10 22:22:59 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 Wed Jul 2 21:22:38 2003
+++ b/mm/mmap.c Thu Jul 10 19:46:52 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 Wed Jul 2 18:18:55 2003
+++ b/mm/nommu.c Thu Jul 10 22:22:59 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 Wed Apr 23 03:15:53 2003
+++ b/mm/oom_kill.c Thu Jul 10 22:23:56 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 6 13:23:51 2003
+++ b/mm/readahead.c Thu Jul 10 22:22:59 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 Jun 29 23:49:04 2003
+++ b/mm/shmem.c Thu Jul 10 22:22:59 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 Wed Jul 2 21:22:38 2003
+++ b/mm/swapfile.c Thu Jul 10 22:22:59 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/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c Tue Jul 8 17:51:54 2003
+++ b/net/ipv4/igmp.c Thu Jul 10 19:32:15 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/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c Tue Jul 8 17:51:54 2003
+++ b/net/ipv4/raw.c Thu Jul 10 17:34:53 2003
@@ -383,7 +383,7 @@
* IP_HDRINCL is much more convenient.
*/
} else {
- err = -EINVAL;
+ err = -EDESTADDRREQ;
if (sk->sk_state != TCP_ESTABLISHED)
goto out;
daddr = inet->daddr;
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c Wed Jul 9 20:22:27 2003
+++ b/net/ipv4/tcp_input.c Thu Jul 10 17:16:22 2003
@@ -3694,6 +3694,13 @@
tcp_sync_mss(sk, tp->pmtu_cookie);
tcp_initialize_rcv_mss(sk);
+ /* Remember, tcp_poll() does not lock socket!
+ * Change state from SYN-SENT only after copied_seq
+ * is initialized. */
+ tp->copied_seq = tp->rcv_nxt;
+ mb();
+ tcp_set_state(sk, TCP_ESTABLISHED);
+
/* Make sure socket is routed, for correct metrics. */
tp->af_specific->rebuild_header(sk);
@@ -3713,13 +3720,6 @@
__tcp_fast_path_on(tp, tp->snd_wnd);
else
tp->pred_flags = 0;
-
- /* Remember, tcp_poll() does not lock socket!
- * Change state from SYN-SENT only after copied_seq
- * is initialized. */
- tp->copied_seq = tp->rcv_nxt;
- mb();
- tcp_set_state(sk, TCP_ESTABLISHED);
if (!sock_flag(sk, SOCK_DEAD)) {
sk->sk_state_change(sk);
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c Wed Jun 18 13:59:01 2003
+++ b/net/ipv4/udp.c Thu Jul 10 17:34:53 2003
@@ -540,7 +540,7 @@
return -EINVAL;
} else {
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ return -EDESTADDRREQ;
daddr = inet->daddr;
dport = inet->dport;
/* Open fast path for connected socket.
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c Tue Jul 8 08:22:38 2003
+++ b/net/ipv6/ip6_output.c Thu Jul 10 17:24:53 2003
@@ -1247,11 +1247,9 @@
inet->cork.length = 0;
inet->sndmsg_page = NULL;
inet->sndmsg_off = 0;
- if ((exthdrlen = rt->u.dst.header_len) != 0) {
- length += exthdrlen;
- transhdrlen += exthdrlen;
- }
- exthdrlen += opt ? opt->opt_flen : 0;
+ exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0);
+ length += exthdrlen;
+ transhdrlen += exthdrlen;
} else {
rt = np->cork.rt;
if (inet->cork.flags & IPCORK_OPT)
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c Tue Jul 8 19:09:59 2003
+++ b/net/ipv6/raw.c Thu Jul 10 17:34:53 2003
@@ -602,7 +602,7 @@
fl.oif = sin6->sin6_scope_id;
} else {
if (sk->sk_state != TCP_ESTABLISHED)
- return(-EINVAL);
+ return -EDESTADDRREQ;
proto = inet->num;
daddr = &np->daddr;
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c Mon Jun 30 08:59:07 2003
+++ b/net/ipv6/udp.c Thu Jul 10 17:34:53 2003
@@ -862,7 +862,7 @@
fl.oif = sin6->sin6_scope_id;
} else {
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ return -EDESTADDRREQ;
up->dport = inet->dport;
daddr = &np->daddr;
diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
--- a/net/irda/ircomm/ircomm_tty.c Wed Jun 11 12:32:33 2003
+++ b/net/irda/ircomm/ircomm_tty.c Wed Jul 9 04:54:24 2003
@@ -119,6 +119,7 @@
driver->driver_name = "ircomm";
driver->name = "ircomm";
+ driver->devfs_name = "ircomm";
driver->major = IRCOMM_TTY_MAJOR;
driver->minor_start = IRCOMM_TTY_MINOR;
driver->type = TTY_DRIVER_TYPE_SERIAL;
diff -Nru a/net/irda/irlap.c b/net/irda/irlap.c
--- a/net/irda/irlap.c Sun May 25 19:36:24 2003
+++ b/net/irda/irlap.c Wed Jun 4 08:21:29 2003
@@ -79,6 +79,13 @@
int __init irlap_init(void)
{
+ /* Check if the compiler did its job properly.
+ * May happen on some ARM configuration, check with Russell King. */
+ ASSERT(sizeof(struct xid_frame) == 14, ;);
+ ASSERT(sizeof(struct test_frame) == 10, ;);
+ ASSERT(sizeof(struct ua_frame) == 10, ;);
+ ASSERT(sizeof(struct snrm_frame) == 11, ;);
+
/* Allocate master array */
irlap = hashbin_new(HB_LOCK);
if (irlap == NULL) {
diff -Nru a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
--- a/net/irda/irnet/irnet_irda.c Thu Jun 19 17:28:31 2003
+++ b/net/irda/irnet/irnet_irda.c Wed Jul 9 04:50:34 2003
@@ -953,7 +953,7 @@
(void *) &irnet_server.s);
#endif
- DEXIT(IRDA_SERV_TRACE, " - self=0x%X\n", (unsigned int) &irnet_server.s);
+ DEXIT(IRDA_SERV_TRACE, " - self=0x%p\n", &irnet_server.s);
return 0;
}
diff -Nru a/net/irda/irttp.c b/net/irda/irttp.c
--- a/net/irda/irttp.c Thu Jun 19 17:28:31 2003
+++ b/net/irda/irttp.c Wed Jun 4 06:34:45 2003
@@ -1094,7 +1094,8 @@
* Check that the client has reserved enough space for
* headers
*/
- ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;);
+ ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
+ { dev_kfree_skb(tx_skb); return -1; } );
}
/* Initialize connection parameters */
@@ -1123,7 +1124,7 @@
/* SAR enabled? */
if (max_sdu_size > 0) {
ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
- return -1;);
+ { dev_kfree_skb(tx_skb); return -1; } );
/* Insert SAR parameters */
frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);