]> git.neil.brown.name Git - history.git/commitdiff
Import 2.4.0-test6pre9 2.4.0-test6pre9
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:37:43 +0000 (15:37 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:37:43 +0000 (15:37 -0500)
61 files changed:
Documentation/sysctl/vm.txt
arch/i386/kernel/i386_ksyms.c
arch/i386/lib/Makefile
arch/i386/lib/memcpy.c [new file with mode: 0644]
drivers/block/raid0.c
drivers/block/raid1.c
drivers/block/raid5.c
drivers/char/Config.in
drivers/char/agp/agp.h
drivers/char/agp/agpgart_be.c
drivers/char/console.c
drivers/char/drm/Config.in
drivers/char/drm/README.drm
drivers/char/drm/agpsupport.c
drivers/char/drm/drmP.h
drivers/char/drm/drm_syms.c [deleted file]
drivers/char/drm/gamma_drv.c
drivers/char/drm/i810_drv.c
drivers/char/drm/memory.c
drivers/char/drm/mga_drv.c
drivers/char/drm/r128_drv.c
drivers/char/drm/tdfx_drv.c
drivers/char/drm/vm.c
drivers/char/ftape/lowlevel/ftape-buffer.c
drivers/isdn/hisax/callc.c
drivers/isdn/hisax/l3_1tr6.c
drivers/isdn/hisax/l3dss1.c
drivers/isdn/isdn_common.c
drivers/isdn/isdn_common.h
drivers/isdn/isdn_net.c
drivers/isdn/isdn_net.h
drivers/isdn/isdn_ppp.c
drivers/isdn/isdn_ppp.h
drivers/isdn/isdn_tty.c
drivers/isdn/isdn_tty.h
drivers/net/82596.c
drivers/net/eth16i.c
drivers/scsi/53c7,8xx.c
drivers/scsi/53c7xx.c
drivers/scsi/README.st
drivers/scsi/st.c
drivers/sound/dmabuf.c
drivers/sound/sscape.c
fs/fcntl.c
fs/open.c
fs/proc/kcore.c
fs/super.c
include/asm-i386/pgtable.h
include/asm-mips64/mmu_context.h
include/linux/fs.h
include/linux/isdn.h
include/linux/isdn_ppp.h
include/linux/isdnif.h
include/linux/list.h
include/linux/raid/linear.h
include/linux/raid/raid0.h
include/linux/raid/raid1.h
include/linux/raid/raid5.h
include/linux/slab.h
kernel/fork.c
net/packet/af_packet.c

index cc447c1b565b1e9f36683d1453a0dfe48aadfcec..30e32d315770ccc7c195438e3edfd4e0c6c04f96 100644 (file)
@@ -168,7 +168,7 @@ the system pretends there's always enough memory.
 
 This feature can be very useful because there are a lot of
 programs that malloc() huge amounts of memory "just-in-case"
-and don't much of it.
+and don't use much of it.
 
 Look at: mm/mmap.c::vm_enough_memory() for more information.
 
index c11ab01f2cfa96ffa94f33544a16bab12c0170ed..ed35734265cd24a91bc4c21acef3331b19968f4b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/apm_bios.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -24,6 +25,7 @@
 #include <asm/irq.h>
 #include <asm/mmx.h>
 #include <asm/desc.h>
+#include <asm/pgtable.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
@@ -142,3 +144,14 @@ EXPORT_SYMBOL(screen_info);
 EXPORT_SYMBOL(get_wchan);
 
 EXPORT_SYMBOL(rtc_lock);
+
+#undef memcpy
+#undef memset
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+
+#ifdef CONFIG_X86_PAE
+EXPORT_SYMBOL(empty_zero_page);
+#endif
index 30e9a207c86c4088cd8917027e2c8c9fe133cc23..abafc528dabe4b14d96c9ee782297adcbd8deedc 100644 (file)
@@ -7,7 +7,8 @@
 
 L_TARGET = lib.a
 L_OBJS  = checksum.o old-checksum.o delay.o \
-       usercopy.o getuser.o putuser.o iodebug.o
+       usercopy.o getuser.o putuser.o iodebug.o \
+       memcpy.o
 
 ifdef CONFIG_X86_USE_3DNOW
 L_OBJS += mmx.o
diff --git a/arch/i386/lib/memcpy.c b/arch/i386/lib/memcpy.c
new file mode 100644 (file)
index 0000000..4cb37b6
--- /dev/null
@@ -0,0 +1,19 @@
+#include <linux/config.h>
+#include <linux/string.h>
+
+#undef memcpy
+#undef memset
+
+void * memcpy(void * to, const void * from, size_t n)
+{
+#ifdef CONFIG_X86_USE_3DNOW
+       return __memcpy3d(to, from, n);
+#else
+       return __memcpy(to, from, n);
+#endif
+}
+
+void * memset(void * s, int c, size_t count)
+{
+       return __memset(s, c, count);
+}
index 4a298bc0d7f75a3e88ae62e3637645f2abdc4a6b..acbf07be4dc0e8623141aff4670703b0843bcaab 100644 (file)
@@ -28,7 +28,7 @@
 static int create_strip_zones (mddev_t *mddev)
 {
        int i, c, j, j1, j2;
-       int current_offset, curr_zone_offset;
+       unsigned long current_offset, curr_zone_offset;
        raid0_conf_t *conf = mddev_to_conf(mddev);
        mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
  
@@ -226,12 +226,12 @@ static int raid0_stop (mddev_t *mddev)
 static int raid0_make_request (mddev_t *mddev,
                               int rw, struct buffer_head * bh)
 {
-       unsigned int sect_in_chunk, chunksize_bits, chunk, chunk_size;
+       unsigned int sect_in_chunk, chunksize_bits,  chunk_size;
        raid0_conf_t *conf = mddev_to_conf(mddev);
        struct raid0_hash *hash;
        struct strip_zone *zone;
        mdk_rdev_t *tmp_dev;
-       unsigned long block, rsect;
+       unsigned long chunk, block, rsect;
 
        chunk_size = mddev->param.chunk_size >> 10;
        chunksize_bits = ffz(~chunk_size);
index 7027d2dd6207559f08e4e24f468f14538b88c8cd..baf839b1d5639888c72e415b5aa6756f05ee8c55 100644 (file)
@@ -448,7 +448,7 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
 {
        int new_disk = conf->last_used;
        const int sectors = bh->b_size >> 9;
-       const long this_sector = bh->b_blocknr * sectors;
+       const unsigned long this_sector = bh->b_rsector;
        int disk = new_disk;
        unsigned long new_distance;
        unsigned long current_distance;
index a6c7b39e95d1f53b11940f852a5e3d0fc4e52fab..346cc2759a5f9e39dd2061b03677871d20ff9353 100644 (file)
@@ -631,7 +631,7 @@ static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, i
        raid5_conf_t *conf = sh->raid_conf;
        char *b_data;
        struct page *b_page;
-       int block = sh->sector / (sh->size >> 9);
+       unsigned long block = sh->sector / (sh->size >> 9);
 
        b_data = bh->b_data;
        b_page = bh->b_page;
@@ -715,12 +715,13 @@ static int raid5_error (mddev_t *mddev, kdev_t dev)
  * Input: a 'big' sector number,
  * Output: index of the data and parity disk, and the sector # in them.
  */
-static unsigned long raid5_compute_sector(int r_sector, unsigned int raid_disks,
+static unsigned long raid5_compute_sector(unsigned long r_sector, unsigned int raid_disks,
                        unsigned int data_disks, unsigned int * dd_idx,
                        unsigned int * pd_idx, raid5_conf_t *conf)
 {
-       unsigned int stripe;
-       int chunk_number, chunk_offset;
+       unsigned long stripe;
+       unsigned long chunk_number;
+       unsigned int chunk_offset;
        unsigned long new_sector;
        int sectors_per_chunk = conf->chunk_size >> 9;
 
index 2ac91160de87fafd5b74351fbaf6cc99623c38ae..08b50aaa10fe5e8b2d253fe360095aca9fdbaf09 100644 (file)
@@ -260,7 +260,7 @@ endmenu
 tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP
 if [ "$CONFIG_AGP" != "n" ]; then
    bool '  Intel 440LX/BX/GX 840 support' CONFIG_AGP_INTEL
-   bool '  Intel I810/I810 DC100/I810e support' CONFIG_AGP_I810
+   bool '  Intel I810/I815 support' CONFIG_AGP_I810
    bool '  VIA chipset support' CONFIG_AGP_VIA
    bool '  AMD Irongate support' CONFIG_AGP_AMD
    bool '  Generic SiS support' CONFIG_AGP_SIS
index 355a9a8d11157c04e0fb730a021bc25a1922e22d..af32ba284e8b483e82d252f314b5a81d143c415e 100644 (file)
@@ -181,6 +181,12 @@ struct agp_bridge_data {
 #ifndef PCI_DEVICE_ID_INTEL_810_E_1
 #define PCI_DEVICE_ID_INTEL_810_E_1     0x7125
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_815_0
+#define PCI_DEVICE_ID_INTEL_815_0       0x1130
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_815_1
+#define PCI_DEVICE_ID_INTEL_815_1       0x1132
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_82443GX_1
 #define PCI_DEVICE_ID_INTEL_82443GX_1   0x71a1
 #endif
index a31a6acf7d954ca43c534536b2e4d6f040e7e1c4..e5fbba8b540c46ab19ddbc69f479d1205914f38b 100644 (file)
@@ -108,6 +108,9 @@ static void smp_flush_cache(void)
 
 int agp_backend_acquire(void)
 {
+       if (agp_bridge.type == NOT_SUPPORTED) {
+               return -EINVAL;
+       }
        atomic_inc(&agp_bridge.agp_in_use);
 
        if (atomic_read(&agp_bridge.agp_in_use) != 1) {
@@ -120,6 +123,9 @@ int agp_backend_acquire(void)
 
 void agp_backend_release(void)
 {
+       if (agp_bridge.type == NOT_SUPPORTED) {
+               return;
+       }
        atomic_dec(&agp_bridge.agp_in_use);
        MOD_DEC_USE_COUNT;
 }
@@ -224,7 +230,7 @@ void agp_free_memory(agp_memory * curr)
 {
        int i;
 
-       if (curr == NULL) {
+       if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) {
                return;
        }
        if (curr->is_bound == TRUE) {
@@ -255,6 +261,9 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
        agp_memory *new;
        int i;
 
+       if (agp_bridge.type == NOT_SUPPORTED) {
+               return NULL;
+       }
        if ((atomic_read(&agp_bridge.current_memory_agp) + page_count) >
            agp_bridge.max_memory_agp) {
                return NULL;
@@ -334,6 +343,10 @@ static int agp_return_size(void)
 void agp_copy_info(agp_kern_info * info)
 {
        memset(info, 0, sizeof(agp_kern_info));
+       if (agp_bridge.type == NOT_SUPPORTED) {
+               info->chipset = agp_bridge.type;
+               return;
+       }
        info->version.major = agp_bridge.version->major;
        info->version.minor = agp_bridge.version->minor;
        info->device = agp_bridge.dev;
@@ -357,7 +370,8 @@ int agp_bind_memory(agp_memory * curr, off_t pg_start)
 {
        int ret_val;
 
-       if ((curr == NULL) || (curr->is_bound == TRUE)) {
+       if ((agp_bridge.type == NOT_SUPPORTED) ||
+           (curr == NULL) || (curr->is_bound == TRUE)) {
                return -EINVAL;
        }
        if (curr->is_flushed == FALSE) {
@@ -378,7 +392,7 @@ int agp_unbind_memory(agp_memory * curr)
 {
        int ret_val;
 
-       if (curr == NULL) {
+       if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) {
                return -EINVAL;
        }
        if (curr->is_bound != TRUE) {
@@ -623,7 +637,7 @@ static int agp_generic_create_gatt_table(void)
        }
        table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
-       for (page = virt_to_page(table); page < get_mem_map(table_end); page++)
+       for (page = virt_to_page(table); page < virt_to_page(table_end); page++)
                set_bit(PG_reserved, &page->flags);
 
        agp_bridge.gatt_table_real = (unsigned long *) table;
@@ -633,7 +647,7 @@ static int agp_generic_create_gatt_table(void)
        CACHE_FLUSH();
 
        if (agp_bridge.gatt_table == NULL) {
-               for (page = virt_to_page(table); page < get_mem_map(table_end); page++)
+               for (page = virt_to_page(table); page < virt_to_page(table_end); page++)
                        clear_bit(PG_reserved, &page->flags);
 
                free_pages((unsigned long) table, page_order);
@@ -690,7 +704,7 @@ static int agp_generic_free_gatt_table(void)
        table = (char *) agp_bridge.gatt_table_real;
        table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
-       for (page = virt_to_page(table); page < get_mem_map(table_end); page++)
+       for (page = virt_to_page(table); page < virt_to_page(table_end); page++)
                clear_bit(PG_reserved, &page->flags);
 
        free_pages((unsigned long) agp_bridge.gatt_table_real, page_order);
@@ -789,6 +803,7 @@ static void agp_generic_free_by_type(agp_memory * curr)
 
 void agp_enable(u32 mode)
 {
+       if (agp_bridge.type == NOT_SUPPORTED) return;
        agp_bridge.agp_enable(mode);
 }
 
@@ -2264,6 +2279,27 @@ static int __init agp_find_supported_device(void)
                        agp_bridge.type = INTEL_I810;
                        return intel_i810_setup(i810_dev);
 
+                case PCI_DEVICE_ID_INTEL_815_0:
+                  /* The i815 can operate either as an i810 style
+                   * integrated device, or as an AGP4X motherboard.
+                   *
+                   * This only addresses the first mode:
+                   */
+                       i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+                                                  PCI_DEVICE_ID_INTEL_815_1,
+                                                  NULL);
+                       if (i810_dev == NULL) {
+                               printk(KERN_ERR PFX "agpgart: Detected an "
+                                      "Intel i815, but could not find the"
+                                      " secondary device.\n");
+                               agp_bridge.type = NOT_SUPPORTED;
+                               return -ENODEV;
+                       }
+                       printk(KERN_INFO PFX "agpgart: Detected an Intel i815 "
+                              "Chipset.\n");
+                       agp_bridge.type = INTEL_I810;
+                       return intel_i810_setup(i810_dev);
+
                default:
                        break;
                }
@@ -2454,11 +2490,13 @@ static int __init agp_init(void)
               AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
 
        ret_val = agp_backend_initialize();
-       if (ret_val)
+       if (ret_val) {
+               agp_bridge.type = NOT_SUPPORTED;
                return ret_val;
-
+       }
        ret_val = agp_frontend_initialize();
        if (ret_val) {
+               agp_bridge.type = NOT_SUPPORTED;
                agp_backend_cleanup();
                return ret_val;
        }
index 0ed2b17ca6c413ac4b51459e581d062dde9f3aa8..3f51c056a05ec3a9a46a358c0bed918684eda140 100644 (file)
@@ -586,12 +586,12 @@ void redraw_screen(int new_console, int is_switch)
        }
 
        if (redraw) {
+               int update;
                set_origin(currcons);
-               if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) {
-                       /* Update the screen contents */
-                       set_palette(currcons);
+               update = sw->con_switch(vc_cons[currcons].d);
+               set_palette(currcons);
+               if (update && vcmode != KD_GRAPHICS)
                        do_update_region(currcons, origin, screenbuf_size/2);
-               }
        }
        set_cursor(currcons);
        if (is_switch) {
@@ -2940,7 +2940,9 @@ EXPORT_SYMBOL(video_scan_lines);
 EXPORT_SYMBOL(vc_resize);
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
-
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(vt_cons);
+#endif
 #ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
 EXPORT_SYMBOL(give_up_console);
index d24d6597004dd612d9c11412b033cdfcca4994c6..c69d37db5891ac2aa4b27411d3df10fe13b7e598 100644 (file)
@@ -5,7 +5,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.x.
 #
 
-tristate 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
+bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
 if [ "$CONFIG_DRM" != "n" ]; then
     tristate '  3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
     tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA
index 1cc4c277033caf8a3fc5a8030c73ac8850d330a4..6441e01e587c09d8505e0b632feb8f96276c40ad 100644 (file)
@@ -1,3 +1,7 @@
+************************************************************
+* For the very latest on DRI development, please see:      *
+*     http://dri.sourceforge.net/                          *
+************************************************************
 
 The Direct Rendering Manager (drm) is a device-independent kernel-level
 device driver that provides support for the XFree86 Direct Rendering
@@ -36,6 +40,7 @@ For specific information about kernel-level support, see:
     A Security Analysis of the Direct Rendering Infrastructure
     http://precisioninsight.com/dr/security.html
 
-
-
-$XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/README.drm,v 1.2 1999/09/27 14:59:24 dawes Exp $
+************************************************************
+* For the very latest on DRI development, please see:      *
+*     http://dri.sourceforge.net/                          *
+************************************************************
index e1e1ccedddf09d64ff8bccd142b72f3778548ca5..7ed234e153f4b3b0cc40974eb03a246af46109f1 100644 (file)
@@ -287,24 +287,40 @@ drm_agp_head_t *drm_agp_init(void)
                        return NULL;
                memset((void *)head, 0, sizeof(*head));
                (*drm_agp.copy_info)(&head->agp_info);
+               if (head->agp_info.chipset == NOT_SUPPORTED) {
+                       drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+                       return NULL;
+               }
                head->memory = NULL;
                switch (head->agp_info.chipset) {
-               case INTEL_GENERIC:    head->chipset = "Intel";            break;
-               case INTEL_LX:         head->chipset = "Intel 440LX";      break;
-               case INTEL_BX:         head->chipset = "Intel 440BX";      break;
-               case INTEL_GX:         head->chipset = "Intel 440GX";      break;
-               case INTEL_I810:       head->chipset = "Intel i810";       break;
-               case VIA_GENERIC:      head->chipset = "VIA";              break;
-               case VIA_VP3:          head->chipset = "VIA VP3";          break;
-               case VIA_MVP3:         head->chipset = "VIA MVP3";         break;
-               case VIA_APOLLO_PRO:   head->chipset = "VIA Apollo Pro";   break;
-               case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super"; break;
-               case SIS_GENERIC:      head->chipset = "SiS";              break;
-               case AMD_GENERIC:      head->chipset = "AMD";              break;
-               case AMD_IRONGATE:     head->chipset = "AMD Irongate";     break;
-               case ALI_GENERIC:      head->chipset = "ALi";              break;
-               case ALI_M1541:        head->chipset = "ALi M1541";        break;
-               default:
+               case INTEL_GENERIC:     head->chipset = "Intel";         break;
+               case INTEL_LX:          head->chipset = "Intel 440LX";   break;
+               case INTEL_BX:          head->chipset = "Intel 440BX";   break;
+               case INTEL_GX:          head->chipset = "Intel 440GX";   break;
+               case INTEL_I810:        head->chipset = "Intel i810";    break;
+
+#if LINUX_VERSION_CODE >= 0x020400
+               case INTEL_I840:        head->chipset = "Intel i840";    break;
+#endif
+
+               case VIA_GENERIC:       head->chipset = "VIA";           break;
+               case VIA_VP3:           head->chipset = "VIA VP3";       break;
+               case VIA_MVP3:          head->chipset = "VIA MVP3";      break;
+
+#if LINUX_VERSION_CODE >= 0x020400
+               case VIA_MVP4:          head->chipset = "VIA MVP4";      break;
+               case VIA_APOLLO_SUPER:  head->chipset = "VIA Apollo Super"; 
+                       break;
+#endif
+
+               case VIA_APOLLO_PRO:    head->chipset = "VIA Apollo Pro";
+                       break;
+               case SIS_GENERIC:       head->chipset = "SiS";           break;
+               case AMD_GENERIC:       head->chipset = "AMD";           break;
+               case AMD_IRONGATE:      head->chipset = "AMD Irongate";  break;
+               case ALI_GENERIC:       head->chipset = "ALi";           break;
+               case ALI_M1541:         head->chipset = "ALi M1541";     break;
+               default:                head->chipset = "Unknown";       break;
                }
                DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n",
                         head->agp_info.version.major,
index e4783c8db90d99cb25ed9c19e24f6aeb6fed37dd..4f85d07ca931fd8fc79d68df1bba3e27b11ef0a9 100644 (file)
@@ -137,6 +137,11 @@ typedef struct wait_queue *wait_queue_head_t;
 #endif
 #ifndef module_exit
 #define module_exit(x)  void cleanup_module(void) { x(); }
+#endif
+
+                               /* virt_to_page added in 2.4.0-test6 */
+#ifndef virt_to_page
+#define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr))
 #endif
 
                                /* Generic cmpxchg added in 2.3.x */
@@ -558,6 +563,9 @@ extern unsigned long drm_vm_nopage(struct vm_area_struct *vma,
 extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma,
                                       unsigned long address,
                                       int write_access);
+extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+                                           unsigned long address,
+                                           int write_access);
 extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
                                       unsigned long address,
                                       int write_access);
@@ -569,6 +577,9 @@ extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
 extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
                                      unsigned long address,
                                      int write_access);
+extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+                                          unsigned long address,
+                                          int write_access);
 extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
                                      unsigned long address,
                                      int write_access);
@@ -578,9 +589,7 @@ extern void      drm_vm_close(struct vm_area_struct *vma);
 extern int          drm_mmap_dma(struct file *filp,
                                  struct vm_area_struct *vma);
 extern int          drm_mmap(struct file *filp, struct vm_area_struct *vma);
-extern struct vm_operations_struct drm_vm_ops;
-extern struct vm_operations_struct drm_vm_shm_ops;
-extern struct vm_operations_struct drm_vm_dma_ops;
+
 
                                /* Proc support (proc.c) */
 extern int          drm_proc_init(drm_device_t *dev);
diff --git a/drivers/char/drm/drm_syms.c b/drivers/char/drm/drm_syms.c
deleted file mode 100644 (file)
index 661ac48..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <linux/config.h>
-#include "drmP.h"
-
-/* Misc. support (init.c) */
-EXPORT_SYMBOL(drm_flags);
-EXPORT_SYMBOL(drm_parse_options);
-EXPORT_SYMBOL(drm_cpu_valid);
-
-/* Device support (fops.c) */
-EXPORT_SYMBOL(drm_open_helper);
-EXPORT_SYMBOL(drm_flush);
-EXPORT_SYMBOL(drm_release);
-EXPORT_SYMBOL(drm_fasync);
-EXPORT_SYMBOL(drm_read);
-EXPORT_SYMBOL(drm_write_string);
-EXPORT_SYMBOL(drm_poll);
-
-/* Mapping support (vm.c) */
-#if LINUX_VERSION_CODE < 0x020317
-EXPORT_SYMBOL(drm_vm_nopage);
-EXPORT_SYMBOL(drm_vm_shm_nopage);
-EXPORT_SYMBOL(drm_vm_dma_nopage);
-#else
-/* Return type changed in 2.3.23 */
-EXPORT_SYMBOL(drm_vm_nopage);
-EXPORT_SYMBOL(drm_vm_shm_nopage);
-EXPORT_SYMBOL(drm_vm_dma_nopage);
-#endif
-
-EXPORT_SYMBOL(drm_vm_open);
-EXPORT_SYMBOL(drm_vm_close);
-EXPORT_SYMBOL(drm_mmap_dma);
-EXPORT_SYMBOL(drm_mmap);
-EXPORT_SYMBOL(drm_vm_ops);
-EXPORT_SYMBOL(drm_vm_shm_ops);
-EXPORT_SYMBOL(drm_vm_dma_ops);
-
-/* Proc support (proc.c) */
-EXPORT_SYMBOL(drm_proc_init);
-EXPORT_SYMBOL(drm_proc_cleanup);
-
-/* Memory management support (memory.c) */
-EXPORT_SYMBOL(drm_mem_init);
-EXPORT_SYMBOL(drm_mem_info);
-EXPORT_SYMBOL(drm_alloc);
-EXPORT_SYMBOL(drm_realloc);
-EXPORT_SYMBOL(drm_strdup);
-EXPORT_SYMBOL(drm_strfree);
-EXPORT_SYMBOL(drm_free);
-EXPORT_SYMBOL(drm_alloc_pages);
-EXPORT_SYMBOL(drm_free_pages);
-EXPORT_SYMBOL(drm_ioremap);
-EXPORT_SYMBOL(drm_ioremapfree);
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-EXPORT_SYMBOL(drm_alloc_agp);
-EXPORT_SYMBOL(drm_free_agp);
-EXPORT_SYMBOL(drm_bind_agp);
-EXPORT_SYMBOL(drm_unbind_agp);
-#endif
-
-/* Buffer management support (bufs.c) */
-EXPORT_SYMBOL(drm_order);
-EXPORT_SYMBOL(drm_addmap);
-EXPORT_SYMBOL(drm_addbufs);
-EXPORT_SYMBOL(drm_infobufs);
-EXPORT_SYMBOL(drm_markbufs);
-EXPORT_SYMBOL(drm_freebufs);
-EXPORT_SYMBOL(drm_mapbufs);
-
-/* Buffer list management support (lists.c) */
-EXPORT_SYMBOL(drm_waitlist_create);
-EXPORT_SYMBOL(drm_waitlist_destroy);
-EXPORT_SYMBOL(drm_waitlist_put);
-EXPORT_SYMBOL(drm_waitlist_get);
-EXPORT_SYMBOL(drm_freelist_create);
-EXPORT_SYMBOL(drm_freelist_destroy);
-EXPORT_SYMBOL(drm_freelist_put);
-EXPORT_SYMBOL(drm_freelist_get);
-
-/* DMA support (gen_dma.c) */
-EXPORT_SYMBOL(drm_dma_setup);
-EXPORT_SYMBOL(drm_dma_takedown);
-EXPORT_SYMBOL(drm_free_buffer);
-EXPORT_SYMBOL(drm_reclaim_buffers);
-EXPORT_SYMBOL(drm_context_switch);
-EXPORT_SYMBOL(drm_context_switch_complete);
-EXPORT_SYMBOL(drm_clear_next_buffer);
-EXPORT_SYMBOL(drm_select_queue);
-EXPORT_SYMBOL(drm_dma_enqueue);
-EXPORT_SYMBOL(drm_dma_get_buffers);
-#if DRM_DMA_HISTOGRAM
-EXPORT_SYMBOL(drm_histogram_slot);
-EXPORT_SYMBOL(drm_histogram_compute);
-#endif
-
-/* Misc. IOCTL support (ioctl.c) */
-EXPORT_SYMBOL(drm_irq_busid);
-EXPORT_SYMBOL(drm_getunique);
-EXPORT_SYMBOL(drm_setunique);
-
-/* Context IOCTL support (context.c) */
-EXPORT_SYMBOL(drm_resctx);
-EXPORT_SYMBOL(drm_addctx);
-EXPORT_SYMBOL(drm_modctx);
-EXPORT_SYMBOL(drm_getctx);
-EXPORT_SYMBOL(drm_switchctx);
-EXPORT_SYMBOL(drm_newctx);
-EXPORT_SYMBOL(drm_rmctx);
-
-/* Drawable IOCTL support (drawable.c) */
-EXPORT_SYMBOL(drm_adddraw);
-EXPORT_SYMBOL(drm_rmdraw);
-
-/* Authentication IOCTL support (auth.c) */
-EXPORT_SYMBOL(drm_add_magic);
-EXPORT_SYMBOL(drm_remove_magic);
-EXPORT_SYMBOL(drm_getmagic);
-EXPORT_SYMBOL(drm_authmagic);
-
-/* Locking IOCTL support (lock.c) */
-EXPORT_SYMBOL(drm_block);
-EXPORT_SYMBOL(drm_unblock);
-EXPORT_SYMBOL(drm_lock_take);
-EXPORT_SYMBOL(drm_lock_transfer);
-EXPORT_SYMBOL(drm_lock_free);
-EXPORT_SYMBOL(drm_finish);
-EXPORT_SYMBOL(drm_flush_unblock);
-EXPORT_SYMBOL(drm_flush_block_and_flush);
-
-/* Context Bitmap support (ctxbitmap.c) */
-EXPORT_SYMBOL(drm_ctxbitmap_init);
-EXPORT_SYMBOL(drm_ctxbitmap_cleanup);
-EXPORT_SYMBOL(drm_ctxbitmap_next);
-EXPORT_SYMBOL(drm_ctxbitmap_free);
-
-/* AGP/GART support (agpsupport.c) */
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-EXPORT_SYMBOL(drm_agp);
-EXPORT_SYMBOL(drm_agp_init);
-EXPORT_SYMBOL(drm_agp_uninit);
-EXPORT_SYMBOL(drm_agp_acquire);
-EXPORT_SYMBOL(drm_agp_release);
-EXPORT_SYMBOL(drm_agp_enable);
-EXPORT_SYMBOL(drm_agp_info);
-EXPORT_SYMBOL(drm_agp_alloc);
-EXPORT_SYMBOL(drm_agp_free);
-EXPORT_SYMBOL(drm_agp_unbind);
-EXPORT_SYMBOL(drm_agp_bind);
-#endif
index 32b2ba2b9c3c17a4aac9495f16acb94d32c805d5..13d37c2459f01ad3c8bd4b8bc0d4bcc6ed2c0060 100644 (file)
@@ -50,8 +50,8 @@
 static drm_device_t          gamma_device;
 
 static struct file_operations gamma_fops = {
-#if LINUX_VERSION_CODE >= 0x020322
-                               /* This started being used approx. 2.3.34 */
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* This started being used during 2.4.0-test */
        owner:   THIS_MODULE,
 #endif
        open:    gamma_open,
index 5cab071e4ab87196779a6f47eb5bc5b72a0163f8..275663a1bdb8bc46a9b6ecc22857cb4080a397d4 100644 (file)
@@ -44,8 +44,8 @@ static drm_device_t         i810_device;
 drm_ctx_t                    i810_res_ctx;
 
 static struct file_operations i810_fops = {
-#if LINUX_VERSION_CODE >= 0x020322
-                               /* This started being used approx. 2.3.34 */
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* This started being used during 2.4.0-test */
        owner:   THIS_MODULE,
 #endif
        open:    i810_open,
index 43e46f1d63fd388d459b5a350cb2ef394c8f68ea..34d19b203665010c2fb2404d8575cdbebaf43a69 100644 (file)
@@ -32,6 +32,7 @@
 #define __NO_VERSION__
 #include <linux/config.h>
 #include "drmP.h"
+#include <linux/wrapper.h>
 
 typedef struct drm_mem_stats {
        const char        *name;
@@ -246,7 +247,12 @@ unsigned long drm_alloc_pages(int order, int area)
        for (addr = address, sz = bytes;
             sz > 0;
             addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* Argument type changed in 2.4.0-test6/pre8 */
                mem_map_reserve(virt_to_page(addr));
+#else
+               mem_map_reserve(MAP_NR(addr));
+#endif
        }
        
        return address;
@@ -267,7 +273,12 @@ void drm_free_pages(unsigned long address, int order, int area)
                for (addr = address, sz = bytes;
                     sz > 0;
                     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* Argument type changed in 2.4.0-test6/pre8 */
                        mem_map_unreserve(virt_to_page(addr));
+#else
+                       mem_map_unreserve(MAP_NR(addr));
+#endif
                }
                free_pages(address, order);
        }
index 7aae6f3e9a29fd7dfa35e1d2ed26637ec87df876..acc42b833f2768dfe9c2505f3a2e95268f27eb40 100644 (file)
@@ -45,8 +45,8 @@ static drm_device_t         mga_device;
 drm_ctx_t                    mga_res_ctx;
 
 static struct file_operations mga_fops = {
-#if LINUX_VERSION_CODE >= 0x020322
-                               /* This started being used approx. 2.3.34 */
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* This started being used during 2.4.0-test */
        owner:   THIS_MODULE,
 #endif
        open:    mga_open,
index 6b1b19d5e28272328f2b0b526418ce1cea799441..fac882471d276f6dd536ffc57f5b24b4db635f42 100644 (file)
@@ -44,8 +44,8 @@ static drm_device_t         r128_device;
 drm_ctx_t                    r128_res_ctx;
 
 static struct file_operations r128_fops = {
-#if LINUX_VERSION_CODE >= 0x020322
-                               /* This started being used approx. 2.3.34 */
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* This started being used during 2.4.0-test */
        owner:   THIS_MODULE,
 #endif
        open:    r128_open,
index ba8c40ceb849c21199d81b21ce9183dc94368f66..59f1019708b60b5c629765e4acfc0f0a37e11926 100644 (file)
@@ -45,8 +45,8 @@ static drm_device_t         tdfx_device;
 drm_ctx_t                    tdfx_res_ctx;
 
 static struct file_operations tdfx_fops = {
-#if LINUX_VERSION_CODE >= 0x020322
-                               /* This started being used approx. 2.3.34 */
+#if LINUX_VERSION_CODE >= 0x020400
+                               /* This started being used during 2.4.0-test */
        owner:   THIS_MODULE,
 #endif
        open:    tdfx_open,
index 1386bd172eb0ca8e7f8489e70fcff5785bd1d0f1..d295529ba76d79bbffd13f0ffd6562a2b9765d74 100644 (file)
@@ -44,6 +44,12 @@ struct vm_operations_struct   drm_vm_shm_ops = {
        close:   drm_vm_close,
 };
 
+struct vm_operations_struct   drm_vm_shm_lock_ops = {
+       nopage:  drm_vm_shm_nopage_lock,
+       open:    drm_vm_open,
+       close:   drm_vm_close,
+};
+
 struct vm_operations_struct   drm_vm_dma_ops = {
        nopage:  drm_vm_dma_nopage,
        open:    drm_vm_open,
@@ -76,6 +82,40 @@ struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
                               unsigned long address,
                               int write_access)
 #endif
+{
+#if LINUX_VERSION_CODE >= 0x020300
+       drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
+#else
+       drm_map_t        *map    = (drm_map_t *)vma->vm_pte;
+#endif
+       unsigned long    physical;
+       unsigned long    offset;
+
+       if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+       if (!map)                  return NOPAGE_OOM;  /* Nothing allocated */
+
+       offset   = address - vma->vm_start;
+       physical = (unsigned long)map->handle + offset;
+       atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
+
+       DRM_DEBUG("0x%08lx => 0x%08lx\n", address, physical);
+#if LINUX_VERSION_CODE < 0x020317
+       return physical;
+#else
+       return virt_to_page(physical);
+#endif
+}
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+                                    unsigned long address,
+                                    int write_access)
+#else
+                               /* Return type changed in 2.3.23 */
+struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+                                   unsigned long address,
+                                   int write_access)
+#endif
 {
        drm_file_t       *priv   = vma->vm_file->private_data;
        drm_device_t     *dev    = priv->dev;
@@ -89,13 +129,13 @@ struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
        offset   = address - vma->vm_start;
        page     = offset >> PAGE_SHIFT;
        physical = (unsigned long)dev->lock.hw_lock + offset;
-       atomic_inc(&virt_to_page(physical)->count);     /* Dec. by kernel */
+       atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
 
        DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical);
 #if LINUX_VERSION_CODE < 0x020317
        return physical;
 #else
-       return (virt_to_page(physical));
+       return virt_to_page(physical);
 #endif
 }
 
@@ -130,7 +170,7 @@ struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
 #if LINUX_VERSION_CODE < 0x020317
        return physical;
 #else
-       return (virt_to_page(physical));
+       return virt_to_page(physical);
 #endif
 }
 
@@ -298,7 +338,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_SHM:
-               vma->vm_ops = &drm_vm_shm_ops;
+               if (map->flags & _DRM_CONTAINS_LOCK)
+                       vma->vm_ops = &drm_vm_shm_lock_ops;
+               else {
+                       vma->vm_ops = &drm_vm_shm_ops;
+#if LINUX_VERSION_CODE >= 0x020300
+                       vma->vm_private_data = (void *)map;
+#else
+                       vma->vm_pte = (unsigned long)map;
+#endif
+               }
+
                                /* Don't let this area swap.  Change when
                                   DRM_KERNEL advisory is supported. */
                vma->vm_flags |= VM_LOCKED;
index bf3addcf4ef5b67780bd8113536301abb0fc1cf1..02fe29dac1cf85a9e6022c0fb567e80679caf6fe 100644 (file)
@@ -50,7 +50,7 @@ static inline void *dmaalloc(size_t size)
        if (addr) {
                struct page *page;
 
-               for (page = virt_to_page(addr); page < get_mem_map(addr+size); page++)
+               for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
                        mem_map_reserve(page);
        }
        return (void *)addr;
index f4f61d850c61be53fed64f2db8fc71a70fee3a2f..9ed33d0f38b545be8be37ffe503556c51d3d63e5 100644 (file)
@@ -366,7 +366,7 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
                 * No need to return "unknown" for calls without OAD,
                 * cause that's handled in linklevel now (replaced by '0')
                 */
-               ic.parm.setup = chanp->proc->para.setup;
+               memcpy (&ic.parm.setup, &chanp->proc->para.setup, sizeof(ic.parm.setup));
                ret = chanp->cs->iif.statcallb(&ic);
                if (chanp->debug & 1)
                        link_debug(chanp, 1, "statcallb ret=%d", ret);
@@ -383,7 +383,7 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
                                FsmChangeState(fi, ST_IN_PROCEED_SEND);
                                chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
                                if (ret == 5) {
-                                       chanp->setup = ic.parm.setup;
+                                       memcpy (&chanp->setup, &ic.parm.setup, sizeof(chanp->setup));
                                        chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
                                }
                                break;
@@ -1506,7 +1506,7 @@ HiSax_command(isdn_ctrl * ic)
                                link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
                                        ic->parm.setup.eazmsn, ic->parm.setup.phone,
                                        ic->parm.setup.si1, ic->parm.setup.si2);
-                       chanp->setup = ic->parm.setup;
+                       memcpy (&chanp->setup, &ic->parm.setup, sizeof (chanp->setup));
                        if (!strcmp(chanp->setup.eazmsn, "0"))
                                chanp->setup.eazmsn[0] = '\0';
                        /* this solution is dirty and may be change, if
@@ -1722,7 +1722,7 @@ HiSax_command(isdn_ctrl * ic)
                        chanp = csta->channel + ic->arg;
                        if (chanp->debug & 1)
                                link_debug(chanp, 1, "REDIR");
-                       chanp->setup = ic->parm.setup;
+                       memcpy (&chanp->setup, &ic->parm.setup, sizeof(chanp->setup));
                        FsmEvent(&chanp->fi, EV_REDIR, NULL);
                        break;
 
index 2d01819ae35dd1fbb57a042aeac2ba7d120b4c5e..ee56447c8b7bff18fc1364c464ebdf386bece154 100644 (file)
@@ -883,7 +883,7 @@ down1tr6(struct PStack *st, int pr, void *arg)
                } else {
                        proc->chan = chan;
                        chan->proc = proc;
-                       proc->para.setup = chan->setup;
+                       memcpy (&proc->para.setup, &chan->setup, sizeof (chan->setup));
                        proc->callref = cr;
                }
        } else {
index 43ce9c9568158da1ae9da7bec08f4b0a7b50bf6c..32ae7576f95db049150c442759c712ec0c280f84 100644 (file)
@@ -3081,7 +3081,7 @@ dss1down(struct PStack *st, int pr, void *arg)
                if ((proc = dss1_new_l3_process(st, cr))) {
                        proc->chan = chan;
                        chan->proc = proc;
-                       proc->para.setup = chan->setup;
+                       memcpy (&proc->para.setup, &chan->setup, sizeof (chan->setup));
                        proc->callref = cr;
                }
        } else {
index 9204a878abb8f3aa3f8985f94417a53a0a6beb99..caf46b11202cc56afb19127bf82a90aa09edff9a 100644 (file)
@@ -48,7 +48,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.101 $";
+static char *isdn_revision = "$Revision: 1.108 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -73,6 +73,7 @@ static int isdn_writebuf_stub(int, int, const u_char *, int, int);
 static void set_global_features(void);
 static void isdn_register_devfs(int);
 static void isdn_unregister_devfs(int);
+static int isdn_wildmat(char *s, char *p);
 
 void
 isdn_lock_drivers(void)
@@ -166,7 +167,7 @@ isdn_star(char *s, char *p)
  * [^xyz]  matches any single character not in the set of characters
  */
 
-int
+static int
 isdn_wildmat(char *s, char *p)
 {
        register int last;
@@ -212,6 +213,23 @@ isdn_wildmat(char *s, char *p)
        return (*s == '\0')?0:nostar;
 }
 
+int isdn_msncmp( const char * msn1, const char * msn2 )
+{
+       char TmpMsn1[ ISDN_MSNLEN ];
+       char TmpMsn2[ ISDN_MSNLEN ];
+       char *p;
+
+       for ( p = TmpMsn1; *msn1 && *msn1 != ':'; )  // Strip off a SPID
+               *p++ = *msn1++;
+       *p = '\0';
+
+       for ( p = TmpMsn2; *msn2 && *msn2 != ':'; )  // Strip off a SPID
+               *p++ = *msn2++;
+       *p = '\0';
+
+       return isdn_wildmat( TmpMsn1, TmpMsn2 );
+}
+
 static void
 isdn_free_queue(struct sk_buff_head *queue)
 {
@@ -275,10 +293,6 @@ isdn_timer_funct(ulong dummy)
                        }
                        if (tf & ISDN_TIMER_CARRIER)
                                isdn_tty_carrier_timeout();
-#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
-                       if (tf & ISDN_TIMER_IPPP)
-                               isdn_ppp_timer_timeout();
-#endif
                }
        }
        if (tf) 
@@ -439,6 +453,7 @@ isdn_status_callback(isdn_ctrl * c)
        int r;
        int retval = 0;
        isdn_ctrl cmd;
+       isdn_net_dev *p;
 
        di = c->driver;
        i = isdn_dc2minor(di, c->arg);
@@ -487,7 +502,7 @@ isdn_status_callback(isdn_ctrl * c)
                                return 0;
                        }
                        /* Try to find a network-interface which will accept incoming call */
-                       r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup));
+                       r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
                        switch (r) {
                                case 0:
                                        /* No network-device replies.
@@ -496,7 +511,7 @@ isdn_status_callback(isdn_ctrl * c)
                                         * 3 on eventually match, if CID is longer.
                                         */
                                         if (c->command == ISDN_STAT_ICALL)
-                                         if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval);
+                                         if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval);
 #ifdef CONFIG_ISDN_DIVERSION 
                                          if (divert_if)
                                          if ((retval = divert_if->stat_callback(c))) 
@@ -517,9 +532,16 @@ isdn_status_callback(isdn_ctrl * c)
                                        cmd.driver = di;
                                        cmd.arg = c->arg;
                                        cmd.command = ISDN_CMD_ACCEPTD;
-                                       isdn_command(&cmd);
-                                       retval = 1;
+                                       for ( p = dev->netdev; p; p = p->next )
+                                               if ( p->local->isdn_channel == cmd.arg )
+                                               {
+                                                       strcpy( cmd.parm.setup.eazmsn, p->local->msn );
+                                                       isdn_command(&cmd);
+                                                       retval = 1;
+                                                       break;
+                                               }
                                        break;
+
                                case 2: /* For calling back, first reject incoming call ... */
                                case 3: /* Interface found, but down, reject call actively  */
                                        retval = 2;
@@ -968,54 +990,78 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
        ulong flags;
        int drvidx;
        int chidx;
+       int retval;
        char *p;
 
        if (off != &file->f_pos)
                return -ESPIPE;
 
+       lock_kernel();
        if (minor == ISDN_MINOR_STATUS) {
                if (!file->private_data) {
-                       if (file->f_flags & O_NONBLOCK)
-                               return -EAGAIN;
+                       if (file->f_flags & O_NONBLOCK) {
+                               retval = -EAGAIN;
+                               goto out;
+                       }
                        interruptible_sleep_on(&(dev->info_waitq));
                }
                p = isdn_statstr();
                file->private_data = 0;
                if ((len = strlen(p)) <= count) {
-                       if (copy_to_user(buf, p, len))
-                               return -EFAULT;
+                       if (copy_to_user(buf, p, len)) {
+                               retval = -EFAULT;
+                               goto out;
+                       }
                        *off += len;
-                       return len;
+                       retval = len;
+                       goto out;
                }
-               return 0;
+               retval = 0;
+               goto out;
+       }
+       if (!dev->drivers) {
+               retval = -ENODEV;
+               goto out;
        }
-       if (!dev->drivers)
-               return -ENODEV;
        if (minor < ISDN_MINOR_CTRL) {
+               printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
                drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0)
-                       return -ENODEV;
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-                       return -ENODEV;
+               if (drvidx < 0) {
+                       retval = -ENODEV;
+                       goto out;
+               }
+               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
+                       retval = -ENODEV;
+                       goto out;
+               }
                chidx = isdn_minor2chan(minor);
-               if(  ! (p = kmalloc(count,GFP_KERNEL))  ) return -ENOMEM;
+               if (!(p = kmalloc(count, GFP_KERNEL))) {
+                       retval = -ENOMEM;
+                       goto out;
+               }
                save_flags(flags);
                cli();
                len = isdn_readbchan(drvidx, chidx, p, 0, count,
                                     &dev->drv[drvidx]->rcv_waitq[chidx]);
                *off += len;
                restore_flags(flags);
-               if( copy_to_user(buf,p,len) ) len = -EFAULT;
+               if (copy_to_user(buf,p,len)) 
+                       len = -EFAULT;
                kfree(p);
-               return len;
+               retval = len;
+               goto out;
        }
        if (minor <= ISDN_MINOR_CTRLMAX) {
                drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-               if (drvidx < 0)
-                       return -ENODEV;
+               if (drvidx < 0) {
+                       retval = -ENODEV;
+                       goto out;
+               }
                if (!dev->drv[drvidx]->stavail) {
-                       if (file->f_flags & O_NONBLOCK)
-                               return -EAGAIN;
+                       if (file->f_flags & O_NONBLOCK) {
+                               retval = -EAGAIN;
+                               goto out;
+                       }
                        interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
                }
                if (dev->drv[drvidx]->interface->readstat)
@@ -1032,17 +1078,23 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
                        dev->drv[drvidx]->stavail = 0;
                restore_flags(flags);
                *off += len;
-               return len;
+               retval = len;
+               goto out;
        }
 #ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX)
-               return (isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count));
+       if (minor <= ISDN_MINOR_PPPMAX) {
+               retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
+               goto out;
+       }
 #endif
-       return -ENODEV;
+       retval = -ENODEV;
+ out:
+       unlock_kernel();
+       return retval;
 }
 
 static loff_t
-isdn_lseek(struct file *file, loff_t offset, int orig)
+isdn_llseek(struct file *file, loff_t offset, int orig)
 {
        return -ESPIPE;
 }
@@ -1053,6 +1105,7 @@ isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
        uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
        int drvidx;
        int chidx;
+       int retval;
 
        if (off != &file->f_pos)
                return -ESPIPE;
@@ -1061,21 +1114,31 @@ isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
                return -EPERM;
        if (!dev->drivers)
                return -ENODEV;
+
+       lock_kernel();
        if (minor < ISDN_MINOR_CTRL) {
+               printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
                drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0)
-                       return -ENODEV;
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-                       return -ENODEV;
+               if (drvidx < 0) {
+                       retval = -ENODEV;
+                       goto out;
+               }
+               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
+                       retval = -ENODEV;
+                       goto out;
+               }
                chidx = isdn_minor2chan(minor);
                while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
                        interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
-               return count;
+               retval = count;
+               goto out;
        }
        if (minor <= ISDN_MINOR_CTRLMAX) {
                drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-               if (drvidx < 0)
-                       return -ENODEV;
+               if (drvidx < 0) {
+                       retval = -ENODEV;
+                       goto out;
+               }
                /*
                 * We want to use the isdnctrl device to load the firmware
                 *
@@ -1083,16 +1146,22 @@ isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
                 return -ENODEV;
                 */
                if (dev->drv[drvidx]->interface->writecmd)
-                       return (dev->drv[drvidx]->interface->
-                               writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor)));
+                       retval = dev->drv[drvidx]->interface->
+                               writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor));
                else
-                       return count;
+                       retval = count;
+               goto out;
        }
 #ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX)
-               return (isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count));
+       if (minor <= ISDN_MINOR_PPPMAX) {
+               retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
+               goto out;
+       }
 #endif
-       return -ENODEV;
+       retval = -ENODEV;
+ out:
+       unlock_kernel();
+       return retval;
 }
 
 static unsigned int
@@ -1102,32 +1171,38 @@ isdn_poll(struct file *file, poll_table * wait)
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 
+       lock_kernel();
        if (minor == ISDN_MINOR_STATUS) {
                poll_wait(file, &(dev->info_waitq), wait);
                /* mask = POLLOUT | POLLWRNORM; */
                if (file->private_data) {
                        mask |= POLLIN | POLLRDNORM;
                }
-               return mask;
+               goto out;
        }
        if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
                if (drvidx < 0) {
                        /* driver deregistered while file open */
-                       return POLLHUP;
+                       mask = POLLHUP;
+                       goto out;
                }
                poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
                mask = POLLOUT | POLLWRNORM;
                if (dev->drv[drvidx]->stavail) {
                        mask |= POLLIN | POLLRDNORM;
                }
-               return mask;
+               goto out;
        }
 #ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX)
-               return (isdn_ppp_poll(file, wait));
+       if (minor <= ISDN_MINOR_PPPMAX) {
+               mask = isdn_ppp_poll(file, wait);
+               goto out;
+       }
 #endif
-       printk(KERN_ERR "isdn_common: isdn_poll 2 -> what the hell\n");
-       return POLLERR;
+       mask = POLLERR;
+ out:
+       unlock_kernel();
+       return mask;
 }
 
 
@@ -1602,6 +1677,7 @@ isdn_open(struct inode *ino, struct file *filep)
        if (!dev->channels)
                return -ENODEV;
        if (minor < ISDN_MINOR_CTRL) {
+               printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
                drvidx = isdn_minor2drv(minor);
                if (drvidx < 0)
                        return -ENODEV;
@@ -1680,7 +1756,7 @@ isdn_close(struct inode *ino, struct file *filep)
 static struct file_operations isdn_fops =
 {
        owner:          THIS_MODULE,
-       llseek:         isdn_lseek,
+       llseek:         isdn_llseek,
        read:           isdn_read,
        write:          isdn_write,
        poll:           isdn_poll,
@@ -1865,7 +1941,6 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
                skb_pull(nskb, sizeof(int));
                if (!nskb->len) {
                        dev_kfree_skb(nskb);
-                       dev_kfree_skb(skb);
                        return v110_ret;
                }
                /* V.110 must always be acknowledged */
@@ -1904,9 +1979,10 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
                        atomic_inc(&dev->v110use[idx]);
                        dev->v110[idx]->skbuser++;
                        atomic_dec(&dev->v110use[idx]);
-                       dev_kfree_skb(skb);
                        /* For V.110 return unencoded data length */
                        ret = v110_ret;
+                       /* if the complete frame was send we free the skb;
+                          if not upper function will requeue the skb */ 
                        if (ret == skb->len)
                                dev_kfree_skb(skb);
                }
@@ -2228,7 +2304,7 @@ static void isdn_init_devfs(void)
                            &isdn_fops, NULL);
        dev->devfs_handle_isdnctrl =
            devfs_register (devfs_handle, "isdnctrl", DEVFS_FL_DEFAULT,
-                           ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR,
+                           ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, 
                            &isdn_fops, NULL);
 }
 
index bf4c4cedc914a985fcb4d1862b4abf18f300ec62..b23506ebb5042a6a641126ec0115ebfc6950be05 100644 (file)
@@ -50,7 +50,7 @@ extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *
 extern int isdn_get_free_channel(int, int, int, int, int, char *);
 extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int register_isdn(isdn_if * i);
-extern int isdn_wildmat(char *, char *);
+extern int isdn_msncmp( const char *,  const char *);
 extern int isdn_add_channels(driver *, int, int, int);
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
 extern void isdn_dumppkt(char *, u_char *, int, int);
index 2ad00bee58ee159d0a23dead2c1f3bb5105fc81c..4951bb29eb1993f422649283010d565dd691fd88 100644 (file)
@@ -455,7 +455,8 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 #endif /* CONFIG_ISDN_X25 */
                                if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
 #ifdef CONFIG_ISDN_PPP
-                                       isdn_ppp_free(lp);
+                                       if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+                                               isdn_ppp_free(lp);
 #endif
                                        isdn_net_lp_disconnected(lp);
                                        isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
@@ -847,9 +848,19 @@ isdn_net_hangup(struct net_device *d)
 #endif
 
        if (lp->flags & ISDN_NET_CONNECTED) {
+               if (lp->slave != NULL) {
+                       isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
+                       if (slp->flags & ISDN_NET_CONNECTED) {
+                               printk(KERN_INFO
+                                       "isdn_net: hang up slave %s before %s\n",
+                                       slp->name, lp->name);
+                               isdn_net_hangup(lp->slave);
+                       }
+               }
                printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
 #ifdef CONFIG_ISDN_PPP
-               isdn_ppp_free(lp);
+               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+                       isdn_ppp_free(lp);
 #endif
                isdn_net_lp_disconnected(lp);
 #ifdef CONFIG_ISDN_X25
@@ -979,8 +990,7 @@ void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
        }
 
        spin_lock_bh(&lp->xmit_lock);
-       if (!isdn_net_lp_busy(lp))
-       {
+       if (!isdn_net_lp_busy(lp)) {
                isdn_net_writebuf_skb(lp, skb);
        } else {
                skb_queue_tail(&lp->super_tx_queue, skb);
@@ -1081,7 +1091,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
 
        lp = isdn_net_get_locked_lp(nd);
        if (!lp) {
-               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", lp->name);
+               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
                return 1;
        }
        /* we have our lp locked from now on */
@@ -1894,7 +1904,7 @@ isdn_net_swap_usage(int i1, int i2)
  *                   would eventually match if CID was longer.
  */
 int
-isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
+isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
 {
        char *eaz;
        int si1;
@@ -1910,19 +1920,19 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
        /* Search name in netdev-chain */
        save_flags(flags);
        cli();
-       if (!setup.phone[0]) {
+       if (!setup->phone[0]) {
                nr[0] = '0';
                nr[1] = '\0';
                printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
        } else
-               strcpy(nr, setup.phone);
-       si1 = (int) setup.si1;
-       si2 = (int) setup.si2;
-       if (!setup.eazmsn[0]) {
+               strcpy(nr, setup->phone);
+       si1 = (int) setup->si1;
+       si2 = (int) setup->si2;
+       if (!setup->eazmsn[0]) {
                printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
                eaz = "0";
        } else
-               eaz = setup.eazmsn;
+               eaz = setup->eazmsn;
        if (dev->net_verbose > 1)
                printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
        /* Accept only calls with Si1 = 7 (Data-Transmission) */
@@ -1953,7 +1963,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
                                break;
                }
                swapped = 0;
-               if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di))))
+               if (!(matchret = isdn_msncmp(eaz, isdn_map_eaz2msn(lp->msn, di))))
                        ematch = 1;
                /* Remember if more numbers eventually can match */
                if (matchret > wret)
@@ -2045,7 +2055,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
                        n = lp->phone[0];
                        if (lp->flags & ISDN_NET_SECURE) {
                                while (n) {
-                                       if (!isdn_wildmat(nr, n->num))
+                                       if (!isdn_msncmp(nr, n->num))
                                                break;
                                        n = (isdn_net_phone *) n->next;
                                }
@@ -2356,11 +2366,6 @@ isdn_net_new(char *name, struct net_device *master)
        }
        netdev->local->magic = ISDN_NET_MAGIC;
 
-#ifdef CONFIG_ISDN_PPP
-       netdev->mp_last = NULL; /* mpqueue is empty */
-       netdev->ib.next_num = 0;
-       netdev->ib.last = NULL;
-#endif
        netdev->queue = netdev->local;
        spin_lock_init(&netdev->queue_lock);
 
index ddf23562b2aa6eb3e46eccbdfaac656d1fc3db02..b852e23acacf70db37a26944aab2530ed7643393 100644 (file)
@@ -75,7 +75,7 @@ extern int isdn_net_addphone(isdn_net_ioctl_phone *);
 extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
 extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
 extern int isdn_net_delphone(isdn_net_ioctl_phone *);
-extern int isdn_net_find_icall(int, int, int, setup_parm);
+extern int isdn_net_find_icall(int, int, int, setup_parm *);
 extern void isdn_net_hangup(struct net_device *);
 extern void isdn_net_dial(void);
 extern void isdn_net_autohup(void);
@@ -116,13 +116,15 @@ static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
        while (isdn_net_lp_busy(nd->queue)) {
                spin_unlock_bh(&nd->queue->xmit_lock);
                nd->queue = nd->queue->next;
-               if (nd->queue == lp) /* not found -- should never happen */
-                       return 0;
+               if (nd->queue == lp) { /* not found -- should never happen */
+                       lp = NULL;
+                       goto errout;
+               }
                spin_lock_bh(&nd->queue->xmit_lock);
        }
        lp = nd->queue;
-
        nd->queue = nd->queue->next;
+errout:
        spin_unlock_irqrestore(&nd->queue_lock, flags);
        return lp;
 }
index 5fb2bab395ee0f73256f409df2b2711149e52f28..20499506114cdd2e76223cc0f69a8521061e3c39 100644 (file)
@@ -74,17 +74,18 @@ static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
 
 
 #ifdef CONFIG_ISDN_MPP
-static int isdn_ppp_bundle(struct ippp_struct *, int unit);
-static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
-static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min);
-static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev, isdn_net_local *, long min);
-static void isdn_ppp_free_sqqueue(isdn_net_dev *);
-static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
-                                int BEbyte, long *sqno, int min_sqno);
-static void isdn_ppp_free_mpqueue(isdn_net_dev *);
-#endif
+static ippp_bundle * isdn_ppp_bundle_arr = NULL;
+static int isdn_ppp_mp_bundle_array_init(void);
+static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to );
+static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, 
+                                                       struct sk_buff *skb);
+static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
 
-char *isdn_ppp_revision = "$Revision: 1.69 $";
+static int isdn_ppp_bundle(struct ippp_struct *, int unit);
+#endif /* CONFIG_ISDN_MPP */
+  
+char *isdn_ppp_revision = "$Revision: 1.77 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
@@ -119,7 +120,6 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot
 int
 isdn_ppp_free(isdn_net_local * lp)
 {
-       isdn_net_local *master_lp = lp;
        unsigned long flags;
        struct ippp_struct *is;
 
@@ -130,17 +130,18 @@ isdn_ppp_free(isdn_net_local * lp)
        cli();
 
 #ifdef CONFIG_ISDN_MPP
-       if (lp->next == lp) {   /* last link in queue? */
-               master_lp->netdev->ib.bundled = 0;
-               isdn_ppp_free_mpqueue(master_lp->netdev);
-               isdn_ppp_free_sqqueue(master_lp->netdev);
-       }
+       spin_lock(&lp->netdev->pb->lock);
 #endif
-
        isdn_net_rm_from_bundle(lp);
+#ifdef CONFIG_ISDN_MPP
+       if (lp->netdev->pb->ref_ct == 1)        /* last link in queue? */
+               isdn_ppp_mp_cleanup(lp);
+
+       lp->netdev->pb->ref_ct--;
+       spin_unlock(&lp->netdev->pb->lock);
+#endif /* CONFIG_ISDN_MPP */
 
        is = ippp_table[lp->ppp_slot];
-       
        if ((is->state & IPPP_CONNECT))
                isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
        else if (is->state & IPPP_ASSIGNED)
@@ -153,7 +154,6 @@ isdn_ppp_free(isdn_net_local * lp)
        lp->ppp_slot = -1;      /* is this OK ?? */
 
        restore_flags(flags);
-
        return 0;
 }
 
@@ -170,7 +170,6 @@ isdn_ppp_bind(isdn_net_local * lp)
 
        save_flags(flags);
        cli();
-
        if (lp->pppbind < 0) {  /* device bounded to ippp device ? */
                isdn_net_dev *net_dev = dev->netdev;
                char exclusive[ISDN_MAX_CHANNELS];      /* exclusive flags */
@@ -207,20 +206,16 @@ isdn_ppp_bind(isdn_net_local * lp)
                printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
                return -1;
        }
+       
        lp->ppp_slot = i;
-
-       /* reset some values */
-       lp->netdev->ib.bundled = 0;
-       lp->netdev->ib.next_num = 0;
-       lp->netdev->ib.modify = 0;
-       lp->netdev->ib.last = NULL;
-       lp->netdev->ib.min = 0;
-       lp->netdev->ib.sq = NULL;
-
        is = ippp_table[i];
        is->lp = lp;
        is->unit = unit;
        is->state = IPPP_OPEN | IPPP_ASSIGNED;  /* assigned to a netdevice but not connected */
+#ifdef CONFIG_ISDN_MPP
+       if (isdn_ppp_mp_init(lp, NULL) < 0)
+               return -ENOMEM;
+#endif /* CONFIG_ISDN_MPP */
 
        restore_flags(flags);
 
@@ -313,7 +308,6 @@ isdn_ppp_open(int min, struct file *file)
        is->mp_seqno = 0;       /* MP sequence number */
        is->pppcfg = 0;         /* ppp configuration */
        is->mpppcfg = 0;        /* mppp configuration */
-       is->range = 0x1000000;  /* MP: 24 bit range */
        is->last_link_seqno = -1;       /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
        is->unit = -1;          /* set, when we have our interface */
        is->mru = 1524;         /* MRU, default 1524 */
@@ -810,6 +804,11 @@ isdn_ppp_init(void)
 {
        int i,
         j;
+        
+#ifdef CONFIG_ISDN_MPP
+       if( isdn_ppp_mp_bundle_array_init() < 0 )
+               return -ENOMEM;
+#endif /* CONFIG_ISDN_MPP */
 
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                if (!(ippp_table[i] = (struct ippp_struct *)
@@ -841,6 +840,12 @@ isdn_ppp_cleanup(void)
 
        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
                kfree(ippp_table[i]);
+
+#ifdef CONFIG_ISDN_MPP
+       if (isdn_ppp_bundle_arr)
+               kfree(isdn_ppp_bundle_arr);
+#endif /* CONFIG_ISDN_MPP */
+
 }
 
 /*
@@ -866,9 +871,16 @@ static int isdn_ppp_strip_proto(struct sk_buff *skb)
 void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
 {
        struct ippp_struct *is;
+       int slot;
        int proto;
 
-       is = ippp_table[lp->ppp_slot];
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+               kfree_skb(skb);
+               return;
+       }
+       is = ippp_table[slot];
 
        if (is->debug & 0x4) {
                printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
@@ -890,7 +902,6 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
 
 #ifdef CONFIG_ISDN_MPP
        if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
-               int sqno_end;
 
                if(is->compflags & SC_LINK_DECOMP_ON) { 
                        if(proto == PPP_COMPFRAG) {
@@ -906,150 +917,12 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                }
 
                if (proto == PPP_MP) {
-                       isdn_net_local *lpq;
-                       long sqno, min_sqno, tseq;
-
-                       u_char BEbyte = skb->data[0];
-                       if (is->debug & 0x8)
-                               printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto,
-                                      (int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
-                                      (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
-                       if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) {
-                               sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
-                               skb_pull(skb, 4);
-                       } else {
-                               sqno = (((int) skb->data[0] & 0xf) << 8) + (int) skb->data[1];
-                               skb_pull(skb, 2);
-                       }
-
-                       /*
-                        * new sequence number lower than last number? (this is only allowed
-                        * for overflow case)
-                        */
-                       if ((tseq = is->last_link_seqno) >= sqno) {
-                               int range = is->range;
-                               if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
-                                       printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq);
-                               else {
-                                       sqno += range;
-                                       is->last_link_seqno = sqno;
-                               }
-                       } else {
-                               /* here, we should also add an redundancy check */
-                               is->last_link_seqno = sqno;
-                       }
-
-                       /* 
-                        * step over all links to find lowest link number
-                        */
-                       for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) {
-                               long lls = ippp_table[lpq->ppp_slot]->last_link_seqno;
-                               if (lls >= 0 && lls < min_sqno)
-                                       min_sqno = lls;
-                               lpq = lpq->next;
-                               if (lpq == net_dev->queue)
-                                       break;
-                       }
-
-                       /*
-                        * for the case, that the last frame numbers of all 
-                        * links are overflowed: mask/reduce the sequenece number to
-                        * 'normal' numbering.
-                        */
-                       if (min_sqno >= ippp_table[lpq->ppp_slot]->range) {
-                               int mask = ippp_table[lpq->ppp_slot]->range-1;  /* range is power of two, so a mask will do the job */
-                               isdn_ppp_mask_queue(net_dev, mask);
-                               net_dev->ib.next_num &= mask;
-                               {
-                                       struct sqqueue *q = net_dev->ib.sq;
-                                       while (q) {
-                                               q->sqno_start &= mask;
-                                               q->sqno_end &= mask;
-                                       }
-                               }
-                               min_sqno &= mask;
-                               for (lpq = net_dev->queue;;) {
-                                       if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0)
-                                               ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
-                                       lpq = lpq->next;
-                                       if (lpq == net_dev->queue)
-                                               break;
-                               }
-                       }
-                       if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
-                               static int dmes = 0;
-                               if( !dmes ) {
-                                       printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
-                                       dmes = 1;
-                               }
-                               if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb, BEbyte, &sqno, min_sqno)) < 0) {
-                                       net_dev->ib.modify = 1; /* block timeout-timer */
-                                       isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno);
-                                       net_dev->ib.modify = 0;
-                                       return; /* no packet complete */
-                               }
-                       } else
-                               sqno_end = sqno;
-
-                       if (is->debug & 0x40)
-                               printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n", min_sqno, sqno_end, net_dev->ib.next_num);
-
-                       /*
-                        * MP buffer management .. reorders incoming packets ..
-                        * lotsa mem-copies and not heavily tested.
-                        *
-                        * first check whether there is more than one link in the bundle
-                        * then check whether the number is in order
-                        */
-                       net_dev->ib.modify = 1; /* block timeout-timer */
-                       if (net_dev->ib.bundled && net_dev->ib.next_num != sqno) {
-                               /*
-                                * packet is not 'in order'
-                                */
-                               struct sqqueue *q;
-
-                               q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC);
-                               if (!q) {
-                                       net_dev->ib.modify = 0;
-                                       printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n");
-                                       dev_kfree_skb(skb);
-                                       return; /* discard */
-                               }
-                               q->skb = skb;
-                               q->sqno_end = sqno_end;
-                               q->sqno_start = sqno;
-                               q->timer = jiffies + (ISDN_TIMER_1SEC) * 5;     /* timeout after 5 seconds */
-
-                               if (!net_dev->ib.sq) {
-                                       net_dev->ib.sq = q;
-                                       q->next = NULL;
-                               } else {
-                                       struct sqqueue *ql = net_dev->ib.sq;
-                                       if (ql->sqno_start > q->sqno_start) {
-                                               q->next = ql;
-                                               net_dev->ib.sq = q;
-                                       } else {
-                                               while (ql->next && ql->next->sqno_start < q->sqno_start)
-                                                       ql = ql->next;
-                                               q->next = ql->next;
-                                               ql->next = q;
-                                       }
-                               }
-                       } else {
-                               /*
-                                * packet was 'in order' .. push it higher
-                                */
-                               net_dev->ib.next_num = sqno_end + 1;
-                               proto = isdn_ppp_strip_proto(skb);
-                               isdn_ppp_push_higher(net_dev, lp, skb, proto);
-                       }
-                       isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno);
-                       net_dev->ib.modify = 0;
-
-               } else
+                       isdn_ppp_mp_receive(net_dev, lp, skb);
+               } 
+               else
                        isdn_ppp_push_higher(net_dev, lp, skb, proto);
        } else
-#endif
+#endif /* CONFIG_ISDN_MPP */
                isdn_ppp_push_higher(net_dev, lp, skb, proto);
 }
 
@@ -1061,8 +934,16 @@ static void
 isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
 {
        struct net_device *dev = &net_dev->dev;
-       struct ippp_struct *is = ippp_table[lp->ppp_slot];
+       struct ippp_struct *is;
+       int slot;
 
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot);
+               kfree_skb(skb);
+               return;
+       }
+       is = ippp_table[slot];
        if (is->debug & 0x10) {
                printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
                isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
@@ -1219,11 +1100,18 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
        isdn_net_dev *nd;
        unsigned int proto = PPP_IP;     /* 0x21 */
        struct ippp_struct *ipt,*ipts;
+       int slot;
 
        mlp = (isdn_net_local *) (netdev->priv);
-
        nd = mlp->netdev;       /* get master lp */
-       ipts = ippp_table[mlp->ppp_slot];
+
+       slot = mlp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", mlp->ppp_slot);
+               kfree_skb(skb);
+               return 0;
+       }
+       ipts = ippp_table[slot];
 
        if (!(ipts->pppcfg & SC_ENABLE_IP)) {   /* PPP connected ? */
                if (ipts->debug & 0x1)
@@ -1247,12 +1135,18 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        lp = isdn_net_get_locked_lp(nd);
        if (!lp) {
-               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", lp->name);
+               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
                return 1;
        }
        /* we have our lp locked from now on */
 
-       ipt = ippp_table[lp->ppp_slot];
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", lp->ppp_slot);
+               kfree_skb(skb);
+               return 0;
+       }
+       ipt = ippp_table[slot];
        lp->huptimer = 0;
 
        /*
@@ -1399,351 +1293,466 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 #ifdef CONFIG_ISDN_MPP
 
-/*
- * free SQ queue
- * -------------
- * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames,
- * that can't be delivered, because there is an outstanding earlier frame
+/* this is _not_ rfc1990 header, but something we convert both short and long
+ * headers to for convinience's sake:
+ *     byte 0 is flags as in rfc1990
+ *     bytes 1...4 is 24-bit seqence number converted to host byte order 
  */
-static void
-isdn_ppp_free_sqqueue(isdn_net_dev * p)
-{
-       struct sqqueue *q = p->ib.sq;
+#define MP_HEADER_LEN  5
 
-       p->ib.sq = NULL;
-       while (q) {
-               struct sqqueue *qn = q->next;
-               if (q->skb)
-                       dev_kfree_skb(q->skb);
-               kfree(q);
-               q = qn;
-       }
+#define MP_LONGSEQ_MASK                0x00ffffff
+#define MP_SHORTSEQ_MASK       0x00000fff
+#define MP_LONGSEQ_MAX         MP_LONGSEQ_MASK
+#define MP_SHORTSEQ_MAX                MP_SHORTSEQ_MASK
+#define MP_LONGSEQ_MAXBIT      ((MP_LONGSEQ_MASK+1)>>1)
+#define MP_SHORTSEQ_MAXBIT     ((MP_SHORTSEQ_MASK+1)>>1)
 
-}
+/* sequence-wrap safe comparisions (for long sequence)*/ 
+#define MP_LT(a,b)     ((a-b)&MP_LONGSEQ_MAXBIT)
+#define MP_LE(a,b)     !((b-a)&MP_LONGSEQ_MAXBIT)
+#define MP_GT(a,b)     ((b-a)&MP_LONGSEQ_MAXBIT)
+#define MP_GE(a,b)     !((a-b)&MP_LONGSEQ_MAXBIT)
 
-/*
- * free MP queue
- * -------------
- * Note: The MP queue holds all frame fragments of frames, that can't be
- * reassembled, because there is at least one missing fragment.
- */
-static void 
-isdn_ppp_free_mpqueue(isdn_net_dev * p)
-{
-       struct mpqueue *q = p->mp_last;
-       p->mp_last = NULL;
+#define MP_SEQ(f)      ((*(u32*)(f->data+1)))
+#define MP_FLAGS(f)    (f->data[0])
 
-       while (q) {
-               struct mpqueue *ql = q->next;
-               dev_kfree_skb(q->skb);
-               kfree(q);
-               q = ql;
-       }
+static int isdn_ppp_mp_bundle_array_init(void)
+{
+       int i;
+       int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
+       if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, 
+                                                       GFP_KERNEL)) == NULL )
+               return -ENOMEM;
+       memset(isdn_ppp_bundle_arr, 0, sz);
+       for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
+               spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
+       return 0;
 }
 
-static int
-isdn_ppp_bundle(struct ippp_struct *is, int unit)
+static ippp_bundle * isdn_ppp_mp_bundle_alloc(void)
 {
-       char ifn[IFNAMSIZ + 1];
-       long flags;
-       isdn_net_dev *p;
-       isdn_net_local *lp, *nlp;
-
-       sprintf(ifn, "ippp%d", unit);
-       p = isdn_net_findif(ifn);
-       if (!p)
-               return -1;
-
-       save_flags(flags);
-       cli();
-       isdn_timer_ctrl(ISDN_TIMER_IPPP, 1);    /* enable timer for ippp/MP */
-
-       nlp = is->lp;
-       lp = p->queue;
-       isdn_net_add_to_bundle(p, nlp);
-       p->ib.bundled = 1;
-
-       ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
-/* maybe also SC_CCP stuff */
-       ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
-           (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
-
-       ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
-           (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
-       restore_flags(flags);
-       return 0;
+       int i;
+       for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
+               if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
+                       return (isdn_ppp_bundle_arr + i);
+       return NULL;
 }
 
-/*
- * Mask sequence numbers in MP queue
- */
-static void
-isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
+static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
 {
-       struct mpqueue *q = dev->mp_last;
-       while (q) {
-               q->sqno &= mask;
-               q = q->next;
-       }
+       struct ippp_struct * is = ippp_table[lp->ppp_slot];
+   
+       if (add_to) {
+               if( lp->netdev->pb )
+                       lp->netdev->pb->ref_ct--;
+               lp->netdev->pb = add_to;
+       } else {                /* first link in a bundle */
+               is->mp_seqno = 0;
+               if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
+                       return -ENOMEM;
+               lp->next = lp->last = lp;       /* nobody else in a queue */
+               lp->netdev->pb->frags = NULL;
+               lp->netdev->pb->frames = 0;
+               lp->netdev->pb->seq = LONG_MAX;
+       }
+       lp->netdev->pb->ref_ct++;
+       
+       is->last_link_seqno = 0;
+       return 0;
 }
 
-/*
- * put a fragment at the right place into the MP queue 
- * Also checks, whether this fragment completes a frame. In this case
- * the fragments are copied together into one SKB
- */
-static int
-isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno)
+static u32 isdn_ppp_mp_get_seq( int short_seq, 
+                                       struct sk_buff * skb, u32 last_seq );
+struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+                       struct sk_buff * from, struct sk_buff * to );
+void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+                               struct sk_buff * from, struct sk_buff * to );
+static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
+static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
+
+static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, 
+                                                       struct sk_buff *skb)
 {
-       struct mpqueue *qe,
-       *q1,
-       *q;
-       long cnt,
-        flags;
-       int pktlen,
-        sqno_end;
-       int sqno = *sqnop;
-
-       q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_ATOMIC);
-       if (!q1) {
-               printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
-               save_flags(flags);
-               cli();
-               isdn_ppp_cleanup_mpqueue(dev, min_sqno);
-               restore_flags(flags);
-               return -1;
+       struct ippp_struct *is;
+       isdn_net_local * lpq;
+       ippp_bundle * mp;
+       isdn_mppp_stats * stats;
+       struct sk_buff * newfrag, * frag, * start, *nextf;
+       u32 newseq, minseq, thisseq;
+       unsigned long flags;
+       int slot;
+
+       spin_lock_irqsave(&net_dev->pb->lock, flags);
+       mp = net_dev->pb;
+        stats = &mp->stats;
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               printk(KERN_ERR "isdn_ppp_mp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+               stats->frame_drops++;
+               dev_kfree_skb(skb);
+               spin_unlock_irqrestore(&mp->lock, flags);
+               return;
        }
-       q1->skb = *skb;
-       q1->sqno = sqno;
-       q1->BEbyte = BEbyte;
-       q1->time = jiffies;
+       is = ippp_table[slot];
+       if( ++mp->frames > stats->max_queue_len )
+               stats->max_queue_len = mp->frames;
+       
+       if (is->debug & 0x8)
+               isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
 
-       save_flags(flags);
-       cli();
+       newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, 
+                                               skb, is->last_link_seqno);
 
-       if (!(q = dev->mp_last)) {
-               dev->mp_last = q1;
-               q1->next = NULL;
-               q1->last = NULL;
-               isdn_ppp_cleanup_mpqueue(dev, min_sqno);        /* not necessary */
-               restore_flags(flags);
-               return -1;      /* -1 is not an error. Just says, that this fragment hasn't complete a full frame */
+
+       /* if this packet seq # is less than last already processed one,
+        * toss it right away, but check for sequence start case first 
+        */
+       if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
+               mp->seq = newseq;       /* the first packet: required for
+                                        * rfc1990 non-compliant clients --
+                                        * prevents constant packet toss */
+       } else if( MP_LT(newseq, mp->seq) ) {
+               stats->frame_drops++;
+               isdn_ppp_mp_free_skb(mp, skb);
+               spin_unlock_irqrestore(&mp->lock, flags);
+               return;
        }
-       for (;;) {              /* the faster way would be to step from the queue-end to the start */
-               if (sqno > q->sqno) {
-                       if (q->next) {
-                               q = q->next;
-                               continue;
-                       }
-                       q->next = q1;
-                       q1->next = NULL;
-                       q1->last = q;
-                       break;
+       
+       /* find the minimum received sequence number over all links */
+       is->last_link_seqno = minseq = newseq;
+       for (lpq = net_dev->queue;;) {
+               slot = lpq->ppp_slot;
+               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+                       printk(KERN_ERR "isdn_ppp_mp_receive: lpq->ppp_slot %d\n", lpq->ppp_slot);
+               } else {
+                       u32 lls = ippp_table[slot]->last_link_seqno;
+                       if (MP_LT(lls, minseq))
+                               minseq = lls;
                }
-               if (sqno == q->sqno)
-                       printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n");
-               q1->last = q->last;
-               q1->next = q;
-               if (q->last) {
-                       q->last->next = q1;
-               } else
-                       dev->mp_last = q1;
-               q->last = q1;
-               break;
+               if ((lpq = lpq->next) == net_dev->queue)
+                       break;
        }
-
-/* now we check whether we completed a packet with this fragment */
-       pktlen = -q1->skb->len;
-       q = q1;
-       cnt = q1->sqno;
-       while (!(q->BEbyte & MP_END_FRAG)) {
-               cnt++;
-               if (!(q->next) || q->next->sqno != cnt) {
-                       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
-                       restore_flags(flags);
-                       return -1;
+       if (MP_LT(minseq, mp->seq))
+               minseq = mp->seq;       /* can't go beyond already processed
+                                        * packets */
+       newfrag = skb;
+
+       /* if this new fragment is before the first one, then enqueue it now. */
+       if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
+               newfrag->next = frag;
+               mp->frags = frag = newfrag;
+               newfrag = NULL;
+       }
+
+       start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
+                               MP_SEQ(frag) == mp->seq ? frag : NULL;
+
+       /* 
+        * main fragment traversing loop
+        *
+        * try to accomplish several tasks:
+        * - insert new fragment into the proper sequence slot (once that's done
+        *   newfrag will be set to NULL)
+        * - reassemble any complete fragment sequence (non-null 'start'
+        *   indicates there is a continguous sequence present)
+        * - discard any incomplete sequences that are below minseq -- due
+        *   to the fact that sender always increment sequence number, if there
+        *   is an incomplete sequence below minseq, no new fragments would
+        *   come to complete such sequence and it should be discarded
+        *
+        * loop completes when we accomplished the following tasks:
+        * - new fragment is inserted in the proper sequence ('newfrag' is 
+        *   set to NULL)
+        * - we hit a gap in the sequence, so no reassembly/processing is 
+        *   possible ('start' would be set to NULL)
+        *
+        * algorightm for this code is derived from code in the book
+        * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
+        */
+       while (start != NULL || newfrag != NULL) {
+
+               thisseq = MP_SEQ(frag);
+               nextf = frag->next;
+
+               /* drop any duplicate fragments */
+               if (newfrag != NULL && thisseq == newseq) {
+                       isdn_ppp_mp_free_skb(mp, newfrag);
+                       newfrag = NULL;
+               }
+
+               /* insert new fragment before next element if possible. */
+               if (newfrag != NULL && (nextf == NULL || 
+                                               MP_LT(newseq, MP_SEQ(nextf)))) {
+                       newfrag->next = nextf;
+                       frag->next = nextf = newfrag;
+                       newfrag = NULL;
+               }
+
+               if (start != NULL) {
+                       /* check for misplaced start */
+                       if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
+                               printk(KERN_WARNING"isdn_mppp(seq %d): new "
+                                     "BEGIN flag with no prior END", thisseq);
+                               stats->seqerrs++;
+                               stats->frame_drops++;
+                               start = isdn_ppp_mp_discard(mp, start,frag);
+                               nextf = frag->next;
+                       }
+               } else if (MP_LE(thisseq, minseq)) {            
+                       if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
+                               start = frag;
+                       else {
+                               if (MP_FLAGS(frag) & MP_END_FRAG)
+                                       stats->frame_drops++;
+                               if( mp->frags == frag )
+                                       mp->frags = nextf;      
+                               isdn_ppp_mp_free_skb(mp, frag);
+                               frag = nextf;
+                               continue;
+                       }
                }
-               pktlen += q->skb->len;
-               q = q->next;
-       }
-       pktlen += q->skb->len;
-       qe = q;
-
-       q = q1;
-       cnt = q1->sqno;
-       while (!(q->BEbyte & MP_BEGIN_FRAG)) {
-               cnt--;
-               if (!(q->last) || q->last->sqno != cnt) {
-                       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
-                       restore_flags(flags);
-                       return -1;
+               
+               /* if start is non-null and we have end fragment, then
+                * we have full reassembly sequence -- reassemble 
+                * and process packet now
+                */
+               if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
+                       minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
+                       /* Reassemble the packet then dispatch it */
+                       isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
+      
+                       start = NULL;
+                       frag = NULL;
+
+                       mp->frags = nextf;
+               }
+
+               /* check if need to update start pointer: if we just
+                * reassembled the packet and sequence is contiguous
+                * then next fragment should be the start of new reassembly
+                * if sequence is contiguous, but we haven't reassembled yet,
+                * keep going.
+                * if sequence is not contiguous, either clear everyting
+                * below low watermark and set start to the next frag or
+                * clear start ptr.
+                */ 
+               if (nextf != NULL && 
+                   ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
+                       /* if we just reassembled and the next one is here, 
+                        * then start another reassembly. */
+
+                       if (frag == NULL) {
+                               if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
+                                       start = nextf;
+                               else
+                               {
+                                       printk(KERN_WARNING"isdn_mppp(seq %d):"
+                                               " END flag with no following "
+                                               "BEGIN", thisseq);
+                                       stats->seqerrs++;
+                               }
+                       }
+
+               } else {
+                       if ( nextf != NULL && frag != NULL &&
+                                               MP_LT(thisseq, minseq)) {
+                               /* we've got a break in the sequence
+                                * and we not at the end yet
+                                * and we did not just reassembled
+                                *(if we did, there wouldn't be anything before)
+                                * and we below the low watermark 
+                                * discard all the frames below low watermark 
+                                * and start over */
+                               stats->frame_drops++;
+                               mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
+                       }
+                       /* break in the sequence, no reassembly */
+                       start = NULL;
+               }
+                               
+               frag = nextf;
+       }       /* while -- main loop */
+       
+       if (mp->frags == NULL)
+               mp->frags = frag;
+               
+       /* rather straighforward way to deal with (not very) possible 
+        * queue overflow */
+       if (mp->frames > MP_MAX_QUEUE_LEN) {
+               stats->overflows++;
+               while (mp->frames > MP_MAX_QUEUE_LEN) {
+                       frag = mp->frags->next;
+                       isdn_ppp_mp_free_skb(mp, mp->frags);
+                       mp->frags = frag;
                }
-               pktlen += q->skb->len;
-               q = q->last;
        }
-       pktlen += q->skb->len;
+       spin_unlock_irqrestore(&mp->lock, flags);
+}
 
-       if (q->last)
-               q->last->next = qe->next;
+static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
+{
+       struct sk_buff * frag = lp->netdev->pb->frags;
+       struct sk_buff * nextfrag;
+       while( frag ) {
+               nextfrag = frag->next;
+               isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
+               frag = nextfrag;
+       }
+       lp->netdev->pb->frags = NULL;
+}
+
+static u32 isdn_ppp_mp_get_seq( int short_seq, 
+                                       struct sk_buff * skb, u32 last_seq )
+{
+       u32 seq;
+       int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
+   
+       if( !short_seq )
+       {
+               seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK;
+               skb_push(skb,1);
+       }
        else
-               dev->mp_last = qe->next;
+       {
+               /* convert 12-bit short seq number to 24-bit long one 
+               */
+               seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK;
+       
+               /* check for seqence wrap */
+               if( !(seq &  MP_SHORTSEQ_MAXBIT) && 
+                    (last_seq &  MP_SHORTSEQ_MAXBIT) && 
+                    (unsigned long)last_seq <= MP_LONGSEQ_MAX )
+                       seq |= (last_seq + MP_SHORTSEQ_MAX+1) & 
+                                       (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
+               else
+                       seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
+               
+               skb_push(skb, 3);       /* put converted seqence back in skb */
+       }
+       *(u32*)(skb->data+1) = seq;     /* put seqence back in _host_ byte
+                                        * order */
+       skb->data[0] = flags;           /* restore flags */
+       return seq;
+}
 
-       if (qe->next)
-               qe->next->last = q->last;
-       qe->next = NULL;
-       sqno_end = qe->sqno;
-       *sqnop = q->sqno;
+struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
+                       struct sk_buff * from, struct sk_buff * to )
+{
+       if( from )
+               while (from != to) {
+                       struct sk_buff * next = from->next;
+                       isdn_ppp_mp_free_skb(mp, from);
+                       from = next;
+               }
+       return from;
+}
 
-       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
-       restore_flags(flags);
+void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
+                               struct sk_buff * from, struct sk_buff * to )
+{
+       ippp_bundle * mp = net_dev->pb;
+       int proto;
+       struct sk_buff * skb;
+       unsigned int tot_len;
+
+       if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+               if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+                       printk(KERN_DEBUG"isdn_mppp: reassembly: frame %d, "
+                                       "len %d\n", MP_SEQ(from), from->len );
+               skb = from;
+               skb_pull(skb, MP_HEADER_LEN);
+               mp->frames--;   
+       } else {
+               struct sk_buff * frag;
+               int n;
+
+               for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
+                       tot_len += frag->len - MP_HEADER_LEN;
+
+               if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+                       printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
+                               "to %d, len %d\n", MP_SEQ(from), 
+                               (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
+               if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
+                       printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
+                                       "of size %d\n", tot_len);
+                       isdn_ppp_mp_discard(mp, from, to);
+                       return;
+               }
 
-       *skb = dev_alloc_skb(pktlen + 40);      /* not needed: +40 for VJ compression .. */
+               while( from != to ) {
+                       unsigned int len = from->len - MP_HEADER_LEN;
 
-       if (!(*skb)) {
-               while (q) {
-                       struct mpqueue *ql = q->next;
-                       dev_kfree_skb(q->skb);
-                       kfree(q);
-                       q = ql;
+                       memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len);
+                       frag = from->next;
+                       isdn_ppp_mp_free_skb(mp, from);
+                       from = frag; 
                }
-               return -2;
        }
-       cnt = 0;
-       skb_put(*skb, pktlen);
-       while (q) {
-               struct mpqueue *ql = q->next;
-               memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
-               cnt += q->skb->len;
-               dev_kfree_skb(q->skb);
-               kfree(q);
-               q = ql;
-       }
-
-       return sqno_end;
+       proto = isdn_ppp_strip_proto(skb);
+       isdn_ppp_push_higher(net_dev, lp, skb, proto);
 }
 
-/*
- * check sq-queue, whether we have still buffered the next packet(s)
- * or packets with a sqno less or equal to min_sqno
- * net_dev: master netdevice , lp: 'real' local connection
- */
-static void
-isdn_ppp_cleanup_sqqueue(isdn_net_dev * net_dev, isdn_net_local * lp, long min_sqno)
+static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
 {
-       struct sqqueue *q;
+       dev_kfree_skb(skb);
+       mp->frames--;
+}
 
-       while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) {
-               int proto;
-               if (q->sqno_start != net_dev->ib.next_num) {
-                       printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n", net_dev->ib.next_num);
-#ifdef CONFIG_ISDN_PPP_VJ
-                       slhc_toss(ippp_table[net_dev->local->ppp_slot]->slcomp);
-#endif
-               }
-               proto = isdn_ppp_strip_proto(q->skb);
-               isdn_ppp_push_higher(net_dev, lp, q->skb, proto);
-               net_dev->ib.sq = q->next;
-               net_dev->ib.next_num = q->sqno_end + 1;
-               kfree(q);
-       }
+static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb )
+{
+       printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n", 
+               slot, (int) skb->len, 
+               (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
+               (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
 }
 
-/*
- * remove stale packets from list
- */
-static void
-isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno)
+static int
+isdn_ppp_bundle(struct ippp_struct *is, int unit)
 {
-#ifdef CONFIG_ISDN_PPP_VJ
-       int toss = 0;
-#endif
-       /* currently we just discard ancient packets. 
-          To do: 
-          Maybe, as long as there's no B-packet in front and sqno <= min_sqno: discard.
-          If sqno < min_sqno and there are gaps: discard (the gaps won't be filled anyway).
-          Packets with sqno > min_sqno: Larger than mp_mrru: If sum of all pktlen of pending
-          packets large than mrru: discard - packets need to be consecutive, though, if not 
-          there could be an B and an E-packet in between.
-       */
+       char ifn[IFNAMSIZ + 1];
+       isdn_net_dev *p;
+       isdn_net_local *lp, *nlp;
+       int rc;
+       unsigned long flags;
 
-       struct mpqueue *ql,
-       *q = dev->mp_last;
-       while(q && (q->sqno < min_sqno) ) {
-               if ( (q->BEbyte & MP_END_FRAG) || 
-                        (q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & MP_BEGIN_FRAG)) ) {
-                       printk(KERN_DEBUG "ippp: freeing stale packet(s), min_sq: %ld!\n",min_sqno);
-                       if ((dev->mp_last = q->next))
-                               q->next->last = NULL;
-                       while (q) {
-                               ql = q->last;
-                               printk(KERN_DEBUG "ippp, freeing packet with sqno: %ld\n",q->sqno);
-                               dev_kfree_skb(q->skb);
-                               kfree(q);
-#ifdef CONFIG_ISDN_PPP_VJ
-                               toss = 1;
-#endif
-                               q = ql;
-                       }
-                       q = dev->mp_last;
-               } else
-                       q = q->next;
+       sprintf(ifn, "ippp%d", unit);
+       p = isdn_net_findif(ifn);
+       if (!p) {
+               printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
+               return -EINVAL;
        }
-#ifdef CONFIG_ISDN_PPP_VJ
-       /* did we free a stale frame ? */
-       if (toss)
-               slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
-#endif
-}
-#endif
 
-/*
- * a buffered packet timed-out?
- */
-void
-isdn_ppp_timer_timeout(void)
-{
-#ifdef CONFIG_ISDN_MPP
-       isdn_net_dev *net_dev = dev->netdev;
-       struct sqqueue *q,
-       *ql = NULL,
-       *qn;
-
-       while (net_dev) {
-               isdn_net_local *lp = net_dev->local;
-               if (net_dev->ib.modify || lp->master) { /* interface locked or slave? */
-                       net_dev = net_dev->next;
-                       continue;
-               }
-               q = net_dev->ib.sq;
-               while (q) {
-                       if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
+       spin_lock_irqsave(&p->pb->lock, flags);
 
-#ifdef CONFIG_ISDN_PPP_VJ
-                               /* did we step over a missing frame ? */
-                               if (q->sqno_start != net_dev->ib.next_num)
-                                       slhc_toss(ippp_table[lp->ppp_slot]->slcomp);
-#endif
+       nlp = is->lp;
+       lp = p->queue;
+       if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
+               lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) {
+               printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
+                       nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ? 
+                       nlp->ppp_slot : lp->ppp_slot );
+               rc = -EINVAL;
+               goto out;
+       }
 
-                               ql = net_dev->ib.sq;
-                               net_dev->ib.sq = q->next;
-                               net_dev->ib.next_num = q->sqno_end + 1;
-                               q->next = NULL;
-                               for (; ql;) {
-                                       int proto = isdn_ppp_strip_proto(ql->skb);
-                                       isdn_ppp_push_higher(net_dev, lp, ql->skb, proto);
-                                       qn = ql->next;
-                                       kfree(ql);
-                                       ql = qn;
-                               }
-                               q = net_dev->ib.sq;
-                       } else
-                               q = q->next;
-               }
-               net_dev = net_dev->next;
-       }
-#endif
-}
+       isdn_net_add_to_bundle(p, nlp);
+
+       ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
 
+       /* maybe also SC_CCP stuff */
+       ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
+               (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
+       ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
+               (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
+       rc = isdn_ppp_mp_init(nlp, p->pb);
+out:
+       spin_unlock_irqrestore(&p->pb->lock, flags);
+       return rc;
+}
+  
+#endif /* CONFIG_ISDN_MPP */
+  
 /*
  * network device ioctl handlers
  */
index 1e33cb2194c52843cd1643d646a8a8dd655adb11..20ab41046cb05f03d32ed554008abc37d71b8ae3 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <linux/ppp_defs.h>     /* for PPP_PROTOCOL */
 #include <linux/isdn_ppp.h>    /* for isdn_ppp info */
-extern void isdn_ppp_timer_timeout(void);
 extern int isdn_ppp_read(int, struct file *, char *, int);
 extern int isdn_ppp_write(int, struct file *, const char *, int);
 extern int isdn_ppp_open(int, struct file *);
index f9bfc60dee4ba2859609ea75819b0a46a6cb8ad8..25e1139b9bec3de2a9ac607485bb89b6fde9d62b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.92 2000/06/21 09:54:29 keil Exp $
+/* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -66,7 +66,7 @@ static int bit2si[8] =
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.92 $";
+char *isdn_tty_revision = "$Revision: 1.93 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -1183,6 +1183,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
        int c;
        int total = 0;
        modem_info *info = (modem_info *) tty->driver_data;
+       atemu *m = &info->emu;
 
        if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
                return 0;
@@ -1203,8 +1204,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
                    || (info->vonline & 3)
 #endif
                        ) {
-                       atemu *m = &info->emu;
-
 #ifdef CONFIG_ISDN_AUDIO
                        if (!info->vonline)
 #endif
@@ -1262,7 +1261,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
                                        isdn_command(&c);
                                }
                                info->vonline = 0;
-                               printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc,c);
+#ifdef ISDN_DEBUG_MODEM_VOICE
+                               printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);
+#endif
                                info->xmit_count += cc;
                        } else
 #endif
@@ -1284,9 +1285,14 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
                count -= c;
                total += c;
        }
-       if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
-               isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
        atomic_dec(&info->xmit_lock);
+       if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {
+               if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
+                       isdn_tty_senddown(info);
+                       isdn_tty_tint(info);
+               }
+               isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
+       }
        if (from_user)
                up(&info->write_sem);
        return total;
@@ -2157,7 +2163,7 @@ isdn_tty_match_icall(char *cid, atemu *emu, int di)
                while (1) {
                        if ((q = strchr(p, ';')))
                                *q = '\0';
-                       if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret)
+                       if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret)
                                ret = tmp;
 #ifdef ISDN_DEBUG_MODEM_ICALL
                        printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
@@ -2176,7 +2182,7 @@ isdn_tty_match_icall(char *cid, atemu *emu, int di)
                return ret;
        } else {
                int tmp;
-               tmp = isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+               tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));
 #ifdef ISDN_DEBUG_MODEM_ICALL
                        printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
                               isdn_map_eaz2msn(emu->msn, di), tmp);
@@ -2197,7 +2203,7 @@ isdn_tty_match_icall(char *cid, atemu *emu, int di)
  *      CID is longer.
  */
 int
-isdn_tty_find_icall(int di, int ch, setup_parm setup)
+isdn_tty_find_icall(int di, int ch, setup_parm *setup)
 {
        char *eaz;
        int i;
@@ -2208,18 +2214,18 @@ isdn_tty_find_icall(int di, int ch, setup_parm setup)
        char *nr;
        ulong flags;
 
-       if (!setup.phone[0]) {
+       if (!setup->phone[0]) {
                nr = "0";
                printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
        } else
-               nr = setup.phone;
-       si1 = (int) setup.si1;
-       si2 = (int) setup.si2;
-       if (!setup.eazmsn[0]) {
+               nr = setup->phone;
+       si1 = (int) setup->si1;
+       si2 = (int) setup->si2;
+       if (!setup->eazmsn[0]) {
                printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
                eaz = "0";
        } else
-               eaz = setup.eazmsn;
+               eaz = setup->eazmsn;
 #ifdef ISDN_DEBUG_MODEM_ICALL
        printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
 #endif
@@ -2261,8 +2267,8 @@ isdn_tty_find_icall(int di, int ch, setup_parm setup)
                                        strcpy(dev->num[idx], nr);
                                        strcpy(info->emu.cpn, eaz);
                                        info->emu.mdmreg[REG_SI1I] = si2bit[si1];
-                                       info->emu.mdmreg[REG_PLAN] = setup.plan;
-                                       info->emu.mdmreg[REG_SCREEN] = setup.screen;
+                                       info->emu.mdmreg[REG_PLAN] = setup->plan;
+                                       info->emu.mdmreg[REG_SCREEN] = setup->screen;
                                        isdn_info_update();
                                        restore_flags(flags);
                                        printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
@@ -2369,11 +2375,21 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
 #ifdef ISDN_TTY_STAT_DEBUG
                                printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
 #endif
+                               /* Wake up any processes waiting
+                                * for incoming call of this device when
+                                * DCD follow the state of incoming carrier
+                                */
+                               if (info->blocked_open &&
+                                  (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
+                                       wake_up_interruptible(&info->open_wait);
+                               }
+
                                /* Schedule CONNECT-Message to any tty
                                 * waiting for it and
                                 * set DCD-bit of its modem-status.
                                 */
-                               if (TTY_IS_ACTIVE(info)) {
+                               if (TTY_IS_ACTIVE(info) ||
+                                   (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
                                        info->msr |= UART_MSR_DCD;
                                        info->emu.charge = 0;
                                        if (info->dialing & 0xf)
@@ -2827,8 +2843,8 @@ isdn_tty_get_msnstr(char *n, char **p)
        int limit = ISDN_MSNLEN - 1;
 
        while (((*p[0] >= '0' && *p[0] <= '9') ||
-              /* Why a comma ??? */
-              (*p[0] == ',')) &&
+               /* Why a comma ??? */
+               (*p[0] == ',') || (*p[0] == ':')) &&
                (limit--))
                *n++ = *p[0]++;
        *n = '\0';
index 2921f96594866320c248896bd8541fe420e5ce50..4553cf5687b2645cbc23cb03cc89a2c19d5f46a9 100644 (file)
@@ -57,6 +57,8 @@
 #define REG_CPPP     12
 #define BIT_CPPP    128
 
+#define REG_DXMT     13
+#define BIT_DXMT      1
 #define REG_T70      13
 #define BIT_T70       2
 #define BIT_T70_EXT  32
@@ -113,7 +115,7 @@ extern void isdn_tty_carrier_timeout(void);
 extern void isdn_tty_modem_xmit(void);
 extern int isdn_tty_modem_init(void);
 extern void isdn_tty_readmodem(void);
-extern int isdn_tty_find_icall(int, int, setup_parm);
+extern int isdn_tty_find_icall(int, int, setup_parm *);
 extern void isdn_tty_cleanup_xmit(modem_info *);
 extern int isdn_tty_stat_callback(int, isdn_ctrl *);
 extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
index 6a458a39cd85afb400c09ea5160e057bf979a185..dfb1186ecf58ced3431c839025e6bc085760c799 100644 (file)
@@ -707,7 +707,7 @@ static int init_i596_mem(struct net_device *dev)
        spin_lock_irqsave (&lp->lock, flags);
 
        if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) {
-               spin_unlock_irqrestore ((&lp->lock, flags);
+               spin_unlock_irqrestore (&lp->lock, flags);
                goto failed;
        }
        DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name));
index 96d8058b8d421254ca6547446147f8926cbf66ac..d1927ff704449c083d71f476b875f479e73b8cfb 100644 (file)
@@ -663,7 +663,7 @@ static int eth16i_probe_port(int ioaddr)
 {
        int i;
        int retcode;
-       unsigned char dummy_packet[64] = { 0 };
+       unsigned char dummy_packet[64];
 
        /* Powerup the chip */
        outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
@@ -679,6 +679,7 @@ static int eth16i_probe_port(int ioaddr)
 
        dummy_packet[12] = 0x00;
        dummy_packet[13] = 0x04;
+       memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14);
 
        eth16i_select_regbank(2, ioaddr);
 
index 7a3e28f7adc3f73d7adec59f7c82ec26cfd940a5..547b04c4f840fd3b9084c76f21d7b03297715f22 100644 (file)
@@ -5389,9 +5389,10 @@ print_insn (struct Scsi_Host *host, const u32 *insn,
      * to use vverify()?
      */
 
-    if (MAP_NR(insn) < 1 || MAP_NR(insn + 8) > MAP_NR(high_memory) || 
+    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
+       virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
        ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
-       MAP_NR(insn + 12) > MAP_NR(high_memory))) {
+       virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
        size = 0;
        sprintf (buf, "%s%p: address out of range\n",
            prefix, insn);
@@ -6381,8 +6382,7 @@ dump_events (struct Scsi_Host *host, int count) {
 
 static int 
 check_address (unsigned long addr, int size) {
-    return (MAP_NR(addr) < 1 || MAP_NR(addr + size) > MAP_NR(high_memory) ?
-           -1 : 0);
+    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
 }
 
 #ifdef MODULE
index a5e0ca0a263c04d0f2e2250042730ce6d8134c85..14a354623751597ca7b8dcc6b3eb8fe7fdfbaf93 100644 (file)
@@ -5068,9 +5068,10 @@ print_insn (struct Scsi_Host *host, const u32 *insn,
      * to use vverify()?
      */
 
-    if (MAP_NR(insn) < 1 || MAP_NR(insn + 8) > MAP_NR(high_memory) ||
+    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
+       virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
        ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
-       MAP_NR(insn + 12) > MAP_NR(high_memory))) {
+       virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
        size = 0;
        sprintf (buf, "%s%p: address out of range\n",
            prefix, insn);
@@ -6052,8 +6053,7 @@ dump_events (struct Scsi_Host *host, int count) {
 
 static int 
 check_address (unsigned long addr, int size) {
-    return (MAP_NR(addr) < 1 || MAP_NR(addr + size) > MAP_NR(high_memory) ?
-           -1 : 0);
+    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
 }
 
 #ifdef MODULE
index 118b351f4d8b3ed77c68662202645e50e9131942..2c88ef4ad3168f7a17588c6560f86af35bb2aa97 100644 (file)
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sat Apr 22 14:50:25 2000 by makisara@kai.makisara.local
+Last modified: Sat Aug  5 10:29:07 2000 by makisara@kai.makisara.local
 
 
 BASICS
@@ -67,7 +67,7 @@ non-rewind devices (minor is 128 + device number) are implemented.
 In variable block mode, the byte count in write() determines the size
 of the physical block on tape. When reading, the drive reads the next
 tape block and returns to the user the data if the read() byte count
-is at least the block size. Otherwise the data is truncated.
+is at least the block size. Otherwise, error ENOMEM is returned.
 
 In fixed block mode, the data transfer between the drive and the
 driver is in multiples of the block size. The write() byte count must
index 2ac10c83246f9b92ad2e86ae10e4b6abaaffae00..7122c49bd58929048607781c2c9b8b4ded58b7c3 100644 (file)
    Copyright 1992 - 2000 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Sat Jun 17 15:21:49 2000 by makisara@kai.makisara.local
+   Last modified: Sun Aug  6 23:02:13 2000 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
+
+   Reminder: write_lock_irqsave() can be replaced by write_lock() when the old SCSI
+   error handling will be discarded.
  */
 
 #include <linux/module.h>
@@ -141,7 +144,7 @@ static Scsi_Tape **scsi_tapes = NULL;
 
 static int modes_defined;
 
-static ST_buffer *new_tape_buffer(int, int);
+static ST_buffer *new_tape_buffer(int, int, int);
 static int enlarge_buffer(ST_buffer *, int, int);
 static void normalize_buffer(ST_buffer *);
 static int append_to_buffer(const char *, ST_buffer *, int);
@@ -587,10 +590,11 @@ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm)
 }
 \f
 
-/* Open the device */
-static int scsi_tape_open(struct inode *inode, struct file *filp)
+/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
+   module count. */
+static int st_open(struct inode *inode, struct file *filp)
 {
-       unsigned short flags;
+       unsigned short st_flags;
        int i, need_dma_buffer, new_session = FALSE;
        int retval;
        unsigned char cmd[MAX_COMMAND_SIZE];
@@ -600,28 +604,32 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
        ST_partstat *STps;
        int dev = TAPE_NR(inode->i_rdev);
        int mode = TAPE_MODE(inode->i_rdev);
+       unsigned long flags;
 
-       read_lock(&st_dev_arr_lock);
+       write_lock_irqsave(&st_dev_arr_lock, flags);
        STp = scsi_tapes[dev];
        if (dev >= st_template.dev_max || STp == NULL) {
-               read_unlock(&st_dev_arr_lock);
+               write_unlock_irqrestore(&st_dev_arr_lock, flags);
                return (-ENXIO);
        }
-       read_unlock(&st_dev_arr_lock);
 
-       if (!scsi_block_when_processing_errors(STp->device)) {
-               return -ENXIO;
-       }
        if (STp->in_use) {
+               write_unlock_irqrestore(&st_dev_arr_lock, flags);
                DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
                return (-EBUSY);
        }
        STp->in_use = 1;
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
        STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
 
        if (STp->device->host->hostt->module)
                __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
 
+       if (!scsi_block_when_processing_errors(STp->device)) {
+               retval = (-ENXIO);
+               goto err_out;
+       }
+
        if (mode != STp->current_mode) {
                 DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n",
                               dev, STp->current_mode, mode));
@@ -632,16 +640,17 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
 
        /* Allocate a buffer for this user */
        need_dma_buffer = STp->restr_dma;
-       read_lock(&st_dev_arr_lock);
+       write_lock_irqsave(&st_dev_arr_lock, flags);
        for (i = 0; i < st_nbr_buffers; i++)
                if (!st_buffers[i]->in_use &&
                    (!need_dma_buffer || st_buffers[i]->dma)) {
                        STp->buffer = st_buffers[i];
+                       (STp->buffer)->in_use = 1;
                        break;
                }
-       read_unlock(&st_dev_arr_lock);
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
        if (i >= st_nbr_buffers) {
-               STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
+               STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
                if (STp->buffer == NULL) {
                        printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
                        retval = (-EBUSY);
@@ -649,7 +658,6 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                }
        }
 
-       (STp->buffer)->in_use = 1;
        (STp->buffer)->writing = 0;
        (STp->buffer)->syscall_result = 0;
        (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
@@ -663,8 +671,8 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
                        (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
        }
 
-       flags = filp->f_flags;
-       STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
+       st_flags = filp->f_flags;
+       STp->write_prot = ((st_flags & O_ACCMODE) == O_RDONLY);
 
        STp->dirty = 0;
        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
@@ -813,7 +821,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
 
                 DEBC(printk(ST_DEB_MSG "st%d: Write protected\n", dev));
 
-               if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
+               if ((st_flags & O_ACCMODE) == O_WRONLY || (st_flags & O_ACCMODE) == O_RDWR) {
                        retval = (-EROFS);
                        goto err_out;
                }
@@ -864,7 +872,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
 \f
 
 /* Flush the tape buffer before close */
-static int scsi_tape_flush(struct file *filp)
+static int st_flush(struct file *filp)
 {
        int result = 0, result2;
        unsigned char cmd[MAX_COMMAND_SIZE];
@@ -982,17 +990,18 @@ static int scsi_tape_flush(struct file *filp)
 }
 
 
-/* Close the device and release it */
-static int scsi_tape_close(struct inode *inode, struct file *filp)
+/* Close the device and release it. BKL is not needed: this is the only thread
+   accessing this tape. */
+static int st_release(struct inode *inode, struct file *filp)
 {
        int result = 0;
        Scsi_Tape *STp;
+       unsigned long flags;
 
        kdev_t devt = inode->i_rdev;
        int dev;
 
        dev = TAPE_NR(devt);
-       lock_kernel();
        read_lock(&st_dev_arr_lock);
        STp = scsi_tapes[dev];
        read_unlock(&st_dev_arr_lock);
@@ -1002,13 +1011,18 @@ static int scsi_tape_close(struct inode *inode, struct file *filp)
 
        if (STp->buffer != NULL) {
                normalize_buffer(STp->buffer);
+               write_lock_irqsave(&st_dev_arr_lock, flags);
                (STp->buffer)->in_use = 0;
+               STp->buffer = NULL;
+       }
+       else {
+               write_lock_irqsave(&st_dev_arr_lock, flags);
        }
 
        STp->in_use = 0;
+       write_unlock_irqrestore(&st_dev_arr_lock, flags);
        if (STp->device->host->hostt->module)
                __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
-       unlock_kernel();
 
        return result;
 }
@@ -1452,8 +1466,11 @@ static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt)
 
                                if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */
                                        if (STp->block_size == 0) {
-                                               if (transfer <= 0)
-                                                       transfer = 0;
+                                               if (transfer < 0) {
+                                                       if (STps->drv_block >= 0)
+                                                               STps->drv_block += 1;
+                                                       return (-ENOMEM);
+                                               }
                                                (STp->buffer)->buffer_bytes = bytes - transfer;
                                        } else {
                                                scsi_release_request(SRpnt);
@@ -3112,7 +3129,7 @@ static int st_ioctl(struct inode *inode, struct file *file,
 /* Try to allocate a new tape buffer. Calling function must not hold
    dev_arr_lock. */
 static ST_buffer *
- new_tape_buffer(int from_initialization, int need_dma)
+ new_tape_buffer(int from_initialization, int need_dma, int in_use)
 {
        int i, priority, b_size, order, got = 0, segs = 0;
        unsigned long flags;
@@ -3205,7 +3222,7 @@ static ST_buffer *
                     "st: segment sizes: first %d, last %d bytes.\n",
                     tb->sg[0].length, tb->sg[segs - 1].length);
        )
-       tb->in_use = 0;
+       tb->in_use = in_use;
        tb->dma = need_dma;
        tb->buffer_size = got;
        tb->writing = 0;
@@ -3429,9 +3446,9 @@ static struct file_operations st_fops =
        read:           st_read,
        write:          st_write,
        ioctl:          st_ioctl,
-       open:           scsi_tape_open,
-       flush:          scsi_tape_flush,
-       release:        scsi_tape_close,
+       open:           st_open,
+       flush:          st_flush,
+       release:        st_release,
 };
 
 static int st_attach(Scsi_Device * SDp)
@@ -3595,7 +3612,7 @@ static int st_attach(Scsi_Device * SDp)
        if (target_nbr > st_max_buffers)
                target_nbr = st_max_buffers;
        for (i=st_nbr_buffers; i < target_nbr; i++)
-               if (!new_tape_buffer(TRUE, TRUE)) {
+               if (!new_tape_buffer(TRUE, TRUE, FALSE)) {
                        printk(KERN_INFO "st: Unable to allocate new static buffer.\n");
                        break;
                }
index c11c1fe73b5786f0fbd800ce38e0b665d4e64a49..b46d4e086b24a0a71ced62293bbd21b8ec0b1ca9 100644 (file)
@@ -26,6 +26,7 @@
 #define SAMPLE_ROUNDUP 0
 
 #include "sound_config.h"
+#include <linux/wrapper.h>
 
 #define DMAP_FREE_ON_CLOSE      0
 #define DMAP_KEEP_ON_CLOSE      1
@@ -114,7 +115,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap)
        dmap->raw_buf = start_addr;
        dmap->raw_buf_phys = virt_to_bus(start_addr);
 
-       for (page = virt_to_page(start_addr); page <= get_mem_map(end_addr); page++)
+       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
                mem_map_reserve(page);
        return 0;
 }
@@ -134,7 +135,7 @@ static void sound_free_dmap(struct dma_buffparms *dmap)
        start_addr = (unsigned long) dmap->raw_buf;
        end_addr = start_addr + dmap->buffsize;
 
-       for (page = virt_to_page(start_addr); page <= get_mem_map(end_addr); page++)
+       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
                mem_map_unreserve(page);
 
        free_pages((unsigned long) dmap->raw_buf, sz);
index e953aac6f14d1a659c1cfda6097ed12c64de0caf..21fd2ea2e5acb4d34a899e4e59a373dc5dd3b47a 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/wrapper.h>
 
 #include "coproc.h"
 
@@ -849,7 +850,7 @@ static int sscape_alloc_dma(sscape_info *devc)
        devc->raw_buf = start_addr;
        devc->raw_buf_phys = virt_to_bus(start_addr);
 
-       for (page = virt_to_page(start_addr); page <= get_mem_map(end_addr); page++)
+       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
                mem_map_reserve(page);
        return 1;
 }
@@ -865,7 +866,7 @@ static void sscape_free_dma(sscape_info *devc)
        start_addr = (unsigned long) devc->raw_buf;
        end_addr = start_addr + devc->buffsize;
 
-       for (page = virt_to_page(start_addr); page <= get_mem_map(end_addr); page++)
+       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
                mem_map_unreserve(page);
 
        free_pages((unsigned long) devc->raw_buf, sz);
index 65982187328b93cb5cbd758995b186cfa2477601..35a5dbc7df9b278fb8163412eb2b9ea58fd484e7 100644 (file)
@@ -132,7 +132,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
        struct file * file;
        struct files_struct * files = current->files;
 
-       write_lock(&current->files->file_lock);
+       write_lock(&files->file_lock);
        if (!(file = fcheck(oldfd)))
                goto out_unlock;
        err = newfd;
@@ -158,7 +158,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
        FD_SET(newfd, files->open_fds);
        write_unlock(&files->file_lock);
        
-       do_close(newfd, 0);
+       do_close(files, newfd, 0);
 
        write_lock(&files->file_lock);
        allocate_fd(files, file, newfd);
@@ -167,7 +167,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
 out:
        return err;
 out_unlock:
-       write_unlock(&current->files->file_lock);
+       write_unlock(&files->file_lock);
        goto out;
 }
 
index dc2eaebe915f7e7ca90010ad12b68c0a35798462..c42b15a4102a82841b7890c7bae1fba9d5a3af04 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -804,11 +804,10 @@ int filp_close(struct file *filp, fl_owner_t id)
  * or not in the open-files bitmap.  dup2 uses this to retain the fd
  * without races.
  */
-int do_close(unsigned int fd, int release)
+int do_close(struct files_struct *files, unsigned int fd, int release)
 {
        int error;
        struct file * filp;
-       struct files_struct * files = current->files;
 
        error = -EBADF;
        write_lock(&files->file_lock);
@@ -829,7 +828,7 @@ out_unlock:
 
 asmlinkage long sys_close(unsigned int fd)
 {
-       return do_close(fd, 1);
+       return do_close(current->files, fd, 1);
 }
 
 /*
index 01db469dac988510864fe1669afc0f882397cce9..fe944bab6d79d4f6d2b4e68207359e75cc04a693 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/elfcore.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
+#include <asm/io.h>
 
 
 static int open_kcore(struct inode * inode, struct file * filp)
@@ -47,7 +48,7 @@ static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *pp
 
        memset(&dump, 0, sizeof(struct user));
        dump.magic = CMAGIC;
-       dump.u_dsize = max_mapnr;
+       dump.u_dsize = (virt_to_phys(high_memory) >> PAGE_SHIFT);
 #if defined (__i386__)
        dump.start_code = PAGE_OFFSET;
 #endif
@@ -55,7 +56,7 @@ static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *pp
        dump.start_data = PAGE_OFFSET;
 #endif
 
-       memsize = (max_mapnr + 1) << PAGE_SHIFT;
+       memsize = virt_to_phys(high_memory);
        if (p >= memsize)
                return 0;
        if (count > memsize - p)
index 91e17f2b6d389ef95340f309f1db03af288bf950..8576d79d0b3367b4f272e7dc367d46b0e61570f0 100644 (file)
@@ -1566,15 +1566,22 @@ static void chroot_fs_refs(struct dentry *old_root,
                           struct vfsmount *new_rootmnt)
 {
        struct task_struct *p;
+       struct fs_struct *fs;
 
        read_lock(&tasklist_lock);
        for_each_task(p) {
-               /* FIXME - unprotected usage of ->fs + (harmless) race */
-               if (!p->fs) continue;
-               if (p->fs->root == old_root && p->fs->rootmnt == old_rootmnt)
-                       set_fs_root(p->fs, new_rootmnt, new_root);
-               if (p->fs->pwd == old_root && p->fs->pwdmnt == old_rootmnt)
-                       set_fs_pwd(p->fs, new_rootmnt, new_root);
+               task_lock(p);
+               fs = p->fs;
+               if (fs) {
+                       atomic_inc(&fs->count);
+                       task_unlock(p);
+                       if (fs->root==old_root && fs->rootmnt==old_rootmnt)
+                               set_fs_root(fs, new_rootmnt, new_root);
+                       if (fs->pwd==old_root && fs->pwdmnt==old_rootmnt)
+                               set_fs_pwd(fs, new_rootmnt, new_root);
+                       put_fs_struct(fs);
+               } else
+                       task_unlock(p);
        }
        read_unlock(&tasklist_lock);
 }
index 94025647e943d92867a7e8d0f1083961a9eb968a..4de265da0ff9ea76e6c14fd97eb40adf01834fae 100644 (file)
@@ -234,7 +234,6 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd);
 #define pte_none(x)    (!pte_val(x))
 #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(xp)  do { set_pte(xp, __pte(0)); } while (0)
-#define pte_pagenr(x)  ((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
 
 #define pmd_none(x)    (!pmd_val(x))
 #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
@@ -247,7 +246,7 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd);
  */
 #define page_address(page) ((page)->virtual)
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-#define pte_page(x) (mem_map+pte_pagenr(x))
+#define pte_page(x) (mem_map+((unsigned long)((pte_val(x) >> PAGE_SHIFT))))
 
 /*
  * The following only work if pte_present() is true.
index 0a31078da5eadaab90e929aab22a13305fbf6063..0fe300bda61e5623f6a7bb830e1d79f7e28efbf1 100644 (file)
@@ -76,20 +76,17 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 #ifndef CONFIG_SMP
        mm->context = 0;
 #else
-       /* Make sure not to do anything during a clone-vm operation */
-       if ((current == tsk) || (current->mm != mm)) {
-               mm->context = (unsigned long)kmalloc(smp_num_cpus * 
-                                       sizeof(unsigned long), GFP_KERNEL);
-               /*
-                * Init the "context" values so that a tlbpid allocation 
-                * happens on the first switch.
-                */
-               if (mm->context)
-                       memset((void *)mm->context, 0, smp_num_cpus * 
-                                                       sizeof(unsigned long));
-               else
-                       printk("Warning: init_new_context failed\n");
-       }
+       mm->context = (unsigned long)kmalloc(smp_num_cpus * 
+                               sizeof(unsigned long), GFP_KERNEL);
+       /*
+        * Init the "context" values so that a tlbpid allocation 
+        * happens on the first switch.
+        */
+       if (mm->context)
+               memset((void *)mm->context, 0, smp_num_cpus * 
+                                               sizeof(unsigned long));
+       else
+               printk("Warning: init_new_context failed\n");
 #endif
 }
 
index d0e5c62670998ad1bc72e30c66642ecd23b70c6e..570aecf209066184d45e2094e9f44ebfee1f93f9 100644 (file)
@@ -875,7 +875,7 @@ static inline int locks_verify_truncate(struct inode *inode,
 
 asmlinkage long sys_open(const char *, int, int);
 asmlinkage long sys_close(unsigned int);       /* yes, it's really unsigned */
-extern int do_close(unsigned int, int);                /* yes, it's really unsigned */
+extern int do_close(struct files_struct *, unsigned int, int);         /* yes, it's really unsigned */
 extern int do_truncate(struct dentry *, loff_t start);
 
 extern struct file *filp_open(const char *, int, int);
index 427e6c8ac6bf40c7d810fcc0a0fd24e00acf0a9d..e9550db619c21a442347dcf2d7b4fed546bc3066 100644 (file)
@@ -276,7 +276,6 @@ typedef struct {
 #define ISDN_TIMER_MODEMXMIT   8
 #define ISDN_TIMER_NETDIAL    16 
 #define ISDN_TIMER_NETHANGUP  32
-#define ISDN_TIMER_IPPP       64 
 #define ISDN_TIMER_KEEPALIVE 128 /* Cisco-Keepalive */
 #define ISDN_TIMER_CARRIER   256 /* Wait for Carrier */
 #define ISDN_TIMER_FAST      (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
@@ -323,7 +322,7 @@ typedef struct {
 typedef struct isdn_net_local_s {
   ulong                  magic;
   char                   name[10];     /* Name of device                   */
-  struct net_device_stats stats;        /* Ethernet Statistics              */
+  struct net_device_stats stats;       /* Ethernet Statistics              */
   int                    isdn_device;  /* Index to isdn-device             */
   int                    isdn_channel; /* Index to isdn-channel            */
   int                   ppp_slot;     /* PPPD device slot number          */
@@ -421,8 +420,8 @@ typedef struct isdn_net_dev_s {
   void *next;                          /* Pointer to next isdn-interface   */
   struct net_device dev;               /* interface to upper levels        */
 #ifdef CONFIG_ISDN_PPP
-  struct mpqueue *mp_last; 
-  struct ippp_bundle ib;
+  ippp_bundle * pb;            /* pointer to the common bundle structure
+                                * with the the per-bundle data */
 #endif
 #ifdef CONFIG_ISDN_X25
   struct concap_proto  *cprot; /* connection oriented encapsulation protocol */
@@ -690,5 +689,6 @@ extern isdn_dev *dev;
 /* Utility-Macros */
 #define MIN(a,b) ((a<b)?a:b)
 #define MAX(a,b) ((a>b)?a:b)
+
 #endif /* __KERNEL__ */
 #endif /* isdn_h */
index 5536bd43aacc5bf3faf84f591f3b14eaa7b6f512..732daa4535a88868908f03a9ffd89997c78d3f82 100644 (file)
@@ -49,6 +49,8 @@ struct pppcallinfo
 #define MP_END_FRAG    0x40
 #define MP_BEGIN_FRAG  0x80
 
+#define MP_MAX_QUEUE_LEN       16
+
 #define ISDN_PPP_COMP_MAX_OPTIONS 16
 
 #define IPPP_COMP_FLAG_XMIT 0x1
@@ -131,35 +133,28 @@ extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
 extern int isdn_ppp_dial_slave(char *);
 extern int isdn_ppp_hangup_slave(char *);
 
-struct ippp_bundle {
+typedef struct {
+  unsigned long seqerrs;
+  unsigned long frame_drops;
+  unsigned long overflows;
+  unsigned long max_queue_len;
+} isdn_mppp_stats;
+
+typedef struct {
   int mp_mrru;                        /* unused                             */
-  struct mpqueue *last;               /* currently defined in isdn_net_dev  */
-  int min;                            /* currently calculated 'on the fly'  */
-  long next_num;                      /* we wanna see this seq.-number next */
-  struct sqqueue *sq;
-  int modify:1;                       /* set to 1 while modifying sqqueue   */
-  int bundled:1;                      /* bundle active ?                    */
-};
+  struct sk_buff * frags;      /* fragments sl list -- use skb->next */
+  long frames;                 /* number of frames in the frame list */
+  unsigned int seq;            /* last processed packet seq #: any packets
+                                * with smaller seq # will be dropped
+                                * unconditionally */
+  spinlock_t lock;
+  int ref_ct;                           
+  /* statistics */
+  isdn_mppp_stats stats;
+} ippp_bundle;
 
 #define NUM_RCV_BUFFS     64
 
-struct sqqueue {
-  struct sqqueue *next;
-  long sqno_start;
-  long sqno_end;
-  struct sk_buff *skb;
-  long timer;
-};
-
-struct mpqueue {
-  struct mpqueue *next;
-  struct mpqueue *last;
-  long sqno;
-  struct sk_buff *skb;
-  int BEbyte;
-  unsigned long time;
-};
-
 struct ippp_buf_queue {
   struct ippp_buf_queue *next;
   struct ippp_buf_queue *last;
@@ -214,9 +209,8 @@ struct ippp_struct {
   struct isdn_net_local_s *lp;
   int unit;
   int minor;
-  long last_link_seqno;
+  unsigned int last_link_seqno;
   long mp_seqno;
-  long range;
 #ifdef CONFIG_ISDN_PPP_VJ
   unsigned char *cbuf;
   struct slcompress *slcomp;
index 8677f36c7e058aefad5d7bbf2d1afceb06a38d13..15ebaffcba9d2355c730bd051e28948fb16a9f37 100644 (file)
@@ -1,5 +1,5 @@
-/* $Id: isdnif.h,v 1.33 2000/01/20 19:59:43 keil Exp $
- *
+/* $Id: isdnif.h,v 1.35 2000/06/16 13:19:38 keil Exp $
+
  * Linux ISDN subsystem
  *
  * Definition of the interface between the subsystem and its low-level drivers.
 /* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
 /* are supplied by the network and not by the HL.                    */   
 /*********************************************************************/
+
+/*****************/
+/* NI1 commands */ 
+/*****************/
+#define NI1_CMD_INVOKE       ((0x00 << 8) | ISDN_PTYPE_NI1)   /* invoke a supplementary service */
+#define NI1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_NI1)   /* abort a invoke cmd */
+
+/*******************************/
+/* NI1 Status callback values */
+/*******************************/
+#define NI1_STAT_INVOKE_RES  ((0x80 << 8) | ISDN_PTYPE_NI1)   /* Result for invocation */
+#define NI1_STAT_INVOKE_ERR  ((0x81 << 8) | ISDN_PTYPE_NI1)   /* Error Return for invocation */
+#define NI1_STAT_INVOKE_BRD  ((0x82 << 8) | ISDN_PTYPE_NI1)   /* Deliver invoke broadcast info */
+
 typedef struct
   { ulong ll_id; /* ID supplied by LL when executing    */
                 /* a command and returned by HL for    */
@@ -150,7 +164,7 @@ typedef struct
                  /* error value when error callback     */
     int datalen; /* length of cmd or stat data          */
     u_char *data;/* pointer to data delivered or send   */
-  } dss1_cmd_stat;
+  } isdn_cmd_stat;
 
 /*
  * Commands from linklevel to lowlevel
@@ -412,7 +426,7 @@ typedef struct {
                setup_parm setup;/* For SETUP msg                       */
                capi_msg cmsg;  /* For CAPI like messages               */
                char display[85];/* display message data                */ 
-               dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result      */
+               isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result      */
                aux_s aux;      /* for modem commands/indications       */
 #ifdef CONFIG_ISDN_TTY_FAX
                T30_s   *fax;   /* Pointer to ttys fax struct           */
@@ -420,6 +434,9 @@ typedef struct {
        } parm;
 } isdn_ctrl;
 
+#define dss1_io    isdn_io
+#define ni1_io     isdn_io
+
 /*
  * The interface-struct itself (initialized at load-time of lowlevel-driver)
  *
index 99ab9c44ec7aae70e226a3448b4c34b722eadd41..ed38faa2159e0b267ab9418da5ac9a965e4404e7 100644 (file)
@@ -94,7 +94,7 @@ static __inline__ void list_del(struct list_head *entry)
 
 /**
  * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
+ * @entry: the element to delete from the list.
  */
 static __inline__ void list_del_init(struct list_head *entry)
 {
index 55cfab78f12fc3bc56c72b5828d97de340dbb32a..80bf2476791d60e4d936db26bb73e5654546f87c 100644 (file)
@@ -5,8 +5,8 @@
 
 struct dev_info {
        kdev_t          dev;
-       int             size;
-       unsigned int    offset;
+       unsigned long   size;
+       unsigned long   offset;
 };
 
 typedef struct dev_info dev_info_t;
index 3ea74db60c694790c9529e3121809b40f299b325..a27234f673c883aaa2ade848bd79eecb4a56afa0 100644 (file)
@@ -5,9 +5,9 @@
 
 struct strip_zone
 {
-       int zone_offset;                /* Zone offset in md_dev */
-       int dev_offset;                 /* Zone offset in real dev */
-       int size;                       /* Zone size */
+       unsigned long zone_offset;      /* Zone offset in md_dev */
+       unsigned long dev_offset;       /* Zone offset in real dev */
+       unsigned long size;             /* Zone size */
        int nb_dev;                     /* # of devices attached to the zone */
        mdk_rdev_t *dev[MAX_REAL]; /* Devices attached to the zone */
 };
index ffa65d20d64e4b2e61b7f3fc1e9a8ddb77943581..aa17b8472ae1920775c19a4868f8cd6314f672a7 100644 (file)
@@ -48,7 +48,7 @@ struct raid1_private_data {
        md_wait_queue_head_t    wait_buffer;
 
        /* for use when syncing mirrors: */
-       int     start_active, start_ready,
+       unsigned long   start_active, start_ready,
                start_pending, start_future;
        int     cnt_done, cnt_active, cnt_ready,
                cnt_pending, cnt_future;
index ab839ea022eedae08beb3e4e3f92e831cc571ff7..dd5ad01ae269d56e5f8853601c603f5853bcb8b4 100644 (file)
@@ -80,7 +80,6 @@ struct raid5_private_data {
        int                     buffer_size;
        int                     chunk_size, level, algorithm;
        int                     raid_disks, working_disks, failed_disks;
-       int                     sector_count;
        unsigned long           next_sector;
        atomic_t                nr_handle;
        struct stripe_head      *next_free_stripe;
index 10da433df8ad818526de9ec1c18ba0fdf7ddc1c5..76ccf2dbb0740fd98d291a9e5aefc36a01a7973c 100644 (file)
@@ -11,6 +11,7 @@
 
 typedef struct kmem_cache_s kmem_cache_t;
 
+#include       <linux/config.h>
 #include       <linux/mm.h>
 #include       <linux/cache.h>
 
index 594ee79f317689d002dc3caceae83b6685b24572..f77eaa4eefc08b006dca9bf21b61eac4186cd30b 100644 (file)
@@ -128,10 +128,16 @@ static inline int dup_mmap(struct mm_struct * mm)
        struct vm_area_struct * mpnt, *tmp, **pprev;
        int retval;
 
-       /* Kill me slowly. UGLY! FIXME! */
-       memcpy(&mm->start_code, &current->mm->start_code, 15*sizeof(unsigned long));
-
        flush_cache_mm(current->mm);
+       mm->locked_vm = 0;
+       mm->mmap = NULL;
+       mm->mmap_cache = NULL;
+       mm->map_count = 0;
+       mm->context = 0;
+       mm->cpu_vm_mask = 0;
+       mm->swap_cnt = 0;
+       mm->swap_address = 0;
+       mm->segments = NULL;
        pprev = &mm->mmap;
        for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
                struct file *file;
@@ -189,6 +195,22 @@ fail_nomem:
        return retval;
 }
 
+#define allocate_mm()  (kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
+
+static struct mm_struct * mm_init(struct mm_struct * mm)
+{
+       atomic_set(&mm->mm_users, 1);
+       atomic_set(&mm->mm_count, 1);
+       init_MUTEX(&mm->mmap_sem);
+       mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+       mm->pgd = pgd_alloc();
+       if (mm->pgd)
+               return mm;
+       kmem_cache_free(mm_cachep, mm);
+       return NULL;
+}
+       
+
 /*
  * Allocate and initialize an mm_struct.
  */
@@ -196,17 +218,10 @@ struct mm_struct * mm_alloc(void)
 {
        struct mm_struct * mm;
 
-       mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL);
+       mm = allocate_mm();
        if (mm) {
                memset(mm, 0, sizeof(*mm));
-               atomic_set(&mm->mm_users, 1);
-               atomic_set(&mm->mm_count, 1);
-               init_MUTEX(&mm->mmap_sem);
-               mm->page_table_lock = SPIN_LOCK_UNLOCKED;
-               mm->pgd = pgd_alloc();
-               if (mm->pgd)
-                       return mm;
-               kmem_cache_free(mm_cachep, mm);
+               return mm_init(mm);
        }
        return NULL;
 }
@@ -287,9 +302,15 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
 
        retval = -ENOMEM;
        mm = mm_alloc();
+       mm = allocate_mm();
        if (!mm)
                goto fail_nomem;
 
+       /* Copy the current MM stuff.. */
+       memcpy(mm, current->mm, sizeof(*mm));
+       if (!mm_init(mm))
+               goto fail_nomem;
+
        tsk->mm = mm;
        tsk->active_mm = mm;
 
@@ -304,10 +325,11 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
        if (retval)
                goto free_pt;
 
+       init_new_context(tsk,mm);
+
 good_mm:
        tsk->mm = mm;
        tsk->active_mm = mm;
-       init_new_context(tsk,mm);
        return 0;
 
 free_pt:
index 862cc7027ea9065c1a669ac6cb2bb1b7c741f6b9..bf557e2537cb3f0f76135d03de9f1edbd69d1ead 100644 (file)
@@ -1568,7 +1568,7 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
 
                        pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
                        for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
-                               mem_map_unreserve(page);
+                               clear_bit(PG_reserved, &page->flags);
                        free_pages(pg_vec[i], order);
                }
        }
@@ -1623,7 +1623,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
                        pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
                        for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
-                               mem_map_reserve(page);
+                               set_bit(PG_reserved, &page->flags);
                }
                /* Page vector is allocated */