Import 2.0.122.0.12
authorLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:14 +0000 (23 15:11 -0500)
committerLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:14 +0000 (23 15:11 -0500)
50 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/ide.txt
Documentation/ioctl-number.txt
MAINTAINERS
Makefile
arch/alpha/kernel/bios32.c
arch/alpha/kernel/irq.c
drivers/block/Makefile
drivers/block/cmd640.c
drivers/block/floppy.c
drivers/block/ide.c
drivers/block/ide.h
drivers/net/arcnet.c
drivers/net/eepro.c
drivers/net/plip.c
drivers/scsi/fdomain.c
drivers/scsi/hosts.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/sound/sb_audio.c
drivers/sound/sb_midi.c
drivers/sound/soundcard.c
fs/binfmt_elf.c
fs/buffer.c
fs/proc/array.c
fs/super.c
include/asm-alpha/elf.h
include/asm-m68k/elf.h
include/linux/ax25.h
include/linux/elf.h
include/linux/mm.h
include/linux/netrom.h
include/net/ax25.h
include/net/netrom.h
mm/filemap.c
mm/page_alloc.c
net/ax25/af_ax25.c
net/ax25/ax25_in.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ipv4/ip_forward.c
net/ipv4/ip_fragment.c
net/ipv4/tcp_output.c
net/netrom/af_netrom.c
net/netrom/nr_out.c
net/netrom/nr_route.c

index 7abf7b6..1a5e2a3 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -129,6+129,15 @@ N: Ross Biro
 E: bir7@leland.Stanford.Edu
 D: Original author of the Linux networking code
 
+N: Philip Blundell
+E: pjb27@cam.ac.uk 
+E: pb@nexus.co.uk
+E: phil@tazenda.demon.co.uk
+D: Device driver hacking (especially EtherExpress16/3C505 net cards)
+D: Some Linux/ARM stuff
+S: Trinity College
+S: Cambridge, UK. CB2 1TQ
+
 N: Thomas Bogendoerfer
 E: tsbogend@bigbug.franken.de
 D: Lance32 driver
@@ -545,6+554,13 @@ S: Muehlenweg 19
 S: 34266 Niestetal
 S: Germany
 
+N: Richard Henderson
+E: rth@tamu.edu
+D: Alpha/ELF, gcc, binutils, and glibc
+S: 304 E. North Ave.
+S: Bryan, TX  77801-3431
+S: USA
+
 N: Sebastian Hetze
 E: she@lunetix.de
 D: German Linux Documentation,
@@ -568,6+584,14 @@ S: 46030 Manekin Plaza, Suite 160
 S: Dulles, Virginia 20166
 S: USA
 
+N: Kenji Tsutomu Hollis
+E: khollis@bitgate.com
+W: http://www.nurk.org/
+D: Berkshire PC Watchdog Driver
+S: PO Box 15
+S: Grants Pass, OR 97526
+S: USA
+
 N: Nick Holloway
 E: Nick.Holloway@alfie.demon.co.uk
 E: Nick.Holloway@parallax.co.uk
index 08e4aed..be04651 100644 (file)
@@ -26,11+26,11 @@ http://slug.ctv.es/~alfredo/Cambios.html.
 valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
 http://www.datanet.hu/generations/linux/newkernel.html.
 
-   For people who prefer Japanse (thanks to Mitsuhiro Kojima): Kono
-bunshou no nihongo ban ha
+   For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
+bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
-Last updated: July 29, 1996.
+Last updated: August 6, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -135,6+135,18 @@ there's an unofficial libc-4.7.6 release out to which you can upgrade
 to fix this problem.  Libc is available from
 ftp://sunsite.unc.edu/pub/Linux/GCC/.
 
+GCC Signal 11 error
+===================
+
+   Many people have been reporting messages like the following,
+especially when compiling a new kernel:
+
+   `gcc:  Internal compiler error:  program cc1 got fatal signal 11'.
+
+   This is NOT a kernel bug.  Rather, these messages are generally
+caused by hardware problems.  See http://www.bitwizard.nl/sig11/ for
+the sig11 FAQ.
+
 Procps utilities
 ================
 
@@ -259,7+271,11 @@ the following as root:
 ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz.  If you
 upgrade to this release read the `README' file contained into the
 package to get some important information about the `tgetent' function
-changes!
+changes!  Note that there is now a fixed version at
+ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.fix.  If some of your
+apps complain that termcap entries are too long and you don't need some
+of the more esoteric terms in the standard 2.0.8 termcap, just download
+termcap-2.0.8.fix and move it to /etc/termcap.
 
    Also, the console driver is now responsible for keeping track of
 correspondence between character codes and glyph bitmaps.  If you
@@ -271,7+287,7 @@ Hdparm
 
    Hdparm has been upgraded to take advantage of the latest features of
 the kernel drivers.  The latest non-beta version can be found at
-ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.0.tar.gz.
+ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.1.tar.gz.
 
 IP Accounting
 =============
@@ -285,7+301,7 @@ direction (either incoming or outgoing).
    There also exists a possibility to match on device names and/or
 device addresses, so that only packets coming in/going out via that
 device (network interface) match with a rule.  You'll need to get
-ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to
+ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to
 use this.
 
 IP Firewalls
@@ -298,7+314,7 @@ exists a possibility to match on device names and/or device addresses,
 so that only packets coming in/going out via that device (network
 interface) match with a rule.  This is especially useful to prevent
 spoofing.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
 
 IP Masquerading
 ===============
@@ -307,7+323,7 @@ IP Masquerading
 always need to load separate modules (ip_masq_ftp.o and/or
 ip_masq_irc.o) if you are going to use FTP or IRC in combination with
 masquerading.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
 
 ISDN support
 ============
@@ -473,9+489,9 @@ Cyclades Serial Driver
 ======================
 
    The Cyclades driver has been changed so that the minor numbers start
-at 0 instead of 32 (ie: ttyC0 should be major 19, minor 0 in the 2.0.x
-kernels while it used to be major 19, minor 32 in the older kernels).
-You can use mknod to manually fix this or use a newer version of MAKEDEV.
+at 0 instead of 32 (for example, ttyC0 should be major 19, minor 0 for
+2.0.x kernels; in older kernels, it would have been major 19, minor
+32).  Use mknod or a sufficiently new version of MAKEDEV to fix this.
 
 NCR 53c810 SCSI Driver
 ======================
@@ -492,8+508,9 @@ Perl
 
    While we're on the subject, changes made for the 2.0.x series cause
 the connect() Perl (both 4 and 5) call to time out while connecting to
-remote systems.  If you need the connect call for your program, use C
-instead of Perl.
+remote systems.  The problem is not actually in the connect() call;
+rather, the optional bind() call usually used with connect() causes the
+problem.  Remove the bind() call and your Perl scripts should connect.
 
    Also, Perl scripts using the readdir call now misbehave if you're
 using an old version of Perl, due to changes in libc.  Upgrade to a
@@ -508,7+525,10 @@ when present at the end of a line, try setting an appropriate value
 (many have reported success with "latin1", for example) for the
 environmental variable LESSCHARSET.  Another, and probably better,
 solution is to edit the file /usr/lib/man.config and change all
-`-Tlatin1' options to `-Tascii'.
+`-Tlatin1' options to `-Tascii'.  An alternate solution, for those of
+you who can't reformat your man files in .../cat* directories is to
+edit /usr/lib/man.config, setting the PAGER to `PAGER
+(LESSCHARSET=latin1;export LESSCHARSET;/usr/bin/less -is'.
 
 E2fsprogs
 =========
index 8042c52..0a059be 100644 (file)
@@ -3483,7+3483,7 @@ CONFIG_PCWATCHDOG
   it resets your computer after a certain amount of time.  This driver is
   like the WDT501 driver but for different hardware. The PC watchdog cards
   can be ordered from http://www.berkprod.com. Some example rc.local files
-  are available from ftp.bitgame.com.
+  are available from ftp.bitgate.com.
 
 Enhanced Real Time Clock Support
 CONFIG_RTC
index 6f305c0..2af4dd7 100644 (file)
@@ -257,7+257,7 @@ Summary of ide driver parameters for kernel "command line":
                                older/odd IDE drives.
 
  "idebus=xx"           : inform IDE driver of VESA/PCI bus speed in Mhz,
-                               where "xx" is between 25 and 66 inclusive,
+                               where "xx" is between 20 and 66 inclusive,
                                used when tuning chipset PIO modes.
                                For PCI bus, 25 is correct for a P75 system,
                                30 is correct for P90,P120,P180 systems,
index 7587606..771f441 100644 (file)
@@ -1,5+1,5 @@
 Ioctl Numbers
-12 Jun 1996
+6 Aug 1996
 Michael Chastain
 <mec@duracef.shout.net>
 
@@ -50,7+50,8 @@ Following the convention is good because:
 (5) When following the convention, the driver code can use generic
     code to call verify_area to validate parameters.
 
-This table is current to Linux pre2.0.9.
+This table lists ioctls visible from user land for Linux/i386.  It is
+current to Linux 2.0.11.
 
 Code   Seq#    Include File            Comments
 ========================================================
@@ -83,6+84,7 @@ Code  Seq#    Include File            Comments
 'T'    all     linux/soundcard.h       conflict!
 'T'    all     asm-i386/ioctls.h       conflict!
 'V'    all     linux/vt.h
+'W'    00-1F   linux/pcwd.h
 'Y'    all     linux/cyclades.h
 'Z'    all     linux/scc.h             version 2.2 of z8530drv
 'a'    all     various, see http://lrcwww.epfl.ch/linux-atm/magic.html
index a21a996..89d2acb 100644 (file)
@@ -86,7+86,7 @@ M     gpg109@rsphy1.anu.edu.au
 L:     linux-net@vger.rutgers.edu
 S:     Maintained
 
-ETHEREXPRESS NETWORK DRIVER
+ETHEREXPRESS-16 NETWORK DRIVER
 P:     Philip Blundell
 M:     pjb27@cam.ac.uk
 L:     linux-net@vger.rutgers.edu
index 66fdfc9..a5f1d72 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6+1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 11
+SUBLEVEL = 12
 
 ARCH = i386
 
index c9cb96f..1e0a505 100644 (file)
@@ -993,6+993,7 @@ static inline void sio_fixup(void)
                { 0,  0,  2,  1,  0}, /* idsel 11 KN25_PCI_SLOT0 */
                { 1,  1,  0,  2,  1}, /* idsel 12 KN25_PCI_SLOT1 */
                { 2,  2,  1,  0,  2}, /* idsel 13 KN25_PCI_SLOT2 */
+               { 0,  0,  0,  0,  0}, /* idsel 14 AS255 TULIP */
 #endif
        };
        /*
@@ -1005,7+1006,21 @@ static inline void sio_fixup(void)
         * This probably ought to be configurable via MILO.  For
         * example, sound boards seem to like using IRQ 9.
         */
+#ifdef CONFIG_ALPHA_NONAME
+       /*
+        * For UDB, the only available PCI slot must not map to IRQ 9,
+        *  since that's the builtin MSS sound chip. That PCI slot
+        *  will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+        *  instead.
+        *
+        * Unfortunately we have to do this for NONAME as well, since
+        *  they are co-indicated when the platform type "Noname" is
+        *  selected... :-(
+        */
+       const unsigned int route_tab = 0x0b0a0f09;
+#else /* CONFIG_ALPHA_NONAME */
        const unsigned int route_tab = 0x0b0a090f;
+#endif /* CONFIG_ALPHA_NONAME */
        unsigned int level_bits;
        unsigned char pin, slot;
        int pirq;
@@ -1093,8+1108,13 @@ static inline void sio_fixup(void)
         * Now, make all PCI interrupts level sensitive.  Notice:
         * these registers must be accessed byte-wise.  inw()/outw()
         * don't work.
+        *
+        * Make sure to turn off any level bits set for IRQs 9,10,11,15,
+        *  so that the only bits getting set are for devices actually found.
+        * Note that we do preserve the remainder of the bits, which we hope
+        *  will be set correctly by ARC/SRM.
         */
-       level_bits |= (inb(0x4d0) | (inb(0x4d1) << 8));
+       level_bits |= ((inb(0x4d0) | (inb(0x4d1) << 8)) & 0x71ff);
        outb((level_bits >> 0) & 0xff, 0x4d0);
        outb((level_bits >> 8) & 0xff, 0x4d1);
        enable_ide(0x26e);
index 35c19c7..58c112c 100644 (file)
@@ -32,6+32,10 @@ extern void timer_interrupt(struct pt_regs * regs);
 #  error Unable to handle more than 64 irq levels.
 #endif
 
+/* Reserved interrupts.  These must NEVER be requested by any driver!
+ */
+#define        IS_RESERVED_IRQ(irq)    ((irq)==2)      /* IRQ 2 used by hw cascade */
+
 /*
  * Shadow-copy of masked interrupts.
  *  The bits are used as follows:
@@ -185,6+189,8 @@ int request_irq(unsigned int irq,
 
        if (irq >= NR_IRQS)
                return -EINVAL;
+       if (IS_RESERVED_IRQ(irq))
+               return -EINVAL;
        if (!handler)
                return -EINVAL;
        p = irq_action + irq;
@@ -241,6+247,10 @@ void free_irq(unsigned int irq, void *dev_id)
                printk("Trying to free IRQ%d\n",irq);
                return;
        }
+       if (IS_RESERVED_IRQ(irq)) {
+               printk("Trying to free reserved IRQ %d\n", irq);
+               return;
+       }
        for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
                if (action->dev_id != dev_id)
                        continue;
index 6651498..2ebff1c 100644 (file)
 #
 
 #
-# Note : at this point, these files are compiled on all systems. 
+# Note : at this point, these files are compiled on all systems.
 # In the future, some of these should be built conditionally.
 #
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o genhd.o 
+L_OBJS   := ll_rw_blk.o genhd.o
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 LX_OBJS :=
index 15eaaed..6d8581c 100644 (file)
@@ -1,5+1,5 @@
 /*
- *  linux/drivers/block/cmd640.c       Version 0.97  Aug  4, 1996
+ *  linux/drivers/block/cmd640.c       Version 0.99  Aug  6, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
  *  Version 0.96       prevent use of io_32bit when prefetch is off
  *  Version 0.97       fix VLB secondary interface for sjd@slip.net
  *                     other minor tune-ups:  0.96 was very good.
+ *  Version 0.98       ignore PCI version when disabled by BIOS
+ *  Version 0.99       display setup/active/recovery clocks with PIO mode
  */
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
@@ -119,6+121,7 @@ int cmd640_vlb = 0;
 #define VID            0x00
 #define DID            0x02
 #define PCMD           0x04
+#define   PCMD_ENA     0x01
 #define PSTTS          0x06
 #define REVID          0x08
 #define PROGIF         0x09
@@ -288,6+291,10 @@ static int match_pci_cmd640_device (void)
                if (get_cmd640_reg(i) != ven_dev[i])
                        return 0;
        }
+       if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
+               printk("ide: cmd640 on PCI disabled by BIOS\n");
+               return 0;
+       }
        return 1; /* success */
 }
 
@@ -458,6+465,24 @@ static void set_prefetch_mode (unsigned int index, int mode)
 }
 
 /*
+ * Dump out current drive clocks settings
+ */
+static void display_clocks (unsigned int index)
+{
+       byte active_count, recovery_count;
+
+       active_count = active_counts[index];
+       if (active_count == 1)
+               ++active_count;
+       recovery_count = recovery_counts[index];
+       if (active_count > 3 && recovery_count == 1)
+               ++recovery_count;
+       if (cmd640_chip_version > 1)
+               recovery_count += 1;  /* cmd640b uses (count + 1)*/
+       printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
+}
+
+/*
  * Pack active and recovery counts into single byte representation
  * used by controller
  */
@@ -564,7+589,7 @@ static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cyc
        active_time = ide_pio_timings[pio_mode].active_time;
        recovery_time = cycle_time - (setup_time + active_time);
        clock_time = 1000 / bus_speed;
-       cycle_count = (cycle_time + clock_time - 1) / clock_time; 
+       cycle_count = (cycle_time + clock_time - 1) / clock_time;
 
        setup_count = (setup_time + clock_time - 1) / clock_time;
 
@@ -635,12+660,13 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted)
        (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
        cmd640_set_mode (index, d.pio_mode, d.cycle_time);
 
-       printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s\n",
+       printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s",
                drive->name,
                d.pio_mode,
                d.cycle_time,
                d.use_iordy ? "w" : "wo",
                d.overridden ? " (overriding vendor mode)" : "");
+       display_clocks(index);
 }
 
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
@@ -784,8+810,9 @@ int ide_probe_for_cmd640x (void)
                         */
                        retrieve_drive_counts (index);
                        check_prefetch (index);
-                       printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
+                       printk("cmd640: drive%d timings/prefetch(%s) preserved",
                                index, drive->no_io_32bit ? "off" : "on");
+                       display_clocks(index);
                }
 #else
                /*
index 54ae268..6ea0578 100644 (file)
@@ -1685,15+1685,9 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
        }
        if (handler) {
-               if(intr_count >= 2)
-                       {
-                               /* expected interrupt */
-                               floppy_tq.routine = (void *)(void *) handler;
-                               queue_task_irq(&floppy_tq, &tq_immediate);
-                               mark_bh(IMMEDIATE_BH);
-                       }
-               else
-                       handler();
+               /* expected interrupt */
+               floppy_tq.routine = (void *)(void *) handler;
+               queue_task_irq(&floppy_tq, &tq_timer);
        } else
                FDCS->reset = 1;
        is_alive("normal interrupt end");
@@ -1931,8+1925,7 @@ static int wait_til_done(void (*handler)(void), int interruptible)
        unsigned long flags;
 
        floppy_tq.routine = (void *)(void *) handler;
-       queue_task(&floppy_tq, &tq_immediate);
-       mark_bh(IMMEDIATE_BH);
+       queue_task(&floppy_tq, &tq_timer);
        INT_OFF;
        while(command_status < 2 && NO_SIGNAL){
                is_alive("wait_til_done");
@@ -2740,8+2733,7 @@ static void redo_fd_request(void)
                if (TESTF(FD_NEED_TWADDLE))
                        twaddle();
                floppy_tq.routine = (void *)(void *) floppy_start;
-               queue_task(&floppy_tq, &tq_immediate);
-               mark_bh(IMMEDIATE_BH);
+               queue_task(&floppy_tq, &tq_timer);
 #ifdef DEBUGT
                debugt("queue fd request");
 #endif
@@ -2762,8+2754,7 @@ static struct tq_struct request_tq =
 static void process_fd_request(void)
 {
        cont = &rw_cont;
-       queue_task(&request_tq, &tq_immediate);
-       mark_bh(IMMEDIATE_BH);
+       queue_task(&request_tq, &tq_timer);
 }
 
 static void do_fd_request(void)
index 8619e77..a09dd4f 100644 (file)
  *                     fix missing restore_flags() in ide_ioctl
  *                     prevent use of io_32bit on cmd640 with no prefetch
  * Version 5.49                fix minor quirks in probing routines
+ * Version 5.50                allow values as small as 20 for idebus=
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -2807,7+2808,7 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals
  *                             older/odd IDE drives.
  *
  * "idebus=xx"         : inform IDE driver of VESA/PCI bus speed in Mhz,
- *                             where "xx" is between 25 and 66 inclusive,
+ *                             where "xx" is between 20 and 66 inclusive,
  *                             used when tuning chipset PIO modes.
  *                             For PCI bus, 25 is correct for a P75 system,
  *                             30 is correct for P90,P120,P180 systems,
@@ -2912,10+2913,10 @@ void ide_setup (char *s)
        if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
                if (match_parm(&s[6], NULL, vals, 1) != 1)
                        goto bad_option;
-               if (vals[0] >= 25 && vals[0] <= 66)
+               if (vals[0] >= 20 && vals[0] <= 66)
                        idebus_parameter = vals[0];
                else
-                       printk(" -- BAD BUS SPEED! Expected value from 25 to 66");
+                       printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
                goto done;
        }
        /*
index 0e0509c..772f2c6 100644 (file)
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD640
-#if 1
+#if 0  /* change to 1 when debugging cmd640 problems */
 void cmd640_dump_regs (void);
 #define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
 #endif
index 9db0a04..626dff2 100644 (file)
          
        **********************
        
+       v2.55 (96/08/05)
+         - A couple more messages moved to D_EXTRA.
+         - SLOW_XMIT_COPY off by default.
+         - Some tiny changes.
+       
        v2.54 (96/07/05)
          - Under some situations, Stage 5 autoprobe was a little bit too
            picky about the TXACK flag.
          
        TO DO: (semi-prioritized)
        
-         - Smarter recovery from RECON-during-transmit conditions.
+         - Support "arpless" mode like NetBSD does, and as recommended
+           by the (obsoleted) RFC1051.
+         - Smarter recovery from RECON-during-transmit conditions. (ie.
+           retransmit immediately)
          - Make arcnetE_send_packet use arcnet_prepare_tx for loading the
            packet into ARCnet memory.
-        - Probe for multiple devices in one shot (trying to decide whether
-          to do it the "ugly" way or not).
-         - Add support for the new 1.3.x IP header cache features.
-        - Debug level should be changed with a system call, not a hack to
-          the "metric" flag.
+         - Some cards have shared memory with 4k mirrors instead of just 2k,
+           so we (uneventfully) find the "wrong" shmem when probing.
+         - Probe for multiple devices in one shot (trying to decide whether
+           to do it the "ugly" way or not).
+         - Add support for the new 1.3.x IP header cache, and other features.
+         - Debug level should be changed with a system call, not a hack to
+           the "metric" flag.
          - What about cards with shared memory that can be "turned off?"
            (or that have none at all, like the SMC PC500longboard)
          - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
 */
 
 static const char *version =
- "arcnet.c: v2.54 96/07/05 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.55 96/08/05 Avery Pennarun <apenwarr@foxnet.net>\n";
 
  
 
@@ -244,11+254,11 @@ static const char *version =
  * defines; ARCnet probably is not the only driver that can screw up an
  * ftape DMA transfer.
  *
- * Turn this off if you don't have timing-sensitive DMA (ie. a tape drive)
- * and would like the little bit of speed back.  It's on by default because
- * - trust me - it's very difficult to figure out that you need it!
+ * Turn this on if you have timing-sensitive DMA (ie. a tape drive) and
+ * would like to sacrifice a little bit of network speed to reduce tape
+ * write retries or some related problem.
  */
-#define SLOW_XMIT_COPY
+#undef SLOW_XMIT_COPY
 
 /* The card sends the reconfiguration signal when it loses the connection to
  * the rest of its network. It is a 'Hello, is anybody there?' cry.  This
@@ -2310,7+2320,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                        
                if (in->skb)    /* already assembling one! */
                {
-                       BUGMSG(D_NORMAL,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+                       BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
                                in->sequence,arcsoft->split_flag,
                                arcsoft->sequence);
                        kfree_skb(in->skb,FREE_WRITE);
@@ -2407,7+2417,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
 
                if (in->skb && in->sequence!=arcsoft->sequence)
                {
-                       BUGMSG(D_NORMAL,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+                       BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
                                saddr,in->sequence,arcsoft->sequence,
                                arcsoft->split_flag);
                        kfree_skb(in->skb,FREE_WRITE);
@@ -2423,7+2433,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                                arcsoft->split_flag);
                        if (in->skb)    /* already assembling one! */
                        {
-                               BUGMSG(D_NORMAL,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+                               BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
                                        in->sequence,arcsoft->split_flag,
                                        arcsoft->sequence);
                                lp->stats.rx_errors++;
@@ -2437,7+2447,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                        
                        if (in->numpackets>16)
                        {
-                               BUGMSG(D_NORMAL,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+                               BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
                                        arcsoft->split_flag);
                                lp->stats.rx_errors++;
                                lp->stats.rx_length_errors++;
@@ -2477,7+2487,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                         */                     
                        if (!in->skb)
                        {
-                               BUGMSG(D_NORMAL,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
+                               BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
                                        arcsoft->split_flag,arcsoft->sequence);
                                lp->stats.rx_errors++;
                                lp->stats.rx_missed_errors++;
@@ -2490,7+2500,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                                /* harmless duplicate? ignore. */
                                if (packetnum<=in->lastpacket-1)
                                {
-                                       BUGMSG(D_NORMAL,"duplicate splitpacket ignored! (splitflag=%d)\n",
+                                       BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
                                                arcsoft->split_flag);
                                        lp->stats.rx_errors++;
                                        lp->stats.rx_frame_errors++;
@@ -2498,7+2508,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                                }
                                
                                /* "bad" duplicate, kill reassembly */
-                               BUGMSG(D_NORMAL,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",       
+                               BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
                                        in->sequence,arcsoft->split_flag,
                                        arcsoft->sequence);
                                kfree_skb(in->skb,FREE_WRITE);
index 01afc10..582b7cb 100644 (file)
        according to the terms of the GNU Public License,
        incorporated herein by reference.
 
-       The author may be reached at bao@saigon.async.com 
+       The author may be reached at bao.ha@srs.gov 
        or 418 Hastings Place, Martinez, GA 30907.
 
        Things remaining to do:
        Better record keeping of errors.
        Eliminate transmit interrupt to reduce overhead.
        Implement "concurrent processing". I won't be doing it!
-       Allow changes to the partition of the transmit and receive
-       buffers, currently the ratio is 3:1 of receive to transmit
-       buffer ratio.  
 
        Bugs:
 
 
        Versions:
 
+       0.09    Fixed a race condition in the transmit algorithm,
+               which causes crashes under heavy load with fast
+               pentium computers.  The performance should also
+               improve a bit.  The size of RX buffer, and hence
+               TX buffer, can also be changed via lilo or insmod.
+               (BCH, 7/31/96)
+
        0.08    Implement 32-bit I/O for the 82595TX and 82595FX
                based lan cards.  Disable full-duplex mode if TPE
                is not used.  (BCH, 4/8/96)
 */
 
 static const char *version =
-       "eepro.c: v0.08 4/8/96 Bao C. Ha (bao.ha@srs.gov)\n";
+       "eepro.c: v0.09 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
 
 #include <linux/module.h>
 
@@ -110,7+114,7 @@ static unsigned int eepro_portlist[] =
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
-#define NET_DEBUG 2
+#define NET_DEBUG 3
 #endif
 static unsigned int net_debug = NET_DEBUG;
 
@@ -180,15+184,26 @@ single packet.  In other systems with faster computers and more congested
 network traffics, the ring linked list should improve performance by
 allowing up to 8K worth of packets to be queued.
 
+The sizes of the receive and transmit buffers can now be changed via lilo 
+or insmod.  Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
+where rx-buffer is in KB unit.  Modules uses the parameter mem which is
+also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."  
+The receive buffer has to be more than 3K or less than 29K.  Otherwise,
+it is reset to the default of 24K, and, hence, 8K for the trasnmit
+buffer (transmit-buffer = 32K - receive-buffer).
+
 */
 #define        RAM_SIZE        0x8000
 #define        RCV_HEADER      8
-#define        RCV_RAM         0x6000  /* 24KB for RCV buffer */
-#define        RCV_LOWER_LIMIT 0x00    /* 0x0000 */
-#define        RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8)    /* 0x5ffe */
-#define        XMT_RAM         (RAM_SIZE - RCV_RAM)    /* 8KB for XMT buffer */
-#define        XMT_LOWER_LIMIT (RCV_RAM >> 8)  /* 0x6000 */
-#define        XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8)   /* 0x7ffe */
+#define RCV_RAM         0x6000  /* 24KB default for RCV buffer */
+#define RCV_LOWER_LIMIT 0x00    /* 0x0000 */
+/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */    /* 0x5ffe */
+#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)   
+/* #define XMT_RAM         (RAM_SIZE - RCV_RAM) */    /* 8KB for XMT buffer */
+#define XMT_RAM         (RAM_SIZE - (rcv_ram))    /* 8KB for XMT buffer */
+/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */  /* 0x6000 */
+#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) 
+#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8)   /* 0x7ffe */
 #define        XMT_HEADER      8
 
 #define        RCV_DONE        0x0008
@@ -368,6+383,16 @@ int eepro_probe1(struct device *dev, short ioaddr)
                                dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
                                printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
                        }
+                       
+                       if ((dev->mem_end & 0x3f) < 3 ||        /* RX buffer must be more than 3K */
+                               (dev->mem_end & 0x3f) > 29)     /* and less than 29K */
+                               dev->mem_end = RCV_RAM;         /* or it will be set to 24K */
+                       else dev->mem_end = 1024*dev->mem_end;  /* Maybe I should shift << 10 */
+
+                       /* From now on, dev->mem_end contains the actual size of rx buffer */
+                       
+                       if (net_debug > 3)
+                               printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
                                
                        outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
                        id = inb(ioaddr + REG3);
@@ -401,8+426,8 @@ int eepro_probe1(struct device *dev, short ioaddr)
                        }
                        else printk(", %s.\n", ifmap[dev->if_port]);
                        
-                       if ((dev->mem_start & 0xf) > 0)
-                               net_debug = dev->mem_start & 7;
+                       if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
+                               net_debug = dev->mem_start & 7; /* still useful or not */
 
                        if (net_debug > 3) {
                                i = read_eeprom(ioaddr, 5);
@@ -516,7+541,7 @@ static int
 eepro_open(struct device *dev)
 {
        unsigned short temp_reg, old8, old9;
-       int i, ioaddr = dev->base_addr;
+       int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
        if (net_debug > 3)
@@ -654,6+679,7 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
+       int rcv_ram = dev->mem_end;
 
        if (net_debug > 5)
                printk("eepro: entering eepro_send_packet routine.\n");
@@ -662,12+688,13 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev)
                /* If we get here, some higher level has decided we are broken.
                   There should really be a "kick me" function call instead. */
                int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 5)
+               if (tickssofar < 40)
                        return 1;
                if (net_debug > 1)
                        printk("%s: transmit timed out, %s?\n", dev->name,
                                   "network cable problem");
                lp->stats.tx_errors++;
+
                /* Try to restart the adaptor. */
                outb(SEL_RESET_CMD, ioaddr); 
                /* We are supposed to wait for 2 us after a SEL_RESET */
@@ -675,7+702,7 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev)
                SLOW_DOWN_IO;
 
                /* Do I also need to flush the transmit buffers here? YES? */
-               lp->tx_start = lp->tx_end = RCV_RAM
+               lp->tx_start = lp->tx_end = rcv_ram
                lp->tx_last = 0;
        
                dev->tbusy=0;
@@ -722,7+749,7 @@ static void
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        struct device *dev = (struct device *)(irq2dev_map[irq]);
-       int ioaddr, status, boguscount = 0;
+       int ioaddr, status, boguscount = 20;
 
        if (net_debug > 5)
                printk("eepro: entering eepro_interrupt routine.\n");
@@ -737,7+764,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
        do { 
                status = inb(ioaddr + STATUS_REG);
-
+               
                if (status & RX_INT) {
                        if (net_debug > 4)
                                printk("eepro: packet received interrupt.\n");
@@ -748,6+775,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        /* Get the received packets */
                        eepro_rx(dev);
                }
+
                else if (status & TX_INT) {
                        if (net_debug > 4)
                                printk("eepro: packet transmit interrupt.\n");
@@ -757,10+785,9 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
                        /* Process the status of transmitted packets */
                        eepro_transmit_interrupt(dev);
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
-               }               
-       } while ((++boguscount < 10) && (status & 0x06));
+               }
+       
+       } while ((boguscount-- > 0) && (status & 0x06));
 
        dev->interrupt = 0;
        if (net_debug > 5)
@@ -774,6+801,7 @@ eepro_close(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        int ioaddr = dev->base_addr;
+       int rcv_ram = dev->mem_end;
        short temp_reg;
 
        dev->tbusy = 1;
@@ -789,7+817,7 @@ eepro_close(struct device *dev)
 
        /* Flush the Tx and disable Rx. */
        outb(STOP_RCV_CMD, ioaddr); 
-       lp->tx_start = lp->tx_end = RCV_RAM ;
+       lp->tx_start = lp->tx_end = rcv_ram ;
        lp->tx_last = 0;  
 
        /* Mask all the interrupts. */
@@ -912,7+940,9 @@ set_multicast_list(struct device *dev)
                        outw(status | CHAIN_BIT, ioaddr + IO_PORT);
                        lp->tx_end = i ;
                }
-               else lp->tx_start = lp->tx_end = i ;
+               else {
+                       lp->tx_start = lp->tx_end = i ;
+               }
 
                /* Acknowledge that the MC setup is done */
                do { /* We should be doing this in the eepro_interrupt()! */
@@ -993,13+1023,25 @@ hardware_send_packet(struct device *dev, void *buf, short length)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
-       unsigned status, tx_available, last, end, boguscount = 10;
+       int rcv_ram = dev->mem_end;
+       unsigned status, tx_available, last, end, boguscount = 100;
 
        if (net_debug > 5)
                printk("eepro: entering hardware_send_packet routine.\n");
 
        while (boguscount-- > 0) {
 
+               /* Disable RX and TX interrupts.  Necessary to avoid
+               corruption of the HOST_ADDRESS_REG by interrupt
+               service routines. */
+               outb(ALL_MASK, ioaddr + INT_MASK_REG);
+
+               if (dev->interrupt == 1) {  
+                       /* Enable RX and TX interrupts */
+                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+                       continue;
+               }
+
                /* determine how much of the transmit buffer space is available */
                if (lp->tx_end > lp->tx_start)
                        tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
@@ -1007,14+1049,15 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        tx_available = lp->tx_start - lp->tx_end;
                else tx_available = XMT_RAM;
 
-               /* Disable RX and TX interrupts.  Necessary to avoid
-                  corruption of the HOST_ADDRESS_REG by interrupt
-                  service routines. */
-               outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
                if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) 
                        >= tx_available)   /* No space available ??? */
+                       {
+                       eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
+
+                       /* Enable RX and TX interrupts */
+                       outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
                        continue;
+               }
 
                last = lp->tx_end;
                end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
@@ -1023,10+1066,10 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        if ((RAM_SIZE - last) <= XMT_HEADER) {  
                        /* Arrrr!!!, must keep the xmt header together,
                          several days were lost to chase this one down. */
-                               last = RCV_RAM;
+                               last = rcv_ram;
                                end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
                        }       
-                       else end = RCV_RAM + (end - RAM_SIZE);
+                       else end = rcv_ram + (end - RAM_SIZE);
                }
 
                outw(last, ioaddr + HOST_ADDRESS_REG);
@@ -1044,9+1087,17 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
                }
 
-               if (lp->tx_start != lp->tx_end) { 
+               /* A dummy read to flush the DRAM write pipeline */
+               status = inw(ioaddr + IO_PORT); 
+
+               if (lp->tx_start == lp->tx_end) {       
+                       outw(last, ioaddr + XMT_BAR);
+                       outb(XMT_CMD, ioaddr);
+                       lp->tx_start = last;   /* I don't like to change tx_start here */
+               }
+               else {
                        /* update the next address and the chain bit in the 
-                          last packet */
+                       last packet */
                        if (lp->tx_end != last) {
                                outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
                                outw(last, ioaddr + IO_PORT);
@@ -1054,33+1105,26 @@ hardware_send_packet(struct device *dev, void *buf, short length)
                        outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
                        status = inw(ioaddr + IO_PORT);
                        outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-               }
 
-               /* A dummy read to flush the DRAM write pipeline */
-               status = inw(ioaddr + IO_PORT); 
-
-               /* Enable RX and TX interrupts */
-               outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
-       
-               if (lp->tx_start == lp->tx_end) {
-                       outw(last, ioaddr + XMT_BAR);
-                       outb(XMT_CMD, ioaddr);
-                       lp->tx_start = last;   /* I don't like to change tx_start here */
+                       /* Continue the transmit command */
+                       outb(RESUME_XMT_CMD, ioaddr);
                }
-               else    outb(RESUME_XMT_CMD, ioaddr);
 
                lp->tx_last = last;
                lp->tx_end = end;
 
+               /* Enable RX and TX interrupts */
+               outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+       
                if (dev->tbusy) {
                        dev->tbusy = 0;
-                       mark_bh(NET_BH);
                }
 
                if (net_debug > 5)
                        printk("eepro: exiting hardware_send_packet routine.\n");
                return;
        }
+
        dev->tbusy = 1;
        if (net_debug > 5)
                printk("eepro: exiting hardware_send_packet routine.\n");
@@ -1090,7+1134,7 @@ static void
 eepro_rx(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
-       short ioaddr = dev->base_addr;
+       short ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
        short boguscount = 20;
        short rcv_car = lp->rx_start;
        unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
@@ -1171,7+1215,7 @@ eepro_transmit_interrupt(struct device *dev)
 {
        struct eepro_local *lp = (struct eepro_local *)dev->priv;
        short ioaddr = dev->base_addr;
-       short boguscount = 10; 
+       short boguscount = 20; 
        short xmt_status;
 
        while (lp->tx_start != lp->tx_end) { 
@@ -1179,16+1223,15 @@ eepro_transmit_interrupt(struct device *dev)
                outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
                xmt_status = inw(ioaddr+IO_PORT);
                if ((xmt_status & TX_DONE_BIT) == 0) break;
+
                xmt_status = inw(ioaddr+IO_PORT);
                lp->tx_start = inw(ioaddr+IO_PORT);
-       
-               if (dev->tbusy) {
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
-               }
+
+               dev->tbusy = 0;
+               mark_bh(NET_BH);
 
                if (xmt_status & 0x2000)
-                       lp->stats.tx_packets++;
+                       lp->stats.tx_packets++; 
                else {
                        lp->stats.tx_errors++;
                        if (xmt_status & 0x0400)
@@ -1196,10+1239,12 @@ eepro_transmit_interrupt(struct device *dev)
                        printk("%s: XMT status = %#x\n",
                                dev->name, xmt_status);
                }
-               if (xmt_status & 0x000f)
+               if (xmt_status & 0x000f) {
                        lp->stats.collisions += (xmt_status & 0x000f);
-               if ((xmt_status & 0x0040) == 0x0)
+               }
+               if ((xmt_status & 0x0040) == 0x0) {
                        lp->stats.tx_heartbeat_errors++;
+               }
 
                if (--boguscount == 0)
                        break;  
@@ -1216,6+1261,7 @@ static struct device dev_eepro = {
 
 static int io = 0x200;
 static int irq = 0;
+static int mem = (RCV_RAM/1024);       /* Size of the rx buffer in KB */
 
 int
 init_module(void)
@@ -1224,6+1270,7 @@ init_module(void)
                printk("eepro: You should not use auto-probing with insmod!\n");
        dev_eepro.base_addr = io;
        dev_eepro.irq       = irq;
+       dev_eepro.mem_end   = mem;
 
        if (register_netdev(&dev_eepro) != 0)
                return -EIO;
index cd91ea1..9fbf8cf 100644 (file)
@@ -873,9+873,9 @@ plip_rebuild_header(void *buff, struct device *dev, unsigned long dst,
                return 0;
        }
 
-       for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+       for (i=0; i < ETH_ALEN - sizeof(u32); i++)
                eth->h_dest[i] = 0xfc;
-       memcpy(&(eth->h_dest[i]), &dst, sizeof(unsigned long));
+       *(u32 *)(eth->h_dest+i) = dst;
        return 0;
 }
 
@@ -964,9+964,9 @@ plip_open(struct device *dev)
        nl->is_deferred = 0;
 
        /* Fill in the MAC-level header. */
-       for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+       for (i=0; i < ETH_ALEN - sizeof(u32); i++)
                dev->dev_addr[i] = 0xfc;
-       memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(unsigned long));
+       *(u32 *)(dev->dev_addr+i) = dev->pa_addr;
 
        dev->interrupt = 0;
        dev->start = 1;
index ab68e27..1f4f245 100644 (file)
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Thu Apr  4 20:44:47 1996 by r.faith@ieee.org
+ * Revised: Thu Aug  8 14:58:51 1996 by r.faith@ieee.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
  *
- * $Id: fdomain.c,v 5.41 1996/04/05 04:22:25 root Exp $
+ * $Id: fdomain.c,v 5.44 1996/08/08 18:58:53 root Exp $
 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  1.3.34      5.39        12 Oct 1995  V3.60 BIOS; /proc
  1.3.72      5.39         8 Feb 1996  Adaptec AHA-2920 board
  1.3.85      5.41         4 Apr 1996
+ 2.0.12      5.44         8 Aug 1996  Use ID 7 for all PCI cards
 
  
 
@@ -275,7+276,7 @@ struct proc_dir_entry proc_scsi_fdomain = {
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
   
-#define VERSION          "$Revision: 5.41 $"
+#define VERSION          "$Revision: 5.44 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -580,8+581,8 @@ static int fdomain_is_valid_port( int port )
 
                                /* Try to toggle 32-bit mode.  This only
                                   works on an 18c30 chip.  (User reports
-                                  say that this doesn't work at all, so
-                                  we'll use the other method.) */
+                                  say this works, so we should switch to
+                                  it in the near future.) */
 
       outb( 0x80, port + IO_Control );
       if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
@@ -1018,7+1019,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
       tpnt->this_id = (this_id & 0x07);
       adapter_mask  = (1 << tpnt->this_id);
    } else {
-      if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
+      if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
         tpnt->this_id = 7;
         adapter_mask  = 0x80;
       } else {
@@ -1246,7+1247,7 @@ static int fdomain_select( int target )
 #endif
 #if ERRORS_ONLY
    if (!target) {
-      if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */
+      if (!flag) /* Skip first failure for all chips. */
            ++flag;
       else
            printk( "fdomain: Selection failed\n" );
@@ -1394,7+1395,9 @@ void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
         printk( "Status = %x, ", current_SC->SCp.Status );
 #endif
 #if ERRORS_ONLY
-        if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
+        if (current_SC->SCp.Status
+            && current_SC->SCp.Status != 2
+            && current_SC->SCp.Status != 8) {
            printk( "fdomain: target = %d, command = %x, status = %x\n",
                    current_SC->target,
                    current_SC->cmnd[0],
@@ -1666,7+1669,7 @@ void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
            qualifier = (unsigned char)(*((char *)current_SC->request_buffer
                                          + 13));
 
-           if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
+           if (key != UNIT_ATTENTION
                && !(key == NOT_READY
                     && code == 0x04
                     && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
index 3ab1ddc..a77fe82 100644 (file)
@@ -261,6+261,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #ifdef CONFIG_SCSI_QLOGIC_FAS
     QLOGICFAS,
 #endif
+#ifdef CONFIG_SCSI_QLOGIC_ISP
+    QLOGICISP,
+#endif
 #ifdef CONFIG_SCSI_PAS16
     MV_PAS16,
 #endif
@@ -294,9+297,6 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #ifdef CONFIG_SCSI_AM53C974
     AM53C974,
 #endif
-#ifdef CONFIG_SCSI_QLOGIC_ISP
-    QLOGICISP,
-#endif
 #ifdef CONFIG_SCSI_PPA
     PPA,
 #endif
index c60f9a1..0674484 100644 (file)
@@ -490,6+490,9 @@ static void do_sd_request (void)
            if( SDev->removable && !intr_count )
            {
                 scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
+               /* scsi_ioctl may allow CURRENT to change, so start over. */
+               SDev->was_reset = 0;
+               continue;
            }
            SDev->was_reset = 0;
         }
index da34dfd..5897040 100644 (file)
@@ -485,11+485,11 @@ void sr_photocd(struct inode *inode)
                printk(KERN_WARNING"sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
            break; /* if the first ioctl fails, we don't call the second one */
        }
+       is_xa  = (rec[0] == 0x20);
        min    = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
        sec    = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
        frame  = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
        sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
-       is_xa  = (rec[0] == 0x20) || sector;
        if (sector) {
            sector -= CD_BLOCK_OFFSET;
 #ifdef DEBUG
@@ -566,9+566,6 @@ void sr_photocd(struct inode *inode)
            break;
        }
        sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
-       if (rec[6] <= 1) {
-           sector = 0; /* ignore sector offsets from first track */
-       }
        is_xa = !!sector;
 #ifdef DEBUG
        if (sector)
index 7c5bbf5..679fd97 100644 (file)
@@ -629,7+629,7 @@ ess_audio_prepare_for_input (int dev, int bsize, int bcount)
 
   if (devc->channels == 1)
     {
-      if (devc->bits == AFMT_U8 == 0)
+      if (devc->bits == AFMT_U8)
        {                       /* 8 bit mono */
          ess_write (devc, 0xb7, 0x51);
          ess_write (devc, 0xb7, 0xd0);
index 64515e0..9d129cc 100644 (file)
@@ -87,6+87,7 @@ sb_midi_close (int dev)
   sb_dsp_reset (devc);
   devc->intr_active = 0;
   devc->input_opened = 0;
+  devc->opened = 0;
   restore_flags (flags);
 }
 
index a9f61b6..611efac 100644 (file)
@@ -289,7+289,7 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
              size, dmap->bytes_in_use);
     }
 
-  if (remap_page_range (vma_get_start (vma), virt_to_phys(dmap->raw_buf),
+  if (remap_page_range (vma_get_start (vma), (unsigned long)dmap->raw_buf,
                        vma_get_end (vma) - vma_get_start (vma),
                        vma_get_page_prot (vma)))
     return -EAGAIN;
index b5ba740..8503bb4 100644 (file)
@@ -765,7+765,7 @@ do_load_elf_library(int fd){
 
        /* First of all, some simple consistency checks */
        if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-          (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
+          !elf_check_arch(elf_ex.e_machine) ||
           (!inode->i_op || !inode->i_op->default_file_ops->mmap))
                return -ENOEXEC;
        
index aac990e..4dc96aa 100644 (file)
@@ -1101,7+1101,7 @@ static inline void after_unlock_page (struct page * page)
        if (clear_bit(PG_decr_after, &page->flags))
                atomic_dec(&nr_async_pages);
        if (clear_bit(PG_free_after, &page->flags))
-               free_page(page_address(page));
+               __free_page(page);
        if (clear_bit(PG_swap_unlock_after, &page->flags))
                swap_after_unlock_page(page->swap_unlock_entry);
 }
@@ -1322,11+1322,10 @@ bad_count:
  */
 int generic_readpage(struct inode * inode, struct page * page)
 {
-       unsigned long block, address;
+       unsigned long block;
        int *p, nr[PAGE_SIZE/512];
        int i;
 
-       address = page_address(page);
        page->count++;
        set_bit(PG_locked, &page->flags);
        set_bit(PG_free_after, &page->flags);
@@ -1342,7+1341,7 @@ int generic_readpage(struct inode * inode, struct page * page)
        } while (i > 0);
 
        /* IO start */
-       brw_page(READ, address, inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
+       brw_page(READ, page_address(page), inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
        return 0;
 }
 
index 7f85b1e..ea4bd59 100644 (file)
  *
  * Bruno Haible      :  remove 4K limit for the maps file
  * <haible@ma2s2.mathematik.uni-karlsruhe.de>
+ *
+ * Yves Arrouye      :  remove removal of trailing spaces in get_array.
+ *                     <Yves.Arrouye@marin.fdn.fr>
  */
 
 #include <linux/types.h>
@@ -370,7+373,7 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long
        for (;;) {
                addr = get_phys_addr(*p, start);
                if (!addr)
-                       goto ready;
+                       return result;
                do {
                        c = *(char *) addr;
                        if (!c)
@@ -378,17+381,13 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long
                        if (size < PAGE_SIZE)
                                buffer[size++] = c;
                        else
-                               goto ready;
+                               return result;
                        addr++;
                        start++;
                        if (!c && start >= end)
-                               goto ready;
+                               return result;
                } while (addr & ~PAGE_MASK);
        }
-ready:
-       /* remove the trailing blanks, used to fill out argv,envp space */
-       while (result>0 && buffer[result-1]==' ')
-               result--;
        return result;
 }
 
index 6fe8bf1..fdbd038 100644 (file)
@@ -967,7+967,7 @@ static void do_mount_root(void)
 #ifdef CONFIG_BLK_DEV_FD
        if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
                floppy_eject();
-#ifdef CONFIG_BLK_DEV_RAM
+#ifndef CONFIG_BLK_DEV_RAM
                printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
 #endif
                printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
index 98bc3b0..bd38bdd 100644 (file)
@@ -38,4+38,15 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
        memcpy((char *) &_dest, (char *) &_dump.regs,   \
               sizeof(elf_gregset_t)); }
 
+/* $0 is set by ld.so to a pointer to a function which might be 
+   registered using atexit.  This provides a mean for the dynamic
+   linker to call DT_FINI functions for shared libraries that have
+   been loaded before the code runs.
+
+   So that we can use the same startup file with static executables,
+   we start programs with a value of 0 to indicate that there is no
+   such function.  */
+
+#define ELF_PLAT_INIT(_r)       _r->r0 = 0
+
 #endif
index 79935a7..8eec9d2 100644 (file)
@@ -17,17+17,46 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ((x) == EM_M68K)
+#define elf_check_arch(x) ((x) == EM_68K)
 
 /*
  * These are used to set parameters in the core dumps.
- * FIXME(eric) I don't know what the correct endianness to use is.
  */
 #define ELF_CLASS      ELFCLASS32
 #define ELF_DATA       ELFDATA2MSB;
-#define ELF_ARCH       EM_M68K
+#define ELF_ARCH       EM_68K
+
+       /* For SVR4/m68k the function pointer to be registered with
+          `atexit' is passed in %a1.  Although my copy of the ABI has
+          no such statement, it is actually used on ASV.  */
+#define ELF_PLAT_INIT(_r)      _r->a1 = 0
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      4096
 
+#define ELF_CORE_COPY_REGS(pr_reg, regs)                               \
+       /* Bleech. */                                                   \
+       pr_reg[0] = regs->d1;                                           \
+       pr_reg[1] = regs->d2;                                           \
+       pr_reg[2] = regs->d3;                                           \
+       pr_reg[3] = regs->d4;                                           \
+       pr_reg[4] = regs->d5;                                           \
+       pr_reg[7] = regs->a0;                                           \
+       pr_reg[8] = regs->a1;                                           \
+       pr_reg[14] = regs->d0;                                          \
+       pr_reg[15] = rdusp();                                           \
+       pr_reg[16] = 0; /* orig_d0 */                                   \
+       pr_reg[17] = regs->sr;                                          \
+       pr_reg[18] = regs->pc;                                          \
+       {                                                               \
+         struct switch_stack *sw = ((struct switch_stack *)regs) - 1;  \
+         pr_reg[5] = sw->d6;                                           \
+         pr_reg[6] = sw->d7;                                           \
+         pr_reg[9] = sw->a2;                                           \
+         pr_reg[10] = sw->a3;                                          \
+         pr_reg[11] = sw->a4;                                          \
+         pr_reg[12] = sw->a5;                                          \
+         pr_reg[13] = sw->a6;                                          \
+       }
+
 #endif
index 45d1b9a..68871b2 100644 (file)
+/*
+ * These are the public elements of the Linux kernel AX.25 code. A similar
+ * file netrom.h exists for the NET/ROM protocol.
+ */
+#ifndef        AX25_KERNEL_H
+#define        AX25_KERNEL_H
 #define PF_AX25                AF_AX25
 #define AX25_MTU       256
-#define AX25_MAX_DIGIS 6
-
-typedef struct
-{
-       char ax25_call[7];      /* 6 call + SSID (shifted ascii!) */
-}
-ax25_address;
-
-struct sockaddr_ax25
-{
-       short sax25_family;
-       ax25_address sax25_call;
-       int sax25_ndigis;
-       /* Digipeater ax25_address sets follow */
-};
-
-#define sax25_uid      sax25_ndigis
-
-struct full_sockaddr_ax25
-{
-       struct sockaddr_ax25 fsa_ax25;
-       ax25_address fsa_digipeater[AX25_MAX_DIGIS];
-};
-
-struct ax25_routes_struct
-{
-       ax25_address port_addr;
-       ax25_address dest_addr;
-       unsigned char digi_count;
-       ax25_address digi_addr[AX25_MAX_DIGIS];
-};
-
-struct ax25_route_opt_struct
-{
-       ax25_address port_addr;
-       ax25_address dest_addr;
-       int cmd;
-       int arg;
-};
-
-struct ax25_ctl_struct
-{
-       ax25_address port_addr;
-       ax25_address source_addr;
-       ax25_address dest_addr;
-       unsigned int cmd;
-       unsigned long arg;
-};
-
-struct ax25_bpqaddr_struct
-{
-       char dev[16];
-       ax25_address addr;
-};
+#define AX25_MAX_DIGIS 6       /* This is wrong, should be 8 */
 
 #define AX25_WINDOW    1
 #define AX25_T1                2
@@ -79,16+34,8 @@ struct ax25_bpqaddr_struct
 #define SIOCAX25OPTRT          (SIOCPROTOPRIVATE+7)
 #define SIOCAX25CTLCON         (SIOCPROTOPRIVATE+8)
 
-#define AX25_SET_RT_PERMANENT  1
 #define AX25_SET_RT_IPMODE     2
 
-#define AX25_RT_DYNAMIC                0
-#define AX25_RT_PERMANENT      1
-
-#define AX25_RT_IPMODE_DEFAULT ' '
-#define AX25_RT_IPMODE_DATAGRAM        'D'
-#define AX25_RT_IPMODE_VC      'V'
-
 #define AX25_NOUID_DEFAULT     0
 #define AX25_NOUID_BLOCK       1
 
@@ -113,8+60,54 @@ struct ax25_bpqaddr_struct
 #define AX25_VALUES_IPMAXQUEUE  15     /* Maximum number of buffers enqueued */
 #define        AX25_MAX_VALUES         20
 
-struct ax25_parms_struct
-{
+typedef struct {
+       char ax25_call[7];      /* 6 call + SSID (shifted ascii!) */
+} ax25_address;
+
+struct sockaddr_ax25 {
+       short sax25_family;
+       ax25_address sax25_call;
+       int sax25_ndigis;
+       /* Digipeater ax25_address sets follow */
+};
+
+#define sax25_uid      sax25_ndigis
+
+struct full_sockaddr_ax25 {
+       struct sockaddr_ax25 fsa_ax25;
+       ax25_address fsa_digipeater[AX25_MAX_DIGIS];
+};
+
+struct ax25_routes_struct {
+       ax25_address port_addr;
+       ax25_address dest_addr;
+       unsigned char digi_count;
+       ax25_address digi_addr[AX25_MAX_DIGIS];
+};
+
+struct ax25_route_opt_struct {
+       ax25_address port_addr;
+       ax25_address dest_addr;
+       int cmd;
+       int arg;
+};
+
+struct ax25_ctl_struct {
+       ax25_address port_addr;
+       ax25_address source_addr;
+       ax25_address dest_addr;
+       unsigned int cmd;
+       unsigned long arg;
+};
+
+struct ax25_bpqaddr_struct {
+       char dev[16];
+       ax25_address addr;
+};
+
+struct ax25_parms_struct {
        ax25_address port_addr;
        unsigned short values[AX25_MAX_VALUES];
 };
+
+#endif
index ecda000..177c72f 100644 (file)
@@ -38,7+38,6 @@ typedef unsigned long Elf32_Word;
 #define EM_88K   5
 #define EM_486   6   /* Perhaps disused */
 #define EM_860   7
-#define EM_PPC   20
 
 #define EM_MIPS                8       /* MIPS R3000 (officially, big-endian only) */
 
index 4d24a58..846e214 100644 (file)
@@ -116,6+116,9 @@ struct vm_operations_struct {
  * is used for linear searches (eg. clock algorithm scans). 
  */
 typedef struct page {
+       /* these must be first (free area handling) */
+       struct page *next;
+       struct page *prev;
        struct inode *inode;
        unsigned long offset;
        struct page *next_hash;
@@ -124,8+127,6 @@ typedef struct page {
        unsigned dirty:16,
                 age:8;
        struct wait_queue *wait;
-       struct page *next;
-       struct page *prev;
        struct page *prev_hash;
        struct buffer_head * buffers;
        unsigned long swap_unlock_entry;
@@ -247,6+248,7 @@ extern inline unsigned long get_free_page(int priority)
 
 #define free_page(addr) free_pages((addr),0)
 extern void free_pages(unsigned long addr, unsigned long order);
+extern void __free_page(struct page *);
 
 extern void show_free_areas(void);
 extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
index b17198c..abef3c8 100644 (file)
@@ -1,3+1,12 @@
+/*
+ * These are the public elements of the Linux kernel NET/ROM implementation.
+ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
+ * definition of the ax25_address structure.
+ */
+#ifndef        NETROM_KERNEL_H
+#define        NETROM_KERNEL_H
+
 #define PF_NETROM      AF_NETROM
 #define NETROM_MTU     236
 
@@ -45,3+54,5 @@ struct nr_ctl_struct {
        unsigned int  cmd;
        unsigned long arg;
 };
+
+#endif
index 630cbb8..c1e98e9 100644 (file)
 #define        AX25_DEF_N2             10
 #define AX25_DEF_IDLE          20
 #define AX25_DEF_PACLEN                256
-#define AX25_DEF_IPMAXQUEUE    1               /* 1 * ax25->window */
+#define AX25_DEF_IPMAXQUEUE    2               /* 1 * ax25->window */
 #define        AX25_DEF_DIGI           (AX25_DIGI_INBAND|AX25_DIGI_XBAND)
 
 typedef struct ax25_uid_assoc {
@@ -203,15+203,13 @@ extern void dama_check_need_response(ax25_cb *, int, int);        /* dl1bke 960114 */
 extern void dama_establish_data_link(ax25_cb *);
 
 /* ax25_route.c */
-extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *);
 extern int  ax25_rt_get_info(char *, char **, off_t, int, int);
 extern int  ax25_cs_get_info(char *, char **, off_t, int, int);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern void ax25_rt_build_path(ax25_cb *, ax25_address *);
+extern void ax25_rt_build_path(ax25_cb *, ax25_address *, struct device *);
 extern void ax25_dg_build_path(struct sk_buff *, ax25_address *, struct device *);
 extern void ax25_rt_device_down(struct device *);
 extern int  ax25_rt_ioctl(unsigned int, void *);
-extern void ax25_ip_mode_set(ax25_address *, struct device *, char);
 extern char ax25_ip_mode_get(ax25_address *, struct device *);
 extern unsigned short ax25_dev_get_value(struct device *, int);
 extern void ax25_dev_device_up(struct device *);
index ff46c7e..55ca3f7 100644 (file)
@@ -64,10+64,21 @@ typedef struct {
        struct sock             *sk;            /* Backlink to socket */
 } nr_cb;
 
+struct nr_neigh {
+       struct nr_neigh *next;
+       ax25_address    callsign;
+       ax25_digi       *digipeat;
+       struct device   *dev;
+       unsigned char   quality;
+       unsigned char   locked;
+       unsigned short  count;
+       unsigned int    number;
+};
+
 struct nr_route {
-       unsigned char  quality;
-       unsigned char  obs_count;
-       unsigned short neighbour;
+       unsigned char   quality;
+       unsigned char   obs_count;
+       struct nr_neigh *neighbour;
 };
 
 struct nr_node {
@@ -79,17+90,6 @@ struct nr_node {
        struct nr_route routes[3];
 };
 
-struct nr_neigh {
-       struct nr_neigh *next;
-       ax25_address    callsign;
-       ax25_digi       *digipeat;
-       struct device   *dev;
-       unsigned char   quality;
-       unsigned char   locked;
-       unsigned short  count;
-       unsigned short  number;
-};
-
 /* af_netrom.c */
 extern struct nr_parms_struct nr_default;
 extern int  nr_rx_frame(struct sk_buff *, struct device *);
index 5f6f2b5..36a47f5 100644 (file)
@@ -78,7+78,7 @@ void invalidate_inode_pages(struct inode * inode)
                page->prev = NULL;
                remove_page_from_hash_queue(page);
                page->inode = NULL;
-               free_page(page_address(page));
+               __free_page(page);
                continue;
        }
 }
@@ -111,15+111,16 @@ repeat:
                        page->prev = NULL;
                        remove_page_from_hash_queue(page);
                        page->inode = NULL;
-                       free_page(page_address(page));
+                       __free_page(page);
                        continue;
                }
                p = &page->next;
                offset = start - offset;
                /* partial truncate, clear end of page */
                if (offset < PAGE_SIZE) {
-                       memset((void *) (offset + page_address(page)), 0, PAGE_SIZE - offset);
-                       flush_page_to_ram(page_address(page));
+                       unsigned long address = page_address(page);
+                       memset((void *) (offset + address), 0, PAGE_SIZE - offset);
+                       flush_page_to_ram(address);
                }
        }
 }
@@ -175,7+176,7 @@ int shrink_mmap(int priority, int dma)
                                if (page->inode) {
                                        remove_page_from_hash_queue(page);
                                        remove_page_from_inode_queue(page);
-                                       free_page(page_address(page));
+                                       __free_page(page);
                                        return 1;
                                }
 
index 122a9dc..d66c5b0 100644 (file)
@@ -36,30+36,34 @@ int nr_free_pages = 0;
 
 #define NR_MEM_LISTS 6
 
+/* The start of this MUST match the start of "struct page" */
 struct free_area_struct {
-       struct page list;
+       struct page *next;
+       struct page *prev;
        unsigned int * map;
 };
 
+#define memory_head(x) ((struct page *)x)
+
 static struct free_area_struct free_area[NR_MEM_LISTS];
 
-static inline void init_mem_queue(struct page * head)
+static inline void init_mem_queue(struct free_area_struct * head)
 {
-       head->next = head;
-       head->prev = head;
+       head->next = memory_head(head);
+       head->prev = memory_head(head);
 }
 
-static inline void add_mem_queue(struct page * head, struct page * entry)
+static inline void add_mem_queue(struct free_area_struct * head, struct page * entry)
 {
        struct page * next = head->next;
 
-       entry->prev = head;
+       entry->prev = memory_head(head);
        entry->next = next;
        next->prev = entry;
        head->next = entry;
 }
 
-static inline void remove_mem_queue(struct page * head, struct page * entry)
+static inline void remove_mem_queue(struct page * entry)
 {
        struct page * next = entry->next;
        struct page * prev = entry->prev;
@@ -85,9+89,12 @@ static inline void remove_mem_queue(struct page * head, struct page * entry)
 
 /*
  * Buddy system. Hairy. You really aren't expected to understand this
+ *
+ * Hint: -mask = 1+~mask
  */
 static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
 {
+       struct free_area_struct *area = free_area + order;
        unsigned long index = map_nr >> (1 + order);
        unsigned long mask = (~0UL) << order;
        unsigned long flags;
@@ -98,23+105,32 @@ static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
 #define list(x) (mem_map+(x))
 
        map_nr &= mask;
-       nr_free_pages += 1 << order;
-       while (order < NR_MEM_LISTS-1) {
-               if (!change_bit(index, free_area[order].map))
+       nr_free_pages -= mask;
+       while (mask + (1 << (NR_MEM_LISTS-1))) {
+               if (!change_bit(index, area->map))
                        break;
-               remove_mem_queue(&free_area[order].list, list(map_nr ^ (1+~mask)));
+               remove_mem_queue(list(map_nr ^ -mask));
                mask <<= 1;
-               order++;
+               area++;
                index >>= 1;
                map_nr &= mask;
        }
-       add_mem_queue(&free_area[order].list, list(map_nr));
+       add_mem_queue(area, list(map_nr));
 
 #undef list
 
        restore_flags(flags);
 }
 
+void __free_page(struct page *page)
+{
+       if (!PageReserved(page) && atomic_dec_and_test(&page->count)) {
+               unsigned long map_nr = page->map_nr;
+               delete_from_swap_cache(map_nr);
+               free_pages_ok(map_nr, 0);
+       }
+}
+
 void free_pages(unsigned long addr, unsigned long order)
 {
        unsigned long map_nr = MAP_NR(addr);
@@ -141,8+157,8 @@ void free_pages(unsigned long addr, unsigned long order)
 #define RMQUEUE(order, dma) \
 do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
-       do { struct page *prev = &area->list, *ret; \
-               while (&area->list != (ret = prev->next)) { \
+       do { struct page *prev = memory_head(area), *ret; \
+               while (memory_head(area) != (ret = prev->next)) { \
                        if (!dma || CAN_DMA(ret)) { \
                                unsigned long map_nr = ret->map_nr; \
                                (prev->next = ret->next)->prev = prev; \
@@ -162,7+178,7 @@ do { struct free_area_struct * area = free_area+order; \
 do { unsigned long size = 1 << high; \
        while (high > low) { \
                area--; high--; size >>= 1; \
-               add_mem_queue(&area->list, map); \
+               add_mem_queue(area, map); \
                MARK_USED(index, high, area); \
                index += size; \
                map += size; \
@@ -219,7+235,7 @@ void show_free_areas(void)
        for (order=0 ; order < NR_MEM_LISTS; order++) {
                struct page * tmp;
                unsigned long nr = 0;
-               for (tmp = free_area[order].list.next ; tmp != &free_area[order].list ; tmp = tmp->next) {
+               for (tmp = free_area[order].next ; tmp != memory_head(free_area+order) ; tmp = tmp->next) {
                        nr ++;
                }
                total += nr * ((PAGE_SIZE>>10) << order);
@@ -269,7+285,7 @@ unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)
 
        for (i = 0 ; i < NR_MEM_LISTS ; i++) {
                unsigned long bitmap_size;
-               init_mem_queue(&free_area[i].list);
+               init_mem_queue(free_area+i);
                mask += mask;
                end_mem = (end_mem + ~mask) & mask;
                bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
index ac085c9..ece3534 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
  *      AX.25 032      Joerg(DL1BKE)           Fixed DAMA timeout error.
  *                                             ax25_send_frame() limits the number of enqueued
  *                                             datagrams per socket.
+ *                     Jonathan(G4KLX)         Remove auto-router.
  *
  *     To do:
  *             Restructure the ax25_rcv code to be cleaner/faster and
  *     The null address is defined as a callsign of all spaces with an
  *     SSID of zero.
  */
-ax25_address null_ax25_address = {{0x40,0x40,0x40,0x40,0x40,0x40,0x00}};
+ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
 
 ax25_cb *volatile ax25_list = NULL;
 
@@ -137,8+138,7 @@ char *ax2asc(ax25_address *a)
        char c, *s;
        int n;
 
-       for (n = 0, s = buf; n < 6; n++)
-       {
+       for (n = 0, s = buf; n < 6; n++) {
                c = (a->ax25_call[n] >> 1) & 0x7F;
 
                if (c != ' ') *s++ = c;
@@ -146,8+146,7 @@ char *ax2asc(ax25_address *a)
        
        *s++ = '-';
 
-       if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9)
-       {
+       if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
                *s++ = '1';
                n -= 10;
        }
@@ -492,6+491,7 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
                                        return a->uid;
                        }
                        return -ENOENT;
+
                case SIOCAX25ADDUID:
                        if(!suser())
                                return -EPERM;
@@ -505,8+505,8 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
                        a->next = ax25_uid_list;
                        ax25_uid_list = a;
                        return 0;
-               case SIOCAX25DELUID:
-               {
+
+               case SIOCAX25DELUID: {
                        ax25_uid_assoc **l;
                        
                        if(!suser())
@@ -524,6+524,9 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
                        }
                        return -ENOENT;
                }
+               
+               default:
+                       return -EINVAL;
        }
 
        return -EINVAL; /*NOTREACHED */
@@ -673,7+676,7 @@ static ax25_cb *ax25_create_cb(void)
 
        init_timer(&ax25->timer);
 
-       ax25->dama_slave = 0;   /* dl1bke 951121 */
+       ax25->dama_slave = 0;
 
        ax25->rtt     = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
        ax25->t1      = AX25_DEF_T1 * PR_SLOWHZ;
@@ -705,6+708,7 @@ static ax25_cb *ax25_create_cb(void)
        } else {
                ax25->window = AX25_DEF_WINDOW;
        }
+
        ax25->device   = NULL;
        ax25->digipeat = NULL;
        ax25->sk       = NULL;
@@ -789,7+793,7 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
                        } else {
                                ax25_output(ax25, skb);
                        }
-                       ax25->idletimer = ax25->idle;   /* dl1bke 960228 */
+                       ax25->idletimer = ax25->idle;
                        return 1;               /* It already existed */
                }
        }
@@ -809,10+813,10 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
                }
                *ax25->digipeat = *digi;
        } else {
-               ax25_rt_build_path(ax25, dest);
+               ax25_rt_build_path(ax25, dest, dev);
        }
 
-       if (ax25_dev_is_dama_slave(ax25->device))       /* dl1bke 960116 */
+       if (ax25_dev_is_dama_slave(ax25->device))
                dama_establish_data_link(ax25);
        else
                ax25_establish_data_link(ax25);
@@ -1208,7+1212,6 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev)
                        return NULL;
                }
                
-               /* dl1bke 960119: we have to copy the old digipeater list! */
                *ax25->digipeat = *osk->ax25->digipeat;
        }
 
@@ -1414,10+1417,6 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
                }
 
                sk->ax25->digipeat->lastrepeat = 0;
-       } else { /* dl1bke 960117 */
-               if (sk->debug)
-                       printk("building digipeater path\n");
-               ax25_rt_build_path(sk->ax25, &addr->sax25_call);
        }
 
        /*
@@ -1548,7+1547,6 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
 static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
        int *uaddr_len, int peer)
 {
-       ax25_address *addr;
        struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
        struct sock *sk;
        unsigned char ndigi, i;
@@ -1558,25+1556,30 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
        if (peer != 0) {
                if (sk->state != TCP_ESTABLISHED)
                        return -ENOTCONN;
-               addr = &sk->ax25->dest_addr;
+
+               sax->fsa_ax25.sax25_family = AF_AX25;
+               sax->fsa_ax25.sax25_call   = sk->ax25->dest_addr;
+               sax->fsa_ax25.sax25_ndigis = 0;
+               *uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+               if (sk->ax25->digipeat != NULL) {
+                       ndigi = sk->ax25->digipeat->ndigi;
+                       sax->fsa_ax25.sax25_ndigis = ndigi;
+                       for (i = 0; i < ndigi; i++)
+                               sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
+               }
        } else {
-               addr = &sk->ax25->source_addr;
+               sax->fsa_ax25.sax25_family = AF_AX25;
+               sax->fsa_ax25.sax25_call   = sk->ax25->source_addr;
+               sax->fsa_ax25.sax25_ndigis = 1;
+               *uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+               if (sk->ax25->device != NULL)
+                       memcpy(&sax->fsa_digipeater[0], sk->ax25->device->dev_addr, AX25_ADDR_LEN);
+               else
+                       sax->fsa_digipeater[0] = null_ax25_address;
        }
                
-       sax->fsa_ax25.sax25_family = AF_AX25;
-       sax->fsa_ax25.sax25_call   = *addr;
-       sax->fsa_ax25.sax25_ndigis = 0;
-       *uaddr_len = sizeof(struct sockaddr_ax25);
-
-       /* This will supply digipeat path on both getpeername() and getsockname() */
-       if (sk->ax25->digipeat != NULL) {
-               ndigi = sk->ax25->digipeat->ndigi;
-               sax->fsa_ax25.sax25_ndigis = ndigi;
-               *uaddr_len += AX25_ADDR_LEN * ndigi;
-               for (i = 0; i < ndigi; i++)
-                       sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
-       }
-
        return 0;
 }
  
@@ -1615,13+1618,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
        }
 
        /*
-        *      Send the frame to the AX.25 auto-router
-        */
-#ifdef notdef  /* dl1bke 960310 */
-       ax25_rt_rx_frame(&src, dev, &dp);
-#endif
-       
-       /*
         *      Ours perhaps ?
         */
        if (dp.lastrepeat + 1 < dp.ndigi) {             /* Not yet digipeated completely */
@@ -1653,8+1649,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                                return 0;
                        }
 
-                       ax25_rt_rx_frame(&src, dev, &dp);
-
                        build_ax25_addr(skb->data, &src, &dest, &dp, type, MODULUS);
 #ifdef CONFIG_FIREWALL
                        if (call_fw_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
@@ -1702,14+1696,11 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                switch (skb->data[1]) {
 #ifdef CONFIG_INET             
                        case AX25_P_IP:
-                               ax25_rt_rx_frame(&src, dev, &dp);
                                skb_pull(skb,2);                /* drop PID/CTRL */
-                               ax25_ip_mode_set(&src, dev, 'D');
                                ip_rcv(skb, dev, ptype);        /* Note ptype here is the wrong one, fix me later */
                                break;
 
                        case AX25_P_ARP:
-                               ax25_rt_rx_frame(&src, dev, &dp);
                                skb_pull(skb,2);
                                arp_rcv(skb, dev, ptype);       /* Note ptype here is wrong... */
                                break;
@@ -1720,7+1711,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                                        if (sk->rmem_alloc >= sk->rcvbuf) {
                                                kfree_skb(skb, FREE_READ);
                                        } else {
-                                               ax25_rt_rx_frame(&src, dev, &dp);
                                                /*
                                                 *      Remove the control and PID.
                                                 */
@@ -1764,7+1754,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                 *      free it immediately. This routine itself wakes the user context layers so we
                 *      do no further work
                 */
-               ax25_rt_rx_frame(&src, dev, &dp);
                if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)
                        kfree_skb(skb, FREE_READ);
 
@@ -1790,7+1779,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
        /* b) received SABM(E) */
        
        if ((sk = ax25_find_listener(&dest, dev, SOCK_SEQPACKET)) != NULL) {
-               ax25_rt_rx_frame(&src, dev, &dp);
                if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) {
                        if (mine)
                                ax25_return_dm(dev, &src, &dest, &dp);
@@ -1815,8+1803,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                        return 0;
                }
                
-               ax25_rt_rx_frame(&src, dev, &dp);
-
                if ((ax25 = ax25_create_cb()) == NULL) {
                        ax25_return_dm(dev, &src, &dest, &dp);
                        kfree_skb(skb, FREE_READ);
@@ -1826,10+1812,8 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                ax25_fillin_cb(ax25, dev);
                ax25->idletimer = ax25->idle;
 #else
-               if (mine) {
-                       ax25_rt_rx_frame(&src, dev, &dp);
+               if (mine)
                        ax25_return_dm(dev, &src, &dest, &dp);
-               }
 
                kfree_skb(skb, FREE_READ);
                return 0;
@@ -1882,7+1866,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
 
        if (sk != NULL) {
                if (!sk->dead)
-                       sk->data_ready(sk, skb->len );
+                       sk->data_ready(sk, skb->len);
        } else {
                kfree_skb(skb, FREE_READ);
        }
@@ -1944,13+1928,12 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        ax25_digi *dp;
        ax25_digi dtmp;
        int lv;
-       int addr_len=msg->msg_namelen;
+       int addr_len = msg->msg_namelen;
        
-       if (sk->err) {
+       if (sk->err)
                return sock_error(sk);
-       }
 
-       if (flags|| msg->msg_control)
+       if (flags || msg->msg_control)
                return -EINVAL;
 
        if (sk->zapped)
@@ -2079,9+2062,8 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        int er;
        int dama;
 
-       if (sk->err) {
+       if (sk->err)
                return sock_error(sk);
-       }
        
        if (addr_len != NULL)
                *addr_len = sizeof(*sax);
@@ -2176,8+2158,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        put_fs_long(amount, (unsigned long *)arg);
                        return 0;
 
-               case TIOCINQ:
-               {
+               case TIOCINQ: {
                        struct sk_buff *skb;
                        /* These two are safe on a single CPU system as only user tasks fiddle here */
                        if ((skb = skb_peek(&sk->receive_queue)) != NULL)
@@ -2201,8+2182,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
                case SIOCAX25ADDUID:    /* Add a uid to the uid/call map table */
                case SIOCAX25DELUID:    /* Delete a uid from the uid/call map table */
-               case SIOCAX25GETUID:
-               {
+               case SIOCAX25GETUID: {
                        struct sockaddr_ax25 sax25;
                        if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
                                return err;
@@ -2303,7+2283,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
                        ax25->window,
                        ax25->paclen);
                        
-               len += sprintf(buffer + len, " %s", ax25->dama_slave? " slave" : "    no");
+               len += sprintf(buffer + len, " %s", ax25->dama_slave ? " slave" : "    no");
 
                if (ax25->sk != NULL) {
                        len += sprintf(buffer + len, " %5d %5d\n",
@@ -2434,7+2414,6 @@ void ax25_proto_init(struct net_proto *pro)
  *     A small shim to dev_queue_xmit to handle the difference between
  *     KISS AX.25 and BPQ AX.25.
  */
-
 void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
 {
        unsigned char *ptr;
@@ -2449,8+2428,8 @@ void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
        skb->protocol = htons (ETH_P_AX25);
 
 #ifdef CONFIG_BPQETHER
-       if(dev->type == ARPHRD_ETHER) {
-               static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+       if (dev->type == ARPHRD_ETHER) {
+               static char bcast_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
                int size;
 
                if(skb_headroom(skb) < AX25_BPQ_HEADER_LEN) {
@@ -2546,8+2525,7 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des
 
        if (bp[16] == AX25_P_IP) {
                mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
-               if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) 
-               {
+               if (mode == 'V' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
                        /*
                         *      This is a workaround to try to keep the device locking
                         *      straight until skb->free=0 is abolished post 1.4.
@@ -2593,7+2571,6 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des
         * dl1bke 960317: we use ax25_queue_xmit here to allow mode datagram
         *                over ethernet. I don't know if this is valid, though.
         */
-
        ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev);
        ax25_queue_xmit(skb, dev, SOPRI_NORMAL);
 
index d3053e1..bcd2aa9 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
  *                     Joerg(DL1BKE)   Renamed it to "IDLE" with a slightly
  *                                     different behaviour. Fixed defrag
  *                                     routine (I hope)
+ *     AX.25 032       Jonathan(G4KLX) Remove auto-router.
+ *                     Darryl(G7LED)   AX.25 segmentation fixed.
  */
 
 #include <linux/config.h>
@@ -70,66+72,57 @@ static int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
 static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 {
        struct sk_buff *skbn, *skbo;
-       int hdrlen;
+       int hdrlen, nhdrlen;
        
        if (ax25->fragno != 0) {
                if (!(*skb->data & SEG_FIRST)) {
                        if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) {
-                       
-                               /* enqueue fragment */
-                               
+                               /* Enqueue fragment */
                                ax25->fragno = *skb->data & SEG_REM;
                                skb_pull(skb, 1);       /* skip fragno */
                                ax25->fraglen += skb->len;
                                skb_queue_tail(&ax25->frag_queue, skb);
-                               
-                               /* last fragment received? */
 
+                               /* Last fragment received ? */
                                if (ax25->fragno == 0) {
-                                       if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL)
-                                               return 0;
+                                       if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) {
+                                               while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+                                                       kfree_skb(skbo, FREE_READ);
+                                               return 1;
+                                       }
 
                                        skbn->free = 1;
                                        skbn->arp  = 1;
-                                       skbn->dev  = skb->dev;
+                                       skbn->dev  = ax25->device;
 
                                        if (ax25->sk != NULL) {
                                                skbn->sk = ax25->sk;
                                                atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
                                        }
 
-                                       /* get first fragment from queue */
-                                       
+                                       skb_reserve(skbn, AX25_MAX_HEADER_LEN);
+
+                                       /* Get first fragment from queue */
                                        skbo = skb_dequeue(&ax25->frag_queue);
-                                       hdrlen = skbo->data - skbo->h.raw - 2;  /* skip PID & fragno */
-                                       
-                                       skb_push(skbo, hdrlen + 2);             /* start of address field */
-                                       skbn->data = skb_put(skbn, hdrlen);     /* get space for info */
-                                       memcpy(skbn->data, skbo->data, hdrlen); /* copy address field */
-                                       skb_pull(skbo, hdrlen + 2);             /* start of data */
-                                       skb_pull(skbn, hdrlen + 1);             /* ditto */
+                                       hdrlen  = skbo->data - skbo->h.raw;
+                                       nhdrlen = hdrlen - 2;
 
-                                       /* copy data from first fragment */
+                                       skb_push(skbo, hdrlen);
+                                       skb_push(skbn, nhdrlen);
+                                       skbn->h.raw = skbn->data;
 
-                                       memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
-                                       kfree_skb(skbo, FREE_READ);
-                                       
-                                       /* add other fragment's data */
+                                       /* Copy AX.25 headers */
+                                       memcpy(skbn->data, skbo->data, nhdrlen);
+                                       skb_pull(skbn, nhdrlen);
+                                       skb_pull(skbo, hdrlen);
 
-                                       while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
+                                       /* Copy data from the fragments */
+                                       do {
                                                memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
                                                kfree_skb(skbo, FREE_READ);
-                                       }
+                                       } while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL);
 
-                                       ax25->fraglen = 0;              /* reset counter */
-                                       
-                                       /* 
-                                        * mysteriously we need to re-adjust skb->data.
-                                        * Anyway, it seems to work. Do we have the address fields
-                                        * encoded TWICE in one sk_buff?
-                                        */
-                                       
-                                       skb_pull(skbn, hdrlen);
+                                       ax25->fraglen = 0;
 
                                        if (ax25_rx_iframe(ax25, skbn) == 0)
                                                kfree_skb(skbn, FREE_READ);
@@ -139,9+132,10 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
                        }
                }
        } else {
-               /* first fragment received? */
-
+               /* First fragment received */
                if (*skb->data & SEG_FIRST) {
+                       while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+                               kfree_skb(skbo, FREE_READ);
                        ax25->fragno = *skb->data & SEG_REM;
                        skb_pull(skb, 1);               /* skip fragno */
                        ax25->fraglen = skb->len;
@@ -181,7+175,6 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
                case AX25_P_IP:
                        skb_pull(skb, 1);       /* Remove PID */
                        skb->h.raw = skb->data;
-                       ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
                        ip_rcv(skb, ax25->device, NULL);        /* Wrong ptype */
                        queued = 1;
                        break;
@@ -273,7+266,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        break;
 
                default:
-                       if (dama && pf) /* dl1bke 960116 */
+                       if (dama && pf)
                                ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
                        break;
        }
@@ -490,7+483,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        }
                        if (ax25->condition & OWN_RX_BUSY_CONDITION) {
                                if (pf) {
-                                       if (ax25->dama_slave)   /* dl1bke 960114 */
+                                       if (ax25->dama_slave)
                                                dama_enquiry_response(ax25);
                                        else
                                                ax25_enquiry_response(ax25);
@@ -498,20+491,21 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                break;
                        }
                        if (ns == ax25->vr) {
+                               ax25->vr = (ax25->vr + 1) % ax25->modulus;
                                queued = ax25_rx_iframe(ax25, skb);
                                if (ax25->condition & OWN_RX_BUSY_CONDITION) {
+                                       ax25->vr = ns;  /* ax25->vr - 1 */
                                        if (pf) {
-                                               if (ax25->dama_slave)   /* dl1bke 960114 */
+                                               if (ax25->dama_slave)
                                                        dama_enquiry_response(ax25);
                                                else
                                                        ax25_enquiry_response(ax25);
                                        }
                                        break;
                                }
-                               ax25->vr = (ax25->vr + 1) % ax25->modulus;
                                ax25->condition &= ~REJECT_CONDITION;
                                if (pf) {
-                                       if (ax25->dama_slave)   /* dl1bke 960114 */
+                                       if (ax25->dama_slave)
                                                dama_enquiry_response(ax25);
                                        else
                                                ax25_enquiry_response(ax25);
@@ -524,14+518,14 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        } else {
                                if (ax25->condition & REJECT_CONDITION) {
                                        if (pf) {
-                                               if (ax25->dama_slave)   /* dl1bke 960114 */
+                                               if (ax25->dama_slave)
                                                        dama_enquiry_response(ax25);
                                                else
                                                        ax25_enquiry_response(ax25);
                                        }
                                } else {
                                        ax25->condition |= REJECT_CONDITION;
-                                       if (ax25->dama_slave)           /* dl1bke 960114 */
+                                       if (ax25->dama_slave)
                                                dama_enquiry_response(ax25);
                                        else
                                                ax25_send_control(ax25, REJ, pf, C_RESPONSE);
@@ -660,7+654,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        
                case RR:
                        ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-                       if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+                       if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
                                ax25->t1timer = 0;
                                if (ax25_validate_nr(ax25, nr)) {
                                        ax25_frames_acked(ax25, nr);
@@ -691,7+685,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
 
                case REJ:
                        ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-                       if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+                       if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
                                ax25->t1timer = 0;
                                if (ax25_validate_nr(ax25, nr)) {
                                        ax25_frames_acked(ax25, nr);
@@ -735,7+729,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        }
                        ax25_frames_acked(ax25, nr);
                        if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-                               if (pf) {       /* dl1bke 960114 */
+                               if (pf) {
                                        if (ax25->dama_slave)
                                                ax25_enquiry_response(ax25);
                                        else
@@ -744,9+738,11 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                break;
                        }
                        if (ns == ax25->vr) {
+                               ax25->vr = (ax25->vr + 1) % ax25->modulus;
                                queued = ax25_rx_iframe(ax25, skb);
                                if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-                                       if (pf) {       /* dl1bke 960114 */
+                                       ax25->vr = ns;  /* ax25->vr - 1 */
+                                       if (pf) {
                                                if (ax25->dama_slave)
                                                        dama_enquiry_response(ax25);
                                                else
@@ -754,10+750,9 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                        }
                                        break;
                                }
-                               ax25->vr = (ax25->vr + 1) % ax25->modulus;
                                ax25->condition &= ~REJECT_CONDITION;
                                if (pf) {
-                                       if (ax25->dama_slave)   /* dl1bke 960114 */
+                                       if (ax25->dama_slave)
                                                dama_enquiry_response(ax25);
                                        else
                                                ax25_enquiry_response(ax25);
@@ -769,7+764,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                }
                        } else {
                                if (ax25->condition & REJECT_CONDITION) {
-                                       if (pf) {       /* dl1bke 960114 */
+                                       if (pf) {
                                                if (ax25->dama_slave)
                                                        dama_enquiry_response(ax25);
                                                else
@@ -777,7+772,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                        }
                                } else {
                                        ax25->condition |= REJECT_CONDITION;
-                                       if (ax25->dama_slave)           /* dl1bke 960114 */
+                                       if (ax25->dama_slave)
                                                dama_enquiry_response(ax25);
                                        else
                                                ax25_send_control(ax25, REJ, pf, C_RESPONSE);
index a8a7ed5..f0f748e 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
  *     AX.25 030       Jonathan(G4KLX) Added fragmentation to ax25_output.
  *                                     Added support for extended AX.25.
  *     AX.25 031       Joerg(DL1BKE)   Added DAMA support
- *
  *                     Joerg(DL1BKE)   Modified fragmenter to fragment vanilla 
  *                                     AX.25 I-Frames. Added PACLEN parameter.
  *                     Joerg(DL1BKE)   Fixed a problem with buffer allocation
@@ -214,7+213,7 @@ void ax25_kick(ax25_cb *ax25)
                do {
                        if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
                                skb_queue_head(&ax25->write_queue, skb);
-                               return;
+                               break;
                        }
 
                        next = (ax25->vs + 1) % ax25->modulus;
index d770710..ce61626 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
  *                     Joerg(DL1BKE)   Fixed AX.25 routing of IP datagram and VC, new ioctl()
  *                                     "SIOCAX25OPTRT" to set IP mode and a 'permanent' flag
  *                                     on routes.
+ *     AX.25 032       Jonathan(G4KLX) Remove auto-router.
  */
  
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#define        AX25_ROUTE_MAX  128
-
 static struct ax25_route {
        struct ax25_route *next;
        ax25_address callsign;
        struct device *dev;
        ax25_digi *digipeat;
-       struct timeval stamp;
-       int n;
        char ip_mode;
-       char perm;
 } *ax25_route = NULL;
 
 static struct ax25_dev {
@@ -82,120+78,22 @@ static struct ax25_dev {
        unsigned short values[AX25_MAX_VALUES];
 } *ax25_device = NULL;
 
-static struct ax25_route * ax25_find_route(ax25_address *addr);
+static struct ax25_route *ax25_find_route(ax25_address *, struct device *);
 
 /*
  * small macro to drop non-digipeated digipeaters and reverse path
  */
 static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
 {
        int k;
+
        for (k = 0; k < in->ndigi; k++)
                if (!in->repeated[k])
                        break;
-       in->ndigi = k;
-       ax25_digi_invert(in, out);
-
-}
-
-/*
- * dl1bke 960310: new behaviour:
- *
- * * try to find an existing route to 'src', if found:
- *   - if the route was added manually don't adjust the timestamp
- *   - if this route is 'permanent' just do some statistics and return
- *   - overwrite device and digipeater path
- * * no existing route found:
- *   - try to alloc a new entry
- *   - overwrite the oldest, not manually added entry if this fails.
- *
- * * updated on reception of frames directed to us _only_
- *
- */
-
-void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
-{
-       unsigned long flags;
-       extern struct timeval xtime;
-       struct ax25_route *ax25_rt;
-       struct ax25_route *oldest;
-       int count;
-
-       count  = 0;
-       oldest = NULL;
-
-       for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (count == 0 || oldest->stamp.tv_sec == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
-                       oldest = ax25_rt;
-               
-               if (ax25cmp(&ax25_rt->callsign, src) == 0) {
-                       if (ax25_rt->stamp.tv_sec != 0)
-                               ax25_rt->stamp = xtime;
-
-                       if (ax25_rt->perm == AX25_RT_PERMANENT) {
-                               ax25_rt->n++;
-                               return;
-                       }
-                       
-                       ax25_rt->dev = dev;
-                       if (digi == NULL) {
-                               /* drop old digipeater list */
-                               if (ax25_rt->digipeat != NULL) {
-                                       kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
-                                       ax25_rt->digipeat = NULL;
-                               }
-                               return;
-                       }
-                       
-                       if (ax25_rt->digipeat == NULL && (ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
-                                       return;
-                       
-                       ax25_route_invert(digi, ax25_rt->digipeat);
-                       return;
-               }
-
-               count++;
-       }
-
-       if (count > AX25_ROUTE_MAX) {
-               if (oldest->stamp.tv_sec == 0)
-                       return;
-               if (oldest->digipeat != NULL)
-                       kfree_s(oldest->digipeat, sizeof(ax25_digi));
-               ax25_rt = oldest;
-       } else {
-               if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
-                       return;         /* No space */
-       }
-       
-       ax25_rt->callsign = *src;
-       ax25_rt->dev      = dev;
-       ax25_rt->digipeat = NULL;
-       ax25_rt->stamp    = xtime;
-       ax25_rt->n        = 1;
-       ax25_rt->ip_mode  = ' ';
-       ax25_rt->perm     = AX25_RT_DYNAMIC;
-
-       if (digi != NULL) {
-               if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
-                       kfree_s(ax25_rt, sizeof(struct ax25_route));
-                       return;
-               }
-               
-               ax25_route_invert(digi, ax25_rt->digipeat);
-               /* used to be: *ax25_rt->digipeat = *digi; */
-       }
-
-       if (ax25_rt != oldest) {
-               save_flags(flags);
-               cli();
 
-               ax25_rt->next = ax25_route;
-               ax25_route    = ax25_rt;
+       in->ndigi = k;
 
-               restore_flags(flags);
-       }
+       ax25_digi_invert(in, out);
 }
 
 void ax25_rt_device_down(struct device *dev)
@@ -261,7+159,6 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
                                                        ax25_rt->digipeat->calls[i]    = route.digi_addr[i];
                                                }
                                        }
-                                       ax25_rt->stamp.tv_sec = 0;
                                        return 0;
                                }
                        }
@@ -270,10+167,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
                        ax25_rt->callsign     = route.dest_addr;
                        ax25_rt->dev          = dev;
                        ax25_rt->digipeat     = NULL;
-                       ax25_rt->stamp.tv_sec = 0;
-                       ax25_rt->n            = 0;
                        ax25_rt->ip_mode      = ' ';
-                       ax25_rt->perm         = AX25_RT_DYNAMIC;
                        if (route.digi_count != 0) {
                                if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
                                        kfree_s(ax25_rt, sizeof(struct ax25_route));
@@ -323,40+217,36 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
                                }
                        }
                        break;
+
                case SIOCAX25OPTRT:
                        if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
                                return err;
                        memcpy_fromfs(&rt_option, arg, sizeof(rt_option));
                        if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL)
                                return -EINVAL;
-                       ax25_rt = ax25_route;
-                       while (ax25_rt != NULL) {
+                       for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
                                if (ax25_rt->dev == dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
-                                       switch(rt_option.cmd) {
-                                               case AX25_SET_RT_PERMANENT:
-                                                       ax25_rt->perm = (char) rt_option.arg;
-                                                       ax25_rt->stamp.tv_sec = 0;
-                                                       break;
+                                       switch (rt_option.cmd) {
                                                case AX25_SET_RT_IPMODE:
                                                        switch (rt_option.arg) {
-                                                               case AX25_RT_IPMODE_DEFAULT:
-                                                                       ax25_rt->ip_mode = ' ';
-                                                                       break;
-                                                               case AX25_RT_IPMODE_DATAGRAM:
-                                                                       ax25_rt->ip_mode = 'D';
-                                                                       break;
-                                                               case AX25_RT_IPMODE_VC:
-                                                                       ax25_rt->ip_mode = 'V';
+                                                               case ' ':
+                                                               case 'D':
+                                                               case 'V':
+                                                                       ax25_rt->ip_mode = rt_option.arg;
                                                                        break;
                                                                default:
                                                                        return -EINVAL;
                                                        }
                                                        break;
+                                               default:
+                                                       return -EINVAL;
                                        }
                                }
-                               ax25_rt = ax25_rt->next;
                        }
                        break;
+
+               default:
+                       return -EINVAL;
        }
 
        return 0;
@@ -373,26+263,22 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d
   
        cli();
 
-       len += sprintf(buffer, "callsign  dev  count time      mode F digipeaters\n");
+       len += sprintf(buffer, "callsign  dev  mode digipeaters\n");
 
        for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
                if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
                        callsign = "default";
                else
                        callsign = ax2asc(&ax25_rt->callsign);
-               len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
+               len += sprintf(buffer + len, "%-9s %-4s",
                        callsign,
-                       ax25_rt->dev ? ax25_rt->dev->name : "???",
-                       ax25_rt->n,
-                       ax25_rt->stamp.tv_sec);
+                       ax25_rt->dev ? ax25_rt->dev->name : "???");
 
                switch (ax25_rt->ip_mode) {
                        case 'V':
-                       case 'v':
                                len += sprintf(buffer + len, "   vc");
                                break;
                        case 'D':
-                       case 'd':
                                len += sprintf(buffer + len, "   dg");
                                break;
                        default:
@@ -400,20+286,6 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d
                                break;
                }
                
-               switch (ax25_rt->perm) {
-                       case AX25_RT_DYNAMIC:
-                               if (ax25_rt->stamp.tv_sec == 0)
-                                       len += sprintf(buffer + len, " M");
-                               else
-                                       len += sprintf(buffer + len, "  ");
-                               break;
-                       case AX25_RT_PERMANENT:
-                               len += sprintf(buffer + len, " P");
-                               break;
-                       default:
-                               len += sprintf(buffer + len, " ?");
-               }
-
                if (ax25_rt->digipeat != NULL)
                        for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
                                len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
@@ -479,8+351,7 @@ int ax25_cs_get_info(char *buffer, char **start, off_t offset, int length, int d
 /*
  *     Find AX.25 route
  */
-static struct ax25_route * ax25_find_route(ax25_address *addr)
+static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev)
 {
        struct ax25_route *ax25_spe_rt = NULL;
        struct ax25_route *ax25_def_rt = NULL;
@@ -491,10+362,17 @@ static struct ax25_route * ax25_find_route(ax25_address *addr)
         *      route if none is found;
         */
        for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
-                       ax25_spe_rt = ax25_rt;
-               if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
-                       ax25_def_rt = ax25_rt;
+               if (dev == NULL) {
+                       if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
+                               ax25_spe_rt = ax25_rt;
+                       if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
+                               ax25_def_rt = ax25_rt;
+               } else {
+                       if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
+                               ax25_spe_rt = ax25_rt;
+                       if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
+                               ax25_def_rt = ax25_rt;
+               }
        }
 
        if (ax25_spe_rt != NULL)
@@ -508,7+386,6 @@ static struct ax25_route * ax25_find_route(ax25_address *addr)
  *      a target on the digipeater path but w/o having a special route
  *     set before, the path has to be truncated from your target on.
  */
 static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
 {
        int k;
@@ -530,14+407,14 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        struct ax25_route *ax25_rt;
        ax25_address *call;
 
-       if ((ax25_rt = ax25_find_route(addr)) == NULL)
+       if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL)
                return -EHOSTUNREACH;
                
+       ax25->device = ax25_rt->dev;
+
        if ((call = ax25_findbyuid(current->euid)) == NULL) {
                if (ax25_uid_policy && !suser())
                        return -EPERM;
-               if (ax25->device == NULL)
-                       return -ENODEV;
                call = (ax25_address *)ax25->device->dev_addr;
        }
 
@@ -560,19+437,20 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
  *     dl1bke 960117: build digipeater path
  *     dl1bke 960301: use the default route if it exists
  */
-void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr)
+void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev)
 {
        struct ax25_route *ax25_rt;
        
-       ax25_rt = ax25_find_route(addr);
+       if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+               return;
        
-       if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+       if (ax25_rt->digipeat == NULL)
                return;
 
        if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
                return;
 
-       ax25->device = ax25_rt->dev;
+       ax25->device    = ax25_rt->dev;
        *ax25->digipeat = *ax25_rt->digipeat;
        ax25_adjust_path(addr, ax25->digipeat);
 }
@@ -587,8+465,10 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
 
        skb_pull(skb, 1);       /* skip KISS command */
 
-       ax25_rt = ax25_find_route(addr);
-       if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+       if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+               return;
+
+       if (ax25_rt->digipeat == NULL)
                return;
                
        digipeat = *ax25_rt->digipeat;
@@ -611,22+491,6 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
 }
 
 /*
- *     Register the mode of an incoming IP frame. It is assumed that an entry
- *     already exists in the routing table.
- */
-void ax25_ip_mode_set(ax25_address *callsign, struct device *dev, char ip_mode)
-{
-       struct ax25_route *ax25_rt;
-
-       for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) {
-                       ax25_rt->ip_mode = ip_mode;
-                       return;
-               }
-       }
-}
-
-/*
  *     Return the IP mode of a given callsign/device pair.
  */
 char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
@@ -908,6+772,9 @@ int ax25_bpq_ioctl(unsigned int cmd, void *arg)
                        ax25_bpqdev  = bpqdev;
                        restore_flags(flags);
                        break;
+                       
+               default:
+                       return -EINVAL;
        }
 
        return 0;
index b2c837b..e87aedc 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
@@ -101,7+101,7 @@ void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)
                        skb->free = 1;
                        kfree_skb(skb, FREE_WRITE);
                        ax25->va = (ax25->va + 1) % ax25->modulus;
-                       if (ax25->dama_slave)           /* dl1bke 960120 */
+                       if (ax25->dama_slave)
                                ax25->n2count = 0;
                }
        }
index aa34d77..335755f 100644 (file)
@@ -1,5+1,5 @@
 /*
- *     AX.25 release 031
+ *     AX.25 release 032
  *
  *     This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *     releases, misbehave and/or generally screw up. It might even work. 
@@ -113,7+113,7 @@ static void ax25_timer(unsigned long param)
                        if (ax25->sk != NULL) {
                                if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & OWN_RX_BUSY_CONDITION)) {
                                        ax25->condition &= ~OWN_RX_BUSY_CONDITION;
-                                       if (!ax25->dama_slave) /* dl1bke */
+                                       if (!ax25->dama_slave)
                                                ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
                                        ax25->condition &= ~ACK_PENDING_CONDITION;
                                        break;
@@ -123,7+123,7 @@ static void ax25_timer(unsigned long param)
                         * Check for frames to transmit.
                         */
                        if (!ax25->dama_slave)
-                               ax25_kick(ax25);        /* dl1bke 960114 */
+                               ax25_kick(ax25);
                        break;
 
                default:
@@ -134,7+134,7 @@ static void ax25_timer(unsigned long param)
                if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
                        if (ax25->condition & ACK_PENDING_CONDITION) {
                                ax25->condition &= ~ACK_PENDING_CONDITION;
-                               if (!ax25->dama_slave)                  /* dl1bke 960114 */
+                               if (!ax25->dama_slave)
                                        ax25_timeout_response(ax25);
                        }
                }
@@ -272,7+272,7 @@ void ax25_t1_timeout(ax25_cb * ax25)
 #endif
                                ax25_clear_queues(ax25);
                                ax25->state = AX25_STATE_0;
-                               ax25_send_control(ax25, DISC, POLLON, C_COMMAND); /* dl1bke */
+                               ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
                                
                                if (ax25->sk != NULL) {
                                        ax25->sk->state = TCP_CLOSE;
@@ -283,14+283,14 @@ void ax25_t1_timeout(ax25_cb * ax25)
                                }
                        } else {
                                ax25->n2count++;
-                               if (!ax25_dev_is_dama_slave(ax25->device))      /* dl1bke */
+                               if (!ax25_dev_is_dama_slave(ax25->device))
                                        ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
                        }
                        break;
 
                case AX25_STATE_3: 
                        ax25->n2count = 1;
-                       if (!ax25->dama_slave)                  /* dl1bke 960114 */
+                       if (!ax25->dama_slave)
                                ax25_transmit_enquiry(ax25);
                        ax25->state   = AX25_STATE_4;
                        break;
@@ -314,7+314,7 @@ void ax25_t1_timeout(ax25_cb * ax25)
                                }
                        } else {
                                ax25->n2count++;
-                               if (!ax25->dama_slave)          /* dl1bke 960114 */
+                               if (!ax25->dama_slave)
                                        ax25_transmit_enquiry(ax25);
                        }
                        break;
index bc624ed..1d53c61 100644 (file)
@@ -315,7+315,7 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
 #endif
                IS_SKB(skb);
 
-               if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) 
+               if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF))) 
                {
                        ip_statistics.IpFragFails++;
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
index 2f4833c..887371b 100644 (file)
@@ -645,7+645,7 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i
         *      Check for any "DF" flag. [DF means do not fragment]
         */
 
-       if (ntohs(iph->frag_off) & IP_DF)
+       if (iph->frag_off & htons(IP_DF))
        {
                ip_statistics.IpFragFails++;
                NETDEBUG(printk("ip_queue_xmit: frag needed\n"));
index e65be00..ba78c86 100644 (file)
@@ -279,7+279,7 @@ void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk)
        /*
         *      Wait up to 1 second for the buffer to fill.
         */
-       sk->partial_timer.expires = jiffies+HZ;
+       sk->partial_timer.expires = jiffies+HZ/10;
        sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
        sk->partial_timer.data = (unsigned long) sk;
        add_timer(&sk->partial_timer);
@@ -966,6+966,10 @@ void tcp_send_ack(struct sock *sk)
                sock_wfree(sk, buff);
                return;
        }
+#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
+       buff->ip_hdr->frag_off |= htons(IP_DF);
+#endif
+
        t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
 
        /*
index 4f72fdc..79976f4 100644 (file)
@@ -934,7+934,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
                sax->fsa_ax25.sax25_ndigis = 1;
                sax->fsa_ax25.sax25_call = sk->nr->user_addr;
                sax->fsa_digipeater[0]   = sk->nr->dest_addr;
-               *uaddr_len = sizeof(struct sockaddr_ax25) + AX25_ADDR_LEN;
+               *uaddr_len = sizeof(struct full_sockaddr_ax25);
        } else {
                sax->fsa_ax25.sax25_family = AF_NETROM;
                sax->fsa_ax25.sax25_ndigis = 0;
@@ -952,14+952,13 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
        ax25_address *src, *dest, *user;
        unsigned short circuit_index, circuit_id;
        unsigned short frametype, window, timeout;
-       
 
        skb->sk = NULL;         /* Initially we don't know who it's for */
 
        /*
         *      skb->data points to the netrom frame start
         */
-       
+
        src  = (ax25_address *)(skb->data + 0);
        dest = (ax25_address *)(skb->data + 7);
 
@@ -1327,7+1326,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int
   
        cli();
 
-       len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st vs vr va    t1     t2    n2  rtt wnd paclen Snd-Q Rcv-Q\n");
+       len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st  vs  vr  va    t1     t2    n2  rtt wnd paclen Snd-Q Rcv-Q\n");
 
        for (s = nr_list; s != NULL; s = s->next) {
                if ((dev = s->nr->device) == NULL)
@@ -1339,7+1338,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int
                        ax2asc(&s->nr->user_addr));
                len += sprintf(buffer + len, "%-9s ",
                        ax2asc(&s->nr->dest_addr));
-               len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %2d %2d %2d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
+               len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
                        ax2asc(&s->nr->source_addr),
                        devname, s->nr->my_index, s->nr->my_id,
                        s->nr->your_index, s->nr->your_id,
index 158e3f3..288cda0 100644 (file)
@@ -168,7+168,7 @@ void nr_kick(struct sock *sk)
                do {
                        if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
                                skb_queue_head(&sk->write_queue, skb);
-                               return;
+                               break;
                        }
 
                        next = (sk->nr->vs + 1) % NR_MODULUS;
index 5093928..fd61fb3 100644 (file)
  *     NET/ROM 001     Jonathan(G4KLX) First attempt.
  *     NET/ROM 003     Jonathan(G4KLX) Use SIOCADDRT/SIOCDELRT ioctl values
  *                                     for NET/ROM routes.
+ *                                     Use '*' for a blank mnemonic in /proc/net/nr_nodes.
+ *                                     Change default quality for new neighbour when same
+ *                                     as node callsign.
  *                     Alan Cox(GW4PTS) Added the firewall hooks.
- *
- *     TO DO
- *     Sort out the which pointer when shuffling entries in the routes
- *     section. Also reset the which pointer when a route becomes "good"
- *     again, ie when a NODES broadcast is processed via calls to
- *     nr_add_node().
  */
  
 #include <linux/config.h>
 #include <linux/firewall.h>
 #include <net/netrom.h>
 
-static int nr_neigh_no = 1;
+static unsigned int nr_neigh_no = 1;
 static int nr_route_on = 1;
 
 static struct nr_node  *nr_node_list  = NULL;
 static struct nr_neigh *nr_neigh_list = NULL;
 
+static void nr_remove_neigh(struct nr_neigh *);
+
 /*
  *     Add a new route to a node, and in the process add the node and the
  *     neighbour if it is new.
@@ -72,7+71,10 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
        struct nr_route nr_route;
        unsigned long flags;
        int i, found;
-       
+
+       if (nr_dev_get(nr) != NULL)     /* Can't add routes to ourself */
+               return -EINVAL;
+
        for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
                if (ax25cmp(nr, &nr_node->callsign) == 0)
                        break;
@@ -91,7+93,10 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
                nr_neigh->callsign = *ax25;
                nr_neigh->digipeat = NULL;
                nr_neigh->dev      = dev;
-               nr_neigh->quality  = nr_default.quality;
+               if (ax25cmp(nr, ax25) == 0)
+                       nr_neigh->quality = quality;
+               else
+                       nr_neigh->quality = nr_default.quality;
                nr_neigh->locked   = 0;
                nr_neigh->count    = 0;
                nr_neigh->number   = nr_neigh_no++;
@@ -118,14+123,14 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
                        return -ENOMEM;
 
                nr_node->callsign = *nr;
-               memcpy(&nr_node->mnemonic, mnemonic, sizeof(nr_node->mnemonic));
+               strcpy(nr_node->mnemonic, mnemonic);
 
                nr_node->which = 0;
                nr_node->count = 1;
 
                nr_node->routes[0].quality   = quality;
                nr_node->routes[0].obs_count = obs_count;
-               nr_node->routes[0].neighbour = nr_neigh->number;
+               nr_node->routes[0].neighbour = nr_neigh;
                        
                save_flags(flags);
                cli();
@@ -138,10+143,13 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
                nr_neigh->count++;
 
                return 0;
+       } else {
+               if (nr_node->mnemonic[0] == '\0')
+                       strcpy(nr_node->mnemonic, mnemonic);
        }
 
        for (found = 0, i = 0; i < nr_node->count; i++) {
-               if (nr_node->routes[i].neighbour == nr_neigh->number) {
+               if (nr_node->routes[i].neighbour == nr_neigh) {
                        nr_node->routes[i].quality   = quality;
                        nr_node->routes[i].obs_count = obs_count;
                        found = 1;
@@ -157,16+165,22 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
 
                        nr_node->routes[0].quality   = quality;
                        nr_node->routes[0].obs_count = obs_count;
-                       nr_node->routes[0].neighbour = nr_neigh->number;
+                       nr_node->routes[0].neighbour = nr_neigh;
                                
+                       nr_node->which++;
                        nr_node->count++;
                        nr_neigh->count++;
                } else {
                        /* It must be better than the worst */
                        if (quality > nr_node->routes[2].quality) {
+                               nr_node->routes[2].neighbour->count--;
+                               
+                               if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
+                                       nr_remove_neigh(nr_node->routes[2].neighbour);
+                       
                                nr_node->routes[2].quality   = quality;
                                nr_node->routes[2].obs_count = obs_count;
-                               nr_node->routes[2].neighbour = nr_neigh->number;
+                               nr_node->routes[2].neighbour = nr_neigh;
 
                                nr_neigh->count++;
                        }
@@ -212,7+226,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
        }
 
        for (i = 0; i < nr_node->count; i++) {
-               if (nr_node->routes[i].neighbour == nr_neigh->number) {
+               if (nr_node->routes[i].neighbour == nr_neigh) {
                        if (i < nr_node->which)
                                nr_node->which = i;
                        break;
@@ -307,7+321,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct d
        if (nr_neigh == NULL) return -EINVAL;
        
        for (i = 0; i < nr_node->count; i++) {
-               if (nr_node->routes[i].neighbour == nr_neigh->number) {
+               if (nr_node->routes[i].neighbour == nr_neigh) {
                        nr_neigh->count--;
 
                        if (nr_neigh->count == 0 && !nr_neigh->locked)
@@ -403,7+417,7 @@ static int nr_del_neigh(ax25_address *callsign, struct device *dev, unsigned int
  */
 static int nr_dec_obs(void)
 {
-       struct nr_neigh *t, *nr_neigh;
+       struct nr_neigh *nr_neigh;
        struct nr_node  *s, *nr_node;
        int i;
 
@@ -420,21+434,12 @@ static int nr_dec_obs(void)
                                break;
 
                        case 1:         /* From 1 -> 0 */
-                               nr_neigh = nr_neigh_list;
-
-                               while (nr_neigh != NULL) {
-                                       t        = nr_neigh;
-                                       nr_neigh = nr_neigh->next;
-
-                                       if (t->number == s->routes[i].neighbour) {
-                                               t->count--;
+                               nr_neigh = s->routes[i].neighbour;
+                               
+                               nr_neigh->count--;
                                                
-                                               if (t->count == 0 && !t->locked)
-                                                       nr_remove_neigh(t);
-
-                                               break;
-                                       }
-                               }
+                               if (nr_neigh->count == 0 && !nr_neigh->locked)
+                                       nr_remove_neigh(nr_neigh);
 
                                s->count--;
 
@@ -483,7+488,7 @@ void nr_rt_device_down(struct device *dev)
                                nr_node = nr_node->next;
                                
                                for (i = 0; i < t->count; i++) {
-                                       if (t->routes[i].neighbour == s->number) {
+                                       if (t->routes[i].neighbour == s) {
                                                t->count--;
 
                                                switch (i) {
@@ -609,13+614,16 @@ int nr_rt_ioctl(unsigned int cmd, void *arg)
 
                case SIOCNRDECOBS:
                        return nr_dec_obs();
-                       
+
                case SIOCNRRTCTL:
                        if ((err = verify_area(VERIFY_READ, arg, sizeof(int))) != 0)
                                return err;
                        opt = get_fs_long((void *)arg);
                        nr_route_on = opt ? 1 : 0;
                        return 0;
+
+               default:
+                       return -EINVAL;
        }
 
        return 0;
@@ -637,7+645,7 @@ void nr_link_failed(ax25_address *callsign, struct device *dev)
        if (nr_neigh == NULL) return;
        
        for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
-               if (nr_node->which >= nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh->number)
+               if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)
                        nr_node->which++;
 }
 
@@ -645,7+653,6 @@ void nr_link_failed(ax25_address *callsign, struct device *dev)
  *     Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
  *     indicates an internally generated frame.
  */
-
 int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
        ax25_address *nr_src, *nr_dest;
@@ -655,12+662,12 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        unsigned char *dptr;
        
 #ifdef CONFIG_FIREWALL
-
-       if(ax25 && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+       if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
                return 0;
-       if(!ax25 && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+       if (ax25 == NULL && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
                return 0;
 #endif
+
        nr_src  = (ax25_address *)(skb->data + 0);
        nr_dest = (ax25_address *)(skb->data + 7);
 
@@ -684,27+691,20 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        if (nr_node == NULL || nr_node->which >= nr_node->count)
                return 0;
 
-       for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
-               if (nr_neigh->number == nr_node->routes[nr_node->which].neighbour)
-                       break;
-                       
-       if (nr_neigh == NULL)
-               return 0;
+       nr_neigh = nr_node->routes[nr_node->which].neighbour;
 
        if ((dev = nr_dev_first()) == NULL)
                return 0;
 
 #ifdef CONFIG_FIREWALL
-       if(ax25 && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+       if (ax25 != NULL && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
                return 0;
 #endif
 
        dptr  = skb_push(skb, 1);
        *dptr = AX25_P_NETROM;
 
-       ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
-
-       return 1;
+       return ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
 }
 
 int nr_nodes_get_info(char *buffer, char **start, off_t offset,
@@ -715,7+715,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
        off_t pos   = 0;
        off_t begin = 0;
        int i;
-  
+
        cli();
 
        len += sprintf(buffer, "callsign  mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
@@ -723,7+723,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
        for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) {
                len += sprintf(buffer + len, "%-9s %-7s  %d %d",
                        ax2asc(&nr_node->callsign),
-                       nr_node->mnemonic,
+                       (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
                        nr_node->which + 1,
                        nr_node->count);                        
 
@@ -731,7+731,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
                        len += sprintf(buffer + len, "  %3d   %d %05d",
                                nr_node->routes[i].quality,
                                nr_node->routes[i].obs_count,
-                               nr_node->routes[i].neighbour);
+                               nr_node->routes[i].neighbour->number);
                }
 
                len += sprintf(buffer + len, "\n");
@@ -742,7+742,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
                        len   = 0;
                        begin = pos;
                }
-               
+
                if (pos > offset + length)
                        break;
        }
@@ -754,7+754,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
 
        if (len > length) len = length;
 
-       return(len);
+       return len;
 } 
 
 int nr_neigh_get_info(char *buffer, char **start, off_t offset,
@@ -764,7+764,7 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset,
        int len     = 0;
        off_t pos   = 0;
        off_t begin = 0;
-  
+
        cli();
 
        len += sprintf(buffer, "addr  callsign  dev  qual lock count\n");
@@ -796,7+796,7 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset,
 
        if (len > length) len = length;
 
-       return(len);
+       return len;
 } 
 
 #endif
close