diff -u --recursive --new-file v2.2.0-pre1/linux/CREDITS linux/CREDITS --- v2.2.0-pre1/linux/CREDITS Mon Dec 28 15:00:51 1998 +++ linux/CREDITS Tue Dec 29 17:31:48 1998 @@ -147,7 +147,8 @@ E: kgb@manjak.knm.org.pl P: 1024/FA6F16D1 96 D1 1A CF 5F CA 69 EC F9 4F 36 1F 6D 60 7B DA D: Maintainer of the System V file system. -D: SystemV fs update for 2.1.x dcache. +D: System V fs update for 2.1.x dcache. +D: Forward ported a couple of SCSI drivers. D: Various bugfixes. S: ul. Koscielna 12a S: 62-300 Wrzesnia diff -u --recursive --new-file v2.2.0-pre1/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.2.0-pre1/linux/Documentation/Configure.help Mon Dec 28 15:00:51 1998 +++ linux/Documentation/Configure.help Tue Dec 29 17:43:14 1998 @@ -91,6 +91,9 @@ single-CPU machines. On a single-CPU machine, a non-SMP kernel will run faster than an SMP kernel. + i486 based SMP boards don't boot CONFIG_M586/M686 kernels. CONFIG_M686 + SMP kernels might not work on all Pentium based boards. + People using multiprocessor machines should also say Y to "Enhanced Real Time Clock Support", below. The "Advanced Power Management" code will be disabled in an SMP kernel. @@ -1557,23 +1560,25 @@ This is the processor type of your CPU. This information is used for optimizing purposes. In order to compile a kernel that can run on all x86 CPU types (albeit not optimally fast), you can specify - "386" here. If you specify one of "486" or "Pentium" or "PPro", - then the kernel will run on all x86 architectures except on 386. + "386" here. + + If you specify one of "486" or "Pentium" or "PPro", then the kernel + will not necessarily run on earlier architectures (ie a Pentium + optimized kernel will run on a PPro, but not necessarily on a i486). Here are the settings recommended for greatest speed: - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX and Cyrix/TI 486DLC/DLC2. Only "386" kernels will run on a 386 class machine. - "486" for the AMD/Cyrix/IBM/Intel DX4 or 486DX/DX2/SL/SX/SX2, - AMD/Cyrix 5x86, NexGen Nx586 and UMC U5D or U5S - - "Pentium" for the AMD K5, K6 and K6-3D, Cyrix MediaGX, + AMD/Cyrix 5x86, NexGen Nx586 and UMC U5D or U5S. Anything without + the "rdtsc" instruction, apparently including the Cyrix MediaGX. + - "Pentium" for the Intel Pentium/Pentium MMX, AMD K5, K6 and K6-3D, Cyrix/IBM/National Semiconductor 6x86 and GXm, IDT Centaur - WinChip C6, and Intel Pentium/Pentium MMX + WinChip C6. This option will assume that you have a time stamp + counter. - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and - Intel Pentium II/Pentium Pro - - In rare cases, it can make sense to specify "Pentium" even if - running on a 486: the kernel will be smaller but slower. + Intel Pentium II/Pentium Pro. If you don't know what to do, choose "386". @@ -3776,14 +3781,19 @@ given SCSI device. Go with the default unless you know what you're doing. Minimum is 2 and maximum is 8. -Future Domain 16xx SCSI/AHA 2920 support +Future Domain 16xx SCSI/AHA-2920A support CONFIG_SCSI_FUTURE_DOMAIN This is support for Future Domain's 16-bit SCSI host adapters (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and other adapters based on the Future Domain chipsets (Quantum - ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board). + ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board). It is explained in section 3.7 of the SCSI-HOWTO, available via FTP (user: anonymous) at ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. + + NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip and + should use the aic7xxx driver (CONFIG_SCSI_AIC7XXX). The Future Domain + driver works with the older Adaptec AHA-2920A boards with a Future Domain + chip on them. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). diff -u --recursive --new-file v2.2.0-pre1/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt --- v2.2.0-pre1/linux/Documentation/kernel-docs.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/kernel-docs.txt Tue Dec 29 15:47:32 1998 @@ -0,0 +1,331 @@ + + + INDEX OF DOCUMENTATION FOR PEOPLE INTERESTED IN WRITING AND/OR UNDERSTANDING + THE LINUX KERNEL. + + Juan-Mariano de Goyeneche + + + /* + * The latest version of this document may be found at: + * http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html + */ + + The need for a document like this one became apparent in the + linux-kernel mailing list as the same questions, asking for pointers + to information, appeared again and again. + + Fortunately, as more and more people get to GNU/Linux, more and more + get interested in the Kernel. But reading the sources is not always + enough. It is easy to understand the code, but miss the concepts, the + philosophy and design decissions behind this code. + + Unfortunately, not many documents are available for beginners to + start. And, even if they exist, there was no "well-known" place which + kept track of them. These lines try to cover this lack. All documents + available on line known by the author are listed, while some reference + books are also mentioned. + + PLEASE, if you know any paper not listed here or write a new document, + send me an e-mail, and I'll include a reference to it here. Any + corrections, ideas or comments are also wellcomed. + + The papers that follow are listed in no particular order. All are + catalogued with the following fields: the document's "Title", the + "Author"/s, the "URL" where they can be found, some "Keywords" + helpfull when searching for specific topics, and a brief "Description" + of the Document. + + Enjoy! + + + ON-LINE DOCS: + + + Title: "The Linux Kernel" + Author: David A. Rusling. + URL: http://sunsite.unc.edu/linux/LDP/tlk/tlk.html + Keywords: everything!, book. + Description: On line, 200 pages book describing most + aspects of the Linux Kernel. Probably, the first reference + for beginners. Lots of illustrations explaining data + structures use and relationships in the purest Richard W. + Stevens' style. Contents: "1.-Hardware Basics, 2.-Software + Basics, 3.-Memory Management, 4.-Processes, 5.-Interprocess + Communication Mechanisms, 6.-PCI, 7.-Interrupts and Interrupt + Handling, 8.-Device Drivers, 9.-The File system, + 10.-Networks, 11.-Kernel Mechanisms, 12.-Modules, 13.-The + Linux Kernel Sources, A.-Linux Data Structures, B.-The Alpha + AXP Processor, C.-Useful Web and FTP Sites, D.-The GNU + General Public License, Glossary". In short: a must have. + + + Title: "The Linux Kernel Hackers' Guide" + Author: Michael K.Johnson and others. + URL: http://www.redhat.com:8080/HyperNews/get/khg.html + Keywords: everything! + Description: No more Postscript book-like version. Only + HTML now. Many people have contributed. The interface is + similar to web available mailing lists archives. You can find + some articles and then some mails asking questions about them + and/or complementing previous contributions. A little bit + anarchic in this aspect, but with some valuable information + in some cases. + + + Title: "Tour Of the Linux Kernel Source" + Author: Vijo Cherian. + URL: http://www.svrec.ernet.in/~vijo/tolks/tolks.html + Keywords: + Description: The name says it all. A tour of the sources, + describing directories, files, variables, data structures... + It covers general stuff, device drivers, filesystems, IPC and + Network Code. + + + Title: "Overview of the Virtual File System" + Author: Richard Gooch. + URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt + Keywords: VFS, File System, mounting filesystems, opening + files, dentries, + dcache. Description: Brief introduction to the Linux + Virtual File System. What is it, how it works, operations + taken when opening a file or mounting a file system and + description of important data structures explaining the + purpose of each of their entries. + + + Title: "The Linux RAID-1, 4, 5 Code" + Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza. + URL: http://www.ssc.com/lj/issue44/2391.html + Keywords: RAID, MD driver. + Description: Linux Journal Kernel Korner article. Here is + it's abstract: "A description of the implementation of the + RAID-1, RAID-4 and RAID-5 personalities of the MD device + driver in the Linux kernel, providing users with high + performance and reliable, secondary-storage capability using + software". + + + Title: "Dynamic Kernels: Modularized Device Drivers" + Author: Alessandro Rubini. + URL: http://www.ssc.com/lj/issue23/1219.html + Keywords: device driver, module, loading/unloading modules, + allocating + resources. Description: Linux Journal Kernel Korner + article. Here is it's abstract: "This is the first of a + series of four articles co-authored by Alessandro Rubini and + Georg Zezchwitz which present a practical approach to writing + Linux device drivers as kernel loadable modules. This + installment presents an introduction to the topic, preparing + the reader to understand next month's installment". + + + Title: "Dynamic Kernels: Discovery" + Author: Alessandro Rubini. + URL: http://www.ssc.com/lj/issue24/kk24.html + Keywords: character driver, init_module, clean_up module, + autodetection, + mayor number, minor number, file operations, open(), close(). + Description: Linux Journal Kernel Korner article. Here is + it's abstract: "This article, the second of four, introduces + part of the actual code to create custom module implementing + a character device driver. It describes the code for module + initialization and cleanup, as well as the open() and close() + system calls". + + + Title: "The Devil's in the Details" + Author: Georg v. Zezschwitz and Alessandro Rubini. + URL: http://www.ssc.com/lj/issue25/kk25.html + Keywords: read(), write(), select(), ioctl(), blocking/non + blocking mode, + interrupt handler. Description: Linux Journal Kernel Korner + article. Here is it's abstract: "This article, the third of + four on writing character device drivers, introduces concepts + of reading, writing, and using ioctl-calls". + + + Title: "Dissecting Interrupts and Browsing DMA" + Author: Alessandro Rubini and Georg v. Zezschwitz. + URL: http://www.ssc.com/lj/issue26/interrupt.html + Keywords: interrupts, irqs, DMA, bottom halves, task + queues. + Description: Linux Journal Kernel Korner article. Here is + it's abstract: "This is the fourth in a series of articles + about writing character device drivers as loadable kernel + modules. This month, we further investigate the field of + interrupt handling. Though it is conceptually simple, + practical limitations and constraints make this an + ``interesting'' part of device driver writing, and several + different facilities have been provided for different + situations. We also investigate the complex topic of DMA". + + + Title: "Network Buffers And Memory Management" + Author: Alan Cox. + URL: http://www.ssc.com/lj/issue30/kk30.html + Keywords: sk_buffs, network devices, protocol/link layer + variables, network + devices flags, transmit, receive, configuration, multicast. + Description: Linux Journal Kernel Korner. Here is the + abstract: "Writing a network device driver for Linux is + fundamentally simple---most of the complexity (other than + talking to the hardware) involves managing network packets in + memory". + + + Title: "An Introduction to the Linux 1.3.x Networking Code" + Author: Vipul Gupta. + URL: + http://anchor.cs.binghamton.edu/courses/cs628/linux-net.html + Keywords: files, sk_buffs. + Description: A short description of files under the net/ + directory. Each file has a one or two lines paragrahp + description. sk_buffs explained, too, with some beatiful + pictures. A little bit outdated. + + + Title: "Linux ioctl() Primer" + Author: Vipul Gupta. + URL: + http://anchor.cs.binghamton.edu/courses/cs628/ioctl.html + Keywords: ioctl, socket. + Description: Little description and examples on the use and + implementation of the ioctl() system call. A little bit + biased towards sockets. + + + Title: "Writing Linux Device Drivers" + Author: Michael K. Johnson. + URL: http://www.redhat.com/~johnsonm/devices.html + Keywords: files, VFS, file operations, kernel interface, + character vs + block devices, I/O access, hardware interrupts, DMA, access + to user memory, memory allocation, timers. Description: + Introductory 50-minutes (sic) tutorial on writing device + drivers. 12 pages written by the same author of the "Kernel + Hackers' Guide" which give a very good overview of the topic. + + + Title: "The Venus kernel interface" + Author: Peter J. Braam. + URL: + http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html + Keywords: coda, filesystem, venus, cache manager. + Description: "This document describes the communication + between Venus and kernel level file system code needed for + the operation of the Coda filesystem. This version document + is meant to describe the current interface (version 1.0) as + well as improvements we envisage". + + + Title: "Programming PCI-Devices under Linux" + Author: Claus Schroeter. + URL: + ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pc + ip.ps.gz + Keywords: PCI, device, busmastering. + Description: 6 pages tutorial on PCI programming under + Linux. Gives the basic concepts on the architecture of the + PCI subsystem, as long as basic functions and macros to + read/write the devices and perform busmastering. + + + Title: "Writing Character Device Driver for Linux" + Author: R. Baruch and C. Schroeter. + URL: + ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/dr + ivers.ps.gz + Keywords: character device drivers, I/O, signals, DMA, + accesing ports in user space, kernel environment. + Description: 68 pages paper on writing character drivers. A + little bit old (1.993, 1.994) although still useful. + + + + * BOOKS: (Not on-line) + + + Title: "Linux Device Drivers" + Author: Alessandro Rubini. + Publisher: O'Reilly &Associates. + Date: 1998. + ISBN: 1-56592-292-1 + + + Title: "Linux Kernel Internals" + Author: Michael Beck. + Publisher: Addison-Wesley. + Date: 1997. + ISBN: 0-201-33143-8 (second edition) + + + Title: "The Design of the UNIX Operating System" + Author: Maurice J. Bach. + Publisher: Prentice Hall. + Date: 1986. + ISBN: ??? + + + Title: "The Design and Implementation of the 4.3 BSD UNIX + Operating System" + Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael + J. Karels, John S. Quarterman. + Publisher: Addison-Wesley. + Date: 1989 (reprinted with corrections on October, 1990). + ISBN: 0-201-06196-1 + + + Title: "The Design and Implementation of the 4.4 BSD UNIX + Operating System" + Author: Marshall Kirk McKusick, Keith Bostic, Michael J. + Karels, John S. Quarterman. + Publisher: Addison-Wesley. + Date: 1996. + ISBN: 0-201-54979-4 + + + Title: "Programmation Linux 2.0 API systeme et + fonctionnement du noyau" + Author: Remy Card, Eric Dumas, Franck Mevel. + Publisher: Eyrolles. + Date: 1997. + Pages: 520. ISBN: 2-212-08932-5 + + + Title: "Unix internals -- the new frontiers" + Author: Uresh Vahalia. + Publisher: Prentice Hall. + Date: 1996. + Pages: 600. ISBN: 0-13-101908-2 + + + * MISCELLANEOUS: + + + Name: Linux Source Driver. + URL: http://lsd.linux.cz + Keywords: Browsing. + Description: "Linux Source Driver (LSD) is an application, + which can make browsing source codes of Linux kernel easier + than you can imagine. You can select between multiple + versions of kernel (e.g. 0.01, 1.0.0, 2.0.33, 2.0.34pre13, + 2.0.0, 2.1.101 etc.). With LSD you can search Linux kernel + (fulltext, macros, types, functions and variables) and LSD + can generate patches for you on the fly (files, directories + or kernel)". + + + Name: Linux Weekly News. + URL: http://lwn.net + Keywords: last kernel news. + Description: The title says it all. There's a fixed kernel + section summarizing developers' work, bug fixes, new features + and versions produced during the week. Published every + thursday. + + + Name: CuTTiNG.eDGe.LiNuX. + URL: http://edge.linuxhq.com + Keywords: changelist. + Description: Site which provides the changelist for every + kernel release. What's new, what's better, what's changed. + Myrdraal reads the patchs and describes them. Pointers to the + patches are there, too. + + + Name: New linux-kernel Mailing List FAQ. + URL: Original site: + http://www.altern.org/andrebalsa/doc/lkml-faq.html + URL: U.S. mirror site: + http://www.ececs.uc.edu/~rreilova/linux/lkml-faq.html + Keywords: linux-kernel mailing list FAQ. + Description: linux-kernel is a mailing list for developers + to communicate. This FAQ builds on the previous linux-kernel + mailing list FAQ maintained by Frohwalt Egerer, who no longer + maintains it. Read it to see how to join the mailing list. + Dozens of interesting questions regarding the list, Linux, + developers (who is ...?), terms (what is...?) are answered + here too. Just read it. + + + Name: "Linux Virtual File System" + Author: Peter J. Braam. + URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs + Keywords: slides, VFS, inode, superblock, dentry, dcache. + Description: Set of slides, presumably from a presentation + on the Linux VFS layer. Covers version 2.1.x, with dentries + and the dcache. diff -u --recursive --new-file v2.2.0-pre1/linux/MAINTAINERS linux/MAINTAINERS --- v2.2.0-pre1/linux/MAINTAINERS Mon Dec 28 15:00:52 1998 +++ linux/MAINTAINERS Tue Dec 29 15:49:57 1998 @@ -181,12 +181,6 @@ W: http://www.fi.muni.cz/~kas/cosa/ S: Maintained -COSA/SRP SYNC SERIAL DRIVER -P: Jan "Yenya" Kasprzak -M: kas@fi.muni.cz -W: http://www.fi.muni.cz/~kas/cosa/ -S: Maintained - CREDITS FILE P: John A. Martin M: jam@acm.org @@ -350,10 +344,10 @@ S: Maintained IDE DRIVER [GENERAL] -P: Mark Lord -M: mlord@pobox.com +P: Andre Hedrick +M: hedrick@astro.dyer.vanderbilt.edu L: linux-kernel@vger.rutgers.edu -S: Odd Fixes +S: Maintained IDE/ATAPI CDROM DRIVER P: Jens Axboe @@ -405,6 +399,13 @@ P: H. Peter Anvin M: hpa@zytor.com L: autofs@linux.kernel.org +S: Maintained + +KERNEL NFSD +P: G. Allen Morris III +M: gam3@acm.org +L: nfs-devel@linux.kernel.org (Linux NFS) +W: http://csua.berkley.edu/~gam3/knfsd S: Maintained LAPB module diff -u --recursive --new-file v2.2.0-pre1/linux/Makefile linux/Makefile --- v2.2.0-pre1/linux/Makefile Mon Dec 28 15:00:52 1998 +++ linux/Makefile Mon Dec 28 15:01:07 1998 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION =-pre1 +EXTRAVERSION =-pre2 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --recursive --new-file v2.2.0-pre1/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.2.0-pre1/linux/arch/alpha/kernel/alpha_ksyms.c Tue Dec 22 14:16:53 1998 +++ linux/arch/alpha/kernel/alpha_ksyms.c Tue Dec 29 13:56:15 1998 @@ -86,6 +86,7 @@ EXPORT_SYMBOL(strncat); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strtok); +EXPORT_SYMBOL(strpbrk); EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(memcmp); diff -u --recursive --new-file v2.2.0-pre1/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.2.0-pre1/linux/arch/alpha/kernel/entry.S Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/entry.S Tue Dec 29 13:56:15 1998 @@ -689,7 +689,8 @@ .set at mb /* Make the changed data visible before the freed lock. */ stq $31,scheduler_lock - br ret_from_sys_call + lda $26,ret_from_sys_call + jsr $31,schedule_tail .set noat .end ret_from_smpfork #endif /* __SMP__ */ diff -u --recursive --new-file v2.2.0-pre1/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.2.0-pre1/linux/arch/alpha/kernel/irq.c Mon Dec 28 15:00:52 1998 +++ linux/arch/alpha/kernel/irq.c Tue Dec 29 13:56:15 1998 @@ -11,6 +11,7 @@ */ #include +#include #include #include #include diff -u --recursive --new-file v2.2.0-pre1/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.2.0-pre1/linux/arch/alpha/kernel/ptrace.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/ptrace.c Tue Dec 29 16:17:00 1998 @@ -541,7 +541,9 @@ /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: + down(&child->mm->mmap_sem); ret = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp)); if (ret < 0) goto out; @@ -560,7 +562,9 @@ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data)); + down(&child->mm->mmap_sem); ret = write_long(child, addr, data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: /* write the specified register */ diff -u --recursive --new-file v2.2.0-pre1/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.2.0-pre1/linux/arch/alpha/kernel/smp.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/smp.c Tue Dec 29 13:56:15 1998 @@ -30,7 +30,14 @@ #include "proto.h" -struct ipi_msg_flush_tb_struct ipi_msg_flush_tb; +#define DEBUG_SMP 0 +#if DEBUG_SMP +#define DBGS(args) printk args +#else +#define DBGS(args) +#endif + +struct ipi_msg_flush_tb_struct ipi_msg_flush_tb __cacheline_aligned; struct cpuinfo_alpha cpu_data[NR_CPUS]; @@ -39,7 +46,6 @@ unsigned int boot_cpu_id = 0; static int smp_activated = 0; -static unsigned long ipicnt[NR_CPUS] = {0,}; /* IPI counts */ int smp_found_config = 0; /* Have we found an SMP box */ static int max_cpus = -1; @@ -53,10 +59,12 @@ volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; volatile unsigned long smp_spinning[NR_CPUS] = { 0, }; +cycles_t cacheflush_time; + unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; -volatile int ipi_bits[NR_CPUS]; +volatile int ipi_bits[NR_CPUS] __cacheline_aligned; unsigned long boot_cpu_palrev; @@ -73,87 +81,80 @@ static void secondary_cpu_start(int, struct task_struct *); static void send_cpu_msg(char *, int); -/* process bootcommand SMP options, like "nosmp" and "maxcpus=" */ -__initfunc(void smp_setup(char *str, int *ints)) +/* Process bootcommand SMP options, like "nosmp" and "maxcpus=" */ +void __init +smp_setup(char *str, int *ints) { if (ints && ints[0] > 0) max_cpus = ints[1]; - else + else max_cpus = 0; } -void smp_store_cpu_info(int id) +static void __init +smp_store_cpu_info(int id) { /* This is it on Alpha, so far. */ - cpu_data[id].loops_per_sec = loops_per_sec; + cpu_data[id].loops_per_sec = loops_per_sec; } -void smp_commence(void) +void __init +smp_commence(void) { /* Lets the callin's below out of their loop. */ mb(); smp_commenced = 1; } -void smp_callin(void) +void __init +smp_callin(void) { - int cpuid = hard_smp_processor_id(); + int cpuid = hard_smp_processor_id(); -#if 0 - printk("CALLIN %d state 0x%lx\n", cpuid, current->state); -#endif + DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state)); #ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); + local_flush_cache_all(); + local_flush_tlb_all(); #endif #if 0 - set_irq_udt(mid_xlate[boot_cpu_id]); + set_irq_udt(mid_xlate[boot_cpu_id]); #endif - /* Get our local ticker going. */ - smp_setup_percpu_timer(); + /* Get our local ticker going. */ + smp_setup_percpu_timer(); #if 0 - calibrate_delay(); + calibrate_delay(); #endif - smp_store_cpu_info(cpuid); + smp_store_cpu_info(cpuid); #ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); + local_flush_cache_all(); + local_flush_tlb_all(); #endif - /* Allow master to continue. */ - set_bit(cpuid, (unsigned long *)&cpu_callin_map[cpuid]); + /* Allow master to continue. */ + set_bit(cpuid, (unsigned long *)&cpu_callin_map[cpuid]); #ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); + local_flush_cache_all(); + local_flush_tlb_all(); #endif #ifdef NOT_YET - while(!task[cpuid] || current_set[cpuid] != task[cpuid]) - barrier(); -#endif /* NOT_YET */ - -#if 0 - /* Fix idle thread fields. */ - __asm__ __volatile__("ld [%0], %%g6\n\t" - : : "r" (¤t_set[cpuid]) - : "memory" /* paranoid */); - current->mm->mmap->vm_page_prot = PAGE_SHARED; - current->mm->mmap->vm_start = PAGE_OFFSET; - current->mm->mmap->vm_end = init_task.mm->mmap->vm_end; + while(!task[cpuid] || current_set[cpuid] != task[cpuid]) + barrier(); #endif - + #ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); + local_flush_cache_all(); + local_flush_tlb_all(); #endif #if 0 - __sti(); + __sti(); #endif } -asmlinkage int start_secondary(void *unused) +asmlinkage int __init +start_secondary(void *unused) { extern asmlinkage void entInt(void); extern void paging_init_secondary(void); @@ -163,35 +164,83 @@ trap_init(); wrent(entInt, 0); - smp_callin(); - while (!smp_commenced) + smp_callin(); + while (!smp_commenced) barrier(); #if 1 -printk("start_secondary: commencing CPU %d current %p\n", - hard_smp_processor_id(), current); + printk("start_secondary: commencing CPU %d current %p\n", + hard_smp_processor_id(), current); #endif - cpu_idle(NULL); + cpu_idle(NULL); } +static void __init +smp_tune_scheduling (void) +{ + /* + * Rough estimation for SMP scheduling, this is the number of + * cycles it takes for a fully memory-limited process to flush + * the SMP-local cache. + * + * We are not told how much cache there is, so we have to guess. + */ + + struct percpu_struct *cpu; + unsigned long on_chip_cache; + unsigned long freq; + + cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset); + switch (cpu->type) + { + case EV45_CPU: + on_chip_cache = 16 + 16; + break; + + case EV5_CPU: + case EV56_CPU: + on_chip_cache = 8 + 8 + 96; + break; + + case PCA56_CPU: + on_chip_cache = 16 + 8; + break; + + case EV6_CPU: + on_chip_cache = 64 + 64; + break; + + default: + on_chip_cache = 8 + 8; + break; + } + + freq = hwrpb->cycle_freq ? : est_cycle_freq; + + /* Magic estimation stolen from x86 port. */ + cacheflush_time = freq / 1024 * on_chip_cache / 5000; +} + + /* * Cycle through the processors sending START msgs to boot each. */ -void smp_boot_cpus(void) +void __init +smp_boot_cpus(void) { - int cpucount = 0; - int i, first, prev; + int cpucount = 0; + int i, first, prev; - printk("smp_boot_cpus: Entering SMP Mode...\n"); + printk("Entering SMP Mode.\n"); #if 0 - __sti(); + __sti(); #endif - for(i=0; i < NR_CPUS; i++) { + for(i=0; i < NR_CPUS; i++) { cpu_number_map[i] = -1; cpu_logical_map[i] = -1; - prof_counter[i] = 1; - prof_multiplier[i] = 1; + prof_counter[i] = 1; + prof_multiplier[i] = 1; ipi_bits[i] = 0; } @@ -199,159 +248,155 @@ cpu_logical_map[0] = boot_cpu_id; current->processor = boot_cpu_id; /* ??? */ - smp_store_cpu_info(boot_cpu_id); + smp_store_cpu_info(boot_cpu_id); + smp_tune_scheduling(); #ifdef NOT_YET - printk("CPU%d: ", boot_cpu_id); - print_cpu_info(&cpu_data[boot_cpu_id]); - set_irq_udt(mid_xlate[boot_cpu_id]); -#endif /* NOT_YET */ - smp_setup_percpu_timer(); + printk("CPU%d: ", boot_cpu_id); + print_cpu_info(&cpu_data[boot_cpu_id]); + set_irq_udt(mid_xlate[boot_cpu_id]); +#endif + smp_setup_percpu_timer(); #ifdef HUH - local_flush_cache_all(); + local_flush_cache_all(); #endif - if (smp_num_probed == 1) + if (smp_num_probed == 1) return; /* Not an MP box. */ #if NOT_YET - /* - * If SMP should be disabled, then really disable it! - */ - if (!max_cpus) + /* + * If SMP should be disabled, then really disable it! + */ + if (!max_cpus) { smp_found_config = 0; - printk(KERN_INFO "SMP mode deactivated.\n"); - } -#endif /* NOT_YET */ + printk(KERN_INFO "SMP mode deactivated.\n"); + } +#endif - for (i = 0; i < NR_CPUS; i++) { + for (i = 0; i < NR_CPUS; i++) { if (i == boot_cpu_id) continue; - if (cpu_present_map & (1 << i)) { - struct task_struct *idle; - int timeout; - - /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_PID); - idle = task[++cpucount]; + if (cpu_present_map & (1 << i)) { + struct task_struct *idle; + int timeout; + + /* Cook up an idler for this guy. */ + kernel_thread(start_secondary, NULL, CLONE_PID); + idle = task[++cpucount]; if (!idle) panic("No idle process for CPU %d", i); - idle->processor = i; + idle->processor = i; -#if 0 -printk("smp_boot_cpus: CPU %d state 0x%lx flags 0x%lx\n", - i, idle->state, idle->flags); -#endif + DBGS(("smp_boot_cpus: CPU %d state 0x%lx flags 0x%lx\n", + i, idle->state, idle->flags)); - /* whirrr, whirrr, whirrrrrrrrr... */ + /* whirrr, whirrr, whirrrrrrrrr... */ #ifdef HUH - local_flush_cache_all(); + local_flush_cache_all(); #endif - secondary_cpu_start(i, idle); + secondary_cpu_start(i, idle); - /* wheee... it's going... wait for 5 secs...*/ - for (timeout = 0; timeout < 50000; timeout++) { + /* wheee... it's going... wait for 5 secs...*/ + for (timeout = 0; timeout < 50000; timeout++) { if (cpu_callin_map[i]) break; - udelay(100); - } - if (cpu_callin_map[i]) { + udelay(100); + } + if (cpu_callin_map[i]) { /* Another "Red Snapper". */ cpu_number_map[i] = cpucount; - cpu_logical_map[cpucount] = i; - } else { + cpu_logical_map[cpucount] = i; + } else { cpucount--; - printk("smp_boot_cpus: Processor %d" + printk("smp_boot_cpus: Processor %d" " is stuck 0x%lx.\n", i, idle->flags); - } - } - if (!(cpu_callin_map[i])) { + } + } + if (!(cpu_callin_map[i])) { cpu_present_map &= ~(1 << i); - cpu_number_map[i] = -1; - } - } + cpu_number_map[i] = -1; + } + } #ifdef HUH - local_flush_cache_all(); + local_flush_cache_all(); #endif - if (cpucount == 0) { + if (cpucount == 0) { printk("smp_boot_cpus: ERROR - only one Processor found.\n"); - cpu_present_map = (1 << smp_processor_id()); - } else { + cpu_present_map = (1 << smp_processor_id()); + } else { unsigned long bogosum = 0; - for (i = 0; i < NR_CPUS; i++) { + for (i = 0; i < NR_CPUS; i++) { if (cpu_present_map & (1 << i)) bogosum += cpu_data[i].loops_per_sec; - } - printk("smp_boot_cpus: Total of %d Processors activated" + } + printk("smp_boot_cpus: Total of %d Processors activated" " (%lu.%02lu BogoMIPS).\n", - cpucount + 1, - (bogosum + 2500)/500000, - ((bogosum + 2500)/5000)%100); - smp_activated = 1; - smp_num_cpus = cpucount + 1; - } - - /* Setup CPU list for IRQ distribution scheme. */ - first = prev = -1; - for (i = 0; i < NR_CPUS; i++) { + cpucount + 1, + (bogosum + 2500)/500000, + ((bogosum + 2500)/5000)%100); + smp_activated = 1; + smp_num_cpus = cpucount + 1; + } + + /* Setup CPU list for IRQ distribution scheme. */ + first = prev = -1; + for (i = 0; i < NR_CPUS; i++) { if (cpu_present_map & (1 << i)) { if (first == -1) first = i; if (prev != -1) cpu_data[i].next = i; - prev = i; - } - } - cpu_data[prev].next = first; + prev = i; + } + } + cpu_data[prev].next = first; - /* Ok, they are spinning and ready to go. */ - smp_processors_ready = 1; + /* Ok, they are spinning and ready to go. */ + smp_processors_ready = 1; } -__initfunc(void ioapic_pirq_setup(char *str, int *ints)) +static void __init +smp_setup_percpu_timer(void) { - /* this is prolly INTEL-specific */ -} - -static void smp_setup_percpu_timer(void) -{ - int cpu = smp_processor_id(); + int cpu = smp_processor_id(); - prof_counter[cpu] = prof_multiplier[cpu] = 1; + prof_counter[cpu] = prof_multiplier[cpu] = 1; #ifdef NOT_YET - load_profile_irq(mid_xlate[cpu], lvl14_resolution); - if (cpu == boot_cpu_id) + load_profile_irq(mid_xlate[cpu], lvl14_resolution); + if (cpu == boot_cpu_id) enable_pil_irq(14); #endif } extern void update_one_process(struct task_struct *p, unsigned long ticks, - unsigned long user, unsigned long system, + unsigned long user, unsigned long system, int cpu); -void smp_percpu_timer_interrupt(struct pt_regs *regs) +void +smp_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); #ifdef NOT_YET - clear_profile_irq(mid_xlate[cpu]); - if(!user_mode(regs)) + clear_profile_irq(mid_xlate[cpu]); + if(!user_mode(regs)) alpha_do_profile(regs->pc); #endif - if (!--prof_counter[cpu]) { + if (!--prof_counter[cpu]) { int user = user_mode(regs); - if (current->pid) { + if (current->pid) { update_one_process(current, 1, user, !user, cpu); - if (--current->counter < 0) { + if (--current->counter < 0) { current->counter = 0; - current->need_resched = 1; - } + current->need_resched = 1; + } - spin_lock(&ticker_lock); - if (user) { + spin_lock(&ticker_lock); + if (user) { if (current->priority < DEF_PRIORITY) { kstat.cpu_nice++; kstat.per_cpu_nice[cpu]++; @@ -359,93 +404,86 @@ kstat.cpu_user++; kstat.per_cpu_user[cpu]++; } - } else { + } else { kstat.cpu_system++; kstat.per_cpu_system[cpu]++; - } - spin_unlock(&ticker_lock); - } - prof_counter[cpu] = prof_multiplier[cpu]; - } + } + spin_unlock(&ticker_lock); + } + prof_counter[cpu] = prof_multiplier[cpu]; + } } -int setup_profiling_timer(unsigned int multiplier) +int __init +setup_profiling_timer(unsigned int multiplier) { #ifdef NOT_YET - int i; - unsigned long flags; + int i; + unsigned long flags; - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; - - save_and_cli(flags); - for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) { - load_profile_irq(mid_xlate[i], lvl14_resolution / multip + /* Prevent level14 ticker IRQ flooding. */ + if((!multiplier) || (lvl14_resolution / multiplier) < 500) + return -EINVAL; + + save_and_cli(flags); + for(i = 0; i < NR_CPUS; i++) { + if(cpu_present_map & (1 << i)) { + load_profile_irq(mid_xlate[i], lvl14_resolution / multip lier); - prof_multiplier[i] = multiplier; - } - } - restore_flags(flags); + prof_multiplier[i] = multiplier; + } + } + restore_flags(flags); - return 0; + return 0; #endif return -EINVAL; } -/* Only broken Intel needs this, thus it should not even be referenced globally. -*/ -__initfunc(void initialize_secondary(void)) +/* Only broken Intel needs this, thus it should not even be + referenced globally. */ + +void __init +initialize_secondary(void) { - printk("initialize_secondary: entry\n"); } -static void +static void __init secondary_cpu_start(int cpuid, struct task_struct *idle) { struct percpu_struct *cpu; - int timeout; + int timeout; cpu = (struct percpu_struct *) ((char*)hwrpb - + hwrpb->processor_offset - + cpuid * hwrpb->processor_size); + + hwrpb->processor_offset + + cpuid * hwrpb->processor_size); - /* set context to idle thread this CPU will use when running */ - /* assumption is that the idle thread is all set to go... ??? */ + /* Set context to idle thread this CPU will use when running + assumption is that the idle thread is all set to go... ??? */ memcpy(&cpu->hwpcb[0], &idle->tss, sizeof(struct pcb_struct)); cpu->hwpcb[4] = cpu->hwpcb[0]; /* UNIQUE set to KSP ??? */ -#if 0 -printk("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx\n", - cpu->hwpcb[0], cpu->hwpcb[2], hwrpb->vptb); -printk("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", - cpuid, idle->state, idle->tss.pal_flags); -#endif - - /* setup HWRPB fields that SRM uses to activate secondary CPU */ - hwrpb->CPU_restart = __start_cpu; - hwrpb->CPU_restart_data = (unsigned long) idle; - - /* recalculate and update the HWRPB checksum */ - { - unsigned long sum, *lp1, *lp2; - sum = 0; - lp1 = (unsigned long *)hwrpb; - lp2 = &hwrpb->chksum; - while (lp1 < lp2) - sum += *lp1++; - *lp2 = sum; - } + + DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx\n", + cpu->hwpcb[0], cpu->hwpcb[2], hwrpb->vptb)); + DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", + cpuid, idle->state, idle->tss.pal_flags)); + + /* Setup HWRPB fields that SRM uses to activate secondary CPU */ + hwrpb->CPU_restart = __start_cpu; + hwrpb->CPU_restart_data = (unsigned long) idle; + + /* Recalculate and update the HWRPB checksum */ + hwrpb_update_checksum(hwrpb); /* * Send a "start" command to the specified processor. */ /* SRM III 3.4.1.3 */ - cpu->flags |= 0x22; /* turn on Context Valid and Restart Capable */ - cpu->flags &= ~1;/* turn off Bootstrap In Progress */ + cpu->flags |= 0x22; /* turn on Context Valid and Restart Capable */ + cpu->flags &= ~1; /* turn off Bootstrap In Progress */ mb(); send_cpu_msg("START\r\n", cpuid); @@ -454,7 +492,7 @@ for (timeout = 10000; !(cpu->flags & 1); timeout--) { if (timeout <= 0) { printk("Processor %d failed to start\n", cpuid); - /* needed for pset_info to work */ + /* needed for pset_info to work */ #if 0 ipc_processor_enable(cpu_to_processor(cpunum)); #endif @@ -462,49 +500,61 @@ } mdelay(1); } -#if 0 - printk("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid); -#endif + DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid)); } static void send_cpu_msg(char *str, int cpuid) { struct percpu_struct *cpu; - register char *cp1, *cp2; - unsigned long cpumask; - int timeout; + register char *cp1, *cp2; + unsigned long cpumask; + size_t len; + int timeout; - cpu = (struct percpu_struct *) ((char*)hwrpb - + hwrpb->processor_offset - + cpuid * hwrpb->processor_size); + + hwrpb->processor_offset + + cpuid * hwrpb->processor_size); + + cpumask = (1L << cpuid); + if (hwrpb->txrdy & cpumask) + goto delay1; + ready1: + + cp2 = str; + len = strlen(cp2); + *(unsigned int *)&cpu->ipc_buffer[0] = len; + cp1 = (char *) &cpu->ipc_buffer[1]; + memcpy(cp1, cp2, len); + + /* atomic test and set */ + set_bit(cpuid, &hwrpb->rxrdy); + + if (hwrpb->txrdy & cpumask) + goto delay2; + ready2: + return; - cpumask = (1L << cpuid); - for (timeout = 10000; (hwrpb->txrdy & cpumask); timeout--) { - if (timeout <= 0) { - printk("Processor %x not ready\n", cpuid); - return; - } - mdelay(1); - } - - cp1 = (char *) &cpu->ipc_buffer[1]; - cp2 = str; - while (*cp2) *cp1++ = *cp2++; - *(unsigned int *)&cpu->ipc_buffer[0] = cp2 - str; /* hack */ - - /* atomic test and set */ - set_bit(cpuid, &hwrpb->rxrdy); - - for (timeout = 10000; (hwrpb->txrdy & cpumask); timeout--) { - if (timeout <= 0) { - printk("Processor %x not ready\n", cpuid); - return; - } - mdelay(1); - } +delay1: + for (timeout = 10000; timeout > 0; --timeout) { + if (!(hwrpb->txrdy & cpumask)) + goto ready1; + udelay(100); + } + goto timeout; + +delay2: + for (timeout = 10000; timeout > 0; --timeout) { + if (!(hwrpb->txrdy & cpumask)) + goto ready2; + udelay(100); + } + goto timeout; + +timeout: + printk("Processor %x not ready\n", cpuid); + return; } /* @@ -512,7 +562,8 @@ * * called from arch/alpha/kernel/setup.c:setup_arch() when __SMP__ defined */ -__initfunc(void setup_smp(void)) +void __init +setup_smp(void) { struct percpu_struct *cpubase, *cpu; int i; @@ -523,10 +574,10 @@ } if (hwrpb->nr_processors > 1) { -#if 0 -printk("setup_smp: nr_processors 0x%lx\n", - hwrpb->nr_processors); -#endif + + DBGS(("setup_smp: nr_processors %ld\n", + hwrpb->nr_processors)); + cpubase = (struct percpu_struct *) ((char*)hwrpb + hwrpb->processor_offset); boot_cpu_palrev = cpubase->pal_revision; @@ -541,12 +592,11 @@ if (i != boot_cpu_id) cpu->pal_revision = boot_cpu_palrev; } -#if 0 -printk("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n", - i, cpu->flags, cpu->type); - printk("setup_smp: CPU %d: PAL rev 0x%lx\n", - i, cpu->pal_revision); -#endif + + DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n", + i, cpu->flags, cpu->type)); + DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n", + i, cpu->pal_revision)); } } else { smp_num_probed = 1; @@ -560,132 +610,59 @@ static void secondary_console_message(void) { - int mycpu, i, cnt; + int mycpu, i, cnt; unsigned long txrdy = hwrpb->txrdy; char *cp1, *cp2, buf[80]; - struct percpu_struct *cpu; - - mycpu = hard_smp_processor_id(); - -#if 0 -printk("secondary_console_message: TXRDY 0x%lx.\n", txrdy); -#endif - for (i = 0; i < NR_CPUS; i++) { - if (txrdy & (1L << i)) { -#if 0 -printk("secondary_console_message: TXRDY contains CPU %d.\n", i); -#endif - cpu = (struct percpu_struct *) - ((char*)hwrpb - + hwrpb->processor_offset - + i * hwrpb->processor_size); -#if 1 - printk("secondary_console_message: on %d from %d" - " HALT_REASON 0x%lx FLAGS 0x%lx\n", - mycpu, i, cpu->halt_reason, cpu->flags); -#endif - cnt = cpu->ipc_buffer[0] >> 32; - if (cnt <= 0 || cnt >= 80) - strcpy(buf,"<<< BOGUS MSG >>>"); - else { - cp1 = (char *) &cpu->ipc_buffer[11]; - cp2 = buf; - while (cnt--) { - if (*cp1 == '\r' || *cp1 == '\n') { - *cp2++ = ' '; cp1++; - } else - *cp2++ = *cp1++; - } - *cp2 = 0; - } -#if 1 - printk("secondary_console_message: on %d message is '%s'\n", - mycpu, buf); -#endif - } - } - hwrpb->txrdy = 0; - return; -} - -static int -halt_on_panic(unsigned int this_cpu) -{ - halt(); - return 0; -} + struct percpu_struct *cpu; -static int -local_flush_tlb_all(unsigned int this_cpu) -{ - tbia(); - clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask); - return 0; -} + DBGS(("secondary_console_message: TXRDY 0x%lx.\n", txrdy)); -static int -local_flush_tlb_mm(unsigned int this_cpu) -{ - struct mm_struct * mm = ipi_msg_flush_tb.p.flush_mm; - if (mm == current->mm) - flush_tlb_current(mm); - clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask); - return 0; -} + mycpu = hard_smp_processor_id(); -static int -local_flush_tlb_page(unsigned int this_cpu) -{ - struct vm_area_struct * vma = ipi_msg_flush_tb.p.flush_vma; - struct mm_struct * mm = vma->vm_mm; + for (i = 0; i < NR_CPUS; i++) { + if (!(txrdy & (1L << i))) + continue; - if (mm == current->mm) - flush_tlb_current_page(mm, vma, ipi_msg_flush_tb.flush_addr); - clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask); - return 0; -} + DBGS(("secondary_console_message: " + "TXRDY contains CPU %d.\n", i)); -static int -wrapper_local_flush_tlb_page(unsigned int this_cpu) -{ -#if 0 - int cpu = smp_processor_id(); + cpu = (struct percpu_struct *) + ((char*)hwrpb + + hwrpb->processor_offset + + i * hwrpb->processor_size); + + printk("secondary_console_message: on %d from %d" + " HALT_REASON 0x%lx FLAGS 0x%lx\n", + mycpu, i, cpu->halt_reason, cpu->flags); + + cnt = cpu->ipc_buffer[0] >> 32; + if (cnt <= 0 || cnt >= 80) + strcpy(buf, "<<< BOGUS MSG >>>"); + else { + cp1 = (char *) &cpu->ipc_buffer[11]; + cp2 = buf; + strcpy(cp2, cp1); + + while ((cp2 = strchr(cp2, '\r')) != 0) { + *cp2 = ' '; + if (cp2[1] == '\n') + cp2[1] = ' '; + } + } - if (cpu) { - printk("wrapper: ipi_msg_flush_tb.flush_addr 0x%lx [%d]\n", - ipi_msg_flush_tb.flush_addr, atomic_read(&global_irq_count)); + printk("secondary_console_message: on %d message is '%s'\n", + mycpu, buf); } -#endif - local_flush_tlb_page(this_cpu); - return 0; -} -static int -unknown_ipi(unsigned int this_cpu) -{ - printk("unknown_ipi() on CPU %d: ", this_cpu); - return 1; + hwrpb->txrdy = 0; } enum ipi_message_type { - CPU_STOP, - TLB_ALL, - TLB_MM, - TLB_PAGE, - TLB_RANGE -}; - -static int (* ipi_func[32])(unsigned int) = { - halt_on_panic, - local_flush_tlb_all, - local_flush_tlb_mm, - wrapper_local_flush_tlb_page, - local_flush_tlb_mm, /* a.k.a. local_flush_tlb_range */ - unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, - unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, - unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, - unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, unknown_ipi, - unknown_ipi, unknown_ipi, unknown_ipi + IPI_TLB_ALL, + IPI_TLB_MM, + IPI_TLB_PAGE, + IPI_RESCHEDULE, + IPI_CPU_STOP }; void @@ -693,122 +670,165 @@ { int this_cpu = smp_processor_id(); volatile int * pending_ipis = &ipi_bits[this_cpu]; - int ops; + unsigned long ops, which; - mb(); /* Order bit setting and interrupt. */ -#if 0 - printk("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n", - this_cpu, *pending_ipis, regs->pc); -#endif - while ((ops = *pending_ipis)) { - int first; - for (first = 0; (ops & 1) == 0; ++first, ops >>= 1) - ; /* look for the first thing to do */ - clear_bit(first, pending_ipis); - mb(); /* Order bit clearing and data access. */ - if ((*ipi_func[first])(this_cpu)) - printk("%d\n", first); - mb(); /* Order data access and bit clearing. */ + DBGS(("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n", + this_cpu, *pending_ipis, regs->pc)); + + mb(); /* Order interrupt and bit testing. */ + while ((ops = xchg(pending_ipis, 0)) != 0) { + mb(); /* Order bit clearing and data access. */ + do { + unsigned long which; + + which = ops & -ops; + ops &= ~which; + which = ffz(~which); + + if (which < IPI_RESCHEDULE) { + if (which == IPI_TLB_ALL) + tbia(); + else if (which == IPI_TLB_MM) { + struct mm_struct * mm; + mm = ipi_msg_flush_tb.p.flush_mm; + if (mm == current->mm) + flush_tlb_current(mm); + } + else /* IPI_TLB_PAGE */ { + struct vm_area_struct * vma; + struct mm_struct * mm; + unsigned long addr; + + vma = ipi_msg_flush_tb.p.flush_vma; + mm = vma->vm_mm; + addr = ipi_msg_flush_tb.flush_addr; + + if (mm == current->mm) + flush_tlb_current_page(mm, vma, addr); + } + clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask); + } + else if (which == IPI_RESCHEDULE) { + /* Reschedule callback. Everything to be done + is done by the interrupt return path. */ + } + else if (which == IPI_CPU_STOP) { + halt(); + } + else { + printk(KERN_CRIT "unknown_ipi() on CPU %ld: %d\n", + this_cpu, which); + } + } while (ops); + mb(); /* Order data access and bit testing. */ } + + cpu_data[this_cpu].ipi_count++; + if (hwrpb->txrdy) - secondary_console_message(); + secondary_console_message(); } -void -send_ipi_message(long to_whom, enum ipi_message_type operation) +static void +send_ipi_message(unsigned long to_whom, enum ipi_message_type operation) { - int i; - unsigned int j; + long i, j; - mb(); /* Order out-of-band data and bit setting. */ - for (i = 0, j = 1; i < NR_CPUS; ++i, j += j) { - if ((to_whom & j) == 0) - continue; - set_bit(operation, &ipi_bits[i]); - mb(); /* Order bit setting and interrupt. */ - wripir(i); + /* Reduce the number of memory barriers by doing two loops, + one to set the bits, one to invoke the interrupts. */ + + mb(); /* Order out-of-band data and bit setting. */ + + for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { + if (to_whom & j) + set_bit(operation, &ipi_bits[i]); + } + + mb(); /* Order bit setting and interrupt. */ + + for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { + if (to_whom & j) + wripir(i); } } int smp_info(char *buffer) { - int i; + long i; unsigned long sum = 0; for (i = 0; i < NR_CPUS; i++) - sum += ipicnt[i]; + sum += cpu_data[i].ipi_count; - return sprintf(buffer, "CPUs probed %d active %d map 0x%x IPIs %ld\n", + return sprintf(buffer, "CPUs probed %d active %d map 0x%x IPIs %ld\n", smp_num_probed, smp_num_cpus, cpu_present_map, sum); } -/* wrapper for call from panic() */ void -smp_message_pass(int target, int msg, unsigned long data, int wait) +smp_send_reschedule(int cpu) { - int me = smp_processor_id(); - - if (msg != MSG_STOP_CPU) - goto barf; + send_ipi_message(1 << cpu, IPI_RESCHEDULE); +} - send_ipi_message(CPU_STOP, cpu_present_map ^ (1 << me)); - return; -barf: - printk("Yeeee, trying to send SMP msg(%d) on CPU %d\n", msg, me); - panic("Bogon SMP message pass."); +void +smp_send_stop(void) +{ + unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); + send_ipi_message(to_whom, IPI_CPU_STOP); } void flush_tlb_all(void) { - unsigned int to_whom = cpu_present_map ^ (1 << smp_processor_id()); - int timeout = 10000; + unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); + long timeout = 1000000; spin_lock_own(&kernel_flag, "flush_tlb_all"); ipi_msg_flush_tb.flush_tb_mask = to_whom; - send_ipi_message(to_whom, TLB_ALL); + send_ipi_message(to_whom, IPI_TLB_ALL); tbia(); - while (ipi_msg_flush_tb.flush_tb_mask) { - if (--timeout < 0) { - printk("flush_tlb_all: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), - ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; - break; - } - /* Wait for all clear from other CPUs. */ - udelay(100); + while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { + udelay(1); + barrier(); + } + + if (timeout == 0) { + printk("flush_tlb_all: STUCK on CPU %d mask 0x%x\n", + smp_processor_id(), + ipi_msg_flush_tb.flush_tb_mask); + ipi_msg_flush_tb.flush_tb_mask = 0; } } void flush_tlb_mm(struct mm_struct *mm) { - unsigned int to_whom = cpu_present_map ^ (1 << smp_processor_id()); - int timeout = 10000; + unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); + long timeout = 1000000; spin_lock_own(&kernel_flag, "flush_tlb_mm"); - ipi_msg_flush_tb.p.flush_mm = mm; ipi_msg_flush_tb.flush_tb_mask = to_whom; - send_ipi_message(to_whom, TLB_MM); + ipi_msg_flush_tb.p.flush_mm = mm; + send_ipi_message(to_whom, IPI_TLB_MM); if (mm != current->mm) flush_tlb_other(mm); else flush_tlb_current(mm); - while (ipi_msg_flush_tb.flush_tb_mask) { - if (--timeout < 0) { - printk("flush_tlb_mm: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; - break; - } - udelay(100); - ; /* Wait for all clear from other CPUs. */ + while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { + udelay(1); + barrier(); + } + + if (timeout == 0) { + printk("flush_tlb_mm: STUCK on CPU %d mask 0x%x\n", + smp_processor_id(), + ipi_msg_flush_tb.flush_tb_mask); + ipi_msg_flush_tb.flush_tb_mask = 0; } } @@ -816,68 +836,40 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { int cpu = smp_processor_id(); - unsigned int to_whom = cpu_present_map ^ (1 << cpu); + unsigned long to_whom = cpu_present_map ^ (1 << cpu); struct mm_struct * mm = vma->vm_mm; - int timeout = 10000; + int timeout = 1000000; spin_lock_own(&kernel_flag, "flush_tlb_page"); + ipi_msg_flush_tb.flush_tb_mask = to_whom; ipi_msg_flush_tb.p.flush_vma = vma; ipi_msg_flush_tb.flush_addr = addr; - ipi_msg_flush_tb.flush_tb_mask = to_whom; - send_ipi_message(to_whom, TLB_PAGE); + send_ipi_message(to_whom, IPI_TLB_PAGE); if (mm != current->mm) flush_tlb_other(mm); else flush_tlb_current_page(mm, vma, addr); - while (ipi_msg_flush_tb.flush_tb_mask) { - if (--timeout < 0) { - printk("flush_tlb_page: STUCK on CPU %d [0x%x,0x%lx,%d]\n", - cpu, ipi_msg_flush_tb.flush_tb_mask, addr, - global_irq_holder); - ipi_msg_flush_tb.flush_tb_mask = 0; - break; - } - udelay(100); - ; /* Wait for all clear from other CPUs. */ + while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { + udelay(1); + barrier(); + } + + if (timeout == 0) { + printk("flush_tlb_page: STUCK on CPU %d mask 0x%x\n", + smp_processor_id(), + ipi_msg_flush_tb.flush_tb_mask); + ipi_msg_flush_tb.flush_tb_mask = 0; } } void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { -#if 0 + /* On the Alpha we always flush the whole user tlb. */ flush_tlb_mm(mm); -#else - unsigned int to_whom; - int timeout; - - timeout = 10000; - to_whom = cpu_present_map ^ (1 << smp_processor_id()); - - spin_lock_own(&kernel_flag, "flush_tlb_range"); - - ipi_msg_flush_tb.p.flush_mm = mm; - ipi_msg_flush_tb.flush_tb_mask = to_whom; - send_ipi_message(to_whom, TLB_MM); - - if (mm != current->mm) - flush_tlb_other(mm); - else - flush_tlb_current(mm); - - while (ipi_msg_flush_tb.flush_tb_mask) { - if (--timeout < 0) { - printk("flush_tlb_range: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; - break; - } - udelay(100); /* Wait for all clear from other CPUs. */ - } -#endif } #if DEBUG_SPINLOCK @@ -902,8 +894,8 @@ #else -#define spinlock_raise_ipl(LOCK) 0 -#define spinlock_restore_ipl(PREV) ((void)0) +#define spinlock_raise_ipl(LOCK) ((LOCK), 0) +#define spinlock_restore_ipl(PREV) ((void)(PREV)) #endif /* MANAGE_SPINLOCK_IPL */ diff -u --recursive --new-file v2.2.0-pre1/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.2.0-pre1/linux/arch/i386/config.in Mon Dec 28 15:00:52 1998 +++ linux/arch/i386/config.in Tue Dec 29 16:54:20 1998 @@ -15,7 +15,7 @@ "386 CONFIG_M386 \ 486/Cx486 CONFIG_M486 \ Pentium/K5/5x86/6x86 CONFIG_M586 \ - PPro/K6/6x86MX CONFIG_M686" Pentium + PPro/K6/6x86MX CONFIG_M686" PPro bool 'Math emulation' CONFIG_MATH_EMULATION bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP @@ -36,15 +36,14 @@ bool 'Networking support' CONFIG_NET bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then - unset CONFIG_PCI_BIOS CONFIG_PCI_DIRECT choice 'PCI access mode' \ "BIOS CONFIG_PCI_GOBIOS \ Direct CONFIG_PCI_GODIRECT \ Any CONFIG_PCI_GOANY" Any - if [ -n "$CONFIG_PCI_GOBIOS" -o -n "$CONFIG_PCI_GOANY" ]; then + if [ "$CONFIG_PCI_GOBIOS" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then define_bool CONFIG_PCI_BIOS y fi - if [ -n "$CONFIG_PCI_GODIRECT" -o -n "$CONFIG_PCI_GOANY" ]; then + if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then define_bool CONFIG_PCI_DIRECT y fi bool ' PCI quirks' CONFIG_PCI_QUIRKS diff -u --recursive --new-file v2.2.0-pre1/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.2.0-pre1/linux/arch/i386/kernel/i386_ksyms.c Mon Dec 28 15:00:52 1998 +++ linux/arch/i386/kernel/i386_ksyms.c Tue Dec 29 11:18:18 1998 @@ -58,6 +58,9 @@ EXPORT_SYMBOL_NOVERS(__put_user_2); EXPORT_SYMBOL_NOVERS(__put_user_4); +EXPORT_SYMBOL(strtok); +EXPORT_SYMBOL(strpbrk); + EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(clear_user); diff -u --recursive --new-file v2.2.0-pre1/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.2.0-pre1/linux/arch/i386/kernel/irq.c Mon Dec 28 15:00:52 1998 +++ linux/arch/i386/kernel/irq.c Tue Dec 29 11:21:49 1998 @@ -900,7 +900,7 @@ /* * Wait for spurious interrupts to trigger */ - for (delay = jiffies + HZ/10; delay > jiffies; ) + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) /* about 100ms delay */ synchronize_irq(); /* diff -u --recursive --new-file v2.2.0-pre1/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.2.0-pre1/linux/arch/i386/kernel/ptrace.c Fri Nov 27 13:09:22 1998 +++ linux/arch/i386/kernel/ptrace.c Tue Dec 29 15:59:32 1998 @@ -420,7 +420,9 @@ case PTRACE_PEEKDATA: { unsigned long tmp; + down(&child->mm->mmap_sem); ret = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (ret >= 0) ret = put_user(tmp,(unsigned long *) data); goto out; @@ -451,7 +453,9 @@ /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: + down(&child->mm->mmap_sem); ret = write_long(child,addr,data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ diff -u --recursive --new-file v2.2.0-pre1/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.2.0-pre1/linux/arch/i386/kernel/setup.c Sun Nov 8 14:02:42 1998 +++ linux/arch/i386/kernel/setup.c Tue Dec 29 14:20:42 1998 @@ -597,7 +597,7 @@ for(n=0; n cpucount+1)) { do_boot_cpu(i); @@ -1126,9 +1215,9 @@ * Make sure we unmap all failed CPUs */ - if (cpu_number_map[i] == -1 && (cpu_present_map & (1 << i))) { - printk("CPU #%d not responding. Removing from cpu_present_map.\n",i); - cpu_present_map &= ~(1 << i); + if (cpu_number_map[i] == -1 && (cpu_online_map & (1 << i))) { + printk("CPU #%d not responding. Removing from cpu_online_map.\n",i); + cpu_online_map &= ~(1 << i); } } @@ -1168,14 +1257,14 @@ if (cpucount==0) { printk(KERN_ERR "Error: only one processor found.\n"); - cpu_present_map=(1<mm->mmap_sem); ret = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (ret < 0) goto out; ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); @@ -410,7 +412,9 @@ /* If I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: + down(&child->mm->mmap_sem); ret = write_long(child,addr,data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ diff -u --recursive --new-file v2.2.0-pre1/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c --- v2.2.0-pre1/linux/arch/sparc/kernel/ptrace.c Thu May 7 22:51:47 1998 +++ linux/arch/sparc/kernel/ptrace.c Tue Dec 29 16:35:08 1998 @@ -592,7 +592,9 @@ pt_error_return(regs, EINVAL); goto out; } + down(&child->mm->mmap_sem); res = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (res < 0) { pt_error_return(regs, -res); goto out; @@ -619,8 +621,10 @@ pt_error_return(regs, EINVAL); goto out; } + down(&child->mm->mmap_sem); vma = find_extend_vma(child, addr); res = write_long(child, addr, data); + up(&child->mm->mmap_sem); if(res < 0) pt_error_return(regs, -res); else @@ -761,7 +765,9 @@ goto out; } while(len) { + down(&child->mm->mmap_sem); res = read_byte(child, src, &tmp); + up(&child->mm->mmap_sem); if(res < 0) { pt_error_return(regs, -res); goto out; @@ -788,7 +794,9 @@ unsigned long tmp; __get_user(tmp, src); + down(&child->mm->mmap_sem); res = write_byte(child, dest, tmp); + up(&child->mm->mmap_sem); if(res < 0) { pt_error_return(regs, -res); goto out; diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.2.0-pre1/linux/drivers/block/Config.in Thu Nov 19 09:56:28 1998 +++ linux/drivers/block/Config.in Tue Dec 29 11:21:49 1998 @@ -69,7 +69,7 @@ bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580 bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then + if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" ]; then bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 fi fi diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.2.0-pre1/linux/drivers/block/acsi.c Thu Nov 12 16:21:18 1998 +++ linux/drivers/block/acsi.c Tue Dec 29 11:23:59 1998 @@ -425,7 +425,7 @@ { if (INT_LEVEL < 6) { unsigned long maxjif; - for( maxjif = jiffies + timeout; jiffies < maxjif; ) + for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); ) if (!(mfp.par_dt_reg & 0x20)) return( 1 ); } else { @@ -442,7 +442,7 @@ { if (INT_LEVEL < 6) { unsigned long maxjif; - for( maxjif = jiffies + timeout; jiffies < maxjif; ) + for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); ) if (mfp.par_dt_reg & 0x20) return( 1 ); } else { diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c --- v2.2.0-pre1/linux/drivers/block/acsi_slm.c Wed Aug 26 11:37:34 1998 +++ linux/drivers/block/acsi_slm.c Tue Dec 29 11:23:59 1998 @@ -101,17 +101,8 @@ cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \ } while(0) -#define START_TIMER(to) \ - do { \ - del_timer( &slm_timer ); \ - slm_timer.expires = jiffies + (to); \ - add_timer( &slm_timer ); \ - } while(0) - -#define STOP_TIMER() \ - do { \ - del_timer( &slm_timer ); \ - } while(0) +#define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to)) +#define STOP_TIMER() del_timer(&slm_timer) static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 }; diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.2.0-pre1/linux/drivers/block/ataflop.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/ataflop.c Tue Dec 29 11:23:59 1998 @@ -1838,7 +1838,7 @@ FDC_WRITE (FDCREG_TRACK, 0xff00); FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 ); - for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; jiffies < timeout; ) { + for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; time_before(jiffies, timeout); ) { if (!(mfp.par_dt_reg & 0x20)) break; } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c --- v2.2.0-pre1/linux/drivers/block/ide-disk.c Thu Sep 17 17:53:35 1998 +++ linux/drivers/block/ide-disk.c Tue Dec 29 11:24:57 1998 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-disk.c Version 1.04 Jan 7, 1998 + * linux/drivers/block/ide-disk.c Version 1.08 Dec 10, 1998 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -7,6 +7,7 @@ /* * Maintained by Mark Lord * and Gadi Oxman + * and Andre Hedrick * * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. * @@ -19,10 +20,13 @@ * Version 1.05 add capacity support for ATA3 >= 8GB * Version 1.06 get boot-up messages to show full cyl count * Version 1.07 disable door-locking if it fails - * Version 1.07a fixed mult_count enables + * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, + * process of adding new ATA4 compliance. + * fixed problems in allowing fdisk to see + * the entire disk. */ -#define IDEDISK_VERSION "1.07" +#define IDEDISK_VERSION "1.08" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -87,15 +91,28 @@ unsigned long chs_sects = id->cyls * id->heads * id->sectors; unsigned long _10_percent = chs_sects / 10; - /* very large drives (8GB+) may lie about the number of cylinders */ - if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) { + /* + * very large drives (8GB+) may lie about the number of cylinders + * This is a split test for drives 8 Gig and Bigger only. + */ + if ((id->lba_capacity >= 16514064) && (id->cyls == 0x3fff) && + (id->heads == 16) && (id->sectors = 63)) { + id->cyls = lba_sects / (16 * 63); /* correct cyls */ + return 1; /* lba_capacity is our only option */ + } + /* + * very large drives (8GB+) may lie about the number of cylinders + * This is a split test for drives less than 8 Gig only. + */ + if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) && + (id->heads == 16) && (id->sectors = 63)) { id->cyls = lba_sects / (16 * 63); /* correct cyls */ return 1; /* lba_capacity is our only option */ } /* perform a rough sanity check on lba_sects: within 10% is "okay" */ - if ((lba_sects - chs_sects) < _10_percent) + if ((lba_sects - chs_sects) < _10_percent) { return 1; /* lba_capacity is good */ - + } /* some drives have the word order reversed */ lba_sects = (lba_sects << 16) | (lba_sects >> 16); if ((lba_sects - chs_sects) < _10_percent) { @@ -487,13 +504,13 @@ drive->special.b.set_multmode = 1; } +#ifdef CONFIG_PROC_FS + static int smart_enable(ide_drive_t *drive) { return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL); } -#ifdef CONFIG_PROC_FS - static int get_smart_values(ide_drive_t *drive, byte *buf) { (void) smart_enable(drive); @@ -603,7 +620,7 @@ int major = HWIF(drive)->major; int minor = drive->select.b.unit << PARTN_BITS; - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); @@ -676,9 +693,8 @@ drive->sect = drive->bios_sect = id->sectors; } /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads - && (id->cur_heads <= 16) && id->cur_sectors) - { + if ((id->field_valid & 1) && id->cur_cyls && + id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { /* * Extract the physical drive geometry for our use. * Note that we purposely do *not* update the bios info. @@ -703,27 +719,49 @@ } } /* Use physical geometry if what we have still makes no sense */ - if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; + if ((!drive->head || drive->head > 16) && + id->heads && id->heads <= 16) { + if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) { + id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors))); + } + drive->cyl = id->cur_cyls = id->cyls; + drive->head = id->cur_heads = id->heads; + drive->sect = id->cur_sectors = id->sectors; } /* calculate drive capacity, and select LBA if possible */ - (void) idedisk_capacity (drive); + capacity = idedisk_capacity (drive); - /* Correct the number of cyls if the bios value is too small */ - if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) { - if (drive->cyl > drive->bios_cyl) - drive->bios_cyl = drive->cyl; + /* + * if possible, give fdisk access to more of the drive, + * by correcting bios_cyls: + */ + if ((capacity >= (id->cyls * id->heads * id->sectors)) && + (!drive->forced_geom)) { + drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; +#ifdef DEBUG + printk("Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n", + drive->id->cur_cyls, + drive->id->cur_heads, + drive->id->cur_sectors, + drive->bios_cyl, + drive->bios_head, + drive->bios_sect); +#endif + drive->id->cur_cyls = drive->bios_cyl; + drive->id->cur_heads = drive->bios_head; + drive->id->cur_sectors = drive->bios_sect; } + #if 0 /* done instead for entire identify block in arch/ide.h stuff */ /* fix byte-ordering of buffer size field */ id->buf_size = le16_to_cpu(id->buf_size); #endif printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d", - drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2, - drive->bios_cyl, drive->bios_head, drive->bios_sect); + drive->name, id->model, + capacity/2048L, id->buf_size/2, + drive->bios_cyl, drive->bios_head, drive->bios_sect); + if (drive->using_dma) { if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { @@ -735,12 +773,34 @@ } } printk("\n"); + + if (drive->select.b.lba) { + if (*(int *)&id->cur_capacity0 < id->lba_capacity) { +#ifdef DEBUG + printk(" CurSects=%d, LBASects=%d, ", + *(int *)&id->cur_capacity0, id->lba_capacity); +#endif + *(int *)&id->cur_capacity0 = id->lba_capacity; +#ifdef DEBUG + printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0); +#endif + } + } + drive->mult_count = 0; if (id->max_multsect) { +#if 1 /* original, pre IDE-NFG, per request of AC */ + drive->mult_req = INITIAL_MULT_COUNT; + if (drive->mult_req > id->max_multsect) + drive->mult_req = id->max_multsect; + if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) + drive->special.b.set_multmode = 1; +#else id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id->multsect_valid = id->multsect ? 1 : 0; drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; drive->special.b.set_multmode = drive->mult_req ? 1 : 0; +#endif } drive->no_io_32bit = id->dword_io ? 1 : 0; } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c --- v2.2.0-pre1/linux/drivers/block/ide-dma.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/ide-dma.c Tue Dec 29 11:14:57 1998 @@ -68,8 +68,9 @@ * SIIG's UltraIDE Pro CN-2449 * TTI HPT343 Chipset "Modified SCSI Class" but reports as an * unknown storage device. - * NEW check_drive_lists(ide_drive_t *drive, int good_bad) + * NEW check_drive_lists(ide_drive_t *drive, int good_bad) */ + #include #include #include @@ -91,9 +92,8 @@ */ const char *good_dma_drives[] = {"Micropolis 2112A", "CONNER CTMA 4000", + "CONNER CTT8000-A", "ST34342A", /* for Sun Ultra */ - "WDC AC2340F", /* DMA mode1 */ - "WDC AC2340H", /* DMA mode1 */ NULL}; /* @@ -101,7 +101,10 @@ * of drives which supposedly support (U)DMA but which are * known to corrupt data with this interface under Linux. */ -const char *bad_dma_drives[] = {"WDC AC22100H", +const char *bad_dma_drives[] = {"WDC AC11000H", + "WDC AC22100H", + "WDC AC32500H", + "WDC AC33100H", NULL}; /* @@ -331,8 +334,8 @@ return 0; case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - dma_stat = inb(dma_base+2); - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ + outb(inb(dma_base)&~1, dma_base); /* stop DMA */ + dma_stat = inb(dma_base+2); /* get DMA status */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ return (dma_stat & 7) != 4; /* verify good DMA status */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.2.0-pre1/linux/drivers/block/ide.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/ide.c Tue Dec 29 12:01:51 1998 @@ -2275,6 +2275,12 @@ * and quite likely to cause trouble with * older/odd IDE drives. * + * "hdx=slow" : insert a huge pause after each access to the data + * port. Should be used only as a last resort. + * + * "hdx=swapdata" : when the drive is a disk, byte swap all data + * "hdx=bswap" : same as above.......... + * * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, * where "xx" is between 20 and 66 inclusive, * used when tuning chipset PIO modes. @@ -2333,12 +2339,16 @@ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", "serialize", "autotune", "noautotune", - "slow", "swapdata", NULL}; + "slow", "swapdata", "bswap", NULL}; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; hwif = &ide_hwifs[hw]; drive = &hwif->drives[unit]; + if (strncmp(s + 4, "ide-", 4) == 0) { + strncpy(drive->driver_req, s + 4, 9); + goto done; + } switch (match_parm(&s[3], hd_words, vals, 3)) { case -1: /* "none" */ drive->nobios = 1; /* drop into "noprobe" */ @@ -2366,7 +2376,8 @@ case -8: /* "slow" */ drive->slow = 1; goto done; - case -9: /* swapdata */ + case -9: /* swapdata or bswap */ + case -10: drive->bswap = 1; goto done; case 3: /* cyl,head,sect */ @@ -2567,16 +2578,37 @@ const byte *heads = head_vals; unsigned long tracks; - if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom) + if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom) { + /* + * Update the current 3D drive values. + */ + drive->id->cur_cyls = drive->bios_cyl; + drive->id->cur_heads = drive->bios_head; + drive->id->cur_sectors = drive->bios_sect; return 0; + } - if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) + if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) { + /* + * Update the current 3D drive values. + */ + drive->id->cur_cyls = drive->bios_cyl; + drive->id->cur_heads = drive->bios_head; + drive->id->cur_sectors = drive->bios_sect; return 0; /* we already have a translation */ + } printk("%s ", msg); - if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) + if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) { + /* + * Update the current 3D drive values. + */ + drive->id->cur_cyls = drive->bios_cyl; + drive->id->cur_heads = drive->bios_head; + drive->id->cur_sectors = drive->bios_sect; return 0; /* small disk: no translation needed */ + } if (drive->id) { drive->cyl = drive->id->cyls; @@ -2614,6 +2646,12 @@ } drive->part[0].nr_sects = current_capacity(drive); printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect); + /* + * Update the current 3D drive values. + */ + drive->id->cur_cyls = drive->bios_cyl; + drive->id->cur_heads = drive->bios_head; + drive->id->cur_sectors = drive->bios_sect; return 1; } @@ -2703,7 +2741,11 @@ (void) idefloppy_init(); #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ #ifdef CONFIG_BLK_DEV_IDESCSI + #ifdef CONFIG_SCSI (void) idescsi_init(); + #else + #warning ide scsi-emulation selected but no SCSI-subsystem in kernel + #endif #endif /* CONFIG_BLK_DEV_IDESCSI */ } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v2.2.0-pre1/linux/drivers/block/ide.h Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/ide.h Tue Dec 29 15:31:19 1998 @@ -438,6 +438,8 @@ *start = page + off; \ return len; \ } +#else +#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; #endif /* diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c --- v2.2.0-pre1/linux/drivers/block/pdc4030.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/pdc4030.c Tue Dec 29 11:24:57 1998 @@ -92,13 +92,13 @@ timeout = HZ * 10; timeout += jiffies; do { - if(jiffies > timeout) { + if(time_after(jiffies, timeout)) { return 2; /* device timed out */ } /* This is out of delay_10ms() */ /* Delays at least 10ms to give interface a chance */ timer = jiffies + (HZ + 99)/100 + 1; - while (timer > jiffies); + while (time_after(timer, jiffies)); status_val = IN_BYTE(IDE_SECTOR_REG); } while (status_val != 0x50 && status_val != 0x70); @@ -257,7 +257,7 @@ struct request *rq; if (IN_BYTE(IDE_NSECTOR_REG) != 0) { - if (jiffies < hwgroup->poll_timeout) { + if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler (drive, &promise_write_pollfunc, 1); return; /* continue polling... */ } @@ -335,7 +335,7 @@ if(IN_BYTE(IDE_SELECT_REG) & 0x01) return; udelay(1); - } while (jiffies < timeout); + } while (time_before(jiffies, timeout)); printk("%s: reading: No DRQ and not waiting - Odd!\n", drive->name); return; diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.2.0-pre1/linux/drivers/char/console.c Sun Nov 8 14:02:53 1998 +++ linux/drivers/char/console.c Tue Dec 29 14:28:37 1998 @@ -1029,7 +1029,7 @@ */ translate = set_translate(charset == 0 ? G0_charset - : G1_charset); + : G1_charset,currcons); disp_ctrl = 0; toggle_meta = 0; break; @@ -1037,7 +1037,7 @@ * Select first alternate font, lets * chars < 32 be displayed as ROM chars. */ - translate = set_translate(IBMPC_MAP); + translate = set_translate(IBMPC_MAP,currcons); disp_ctrl = 1; toggle_meta = 0; break; @@ -1045,7 +1045,7 @@ * Select second alternate font, toggle * high bit before displaying as ROM char. */ - translate = set_translate(IBMPC_MAP); + translate = set_translate(IBMPC_MAP,currcons); disp_ctrl = 1; toggle_meta = 1; break; @@ -1328,7 +1328,7 @@ color = s_color; G0_charset = saved_G0; G1_charset = saved_G1; - translate = set_translate(charset ? G1_charset : G0_charset); + translate = set_translate(charset ? G1_charset : G0_charset,currcons); update_attr(currcons); need_wrap = 0; } @@ -1343,7 +1343,7 @@ bottom = video_num_lines; vc_state = ESnormal; ques = 0; - translate = set_translate(LAT1_MAP); + translate = set_translate(LAT1_MAP,currcons); G0_charset = LAT1_MAP; G1_charset = GRAF_MAP; charset = 0; @@ -1426,12 +1426,12 @@ return; case 14: charset = 1; - translate = set_translate(G1_charset); + translate = set_translate(G1_charset,currcons); disp_ctrl = 1; return; case 15: charset = 0; - translate = set_translate(G0_charset); + translate = set_translate(G0_charset,currcons); disp_ctrl = 0; return; case 24: case 26: @@ -1738,7 +1738,7 @@ else if (c == 'K') G0_charset = USER_MAP; if (charset == 0) - translate = set_translate(G0_charset); + translate = set_translate(G0_charset,currcons); vc_state = ESnormal; return; case ESsetG1: @@ -1751,7 +1751,7 @@ else if (c == 'K') G1_charset = USER_MAP; if (charset == 1) - translate = set_translate(G1_charset); + translate = set_translate(G1_charset,currcons); vc_state = ESnormal; return; default: diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c --- v2.2.0-pre1/linux/drivers/char/consolemap.c Mon Sep 28 10:51:33 1998 +++ linux/drivers/char/consolemap.c Tue Dec 29 14:28:37 1998 @@ -7,6 +7,8 @@ * aeb, 950210 * * Support for multiple unimaps by Jakub Jelinek , July 1998 + * + * Fix bug in inverse translation. Stanislav Voronyi , Dec 1998 */ #include @@ -167,7 +169,7 @@ #define MAX_GLYPH 512 /* Max possible glyph value */ -static int inv_translate; +static int inv_translate[MAX_NR_CONSOLES]; struct uni_pagedir { u16 **uni_pgdir[32]; @@ -204,9 +206,9 @@ } } -unsigned short *set_translate(int m) +unsigned short *set_translate(int m,int currcons) { - inv_translate = m; + inv_translate[currcons] = m; return translations[m]; } @@ -220,14 +222,13 @@ unsigned char inverse_translate(struct vc_data *conp, int glyph) { struct uni_pagedir *p; - if (glyph < 0 || glyph >= MAX_GLYPH) return 0; else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) || - !p->inverse_translations[inv_translate]) + !p->inverse_translations[inv_translate[conp->vc_num]]) return glyph; else - return p->inverse_translations[inv_translate][glyph]; + return p->inverse_translations[inv_translate[conp->vc_num]][glyph]; } static void update_user_maps(void) diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.2.0-pre1/linux/drivers/char/epca.c Sun Nov 8 14:02:54 1998 +++ linux/drivers/char/epca.c Tue Dec 29 11:24:57 1998 @@ -286,7 +286,8 @@ #ifdef ENABLE_PCI static int init_PCI(int); -static int get_PCI_configuration(char, char, unsigned int *, unsigned int *, +static int get_PCI_configuration(unsigned char, unsigned char, + unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); #endif /* ENABLE_PCI */ @@ -4037,7 +4038,7 @@ #ifdef ENABLE_PCI /* --------------------- Begin get_PCI_configuration ---------------------- */ -int get_PCI_configuration(char bus, char device_fn, +int get_PCI_configuration(unsigned char bus, unsigned char device_fn, unsigned int *base_addr0, unsigned int *base_addr1, unsigned int *base_addr2, unsigned int *base_addr3, unsigned int *base_addr4, unsigned int *base_addr5) diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/ftape/RELEASE-NOTES linux/drivers/char/ftape/RELEASE-NOTES --- v2.2.0-pre1/linux/drivers/char/ftape/RELEASE-NOTES Tue Nov 25 14:45:26 1997 +++ linux/drivers/char/ftape/RELEASE-NOTES Tue Dec 29 11:27:38 1998 @@ -423,9 +423,7 @@ This release is a simple bugfix version. -- Linux/SMP: ftape *should* work, if you remember to add the symbol __SMP__ - to the Makefile (you know what I'm talking about, if you're playing with - Linux/SMP :). +- Linux/SMP: ftape *should* work. - FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and locating this bug and testing the patch. diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/ftape/lowlevel/fdc-io.c linux/drivers/char/ftape/lowlevel/fdc-io.c --- v2.2.0-pre1/linux/drivers/char/ftape/lowlevel/fdc-io.c Thu Nov 12 16:21:19 1998 +++ linux/drivers/char/ftape/lowlevel/fdc-io.c Tue Dec 29 11:27:38 1998 @@ -1348,21 +1348,12 @@ if (fdc.hook == &do_ftape) { /* Get fast interrupt handler. */ -#if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70) if (request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT, "ft", ftape_id)) { TRACE_ABORT(-EIO, ft_t_bug, "Unable to grab IRQ%d for ftape driver", fdc.irq); } -#else - if (request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT, - ftape_id)) { - TRACE_ABORT(-EIO, ft_t_bug, - "Unable to grab IRQ%d for ftape driver", - fdc.irq); - } -#endif if (request_dma(fdc.dma, ftape_id)) { #if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70) free_irq(fdc.irq, ftape_id); @@ -1373,7 +1364,6 @@ "Unable to grab DMA%d for ftape driver", fdc.dma); } - enable_irq(fdc.irq); } if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) { /* Using same dma channel or irq as standard fdc, need @@ -1395,12 +1385,7 @@ if (fdc.hook == &do_ftape) { disable_dma(fdc.dma); /* just in case... */ free_dma(fdc.dma); - disable_irq(fdc.irq); -#if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70) free_irq(fdc.irq, ftape_id); -#else - free_irq(fdc.irq); -#endif } if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) { /* Using same dma channel as standard fdc, need to diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/hfmodem/Config.in linux/drivers/char/hfmodem/Config.in --- v2.2.0-pre1/linux/drivers/char/hfmodem/Config.in Wed Feb 4 11:36:00 1998 +++ linux/drivers/char/hfmodem/Config.in Tue Dec 29 11:28:49 1998 @@ -1,5 +1,5 @@ comment 'Misc. hamradio protocols' -tristate 'Shortwave radio modem driver' CONFIG_HFMODEM +dep_tristate 'Shortwave radio modem driver' CONFIG_HFMODEM $CONFIG_PARPORT if [ "$CONFIG_HFMODEM" != "n" ]; then bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/istallion.c linux/drivers/char/istallion.c --- v2.2.0-pre1/linux/drivers/char/istallion.c Sun Nov 8 14:02:54 1998 +++ linux/drivers/char/istallion.c Tue Dec 29 11:29:54 1998 @@ -2311,7 +2311,7 @@ if (signal_pending(current)) break; stli_delay(2); - if (jiffies >= tend) + if (time_after_eq(jiffies, tend)) break; } } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c --- v2.2.0-pre1/linux/drivers/char/riscom8.c Sun Nov 8 14:02:55 1998 +++ linux/drivers/char/riscom8.c Tue Dec 29 11:29:54 1998 @@ -228,7 +228,7 @@ { unsigned long i; - for (i = jiffies + delay; i > jiffies; ) ; + for (i = jiffies + delay; time_after(i,jiffies); ) ; } /* Reset and setup CD180 chip */ @@ -1172,8 +1172,8 @@ timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->timeout); - if (jiffies > timeout) + schedule_timeout(port->timeout); + if (time_after(jiffies, timeout)) break; } } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/specialix.c linux/drivers/char/specialix.c --- v2.2.0-pre1/linux/drivers/char/specialix.c Sun Nov 8 14:02:56 1998 +++ linux/drivers/char/specialix.c Tue Dec 29 11:29:54 1998 @@ -353,7 +353,7 @@ { unsigned long i; - for (i = jiffies + delay; i > jiffies; ) ; + for (i = jiffies + delay; time_after(i, jiffies); ) ; } @@ -1073,7 +1073,7 @@ /* Set baud rate for port */ tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + CD186x_TPC/2) / CD186x_TPC); - if ((tmp < 0x10) && (again < jiffies)) { + if ((tmp < 0x10) && time_before(again, jiffies)) { again = jiffies + HZ * 60; /* Page 48 of version 2.0 of the CL-CD1865 databook */ if (tmp >= 12) { @@ -1551,8 +1551,8 @@ timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->timeout); - if (jiffies > timeout) { + schedule_timeout(port->timeout); + if (time_after(jiffies, timeout)) { printk (KERN_INFO "Timeout waiting for close\n"); break; } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.2.0-pre1/linux/drivers/char/stallion.c Sun Nov 8 14:02:56 1998 +++ linux/drivers/char/stallion.c Tue Dec 29 11:29:54 1998 @@ -1697,7 +1697,7 @@ if (signal_pending(current)) break; stl_delay(2); - if (jiffies >= tend) + if (time_after_eq(jiffies, tend)) break; } } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in --- v2.2.0-pre1/linux/drivers/isdn/Config.in Wed Apr 1 20:11:49 1998 +++ linux/drivers/isdn/Config.in Tue Dec 29 11:29:54 1998 @@ -38,7 +38,9 @@ bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930 + fi fi fi if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.2.0-pre1/linux/drivers/net/Makefile Tue Dec 22 14:16:55 1998 +++ linux/drivers/net/Makefile Tue Dec 29 11:29:54 1998 @@ -1035,13 +1035,6 @@ # # HIPPI adapters # -ifeq ($(CONFIG_CERN_HIPPI),y) -L_OBJS += cern_hippi.o -else - ifeq ($(CONFIG_CERN_HIPPI),m) - M_OBJS += cern_hippi.o - endif -endif ifeq ($(CONFIG_ROADRUNNER),y) L_OBJS += rrunner.o diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.2.0-pre1/linux/drivers/net/dgrs.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/net/dgrs.c Tue Dec 29 11:32:06 1998 @@ -1098,7 +1098,7 @@ */ proc_reset(dev0, 0); - for (i = jiffies + 8 * HZ; i > jiffies; ) + for (i = jiffies + 8 * HZ; time_after(i, jiffies); ) { if (priv0->bcomm->bc_status >= BC_RUN) break; @@ -1196,7 +1196,7 @@ return (rc); priv->intrcnt = 0; - for (i = jiffies + 2*HZ + HZ/2; i > jiffies; ) + for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); ) if (priv->intrcnt >= 2) break; if (priv->intrcnt < 2) diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v2.2.0-pre1/linux/drivers/net/eepro.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/eepro.c Tue Dec 29 11:30:56 1998 @@ -8,7 +8,7 @@ according to the terms of the GNU Public License, incorporated herein by reference. - The author may be reached at bao.ha@srs.gov + The author may be reached at bao.ha@srs.gov or 418 Hastings Place, Martinez, GA 30907. Things remaining to do: @@ -23,6 +23,33 @@ This is a compatibility hardware problem. Versions: + 0.11b Pascal Dupuis : works as a module under 2.1.xx + debug messages are flagged as KERN_DEBUG to avoid console + flooding + added locking at critical parts + 0.11a Attempt to get 2.1.xx support up (RMC) + 0.11 Brian Candler added support for multiple cards. Tested as + a module, no idea if it works when compiled into kernel. + + 0.10e Rick Bressler notified me that ifconfig up;ifconfig down fails + because the irq is lost somewhere. Fixed that by moving + request_irq and free_irq to eepro_open and eepro_close respectively. + 0.10d Ugh! Now Wakeup works. Was seriously broken in my first attempt. + I'll need to find a way to specify an ioport other than + the default one in the PnP case. PnP definitively sucks. + And, yes, this is not the only reason. + 0.10c PnP Wakeup Test for 595FX. uncomment #define PnPWakeup; + to use. + 0.10b Should work now with (some) Pro/10+. At least for + me (and my two cards) it does. _No_ guarantee for + function with non-Pro/10+ cards! (don't have any) + (RMC, 9/11/96) + + 0.10 Added support for the Etherexpress Pro/10+. The + IRQ map was changed significantly from the old + pro/10. The new interrupt map was provided by + Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu). + (BCH, 9/3/96) 0.09 Fixed a race condition in the transmit algorithm, which causes crashes under heavy load with fast @@ -38,7 +65,7 @@ 0.07a Fix a stat report which counts every packet as a heart-beat failure. (BCH, 6/3/95) - 0.07 Modified to support all other 82595-based lan cards. + 0.07 Modified to support all other 82595-based lan cards. The IRQ vector of the EtherExpress Pro will be set according to the value saved in the EEPROM. For other cards, I will do autoirq_request() to grab the next @@ -48,37 +75,37 @@ print out format. (BCH, 3/9/95 and 3/14/95) 0.06 First stable release that I am comfortable with. (BCH, - 3/2/95) + 3/2/95) - 0.05 Complete testing of multicast. (BCH, 2/23/95) + 0.05 Complete testing of multicast. (BCH, 2/23/95) - 0.04 Adding multicast support. (BCH, 2/14/95) + 0.04 Adding multicast support. (BCH, 2/14/95) - 0.03 First widely alpha release for public testing. - (BCH, 2/14/95) + 0.03 First widely alpha release for public testing. + (BCH, 2/14/95) */ static const char *version = - "eepro.c: v0.09 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n"; + "eepro.c: v0.11b 08/12/1998 dupuis@lei.ucl.ac.be\n"; #include /* Sources: - This driver wouldn't have been written without the availability - of the Crynwr's Lan595 driver source code. It helps me to - familiarize with the 82595 chipset while waiting for the Intel - documentation. I also learned how to detect the 82595 using + This driver wouldn't have been written without the availability + of the Crynwr's Lan595 driver source code. It helps me to + familiarize with the 82595 chipset while waiting for the Intel + documentation. I also learned how to detect the 82595 using the packet driver's technique. This driver is written by cutting and pasting the skeleton.c driver provided by Donald Becker. I also borrowed the EEPROM routine from Donald Becker's 82586 driver. - Datasheet for the Intel 82595 (including the TX and FX version). It - provides just enough info that the casual reader might think that it + Datasheet for the Intel 82595 (including the TX and FX version). It + provides just enough info that the casual reader might think that it documents the i82595. The User Manual for the 82595. It provides a lot of the missing @@ -100,23 +127,59 @@ #include #include #include +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 +#include +#endif #include -#include -#include #include #include #include +/* need to remove these asap */ +/* 2.1.xx compatibility macros... */ +/* */ + + +#include + +/* For linux 2.1.xx */ +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + +#include +#include + +#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) ) +/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */ +#define SLOW_DOWN inb(0x80) +/* udelay(2) */ + +#else +/* for 2.x */ + +#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) ) +#define test_and_set_bit(a,b) set_bit((a),(b)) +#define SLOW_DOWN SLOW_DOWN_IO + +#endif + + /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int eepro_portlist[] __initdata = - { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360, 0}; +static unsigned int eepro_portlist[] = + { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0}; +/* note: 0x300 is default, the 595FX supports ALL IO Ports + from 0x000 to 0x3F0, some of which are reserved in PCs */ + +/* To try the (not-really PnP Wakeup: */ +/* +#define PnPWakeup +*/ /* use 0 for production, 1 for verification, >2 for debug */ #ifndef NET_DEBUG -#define NET_DEBUG 3 +#define NET_DEBUG 0 #endif static unsigned int net_debug = NET_DEBUG; @@ -130,23 +193,107 @@ /* Information that need to be kept for each board. */ struct eepro_local { - struct net_device_stats stats; + struct enet_statistics stats; unsigned rx_start; unsigned tx_start; /* start of the transmit chain */ int tx_last; /* pointer to last packet in the transmit chain */ unsigned tx_end; /* end of the transmit chain (plus 1) */ - int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10, - FALSE = 0 for other 82595-based lan cards. */ + int eepro; /* 1 for the EtherExpress Pro/10, + 2 for the EtherExpress Pro/10+, + 0 for other 82595-based lan cards. */ int version; /* a flag to indicate if this is a TX or FX version of the 82595 chip. */ int stepping; +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + spinlock_t lock; /* to prevent interrupt within interrupts */ +#endif }; /* The station (ethernet) address prefix, used for IDing the board. */ -#define SA_ADDR0 0x00 +#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */ #define SA_ADDR1 0xaa #define SA_ADDR2 0x00 +#define GetBit(x,y) ((x & (1<>y) + +/* EEPROM Word 0: */ +#define ee_PnP 0 /* Plug 'n Play enable bit */ +#define ee_Word1 1 /* Word 1? */ +#define ee_BusWidth 2 /* 8/16 bit */ +#define ee_FlashAddr 3 /* Flash Address */ +#define ee_FlashMask 0x7 /* Mask */ +#define ee_AutoIO 6 /* */ +#define ee_reserved0 7 /* =0! */ +#define ee_Flash 8 /* Flash there? */ +#define ee_AutoNeg 9 /* Auto Negotiation enabled? */ +#define ee_IO0 10 /* IO Address LSB */ +#define ee_IO0Mask 0x /*...*/ +#define ee_IO1 15 /* IO MSB */ + +/* EEPROM Word 1: */ +#define ee_IntSel 0 /* Interrupt */ +#define ee_IntMask 0x7 +#define ee_LI 3 /* Link Integrity 0= enabled */ +#define ee_PC 4 /* Polarity Correction 0= enabled */ +#define ee_TPE_AUI 5 /* PortSelection 1=TPE */ +#define ee_Jabber 6 /* Jabber prevention 0= enabled */ +#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */ +#define ee_SMOUT 8 /* SMout Pin Control 0= Input */ +#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */ +#define ee_reserved1 10 /* .. 12 =0! */ +#define ee_AltReady 13 /* Alternate Ready, 0=normal */ +#define ee_reserved2 14 /* =0! */ +#define ee_Duplex 15 + +/* Word2,3,4: */ +#define ee_IA5 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA4 8 /*bit start for individual Addr Byte 5 */ +#define ee_IA3 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA2 8 /*bit start for individual Addr Byte 5 */ +#define ee_IA1 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA0 8 /*bit start for individual Addr Byte 5 */ + +/* Word 5: */ +#define ee_BNC_TPE 0 /* 0=TPE */ +#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */ +#define ee_BootTypeMask 0x3 +#define ee_NumConn 3 /* Number of Connections 0= One or Two */ +#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */ +#define ee_PortTPE 5 +#define ee_PortBNC 6 +#define ee_PortAUI 7 +#define ee_PowerMgt 10 /* 0= disabled */ +#define ee_CP 13 /* Concurrent Processing */ +#define ee_CPMask 0x7 + +/* Word 6: */ +#define ee_Stepping 0 /* Stepping info */ +#define ee_StepMask 0x0F +#define ee_BoardID 4 /* Manucaturer Board ID, reserved */ +#define ee_BoardMask 0x0FFF + +/* Word 7: */ +#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */ +#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */ + +/*..*/ +#define ee_SIZE 0x40 /* total EEprom Size */ +#define ee_Checksum 0xBABA /* initial and final value for adding checksum */ + + +/* Card identification via EEprom: */ +#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */ +#define ee_addr_id 0x11 /* Word offset for Card ID */ +#define ee_addr_SN 0x12 /* Serial Number */ +#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */ + + +#define ee_vendor_intel0 0x25 /* Vendor ID Intel */ +#define ee_vendor_intel1 0xD4 +#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */ +#define ee_id_eepro10p1 0x31 + + /* Index to functions, as function prototypes. */ extern int eepro_probe(struct device *dev); @@ -158,8 +305,8 @@ static void eepro_rx(struct device *dev); static void eepro_transmit_interrupt(struct device *dev); static int eepro_close(struct device *dev); -static struct net_device_stats *eepro_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); +static struct enet_statistics *eepro_get_stats(struct device *dev); +static void set_multicast_list(struct device *dev); static int read_eeprom(int ioaddr, int location); static void hardware_send_packet(struct device *dev, void *buf, short length); @@ -186,10 +333,10 @@ network traffics, the ring linked list should improve performance by allowing up to 8K worth of packets to be queued. -The sizes of the receive and transmit buffers can now be changed via lilo +The sizes of the receive and transmit buffers can now be changed via lilo or insmod. Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0" where rx-buffer is in KB unit. Modules uses the parameter mem which is -also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer." +also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer." The receive buffer has to be more than 3K or less than 29K. Otherwise, it is reset to the default of 24K, and, hence, 8K for the trasnmit buffer (transmit-buffer = 32K - receive-buffer). @@ -200,11 +347,11 @@ #define RCV_RAM 0x6000 /* 24KB default for RCV buffer */ #define RCV_LOWER_LIMIT 0x00 /* 0x0000 */ /* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */ -#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8) +#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8) /* #define XMT_RAM (RAM_SIZE - RCV_RAM) */ /* 8KB for XMT buffer */ #define XMT_RAM (RAM_SIZE - (rcv_ram)) /* 8KB for XMT buffer */ /* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */ /* 0x6000 */ -#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) +#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) #define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */ #define XMT_HEADER 8 @@ -218,9 +365,9 @@ #define XMT_CHAIN 0x04 #define XMT_COUNT 0x06 -#define BANK0_SELECT 0x00 -#define BANK1_SELECT 0x40 -#define BANK2_SELECT 0x80 +#define BANK0_SELECT 0x00 +#define BANK1_SELECT 0x40 +#define BANK2_SELECT 0x80 /* Bank 0 registers */ #define COMMAND_REG 0x00 /* Register 0 */ @@ -280,7 +427,7 @@ #define REG13 0x0d #define FDX 0x00 #define A_N_ENABLE 0x02 - + #define I_ADD_REG0 0x04 #define I_ADD_REG1 0x05 #define I_ADD_REG2 0x06 @@ -295,7 +442,7 @@ #define EEDO 0x08 -/* Check for a network adaptor of this type, and return '0' iff one exists. +/* Check for a network adaptor of this type, and return '0' if one exists. If dev->base_addr == 0, probe all likely locations. If dev->base_addr == 1, always return failure. If dev->base_addr == 2, allocate space for the device and return success @@ -307,17 +454,48 @@ struct netdev_entry netcard_drv = {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist}; #else -__initfunc(int -eepro_probe(struct device *dev)) +int +eepro_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; + +#ifdef PnPWakeup + /* XXXX for multiple cards should this only be run once? */ + + /* Wakeup: */ + #define WakeupPort 0x279 + #define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\ + 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\ + 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\ + 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43} + + { + unsigned short int WS[32]=WakeupSeq; + + if (check_region(WakeupPort, 2)==0) { + + if (net_debug>5) + printk(KERN_DEBUG "Waking UP\n"); + + outb_p(0,WakeupPort); + outb_p(0,WakeupPort); + for (i=0; i<32; i++) { + outb_p(WS[i],WakeupPort); + if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]); + } + } else printk("Checkregion Failed!\n"); + } +#endif + + if (base_addr > 0x1ff) /* Check a single specified location. */ return eepro_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ return ENXIO; + for (i = 0; eepro_portlist[i]; i++) { int ioaddr = eepro_portlist[i]; if (check_region(ioaddr, EEPRO_IO_EXTENT)) @@ -330,30 +508,89 @@ } #endif +void printEEPROMInfo(short ioaddr) +{ + unsigned short Word; + int i,j; + + for (i=0, j=ee_Checksum; i>ee_IO0)<<4); + + if (net_debug>4) { + Word=read_eeprom(ioaddr, 1); + printk(KERN_DEBUG "Word1:\n"); + printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask); + printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI)); + printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC)); + printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI)); + printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber)); + printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber)); + printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex)); + } + + Word=read_eeprom(ioaddr, 5); + printk(KERN_DEBUG "Word5:\n"); + printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE)); + printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn)); + printk(KERN_DEBUG " Has "); + if (GetBit(Word,ee_PortTPE)) printk("TPE "); + if (GetBit(Word,ee_PortBNC)) printk("BNC "); + if (GetBit(Word,ee_PortAUI)) printk("AUI "); + printk("port(s) \n"); + + Word=read_eeprom(ioaddr, 6); + printk(KERN_DEBUG "Word6:\n"); + printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask); + printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID); + + Word=read_eeprom(ioaddr, 7); + printk(KERN_DEBUG "Word7:\n"); + printk(KERN_DEBUG " INT to IRQ:\n"); + + printk(KERN_DEBUG); + for (i=0, j=0; i<15; i++) + if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i); + + printk("\n"); +} + /* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probes avoids doing writes, and + probes on the ISA bus. A good device probe avoids doing writes, and verifies that the correct device exists and functions. */ -__initfunc(int eepro_probe1(struct device *dev, short ioaddr)) +int eepro_probe1(struct device *dev, short ioaddr) { unsigned short station_addr[6], id, counter; - int i; - int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10, - FALSE = 0 for other 82595-based lan cards. */ + int i,j, irqMask; + int eepro; const char *ifmap[] = {"AUI", "10Base2", "10BaseT"}; enum iftype { AUI=0, BNC=1, TPE=2 }; /* Now, we are going to check for the signature of the ID_REG (register 2 of bank 0) */ - if (((id=inb(ioaddr + ID_REG)) & ID_REG_MASK) == ID_REG_SIG) { + + id=inb(ioaddr + ID_REG); + + printk(KERN_DEBUG " id: %#x ",id); + printk(" io: %#x ",ioaddr); + + if (((id) & ID_REG_MASK) == ID_REG_SIG) { /* We seem to have the 82595 signature, let's play with its counter (last 2 bits of register 2 of bank 0) to be sure. */ - - counter = (id & R_ROBIN_BITS); - if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == + + counter = (id & R_ROBIN_BITS); + if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == (counter + 0x40)) { /* Yes, the 82595 has been found */ @@ -366,79 +603,110 @@ station_addr[2] = read_eeprom(ioaddr, 4); /* Check the station address for the manufacturer's code */ - - if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) { - eepro = 0; - printk("%s: Intel 82595-based lan card at %#x,", + if (net_debug>3) + printEEPROMInfo(ioaddr); + + if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */ + eepro = 2; + printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", + dev->name, ioaddr); + } else + if (station_addr[2] == 0x00aa) { + eepro = 1; + printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", dev->name, ioaddr); } else { - eepro = 1; - printk("%s: Intel EtherExpress Pro/10 at %#x,", + eepro = 0; + printk("%s: Intel 82595-based lan card at %#x,", dev->name, ioaddr); } /* Fill in the 'dev' fields. */ dev->base_addr = ioaddr; - + for (i=0; i < 6; i++) { dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); } - + if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */ (dev->mem_end & 0x3f) > 29) /* and less than 29K */ dev->mem_end = RCV_RAM; /* or it will be set to 24K */ else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */ /* From now on, dev->mem_end contains the actual size of rx buffer */ - + if (net_debug > 3) printk(", %dK RCV buffer", (int)(dev->mem_end)/1024); + + +// outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ +// id = inb(ioaddr + REG3); +// if (id & TPE_BIT) +// dev->if_port = TPE; +// else dev->if_port = BNC; + + + /* ............... */ + + if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE)) + dev->if_port = BNC; + else dev->if_port = TPE; + + + /* ............... */ - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - id = inb(ioaddr + REG3); - if (id & TPE_BIT) - dev->if_port = TPE; - else dev->if_port = BNC; +// if (net_debug>3) +// printk("id: %x\n", id); - if (dev->irq < 2 && eepro) { + + if ((dev->irq < 2) && (eepro!=0)) { i = read_eeprom(ioaddr, 1); - switch (i & 0x07) { - case 0: dev->irq = 9; break; - case 1: dev->irq = 3; break; - case 2: dev->irq = 5; break; - case 3: dev->irq = 10; break; - case 4: dev->irq = 11; break; - default: /* should never get here !!!!! */ - printk(" illegal interrupt vector stored in EEPROM.\n"); + irqMask = read_eeprom(ioaddr, 7); + i &= 0x07; /* Mask off INT number */ + + for (j=0; ((j<16) && (i>=0)); j++) { + if ((irqMask & (1<irq = j; + break; /* found bit corresponding to irq */ + } + i--; /* count bits set in irqMask */ + } + } + if (dev -> irq<2) { + printk(" Duh! illegal interrupt vector stored in EEPROM.\n"); return ENODEV; - } - } - else if (dev->irq == 2) + } else + + if (dev->irq==2) dev->irq = 9; + + else if (dev->irq == 2) dev->irq = 9; + } if (dev->irq > 2) { printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); - if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) { + /*if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; - } + }*/ } else printk(", %s.\n", ifmap[dev->if_port]); - + if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */ net_debug = dev->mem_start & 7; /* still useful or not */ if (net_debug > 3) { i = read_eeprom(ioaddr, 5); if (i & 0x2000) /* bit 13 of EEPROM word 5 */ - printk("%s: Concurrent Processing is enabled but not used!\n", + printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n", dev->name); } - if (net_debug) + if (net_debug) printk(version); /* Grab the region so we can find another board if autoIRQ fails. */ @@ -450,10 +718,10 @@ return -ENOMEM; memset(dev->priv, 0, sizeof(struct eepro_local)); - dev->open = eepro_open; - dev->stop = eepro_close; - dev->hard_start_xmit = eepro_send_packet; - dev->get_stats = eepro_get_stats; + dev->open = eepro_open; + dev->stop = eepro_close; + dev->hard_start_xmit = eepro_send_packet; + dev->get_stats = eepro_get_stats; dev->set_multicast_list = &set_multicast_list; /* Fill in the fields of the device structure with @@ -481,17 +749,21 @@ */ static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1}; +static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1}; static int eepro_grab_irq(struct device *dev) { - int irqlist[] = { 5, 9, 10, 11, 4, 3, 0}; + int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 }; int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr; outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ + + /* Set the spinlock before activating IRQ! */ + ((struct eepro_local *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg | INT_ENABLE, ioaddr + REG1); - + outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ /* clear all interrupts */ @@ -507,18 +779,20 @@ outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) { + if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) { /* Twinkle the interrupt, and check if it's seen */ autoirq_setup(0); outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ - - if (*irqp == autoirq_report(2) && /* It's a good IRQ line */ - (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0)) + + if (*irqp == autoirq_report(2) )//&& /* It's a good IRQ line */ + /* We don't take irqs on detection anymore. + only when actually turning on the driver (ifconfig) */ + /* //(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0)) */ break; /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + outb(ALL_MASK, ioaddr + STATUS_REG); } } while (*++irqp); @@ -526,40 +800,64 @@ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); + outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + outb(ALL_MASK, ioaddr + INT_MASK_REG); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + outb(ALL_MASK, ioaddr + STATUS_REG); return dev->irq; } -static int -eepro_open(struct device *dev) +static int eepro_open(struct device *dev) { unsigned short temp_reg, old8, old9; + int irqMask; int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end; struct eepro_local *lp = (struct eepro_local *)dev->priv; if (net_debug > 3) - printk("eepro: entering eepro_open routine.\n"); + printk(KERN_DEBUG "eepro: entering eepro_open routine.\n"); - if (dev->dev_addr[0] == SA_ADDR0 && + if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */ + { + lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */ + if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); + } + + else if ((dev->dev_addr[0] == SA_ADDR0 && dev->dev_addr[1] == SA_ADDR1 && - dev->dev_addr[2] == SA_ADDR2) - lp->eepro = 1; /* Yes, an Intel EtherExpress Pro/10 */ + dev->dev_addr[2] == SA_ADDR2)) + { + lp->eepro = 1; + if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n"); + } /* Yes, an Intel EtherExpress Pro/10 */ + else lp->eepro = 0; /* No, it is a generic 82585 lan card */ - /* Get the interrupt vector for the 82595 */ + /* Get the interrupt vector for the 82595 */ if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } + + if (request_irq(dev->irq , &eepro_interrupt, 0, "eepro", dev)) { + printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); + return -EAGAIN; + } + +#ifdef irq2dev_map + if (((irq2dev_map[dev->irq] != 0) + || (irq2dev_map[dev->irq] = dev) == 0) && + (irq2dev_map[dev->irq]!=dev)) { + /* printk("%s: IRQ map wrong\n", dev->name); */ + return -EAGAIN; + } +#endif /* Initialize the 82595. */ @@ -567,18 +865,18 @@ temp_reg = inb(ioaddr + EEPROM_REG); lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ - + if (net_debug > 3) - printk("The stepping of the 82595 is %d\n", lp->stepping); + printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping); if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ outb(temp_reg & 0xef, ioaddr + EEPROM_REG); - for (i=0; i < 6; i++) - outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); - + for (i=0; i < 6; i++) + outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); + temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */ outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */ - | RCV_Discard_BadFrame, ioaddr + REG1); + | RCV_Discard_BadFrame, ioaddr + REG1); temp_reg = inb(ioaddr + REG2); /* Match broadcast */ outb(temp_reg | 0x14, ioaddr + REG2); @@ -589,51 +887,70 @@ /* Set the receiving mode */ outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ + /* Set the interrupt vector */ temp_reg = inb(ioaddr + INT_NO_REG); - outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); + if (lp->eepro == 2) + outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); + else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); + + + temp_reg = inb(ioaddr + INT_NO_REG); + if (lp->eepro == 2) + outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG); + else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); + + if (net_debug > 3) + printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg); + + /* Initialize the RCV and XMT upper and lower limits */ - outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); - outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); - outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); - outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); + outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); + outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); + outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); + outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); + outb(temp_reg | INT_ENABLE, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Let RX and TX events to interrupt */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + outb(ALL_MASK, ioaddr + STATUS_REG); /* Initialize RCV */ - outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); + outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); lp->rx_start = (RCV_LOWER_LIMIT << 8) ; - outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); + outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); /* Initialize XMT */ - outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); + outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); /* Check for the i82595TX and i82595FX */ old8 = inb(ioaddr + 8); outb(~old8, ioaddr + 8); if ((temp_reg = inb(ioaddr + 8)) == old8) { if (net_debug > 3) - printk("i82595 detected!\n"); + printk(KERN_DEBUG "i82595 detected!\n"); lp->version = LAN595; } else { lp->version = LAN595TX; outb(old8, ioaddr + 8); old9 = inb(ioaddr + 9); - outb(~old9, ioaddr + 9); - if ((temp_reg = inb(ioaddr + 9)) == ~old9) { + /*outb(~old9, ioaddr + 9); + if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {*/ + + if (irqMask==ee_FX_INT2IRQ) { enum iftype { AUI=0, BNC=1, TPE=2 }; - if (net_debug > 3) - printk("i82595FX detected!\n"); + + if (net_debug > 3) { + printk(KERN_DEBUG "IrqMask: %#x\n",irqMask); + printk(KERN_DEBUG "i82595FX detected!\n"); + } lp->version = LAN595FX; outb(old9, ioaddr + 9); if (dev->if_port != TPE) { /* Hopefully, this will fix the @@ -647,24 +964,26 @@ outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ } } - else if (net_debug > 3) - printk("i82595TX detected!\n"); + else if (net_debug > 3) { + printk(KERN_DEBUG "temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff)); + printk(KERN_DEBUG "i82595TX detected!\n"); + } } - + outb(SEL_RESET_CMD, ioaddr); /* We are supposed to wait for 2 us after a SEL_RESET */ - - udelay(2); + SLOW_DOWN; + SLOW_DOWN; lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */ - lp->tx_last = 0; - + lp->tx_last = 0; + dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; if (net_debug > 3) - printk("eepro: exiting eepro_open routine.\n"); + printk(KERN_DEBUG "eepro: exiting eepro_open routine.\n"); outb(RCV_ENABLE_CMD, ioaddr); @@ -672,121 +991,168 @@ return 0; } -static int -eepro_send_packet(struct sk_buff *skb, struct device *dev) +static int eepro_send_packet(struct sk_buff *skb, struct device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; int rcv_ram = dev->mem_end; if (net_debug > 5) - printk("eepro: entering eepro_send_packet routine.\n"); - + printk(KERN_DEBUG "eepro: entering eepro_send_packet routine.\n"); + if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) - return 1; - if (net_debug > 1) - printk("%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - lp->stats.tx_errors++; - - /* Try to restart the adaptor. */ - outb(SEL_RESET_CMD, ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - udelay(2); - - /* Do I also need to flush the transmit buffers here? YES? */ - lp->tx_start = lp->tx_end = rcv_ram; - lp->tx_last = 0; - - dev->tbusy=0; - dev->trans_start = jiffies; + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 40) + return 1; + + /* if (net_debug > 1) */ + printk("%s: transmit timed out, %s?\n", dev->name, + "network cable problem"); + /* This is not a duplicate. One message for the console, one for the + the log file */ + printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, + "network cable problem"); + lp->stats.tx_errors++; + + /* Try to restart the adaptor. */ + outb(SEL_RESET_CMD, ioaddr); + /* We are supposed to wait for 2 us after a SEL_RESET */ + SLOW_DOWN; + SLOW_DOWN; + + /* Do I also need to flush the transmit buffers here? YES? */ + lp->tx_start = lp->tx_end = rcv_ram; + lp->tx_last = 0; + + dev->tbusy=0; + dev->trans_start = jiffies; + + outb(RCV_ENABLE_CMD, ioaddr); - outb(RCV_ENABLE_CMD, ioaddr); + } +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20155 + /* If some higher layer thinks we've missed an tx-done interrupt + we are passed NULL. Caution: dev_tint() handles the cli()/sti() + itself. */ + // if (skb == NULL) { + // dev_tint(dev); + // return 0; + // FIXME : what's this code for ? } +#endif /* Block a timer-based transmit from overlapping. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); + printk("%s: Transmitter access conflict.\n", dev->name); else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; + short length; unsigned char *buf; +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + unsigned long flags; - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; + /* Spin on the lock, until we're clear of an IRQ */ + spin_lock_irqsave(&lp->lock, flags); +#endif + length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + buf = skb->data; + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + lp->stats.tx_bytes+=skb->len; +#endif + hardware_send_packet(dev, buf, length); + + dev->trans_start = jiffies; + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + spin_unlock_irqrestore(&lp->lock, flags); +#endif } - dev_kfree_skb (skb); + compat_dev_kfree_skb (skb, FREE_WRITE); /* You might need to clean up and record Tx statistics here. */ /* lp->stats.tx_aborted_errors++; */ if (net_debug > 5) - printk("eepro: exiting eepro_send_packet routine.\n"); - + printk(KERN_DEBUG "eepro: exiting eepro_send_packet routine.\n"); + return 0; } - /* The typical workload of the driver: Handle the network interface interrupts. */ static void eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - struct device *dev = dev_id; + struct device *dev = (struct device *)dev_id; + /* (struct device *)(irq2dev_map[irq]);*/ +#ifdef __SMP__ + struct eepro_local *lp = (struct eepro_local *)dev->priv; +#endif int ioaddr, status, boguscount = 20; - if (net_debug > 5) - printk("eepro: entering eepro_interrupt routine.\n"); + if (test_and_set_bit(0, (void*)&dev->interrupt)) + { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + dev->interrupt = 0; /* Avoid halting machine. */ + return; + } + if (net_debug > 5) + printk(KERN_DEBUG "eepro: entering eepro_interrupt routine.\n"); + if (dev == NULL) { printk ("eepro_interrupt(): irq %d for unknown device.\n", irq); return; } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - - do { - status = inb(ioaddr + STATUS_REG); - - if (status & RX_INT) { - if (net_debug > 4) - printk("eepro: packet received interrupt.\n"); - - /* Acknowledge the RX_INT */ - outb(RX_INT, ioaddr + STATUS_REG); - - /* Get the received packets */ - eepro_rx(dev); - } - - else if (status & TX_INT) { - if (net_debug > 4) - printk("eepro: packet transmit interrupt.\n"); - - /* Acknowledge the TX_INT */ - outb(TX_INT, ioaddr + STATUS_REG); - - /* Process the status of transmitted packets */ - eepro_transmit_interrupt(dev); - } + /* dev->interrupt = 1; */ +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + spin_lock(&lp->lock); +#endif + ioaddr = dev->base_addr; + + do { + status = inb(ioaddr + STATUS_REG); + + if (status & RX_INT) { + if (net_debug > 4) + printk(KERN_DEBUG "eepro: packet received interrupt.\n"); + + /* Acknowledge the RX_INT */ + outb(RX_INT, ioaddr + STATUS_REG); + /* Get the received packets */ + eepro_rx(dev); + } + + else if (status & TX_INT) { + if (net_debug > 4) + printk(KERN_DEBUG "eepro: packet transmit interrupt.\n"); + + /* Acknowledge the TX_INT */ + outb(TX_INT, ioaddr + STATUS_REG); + + /* Process the status of transmitted packets */ + eepro_transmit_interrupt(dev); + } + } while ((boguscount-- > 0) && (status & 0x06)); - dev->interrupt = 0; + dev->interrupt = 0; + if (net_debug > 5) - printk("eepro: exiting eepro_interrupt routine.\n"); + printk(KERN_DEBUG "eepro: exiting eepro_interrupt routine.\n"); +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + spin_unlock(&lp->lock); +#endif return; } -static int -eepro_close(struct device *dev) +static int eepro_close(struct device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; @@ -800,40 +1166,44 @@ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); + outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Flush the Tx and disable Rx. */ - outb(STOP_RCV_CMD, ioaddr); + outb(STOP_RCV_CMD, ioaddr); lp->tx_start = lp->tx_end = rcv_ram ; - lp->tx_last = 0; + lp->tx_last = 0; /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + outb(ALL_MASK, ioaddr + INT_MASK_REG); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + outb(ALL_MASK, ioaddr + STATUS_REG); /* Reset the 82595 */ - outb(RESET_CMD, ioaddr); + outb(RESET_CMD, ioaddr); /* release the interrupt */ free_irq(dev->irq, dev); +#ifdef irq2dev_map + irq2dev_map[dev->irq] = 0; +#endif + /* Update the statistics here. What statistics? */ /* We are supposed to wait for 200 us after a RESET */ + SLOW_DOWN; + SLOW_DOWN; /* May not be enough? */ - udelay(200); - MOD_DEC_USE_COUNT; return 0; } /* Get the current statistics. This may be called with the card open or closed. */ -static struct net_device_stats * +static struct enet_statistics * eepro_get_stats(struct device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; @@ -851,7 +1221,7 @@ unsigned short mode; struct dev_mc_list *dmi=dev->mc_list; - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) + if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) { /* * We must make the kernel realise we had to move @@ -859,17 +1229,17 @@ * the cable. If it was a promisc request the * flag is already set. If not we assert it. */ - dev->flags|=IFF_PROMISC; + dev->flags|=IFF_PROMISC; outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); - outb(mode | PRMSC_Mode, ioaddr + REG2); + outb(mode | PRMSC_Mode, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ printk("%s: promiscuous mode enabled.\n", dev->name); - } - else if (dev->mc_count==0 ) + } + else if (dev->mc_count==0 ) { outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); @@ -878,11 +1248,11 @@ outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ } - else + else { unsigned short status, *eaddrs; int i, boguscount = 0; - + /* Disable RX and TX interrupts. Necessary to avoid corruption of the HOST_ADDRESS_REG by interrupt service routines. */ @@ -890,7 +1260,7 @@ outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); - outb(mode | Multi_IA, ioaddr + REG2); + outb(mode | Multi_IA, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ @@ -899,7 +1269,7 @@ outw(0, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(6*(dev->mc_count + 1), ioaddr + IO_PORT); - for (i = 0; i < dev->mc_count; i++) + for (i = 0; i < dev->mc_count; i++) { eaddrs=(unsigned short *)dmi->dmi_addr; dmi=dmi->next; @@ -916,9 +1286,9 @@ /* Update the transmit queue */ i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1); - if (lp->tx_start != lp->tx_end) - { - /* update the next address and the chain bit in the + if (lp->tx_start != lp->tx_end) + { + /* update the next address and the chain bit in the last packet */ outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); outw(i, ioaddr + IO_PORT); @@ -933,26 +1303,28 @@ /* Acknowledge that the MC setup is done */ do { /* We should be doing this in the eepro_interrupt()! */ - udelay(2); - if (inb(ioaddr + STATUS_REG) & 0x08) + SLOW_DOWN; + SLOW_DOWN; + if (inb(ioaddr + STATUS_REG) & 0x08) { i = inb(ioaddr); outb(0x08, ioaddr + STATUS_REG); if (i & 0x20) { /* command ABORTed */ - printk("%s: multicast setup failed.\n", + printk("%s: multicast setup failed.\n", dev->name); break; } else if ((i & 0x0f) == 0x03) { /* MC-Done */ - printk("%s: set Rx mode to %d addresses.\n", - dev->name, dev->mc_count); + printk("%s: set Rx mode to %d address%s.\n", + dev->name, dev->mc_count, + dev->mc_count > 1 ? "es":""); break; } } } while (++boguscount < 100); /* Re-enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - + outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + } outb(RCV_ENABLE_CMD, ioaddr); } @@ -961,7 +1333,7 @@ /* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */ /* The delay between EEPROM clock transitions. */ -#define eeprom_delay() { udelay(40); } +#define eeprom_delay() { int _i = 40; while (--_i > 0) { SLOW_DOWN; }} #define EE_READ_CMD (6 << 6) int @@ -972,10 +1344,10 @@ short ee_addr = ioaddr + EEPROM_REG; int read_cmd = location | EE_READ_CMD; short ctrl_val = EECS ; - + outb(BANK2_SELECT, ioaddr); outb(ctrl_val, ee_addr); - + /* Shift the read command bits out. */ for (i = 8; i >= 0; i--) { short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI @@ -987,7 +1359,7 @@ eeprom_delay(); } outb(ctrl_val, ee_addr); - + for (i = 16; i > 0; i--) { outb(ctrl_val | EESK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); @@ -1013,7 +1385,7 @@ unsigned status, tx_available, last, end, boguscount = 100; if (net_debug > 5) - printk("eepro: entering hardware_send_packet routine.\n"); + printk(KERN_DEBUG "eepro: entering hardware_send_packet routine.\n"); while (boguscount-- > 0) { @@ -1022,9 +1394,9 @@ service routines. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); - if (dev->interrupt == 1) { + if (dev->interrupt == 1) { /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); continue; } @@ -1035,13 +1407,13 @@ tx_available = lp->tx_start - lp->tx_end; else tx_available = XMT_RAM; - if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) + if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) /* No space available ??? */ { eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */ /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); continue; } @@ -1049,17 +1421,17 @@ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */ - if ((RAM_SIZE - last) <= XMT_HEADER) { + if ((RAM_SIZE - last) <= XMT_HEADER) { /* Arrrr!!!, must keep the xmt header together, several days were lost to chase this one down. */ last = rcv_ram; end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - } + } else end = rcv_ram + (end - RAM_SIZE); } outw(last, ioaddr + HOST_ADDRESS_REG); - outw(XMT_CMD, ioaddr + IO_PORT); + outw(XMT_CMD, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(end, ioaddr + IO_PORT); outw(length, ioaddr + IO_PORT); @@ -1074,48 +1446,46 @@ } /* A dummy read to flush the DRAM write pipeline */ - status = inw(ioaddr + IO_PORT); + status = inw(ioaddr + IO_PORT); - if (lp->tx_start == lp->tx_end) { + if (lp->tx_start == lp->tx_end) { outw(last, ioaddr + XMT_BAR); outb(XMT_CMD, ioaddr); lp->tx_start = last; /* I don't like to change tx_start here */ } else { - /* update the next address and the chain bit in the - last packet */ - if (lp->tx_end != last) { - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(last, ioaddr + IO_PORT); - } - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); + /* update the next address and the chain bit in the + last packet */ + if (lp->tx_end != last) { + outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); + outw(last, ioaddr + IO_PORT); + } + outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); + status = inw(ioaddr + IO_PORT); + outw(status | CHAIN_BIT, ioaddr + IO_PORT); - /* Continue the transmit command */ - outb(RESUME_XMT_CMD, ioaddr); + /* Continue the transmit command */ + outb(RESUME_XMT_CMD, ioaddr); } lp->tx_last = last; lp->tx_end = end; - /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - if (dev->tbusy) { dev->tbusy = 0; } - - lp->stats.tx_bytes += length; + + /* Enable RX and TX interrupts */ + outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); if (net_debug > 5) - printk("eepro: exiting hardware_send_packet routine.\n"); + printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n"); return; } dev->tbusy = 1; if (net_debug > 5) - printk("eepro: exiting hardware_send_packet routine.\n"); + printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n"); } static void @@ -1128,75 +1498,77 @@ unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size; if (net_debug > 5) - printk("eepro: entering eepro_rx routine.\n"); - + printk(KERN_DEBUG "eepro: entering eepro_rx routine.\n"); + /* Set the read pointer to the start of the RCV */ outw(rcv_car, ioaddr + HOST_ADDRESS_REG); rcv_event = inw(ioaddr + IO_PORT); while (rcv_event == RCV_DONE) { - rcv_status = inw(ioaddr + IO_PORT); - rcv_next_frame = inw(ioaddr + IO_PORT); - rcv_size = inw(ioaddr + IO_PORT); - - if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - rcv_size &= 0x3fff; - skb = dev_alloc_skb(rcv_size+5); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb,2); - - if (lp->version == LAN595) - insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1); - else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ - unsigned short temp = inb(ioaddr + INT_MASK_REG); - outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); - insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), (rcv_size + 3) >> 2); - outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); - } - - - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - lp->stats.rx_bytes += rcv_size; - } - else { /* Not sure will ever reach here, - I set the 595 to discard bad received frames */ - lp->stats.rx_errors++; - if (rcv_status & 0x0100) - lp->stats.rx_over_errors++; - else if (rcv_status & 0x0400) - lp->stats.rx_frame_errors++; - else if (rcv_status & 0x0800) - lp->stats.rx_crc_errors++; - printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", - dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); - } - if (rcv_status & 0x1000) - lp->stats.rx_length_errors++; - if (--boguscount == 0) - break; - - rcv_car = lp->rx_start + RCV_HEADER + rcv_size; - lp->rx_start = rcv_next_frame; - outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); - rcv_event = inw(ioaddr + IO_PORT); - - } + rcv_status = inw(ioaddr + IO_PORT); + rcv_next_frame = inw(ioaddr + IO_PORT); + rcv_size = inw(ioaddr + IO_PORT); + + if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) { + /* Malloc up new buffer. */ + struct sk_buff *skb; + +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + lp->stats.rx_bytes+=rcv_size; +#endif + rcv_size &= 0x3fff; + skb = dev_alloc_skb(rcv_size+5); + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + lp->stats.rx_dropped++; + break; + } + skb->dev = dev; + skb_reserve(skb,2); + + if (lp->version == LAN595) + insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1); + else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ + unsigned short temp = inb(ioaddr + INT_MASK_REG); + outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); + insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), + (rcv_size + 3) >> 2); + outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); + } + + skb->protocol = eth_type_trans(skb,dev); + netif_rx(skb); + lp->stats.rx_packets++; + } + else { /* Not sure will ever reach here, + I set the 595 to discard bad received frames */ + lp->stats.rx_errors++; + if (rcv_status & 0x0100) + lp->stats.rx_over_errors++; + else if (rcv_status & 0x0400) + lp->stats.rx_frame_errors++; + else if (rcv_status & 0x0800) + lp->stats.rx_crc_errors++; + printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", + dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); + } + if (rcv_status & 0x1000) + lp->stats.rx_length_errors++; + if (--boguscount == 0) + break; + + rcv_car = lp->rx_start + RCV_HEADER + rcv_size; + lp->rx_start = rcv_next_frame; + outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); + rcv_event = inw(ioaddr + IO_PORT); + + } if (rcv_car == 0) - rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff; + rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff; outw(rcv_car - 1, ioaddr + RCV_STOP); if (net_debug > 5) - printk("eepro: exiting eepro_rx routine.\n"); + printk(KERN_DEBUG "eepro: exiting eepro_rx routine.\n"); } static void @@ -1204,80 +1576,118 @@ { struct eepro_local *lp = (struct eepro_local *)dev->priv; short ioaddr = dev->base_addr; - short boguscount = 20; + short boguscount = 20; short xmt_status; - - while (lp->tx_start != lp->tx_end) { - - outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); - xmt_status = inw(ioaddr+IO_PORT); - if ((xmt_status & TX_DONE_BIT) == 0) break; - - xmt_status = inw(ioaddr+IO_PORT); - lp->tx_start = inw(ioaddr+IO_PORT); - - dev->tbusy = 0; - mark_bh(NET_BH); - - if (xmt_status & 0x2000) - lp->stats.tx_packets++; - else { - lp->stats.tx_errors++; - if (xmt_status & 0x0400) - lp->stats.tx_carrier_errors++; - printk("%s: XMT status = %#x\n", - dev->name, xmt_status); - } - if (xmt_status & 0x000f) { - lp->stats.collisions += (xmt_status & 0x000f); - } - if ((xmt_status & 0x0040) == 0x0) { - lp->stats.tx_heartbeat_errors++; - } - - if (--boguscount == 0) - break; + + /* + if (dev->tbusy == 0) { + printk("%s: transmit_interrupt called with tbusy = 0 ??\n", + dev->name); + printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n", + dev->name); + } + */ + while (lp->tx_start != lp->tx_end) { + outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); + xmt_status = inw(ioaddr+IO_PORT); + if ((xmt_status & TX_DONE_BIT) == 0) break; + + xmt_status = inw(ioaddr+IO_PORT); + lp->tx_start = inw(ioaddr+IO_PORT); + + dev->tbusy = 0; + mark_bh(NET_BH); + + if (xmt_status & 0x2000) + lp->stats.tx_packets++; + else { + lp->stats.tx_errors++; + if (xmt_status & 0x0400) + lp->stats.tx_carrier_errors++; + printk("%s: XMT status = %#x\n", + dev->name, xmt_status); + printk(KERN_DEBUG "%s: XMT status = %#x\n", + dev->name, xmt_status); + } + if (xmt_status & 0x000f) { + lp->stats.collisions += (xmt_status & 0x000f); + } + if ((xmt_status & 0x0040) == 0x0) { + lp->stats.tx_heartbeat_errors++; + } + + if (--boguscount == 0) + break; } } #ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_eepro = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, eepro_probe }; - -static int io = 0x200; -static int irq = 0; -static int mem = (RCV_RAM/1024); /* Size of the rx buffer in KB */ +#define MAX_EEPRO 8 +static char devicename[MAX_EEPRO][9]; +static struct device dev_eepro[MAX_EEPRO]; + +static int io[MAX_EEPRO] = { +#ifdef PnPWakeup + 0x210, /*: default for PnP enabled FX chips */ +#else + 0x200, /* Why? */ +#endif + -1, -1, -1, -1, -1, -1, -1}; +static int irq[MAX_EEPRO] = {0, 0, 0, 0, 0, 0, 0, 0}; +static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */ + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024), + (RCV_RAM/1024) +}; +static int n_eepro = 0; +/* For linux 2.1.xx */ +#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 +MODULE_AUTHOR("Pascal Dupuis for the 2.1 stuff (locking,...)"); +MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver"); MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(mem, "i"); +#endif -int -init_module(void) +int init_module(void) { - if (io == 0) + if (io[0] == 0) printk("eepro: You should not use auto-probing with insmod!\n"); - dev_eepro.base_addr = io; - dev_eepro.irq = irq; - dev_eepro.mem_end = mem; + while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) { + struct device *d = &dev_eepro[n_eepro]; + d->name = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */ + d->mem_end = mem[n_eepro]; + d->base_addr = io[n_eepro]; + d->irq = irq[n_eepro]; + d->init = eepro_probe; - if (register_netdev(&dev_eepro) != 0) - return -EIO; - return 0; + if (register_netdev(d) == 0) + n_eepro++; + } + + return n_eepro ? 0 : -ENODEV; } void cleanup_module(void) { - unregister_netdev(&dev_eepro); - kfree_s(dev_eepro.priv,sizeof(struct eepro_local)); - dev_eepro.priv=NULL; - - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_eepro.base_addr, EEPRO_IO_EXTENT); + int i; + + for (i=0; ipriv,sizeof(struct eepro_local)); + d->priv=NULL; + + /* If we don't do this, we can't re-insmod it later. */ + release_region(d->base_addr, EEPRO_IO_EXTENT); + + } } #endif /* MODULE */ diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/hamradio/Config.in linux/drivers/net/hamradio/Config.in --- v2.2.0-pre1/linux/drivers/net/hamradio/Config.in Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/hamradio/Config.in Tue Dec 29 11:30:56 1998 @@ -13,8 +13,8 @@ tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX -tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR -tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP +dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_PARPORT +dep_tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP $CONFIG_PARPORT tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM if [ "$CONFIG_SOUNDMODEM" != "n" ]; then diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c --- v2.2.0-pre1/linux/drivers/net/hamradio/hdlcdrv.c Fri Nov 27 13:09:24 1998 +++ linux/drivers/net/hamradio/hdlcdrv.c Tue Dec 29 11:30:56 1998 @@ -41,6 +41,7 @@ /*****************************************************************************/ #include +#include #include #include #include @@ -58,10 +59,8 @@ #include #include #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* prototypes for ax25_encapsulate and ax25_rebuild_header */ #include -#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ /* make genksyms happy */ #include diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.2.0-pre1/linux/drivers/net/hp100.c Fri Oct 9 13:27:09 1998 +++ linux/drivers/net/hp100.c Tue Dec 29 11:32:06 1998 @@ -2796,9 +2796,9 @@ time=jiffies+(HZ/4); do{ if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break; - } while (time>jiffies); + } while (time_after(time, jiffies)); - if ( jiffies >= time ) /* no signal->no logout */ + if ( time_before_eq(jiffies, time) ) /* no signal->no logout */ return 0; /* Drop the VG Link by clearing the link up cmd and load addr.*/ @@ -2810,10 +2810,10 @@ time=jiffies+(HZ/2); do{ if ( !(hp100_inb( VG_LAN_CFG_1) & HP100_LINK_UP_ST) ) break; - } while(time>jiffies); + } while(time_after(time, jiffies)); #ifdef HP100_DEBUG - if (jiffies>=time) + if (time_before_eq(jiffies, time)) printk("hp100: %s: down_vg_link: Link does not go down?\n", dev->name); #endif @@ -2848,7 +2848,7 @@ time=jiffies+(HZ*5); do{ if( !(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST) ) break; - } while(time>jiffies); + } while(time_after(time, jiffies)); hp100_orb( HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */ hp100_outl(savelan, 10_LAN_CFG_1); @@ -2857,9 +2857,9 @@ time=jiffies+(3*HZ); /* Timeout 3s */ do { if ( (hp100_inb( VG_LAN_CFG_1 )&HP100_LINK_CABLE_ST) == 0) break; - } while (time>jiffies); + } while (time_after(time, jiffies)); - if(time<=jiffies) + if(time_before_eq(time, jiffies)) { #ifdef HP100_DEBUG printk( "hp100: %s: down_vg_link: timeout\n", dev->name ); @@ -2868,7 +2868,7 @@ } time=jiffies+(2*HZ); /* This seems to take a while.... */ - do {} while (time>jiffies); + do {} while (time_after(time, jiffies)); return 0; } @@ -2918,7 +2918,7 @@ time = jiffies + (HZ/10); do { if (~(hp100_inb( VG_LAN_CFG_1 )& HP100_LINK_UP_ST) ) break; - } while (time>jiffies); + } while (time_after(time, jiffies)); /* Start an addressed training and optionally request promiscuous port */ if ( (dev->flags) & IFF_PROMISC ) @@ -2955,9 +2955,9 @@ time = jiffies + ( 1*HZ ); /* 1 sec timeout for cable st */ do { if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break; - } while ( jiffies < time ); + } while ( time_before(jiffies, time) ); - if ( jiffies >= time ) + if ( time_after_eq(jiffies, time) ) { #ifdef HP100_DEBUG_TRAINING printk( "hp100: %s: Link cable status not ok? Training aborted.\n", dev->name ); @@ -2979,11 +2979,11 @@ #endif break; } - } while ( time > jiffies ); + } while ( time_after(time, jiffies) ); } /* If LINK_UP_ST is set, then we are logged into the hub. */ - if ( (jiffies<=time) && (val & HP100_LINK_UP_ST) ) + if ( time_before_eq(jiffies, time) && (val & HP100_LINK_UP_ST) ) { #ifdef HP100_DEBUG_TRAINING printk( "hp100: %s: Successfully logged into the HUB.\n", dev->name); diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/plip.c linux/drivers/net/plip.c --- v2.2.0-pre1/linux/drivers/net/plip.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/plip.c Tue Dec 29 11:51:50 1998 @@ -21,6 +21,10 @@ * - Make sure other end is OK, before sending a packet. * - Fix immediate timer problem. * + * Al Viro + * - Changed {enable,disable}_irq handling to make it work + * with new ("stack") semantics. + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -120,6 +124,9 @@ #endif static unsigned int net_debug = NET_DEBUG; +#define ENABLE(irq) enable_irq(irq) +#define DISABLE(irq) disable_irq(irq) + /* In micro second */ #define PLIP_DELAY_UNIT 1 @@ -333,6 +340,7 @@ #define OK 0 #define TIMEOUT 1 #define ERROR 2 +#define HS_TIMEOUT 3 typedef int (*plip_func)(struct device *dev, struct net_local *nl, struct plip_local *snd, struct plip_local *rcv); @@ -371,13 +379,22 @@ int error) { unsigned char c0; + /* + * This is tricky. If we got here from the beginning of send (either + * with ERROR or HS_TIMEOUT) we have IRQ enabled. Otherwise it's + * already disabled. With the old variant of {enable,disable}_irq() + * extra disable_irq() was a no-op. Now it became mortal - it's + * unbalanced and thus we'll never re-enable IRQ (until rmmod plip, + * that is). So we have to treat HS_TIMEOUT and ERROR from send + * in a special way. + */ spin_lock_irq(&nl->lock); if (nl->connection == PLIP_CN_SEND) { if (error != ERROR) { /* Timeout */ nl->timeout_count++; - if ((snd->state == PLIP_PK_TRIGGER + if ((error == HS_TIMEOUT && nl->timeout_count <= 10) || nl->timeout_count <= 3) { spin_unlock_irq(&nl->lock); @@ -387,7 +404,8 @@ c0 = inb(PAR_STATUS(dev)); printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n", dev->name, snd->state, c0); - } + } else + error = HS_TIMEOUT; nl->enet_stats.tx_errors++; nl->enet_stats.tx_aborted_errors++; } else if (nl->connection == PLIP_CN_RECEIVE) { @@ -419,8 +437,10 @@ snd->skb = NULL; } spin_unlock_irq(&nl->lock); - disable_irq(dev->irq); - synchronize_irq(); + if (error == HS_TIMEOUT) { + DISABLE(dev->irq); + synchronize_irq(); + } outb(PAR_INTR_OFF, PAR_CONTROL(dev)); dev->tbusy = 1; nl->connection = PLIP_CN_ERROR; @@ -498,7 +518,7 @@ switch (rcv->state) { case PLIP_PK_TRIGGER: - disable_irq(dev->irq); + DISABLE(dev->irq); /* Don't need to synchronize irq, as we can safely ignore it */ outb(PAR_INTR_OFF, PAR_CONTROL(dev)); dev->interrupt = 0; @@ -518,7 +538,7 @@ nl->connection = PLIP_CN_SEND; queue_task(&nl->deferred, &tq_timer); outb(PAR_INTR_ON, PAR_CONTROL(dev)); - enable_irq(dev->irq); + ENABLE(dev->irq); return OK; } } else { @@ -592,13 +612,13 @@ queue_task(&nl->immediate, &tq_immediate); mark_bh(IMMEDIATE_BH); outb(PAR_INTR_ON, PAR_CONTROL(dev)); - enable_irq(dev->irq); + ENABLE(dev->irq); return OK; } else { nl->connection = PLIP_CN_NONE; spin_unlock_irq(&nl->lock); outb(PAR_INTR_ON, PAR_CONTROL(dev)); - enable_irq(dev->irq); + ENABLE(dev->irq); return OK; } } @@ -674,7 +694,7 @@ switch (snd->state) { case PLIP_PK_TRIGGER: if ((inb(PAR_STATUS(dev)) & 0xf8) != 0x80) - return TIMEOUT; + return HS_TIMEOUT; /* Trigger remote rx interrupt. */ outb(0x08, data_addr); @@ -691,12 +711,16 @@ c0 = inb(PAR_STATUS(dev)); if (c0 & 0x08) { spin_unlock_irq(&nl->lock); - disable_irq(dev->irq); + DISABLE(dev->irq); synchronize_irq(); if (nl->connection == PLIP_CN_RECEIVE) { /* Interrupted. We don't need to enable irq, as it is soon disabled. */ + /* Yes, we do. New variant of + {enable,disable}_irq *counts* + them. -- AV */ + ENABLE(dev->irq); nl->enet_stats.collisions++; return OK; } @@ -711,7 +735,7 @@ spin_unlock_irq(&nl->lock); if (--cx == 0) { outb(0x00, data_addr); - return TIMEOUT; + return HS_TIMEOUT; } } @@ -760,7 +784,7 @@ nl->is_deferred = 1; queue_task(&nl->deferred, &tq_timer); outb(PAR_INTR_ON, PAR_CONTROL(dev)); - enable_irq(dev->irq); + ENABLE(dev->irq); return OK; } return OK; @@ -800,7 +824,7 @@ dev->tbusy = 0; dev->interrupt = 0; outb(PAR_INTR_ON, PAR_CONTROL(dev)); - enable_irq(dev->irq); + ENABLE(dev->irq); mark_bh(NET_BH); } else { nl->is_deferred = 1; @@ -1000,7 +1024,7 @@ dev->tbusy = 1; dev->start = 0; - disable_irq(dev->irq); + DISABLE(dev->irq); synchronize_irq(); #ifdef NOTDEF diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/sdla.c linux/drivers/net/sdla.c --- v2.2.0-pre1/linux/drivers/net/sdla.c Sun Jun 7 11:16:32 1998 +++ linux/drivers/net/sdla.c Tue Dec 29 11:32:06 1998 @@ -248,7 +248,7 @@ temp += z80_addr & SDLA_ADDR_MASK; resp = ~resp1; - while ((jiffies < done) && (resp != resp1) && (!resp2 || (resp != resp2))) + while (time_before(jiffies, done) && (resp != resp1) && (!resp2 || (resp != resp2))) { if (jiffies != now) { @@ -257,7 +257,7 @@ resp = *temp; } } - return(jiffies < done ? jiffies - start : -1); + return(time_before(jiffies, done) ? jiffies - start : -1); } /* constants for Z80 CPU speed */ @@ -444,7 +444,7 @@ waiting = 1; len = 0; - while (waiting && (jiffies <= jiffs)) + while (waiting && time_before_eq(jiffies, jiffs)) { if (waiting++ % 3) { diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c --- v2.2.0-pre1/linux/drivers/net/seeq8005.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/seeq8005.c Tue Dec 29 11:32:06 1998 @@ -247,10 +247,10 @@ outw(0x5a5a, SEEQ_BUFFER); } j=jiffies+HZ; - while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && jiffies < j ) + while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && time_before(jiffies, j) ) mb(); outw( 0 , SEEQ_DMAAR); - while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < j+HZ) + while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, j+HZ)) mb(); if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD); @@ -707,7 +707,7 @@ /* drain FIFO */ tmp = jiffies; - while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies < tmp + HZ)) + while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies - tmp < HZ)) mb(); /* doit ! */ @@ -729,7 +729,7 @@ int status; tmp = jiffies + HZ; - while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < tmp) + while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp)) mb(); if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/net/sktr.c linux/drivers/net/sktr.c --- v2.2.0-pre1/linux/drivers/net/sktr.c Sun Nov 8 14:03:00 1998 +++ linux/drivers/net/sktr.c Tue Dec 29 11:32:06 1998 @@ -1020,7 +1020,7 @@ return; sktr_chk_outstanding_cmds(dev); - if(tp->LastSendTime + SEND_TIMEOUT < jiffies + if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies) && (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy)) { /* Anything to send, but stalled to long */ @@ -1526,11 +1526,11 @@ { long tmp; - tmp = time/(1000000/HZ); + tmp = jiffies + time/(1000000/HZ); do { - current->state = TASK_INTERRUPTIBLE; + current->state = TASK_INTERRUPTIBLE; tmp = schedule_timeout(tmp); - } while(tmp); + } while(time_after(tmp, jiffies)); return; } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c --- v2.2.0-pre1/linux/drivers/nubus/nubus.c Thu Sep 17 17:53:36 1998 +++ linux/drivers/nubus/nubus.c Tue Dec 29 11:32:06 1998 @@ -632,7 +632,9 @@ nubus_init_via(); printk("Scanning nubus slots.\n"); nubus_probe_bus(); +#ifdef CONFIG_PROC_FS proc_register(&proc_root, &proc_nubus); +#endif } diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.2.0-pre1/linux/drivers/pci/oldproc.c Mon Dec 28 15:00:52 1998 +++ linux/drivers/pci/oldproc.c Tue Dec 29 14:01:38 1998 @@ -338,6 +338,7 @@ DEVICE( VIA, VIA_86C100A, "VT 86C100A"), DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"), DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP"), + DEVICE( SMC2, SMC2_1211TX, "1211 TX"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510"), @@ -482,6 +483,7 @@ DEVICE( S3, S3_ViRGE_MXP, "ViRGE/MX+"), DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV"), DEVICE( S3, S3_SONICVIBES, "SonicVibes"), + DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter"), DEVICE( INTEL, INTEL_82375, "82375EB"), DEVICE( INTEL, INTEL_82424, "82424ZX Saturn"), DEVICE( INTEL, INTEL_82378, "82378IB"), @@ -739,6 +741,7 @@ case PCI_VENDOR_ID_INIT: return "Initio Corp"; case PCI_VENDOR_ID_TTI: return "Triones Technologies, Inc."; case PCI_VENDOR_ID_VIA: return "VIA Technologies"; + case PCI_VENDOR_ID_SMC2: return "SMC"; case PCI_VENDOR_ID_VORTEX: return "VORTEX"; case PCI_VENDOR_ID_EF: return "Efficient Networks"; case PCI_VENDOR_ID_FORE: return "Fore Systems"; @@ -787,6 +790,7 @@ case PCI_VENDOR_ID_AVANCE: return "Avance"; case PCI_VENDOR_ID_NETVIN: return "NetVin"; case PCI_VENDOR_ID_S3: return "S3 Inc."; + case PCI_VENDOR_ID_DCI: return "Decision Computer Int."; case PCI_VENDOR_ID_INTEL: return "Intel"; case PCI_VENDOR_ID_KTI: return "KTI"; case PCI_VENDOR_ID_ADAPTEC: return "Adaptec"; diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.2.0-pre1/linux/drivers/scsi/Config.in Tue Dec 22 14:16:56 1998 +++ linux/drivers/scsi/Config.in Tue Dec 29 13:54:32 1998 @@ -50,7 +50,7 @@ fi dep_tristate 'EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI -dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI +dep_tristate 'Future Domain 16xx SCSI/AHA-2920A support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI if [ "$CONFIG_MCA" = "y" ]; then if [ "$CONFIG_SCSI" = "y" ]; then bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS @@ -116,7 +116,7 @@ dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI - dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI +# dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI fi dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v2.2.0-pre1/linux/drivers/scsi/advansys.c Mon Dec 28 15:00:52 1998 +++ linux/drivers/scsi/advansys.c Tue Dec 29 11:35:48 1998 @@ -3941,6 +3941,8 @@ advansys_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { +#ifdef CONFIG_PROC_FS + struct Scsi_Host *shp; asc_board_t *boardp; int i; @@ -4147,9 +4149,12 @@ ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); return totcnt; +#else /* CONFIG_PROC_FS */ + return 0; +#endif /* CONFIG_PROC_FS */ + } #endif /* version >= v1.3.0 */ - /* * advansys_detect() * diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.2.0-pre1/linux/drivers/scsi/eata_dma.c Tue Apr 14 14:29:22 1998 +++ linux/drivers/scsi/eata_dma.c Tue Dec 29 11:35:48 1998 @@ -962,7 +962,7 @@ eata_send_command((u32) cp, (u32) base, EATA_CMD_DMA_SEND_CP); i = jiffies + (3 * HZ); - while (fake_int_happened == FALSE && jiffies <= i) + while (fake_int_happened == FALSE && time_before_eq(jiffies, i)) barrier(); DBG(DBG_INTR3, printk(KERN_DEBUG "fake_int_result: %#x hbastat %#x " @@ -973,7 +973,7 @@ scsi_init_free((void *)cp, sizeof(struct eata_ccb)); scsi_init_free((void *)sp, sizeof(struct eata_sp)); - if ((fake_int_result & HA_SERROR) || jiffies > i){ + if ((fake_int_result & HA_SERROR) || time_after(jiffies, i)){ printk(KERN_WARNING "eata_dma: trying to reset HBA at %x to clear " "possible blink state\n", base); /* hard reset the HBA */ diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c --- v2.2.0-pre1/linux/drivers/scsi/eata_dma_proc.c Sun Dec 21 17:04:49 1997 +++ linux/drivers/scsi/eata_dma_proc.c Tue Dec 29 11:35:48 1998 @@ -1,3 +1,4 @@ +#include void swap_statistics(u8 *p) { @@ -68,6 +69,8 @@ int hostno, int inout) { +#ifdef CONFIG_PROC_FS + Scsi_Device *scd, SDev; struct Scsi_Host *HBA_ptr; Scsi_Cmnd scmd; @@ -466,6 +469,9 @@ DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); return (len); +#else /* CONFIG_PROC_FS */ + return 0; +#endif } /* diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.2.0-pre1/linux/drivers/scsi/eata_pio.c Wed May 20 19:10:39 1998 +++ linux/drivers/scsi/eata_pio.c Tue Dec 29 11:35:48 1998 @@ -500,7 +500,7 @@ HD(cmd)->state = RESET; time = jiffies; - while (jiffies < (time + (3 * HZ)) && limit++ < 10000000); + while (time_before(jiffies, time + 3 * HZ) && limit++ < 10000000); DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit)); diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/eata_pio_proc.c linux/drivers/scsi/eata_pio_proc.c --- v2.2.0-pre1/linux/drivers/scsi/eata_pio_proc.c Sun Dec 21 17:04:49 1997 +++ linux/drivers/scsi/eata_pio_proc.c Tue Dec 29 11:35:48 1998 @@ -1,3 +1,5 @@ +#include + /* * eata_set_info * buffer : pointer to the data that has been written to the hostfile @@ -24,7 +26,7 @@ int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { - +#ifdef CONFIG_PROC_FS Scsi_Device *scd; struct Scsi_Host *HBA_ptr; static u8 buff[512]; @@ -108,6 +110,9 @@ DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); return (len); +#else + return 0; +#endif } /* diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.2.0-pre1/linux/drivers/scsi/fdomain.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/scsi/fdomain.c Tue Dec 29 11:44:53 1998 @@ -1,10 +1,8 @@ /* fdomain.c -- Future Domain TMC-16x0 SCSI driver * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu - * Revised: Wed Oct 2 11:10:55 1996 by faith@acm.org + * Revised: Mon Dec 28 21:59:02 1998 by faith@acm.org * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith - * - * Version 5.46 (23-04-1998) + * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org) * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -32,13 +30,34 @@ Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX Future Domain TMC-3260 (PCI) Quantum ISA-200S, ISA-250MG - Adaptec AHA-2920 (PCI) + Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] IBM ? - LILO command-line options: + LILO/INSMOD command-line options: fdomain=,[,] + + NOTE: + + The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + Use the aic7xxx driver for this board. + + The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + driver for that card. Unfortunately, the boxes will probably just say + "2920", so you'll have to look on the card for a Future Domain logo, or a + letter after the 2920. + + + + THANKS: + + Thanks to Adaptec for providing PCI boards for testing. This finally + enabled me to test the PCI detection and correct it for PCI boards that do + not have a BIOS at a standard ISA location. For PCI boards, LILO/INSMOD + command-line options should no longer be needed. --RF 18Nov98 + + DESCRIPTION: This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 @@ -70,7 +89,7 @@ your board. Please refer to the Seagate driver for more information and possible support. - + HISTORY: @@ -108,7 +127,8 @@ 2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x 2.1.97 5.46 23 Apr 1998 Rewritten PCI detection routines [mj] 2.1.11x 5.47 9 Aug 1998 Touched for 8 SCSI disk majors support - + 5.48 18 Nov 1998 BIOS no longer needed for PCI detection + 2.2.0 5.50 28 Dec 1998 Support insmod parameters REFERENCES USED: @@ -207,6 +227,9 @@ patches. New PCI detection code written by Martin Mares + + Insmod parameter code based on patches from Daniel Graham + . All of the alpha testers deserve much thanks. @@ -282,7 +305,7 @@ S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -#define VERSION "$Revision: 5.45 $" +#define VERSION "$Revision: 5.50 $" /* START OF USER DEFINABLE OPTIONS */ @@ -406,6 +429,15 @@ extern void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ); +#ifdef MODULE + /* Allow insmod parameters to be like LILO + parameters. For example: + insmod fdomain fdomain=0x140,11 + */ +static int fdomain[]={ 0, 0, 0 }; +MODULE_PARM(fdomain, "2-3i"); +#endif + static unsigned long addresses[] = { 0xc8000, 0xca000, @@ -504,10 +536,10 @@ if (!shpnt) return; /* This won't ever happen */ if (bios_major < 0 && bios_minor < 0) { - printk( "scsi%d : No BIOS; using scsi id %d\n", + printk( "scsi%d: No BIOS; using scsi id %d\n", shpnt->host_no, shpnt->this_id ); } else { - printk( "scsi%d : BIOS version ", shpnt->host_no ); + printk( "scsi%d: BIOS version ", shpnt->host_no ); if (bios_major >= 0) printk( "%d.", bios_major ); else printk( "?." ); @@ -523,7 +555,7 @@ boards, we will have to modify banner for additional PCI cards, but for now if it's PCI it's a TMC-3260 - JTM */ - printk( "scsi%d : %s chip at 0x%x irq ", + printk( "scsi%d: %s chip at 0x%x irq ", shpnt->host_no, chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" @@ -541,8 +573,9 @@ void fdomain_setup( char *str, int *ints ) { if (setup_called++ || ints[0] < 2 || ints[0] > 3) { - printk( "fdomain: usage: fdomain=,[,]\n" ); - printk( "fdomain: bad LILO parameters?\n" ); + printk( "scsi: " + " Usage: fdomain=,[,]\n" ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); } port_base = ints[0] >= 1 ? ints[1] : 0; @@ -591,8 +624,6 @@ if (inb( port + MSB_ID_Code ) != 0x60) return 0; chip = tmc18c50; -#if 1 - /* Try to toggle 32-bit mode. This only works on an 18c30 chip. (User reports say this works, so we should switch to @@ -606,17 +637,6 @@ FIFO_Size = 0x800; /* 2k FIFO */ } } -#else - - /* That should have worked, but appears to - have problems. Let's assume it is an - 18c30 if the RAM is disabled. */ - - if (inb( port + Configuration2 ) & 0x02) { - chip = tmc18c30; - FIFO_Size = 0x800; /* 2k FIFO */ - } -#endif /* If that failed, we are an 18c50. */ } @@ -656,7 +676,7 @@ int options = inb( base + Configuration1 ); #if DEBUG_DETECT - printk( " Options = %x\n", options ); + printk( "scsi: Options = %x\n", options ); #endif /* Check for board with lowest bios_base -- @@ -673,10 +693,31 @@ static int fdomain_isa_detect( int *irq, int *iobase ) { - int i; + int i, j; int base; int flag = 0; +#if DEBUG_DETECT + printk( "scsi: fdomain_isa_detect:" ); +#endif + + for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { +#if DEBUG_DETECT + printk( " %lx(%lx),", addresses[i], bios_base ); +#endif + for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { + if (check_signature(addresses[i] + signatures[j].sig_offset, + signatures[j].signature, + signatures[j].sig_length )) { + bios_major = signatures[j].major_bios_version; + bios_minor = signatures[j].minor_bios_version; + PCI_bus = (signatures[j].flag == 1); + Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; + bios_base = addresses[i]; + } + } + } + if (bios_major == 2) { /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. Assuming the ROM is enabled (otherwise we wouldn't have been @@ -746,6 +787,11 @@ if ((flag = fdomain_is_valid_port( base ))) break; } +#if DEBUG_DETECT + if (flag) printk( " SUCCESS\n" ); + else printk( " FAILURE\n" ); +#endif + if (!flag) return 0; /* iobase not found */ *irq = fdomain_get_irq( base ); @@ -771,18 +817,21 @@ /* Tell how to print a list of the known PCI devices from bios32 and list vendor and device IDs being used if in debug mode. */ - printk( "\nINFO: use lspci -v to see list of PCI devices\n" ); - printk( "\nTMC-3260 detect:" - " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n", + printk( "scsi: INFO: use lspci -v to see list of PCI devices\n" ); + printk( "scsi: TMC-3260 detect:" + " Using Vendor ID: 0x%x and Device ID: 0x%x\n", PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70 ); #endif - if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) + if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, + PCI_DEVICE_ID_FD_36C70, + pdev)) == NULL) return 0; #if DEBUG_DETECT - printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n", + printk( "scsi: TMC-3260 detect:" + " PCI bus %u, device %u, function %u\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); @@ -793,10 +842,6 @@ pci_base = pdev->base_address[0]; pci_irq = pdev->irq; -#if DEBUG_DETECT - printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", - pci_irq, pci_base ); -#endif /* Now we have the I/O base address and interrupt from the PCI configuration registers. */ @@ -805,18 +850,28 @@ *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK); #if DEBUG_DETECT - printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); - printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase ); + printk( "scsi: TMC-3260 detect:" + " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base ); #endif - if (!fdomain_is_valid_port( *iobase )) return 0; + if (!fdomain_is_valid_port( *iobase )) { + printk( "scsi: " + " PCI card detected, but driver not loaded (invalid port)\n" ); + return 0; + } + + /* Fill in a few global variables. Ugh. */ + bios_major = bios_minor = -1; + PCI_bus = 1; + Quantum = 0; + bios_base = 0; + return 1; } #endif int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) { - int i, j; int retcode; struct Scsi_Host *shpnt; #if DO_DETECT @@ -829,68 +884,44 @@ unsigned char buf[buflen]; #endif -#if DEBUG_DETECT - printk( "fdomain_16x0_detect()," ); -#endif tpnt->proc_dir = &proc_scsi_fdomain; +#ifdef MODULE + if (fdomain[0] || fdomain[1] || fdomain[2]) { + port_base = fdomain[0]; + interrupt_level = fdomain[1]; + this_id = fdomain[2]; + bios_major = bios_minor = -1; + ++setup_called; + } +#endif + if (setup_called) { #if DEBUG_DETECT - printk( "no BIOS, using port_base = 0x%x, irq = %d\n", + printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", port_base, interrupt_level ); #endif if (!fdomain_is_valid_port( port_base )) { - printk( "fdomain: cannot locate chip at port base 0x%x\n", + printk( "scsi: Cannot locate chip at port base 0x%x\n", port_base ); - printk( "fdomain: bad LILO parameters?\n" ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); return 0; } } else { int flag = 0; - - for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { -#if DEBUG_DETECT - printk( " %lx(%lx),", addresses[i], bios_base ); -#endif - for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { - if (check_signature(addresses[i] + signatures[j].sig_offset, - signatures[j].signature, - signatures[j].sig_length )) { - bios_major = signatures[j].major_bios_version; - bios_minor = signatures[j].minor_bios_version; - PCI_bus = (signatures[j].flag == 1); - Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; - bios_base = addresses[i]; - } - } - } - - if (!bios_base) { -#if DEBUG_DETECT - printk( " FAILED: NO BIOS\n" ); -#endif - return 0; - } - if (!PCI_bus) { - flag = fdomain_isa_detect( &interrupt_level, &port_base ); - } else { #ifdef CONFIG_PCI - flag = fdomain_pci_bios_detect( &interrupt_level, &port_base ); -#else - printk(KERN_ERR "No PCI support in this kernel, giving up.\n"); - flag = 0; + /* Try PCI detection first */ + flag = fdomain_pci_bios_detect( &interrupt_level, &port_base ); #endif - } - if (!flag) { -#if DEBUG_DETECT - printk( " FAILED: NO PORT\n" ); -#endif -#ifdef CONFIG_PCI - printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" ); -#endif - return 0; /* Cannot find valid set of ports */ + /* Then try ISA bus detection */ + flag = fdomain_isa_detect( &interrupt_level, &port_base ); + + if (!flag) { + printk( "scsi: Detection failed (no card)\n" ); + return 0; + } } } @@ -911,13 +942,10 @@ fdomain_16x0_reset( NULL, 0 ); if (fdomain_test_loopback()) { -#if DEBUG_DETECT - printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" ); -#endif + printk( "scsi: Detection failed" + " (loopback test failed at port base 0x%x)\n", port_base ); if (setup_called) { - printk( "fdomain: loopback test failed at port base 0x%x\n", - port_base ); - printk( "fdomain: bad LILO parameters?\n" ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); } return 0; } @@ -946,7 +974,9 @@ /* Log IRQ with kernel */ if (!interrupt_level) { - panic( "fdomain: *NO* interrupt level selected!\n" ); + printk( "scsi: " + " Card Detected, but driver not loaded (no IRQ)\n" ); + return 0; } else { /* Register the IRQ with the kernel */ @@ -955,18 +985,21 @@ if (retcode < 0) { if (retcode == -EINVAL) { - printk( "fdomain: IRQ %d is bad!\n", interrupt_level ); - printk( " This shouldn't happen!\n" ); - printk( " Send mail to faith@acm.org\n" ); + printk( "scsi: IRQ %d is bad!\n", interrupt_level ); + printk( " This shouldn't happen!\n" ); + printk( " Send mail to faith@acm.org\n" ); } else if (retcode == -EBUSY) { - printk( "fdomain: IRQ %d is already in use!\n", interrupt_level ); - printk( " Please use another IRQ!\n" ); + printk( "scsi: IRQ %d is already in use!\n", + interrupt_level ); + printk( " Please use another IRQ!\n" ); } else { - printk( "fdomain: Error getting IRQ %d\n", interrupt_level ); - printk( " This shouldn't happen!\n" ); - printk( " Send mail to faith@acm.org\n" ); + printk( "scsi: Error getting IRQ %d\n", + interrupt_level ); + printk( " This shouldn't happen!\n" ); + printk( " Send mail to faith@acm.org\n" ); } - panic( "fdomain: Driver requires interruptions\n" ); + printk( "scsi: Detected, but driver not loaded (IRQ)\n" ); + return 0; } } @@ -987,7 +1020,7 @@ SCinit.use_sg = 0; SCinit.lun = 0; - printk( "fdomain: detection routine scanning for devices:\n" ); + printk( "scsi: detection routine scanning for devices:\n" ); for (i = 0; i < 8; i++) { SCinit.target = i; if (i == tpnt->this_id) /* Skip host adapter */ @@ -1031,10 +1064,10 @@ const char *fdomain_16x0_info( struct Scsi_Host *ignore ) { - static char buffer[80]; + static char buffer[128]; char *pt; - strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" ); + strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" ); if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ strcat( buffer, strchr( VERSION, ':' ) + 1 ); pt = strrchr( buffer, '$') - 1; @@ -1118,7 +1151,7 @@ printk( "Arbitration failed, status = %x\n", status ); #endif #if ERRORS_ONLY - printk( "fdomain: Arbitration failed, status = %x\n", status ); + printk( "scsi: Arbitration failed, status = %x\n", status ); #endif return 1; } @@ -1158,7 +1191,7 @@ if (!flag) /* Skip first failure for all chips. */ ++flag; else - printk( "fdomain: Selection failed\n" ); + printk( "scsi: Selection failed\n" ); } #endif return 1; @@ -1173,9 +1206,9 @@ current_SC->result = error; if (current_SC->scsi_done) current_SC->scsi_done( current_SC ); - else panic( "fdomain: current_SC->scsi_done() == NULL" ); + else panic( "scsi: current_SC->scsi_done() == NULL" ); } else { - panic( "fdomain: my_done() called outside of command\n" ); + panic( "scsi: my_done() called outside of command\n" ); } #if DEBUG_RACE in_interrupt_flag = 0; @@ -1211,7 +1244,7 @@ /* Abort calls my_done, so we do nothing here. */ if (current_SC->SCp.phase & aborted) { #if DEBUG_ABORT - printk( "Interrupt after abort, ignoring\n" ); + printk( "scsi: Interrupt after abort, ignoring\n" ); #endif /* return; */ @@ -1311,7 +1344,7 @@ if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) { - printk( "fdomain: target = %d, command = %x, status = %x\n", + printk( "scsi: target = %d, command = %x, status = %x\n", current_SC->target, current_SC->cmnd[0], current_SC->SCp.Status ); @@ -1329,7 +1362,8 @@ if (!current_SC->SCp.Message) ++done; #if DEBUG_MESSAGES || EVERY_ACCESS if (current_SC->SCp.Message) { - printk( "fdomain: message = %x\n", current_SC->SCp.Message ); + printk( "scsi: message = %x\n", + current_SC->SCp.Message ); } #endif break; @@ -1590,8 +1624,8 @@ || code == 0x24 || !code))) - printk( "fdomain: REQUEST SENSE " - "Key = %x, Code = %x, Qualifier = %x\n", + printk( "scsi: REQUEST SENSE" + " Key = %x, Code = %x, Qualifier = %x\n", key, code, qualifier ); } } @@ -1624,7 +1658,7 @@ int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { if (in_command) { - panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" ); + panic( "scsi: fdomain_16x0_queue() NOT REENTRANT!\n" ); } #if EVERY_ACCESS printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", @@ -1704,7 +1738,8 @@ unsigned int isr; if (!SCpnt || !SCpnt->host) { - printk( "fdomain: cannot provide detailed information\n" ); + printk( "scsi: Cannot provide detailed information\n" ); + return; } printk( "%s\n", fdomain_16x0_info( SCpnt->host ) ); @@ -1770,7 +1805,7 @@ { unsigned long flags; #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT - printk( "fdomain: abort " ); + printk( "scsi: abort " ); #endif save_flags( flags ); @@ -1808,7 +1843,7 @@ #endif #if ERRORS_ONLY - if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" ); + if (SCpnt) printk( "scsi: SCSI Bus Reset\n" ); #endif #if DEBUG_RESET @@ -1893,7 +1928,7 @@ */ if (MAJOR(dev) != SCSI_DISK0_MAJOR) { - printk("fdomain_16x0_biosparam: too many disks"); + printk("scsi: fdomain_16x0_biosparam: too many disks"); return 0; } drive = MINOR(dev) >> 4; diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c --- v2.2.0-pre1/linux/drivers/scsi/ibmmca.c Fri Nov 27 13:09:24 1998 +++ linux/drivers/scsi/ibmmca.c Tue Dec 29 11:40:35 1998 @@ -1567,7 +1567,7 @@ /* first look for the SCSI integrated on the motherboard */ pos2 = mca_read_stored_pos(MCA_INTEGSCSI, 2); - if (pos2 != 0xff) { +// if (pos2 != 0xff) { if ((pos2 & 1) == 0) { port = IM_IO_PORT + ((pos2 & 0x0e) << 2); } else { @@ -1584,7 +1584,7 @@ mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); } - } +// } /* now look for other adapters */ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v2.2.0-pre1/linux/drivers/scsi/scsi.h Fri Oct 23 22:01:21 1998 +++ linux/drivers/scsi/scsi.h Tue Dec 29 15:56:07 1998 @@ -319,7 +319,7 @@ #define ASKED_FOR_SENSE 0x20 -#ifdef __mc68000__ +#if defined(__mc68000__) || defined(CONFIG_APUS) #include #define CONTIGUOUS_BUFFERS(X,Y) \ (virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data)) diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v2.2.0-pre1/linux/drivers/scsi/seagate.c Sat Sep 5 16:46:41 1998 +++ linux/drivers/scsi/seagate.c Tue Dec 29 11:40:35 1998 @@ -379,8 +379,8 @@ { register int count = 0, start = jiffies + 1, stop = start + 25; - while (jiffies < start) ; - for (; jiffies < stop; ++count) ; + while (time_before(jiffies, start)) ; + for (; time_before(jiffies, stop); ++count) ; /* * Ok, we now have a count for .25 seconds. Convert to a @@ -903,9 +903,9 @@ while (((STATUS | STATUS | STATUS) & (STAT_BSY | STAT_SEL)) && - (!st0x_aborted) && (jiffies < clock)); + (!st0x_aborted) && time_before(jiffies, clock)); - if (jiffies > clock) + if (time_after(jiffies, clock)) return retcode (DID_BUS_BUSY); else if (st0x_aborted) return retcode (st0x_aborted); diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c --- v2.2.0-pre1/linux/drivers/scsi/wd7000.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/scsi/wd7000.c Tue Dec 29 11:40:35 1998 @@ -791,7 +791,7 @@ register unsigned WAITbits; register unsigned long WAITtimeout = jiffies + WAITnexttimeout; - while (jiffies <= WAITtimeout) { + while (time_before_eq(jiffies, WAITtimeout)) { WAITbits = inb (port) & mask; if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0)) @@ -806,7 +806,7 @@ { register unsigned long time = jiffies + how_long; - while (jiffies < time); + while (time_before(jiffies, time)); } @@ -868,7 +868,7 @@ spin_unlock_irq(&io_request_lock); for (now = jiffies; now == jiffies; ); /* wait a jiffy */ spin_lock_irq(&io_request_lock); - } while (freescbs < needed && jiffies <= timeout); + } while (freescbs < needed && time_before_eq(jiffies, timeout)); /* * If we get here with enough free Scbs, we can take them. * Otherwise, we timed out and didn't get enough. @@ -1247,7 +1247,7 @@ */ mail_out (host, (struct scb *) &icb); timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ - while (icb.phase && jiffies < timeout) + while (icb.phase && time_before(jiffies, timeout)) barrier (); /* wait for completion */ if (icb.phase) { diff -u --recursive --new-file v2.2.0-pre1/linux/fs/Config.in linux/fs/Config.in --- v2.2.0-pre1/linux/fs/Config.in Mon Dec 28 15:00:52 1998 +++ linux/fs/Config.in Tue Dec 29 11:42:21 1998 @@ -56,7 +56,9 @@ if [ "$CONFIG_NFS_FS" = "y" -a "$CONFIG_IP_PNP" = "y" ]; then bool ' Root file system on NFS' CONFIG_ROOT_NFS fi - tristate 'NFS server support' CONFIG_NFSD + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'NFS server support' CONFIG_NFSD + fi if [ "$CONFIG_NFSD" != "n" ]; then bool ' Emulate SUN NFS server' CONFIG_NFSD_SUN fi diff -u --recursive --new-file v2.2.0-pre1/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.2.0-pre1/linux/fs/fat/inode.c Mon Dec 28 15:00:52 1998 +++ linux/fs/fat/inode.c Tue Dec 29 14:07:40 1998 @@ -366,7 +366,9 @@ CF_LE_W(b->info_sector) * logical_sector_size + 0x1e0; fsinfo = (struct fat_boot_fsinfo *) &bh->b_data[MSDOS_SB(sb)->fsinfo_offset]; - if (CF_LE_L(fsinfo->signature) != 0x61417272) { + if ((MSDOS_SB(sb)->fsinfo_offset - sizeof(MSDOS_SB(sb)->fsinfo_offset) + 1)> bh->b_size) + printk("fat_read_super: Bad fsinfo_offset\n"); + else if (CF_LE_L(fsinfo->signature) != 0x61417272) { printk("fat_read_super: Did not find valid FSINFO " "signature. Found 0x%x\n", CF_LE_L(fsinfo->signature)); diff -u --recursive --new-file v2.2.0-pre1/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.2.0-pre1/linux/fs/isofs/inode.c Mon Sep 28 10:51:34 1998 +++ linux/fs/isofs/inode.c Tue Dec 29 11:40:35 1998 @@ -409,11 +409,13 @@ struct cdrom_multisession ms_info; unsigned int vol_desc_start; struct inode inode_fake; + struct file_operations *fops; extern struct file_operations * get_blkfops(unsigned int); int i; vol_desc_start=0; - if (get_blkfops(MAJOR(dev))->ioctl!=NULL) + fops = get_blkfops(MAJOR(dev)); + if (fops && fops->ioctl) { /* Whoops. We must save the old FS, since otherwise * we would destroy the kernels idea about FS on root @@ -536,17 +538,10 @@ vdp = (struct iso_volume_descriptor *)bh->b_data; hdp = (struct hs_volume_descriptor *)bh->b_data; - if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { - if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) - goto out_freebh; - - s->u.isofs_sb.s_high_sierra = 1; - high_sierra = 1; - opt.rock = 'n'; - h_pri = (struct hs_primary_descriptor *)vdp; - goto root_found; - } - + /* Due to the overlapping physical location of the descriptors, + * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure + * proper identification in this case, we first check for ISO. + */ if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) { if (isonum_711 (vdp->type) == ISO_VD_END) break; @@ -580,9 +575,21 @@ } } #endif - /* Just skip any volume descriptors we don't recognize */ + } else { + if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { + if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) + goto out_freebh; + + s->u.isofs_sb.s_high_sierra = 1; + high_sierra = 1; + opt.rock = 'n'; + h_pri = (struct hs_primary_descriptor *)vdp; + goto root_found; + } } + /* Just skip any volume descriptors we don't recognize */ + brelse(bh); bh = NULL; } @@ -1105,8 +1112,9 @@ } /* There are defective discs out there - we do this to protect - ourselves. A cdrom will never contain more than 800Mb */ - if((inode->i_size < 0 || inode->i_size > 800000000) && + ourselves. A cdrom will never contain more than 800Mb + .. but a DVD may be up to 1Gig (Ulrich Habel) */ + if((inode->i_size < 0 || inode->i_size > 1073741824) && inode->i_sb->u.isofs_sb.s_cruft == 'n') { printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n"); inode->i_sb->u.isofs_sb.s_cruft = 'y'; diff -u --recursive --new-file v2.2.0-pre1/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c --- v2.2.0-pre1/linux/fs/lockd/clntproc.c Sun Nov 8 14:03:06 1998 +++ linux/fs/lockd/clntproc.c Tue Dec 29 11:42:25 1998 @@ -125,7 +125,8 @@ /* If we're cleaning up locks because the process is exiting, * perform the RPC call asynchronously. */ - if (cmd == F_SETLK && fl->fl_type == F_UNLCK + if ((cmd == F_SETLK || cmd == F_SETLKW) + && fl->fl_type == F_UNLCK && (current->flags & PF_EXITING)) { sigfillset(¤t->blocked); /* Mask all signals */ recalc_sigpending(current); @@ -144,7 +145,8 @@ if (cmd == F_GETLK) { status = nlmclnt_test(call, fl); - } else if (cmd == F_SETLK && fl->fl_type == F_UNLCK) { + } else if ((cmd == F_SETLK || cmd == F_SETLKW) + && fl->fl_type == F_UNLCK) { status = nlmclnt_unlock(call, fl); } else if (cmd == F_SETLK || cmd == F_SETLKW) { call->a_args.block = (cmd == F_SETLKW)? 1 : 0; diff -u --recursive --new-file v2.2.0-pre1/linux/fs/lockd/host.c linux/fs/lockd/host.c --- v2.2.0-pre1/linux/fs/lockd/host.c Mon Dec 28 15:00:52 1998 +++ linux/fs/lockd/host.c Tue Dec 29 11:42:25 1998 @@ -92,7 +92,7 @@ /* Lock hash table */ down(&nlm_host_sema); - if (time_after(jiffies, next_gc)) + if (time_after_eq(jiffies, next_gc)) nlm_gc_hosts(); for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) { @@ -173,19 +173,22 @@ /* If we've already created an RPC client, check whether * RPC rebind is required */ if ((clnt = host->h_rpcclnt) != NULL) { - if (time_after(jiffies, host->h_nextrebind)) { + if (time_after_eq(jiffies, host->h_nextrebind)) { clnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; dprintk("lockd: next rebind in %ld jiffies\n", host->h_nextrebind - jiffies); } } else { - uid_t saved_euid = current->euid; + uid_t saved_fsuid = current->fsuid; + kernel_cap_t saved_cap = current->cap_effective; /* Create RPC socket as root user so we get a priv port */ - current->euid = 0; + current->fsuid = 0; + cap_raise (current->cap_effective, CAP_NET_BIND_SERVICE); xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); - current->euid = saved_euid; + current->fsuid = saved_fsuid; + current->cap_effective = saved_cap; if (xprt == NULL) goto forgetit; @@ -219,7 +222,7 @@ nlm_rebind_host(struct nlm_host *host) { dprintk("lockd: rebind host %s\n", host->h_name); - if (host->h_rpcclnt && time_after(jiffies, host->h_nextrebind)) { + if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { host->h_rpcclnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; } @@ -298,7 +301,7 @@ q = &nlm_hosts[i]; while ((host = *q) != NULL) { if (host->h_count || host->h_inuse - || time_before_eq(jiffies, host->h_expires)) { + || time_before(jiffies, host->h_expires)) { q = &host->h_next; continue; } diff -u --recursive --new-file v2.2.0-pre1/linux/fs/lockd/svc.c linux/fs/lockd/svc.c --- v2.2.0-pre1/linux/fs/lockd/svc.c Mon Dec 28 15:00:52 1998 +++ linux/fs/lockd/svc.c Tue Dec 29 11:42:25 1998 @@ -136,7 +136,7 @@ */ if (!nlmsvc_grace_period) { timeout = nlmsvc_retry_blocked(); - } else if (time_after(jiffies, nlmsvc_grace_period)) + } else if (time_before(nlmsvc_grace_period, jiffies)) nlmsvc_grace_period = 0; /* diff -u --recursive --new-file v2.2.0-pre1/linux/fs/lockd/svcproc.c linux/fs/lockd/svcproc.c --- v2.2.0-pre1/linux/fs/lockd/svcproc.c Tue Mar 10 10:03:34 1998 +++ linux/fs/lockd/svcproc.c Tue Dec 29 11:42:25 1998 @@ -499,15 +499,22 @@ /* * NLM Server procedures. */ -#define nlmsvc_proc_none NULL -#define nlmsvc_encode_norep NULL -#define nlmsvc_decode_norep NULL -#define nlmsvc_decode_testres NULL -#define nlmsvc_proc_test_res NULL -#define nlmsvc_proc_lock_res NULL -#define nlmsvc_proc_cancel_res NULL -#define nlmsvc_proc_unlock_res NULL -#define nlmsvc_proc_granted_res NULL + +#define nlmsvc_encode_norep nlmsvc_encode_void +#define nlmsvc_decode_norep nlmsvc_decode_void +#define nlmsvc_decode_testres nlmsvc_decode_void +#define nlmsvc_decode_lockres nlmsvc_decode_void +#define nlmsvc_decode_unlockres nlmsvc_decode_void +#define nlmsvc_decode_cancelres nlmsvc_decode_void +#define nlmsvc_decode_grantedres nlmsvc_decode_void + +#define nlmsvc_proc_none nlmsvc_proc_null +#define nlmsvc_proc_test_res nlmsvc_proc_null +#define nlmsvc_proc_lock_res nlmsvc_proc_null +#define nlmsvc_proc_cancel_res nlmsvc_proc_null +#define nlmsvc_proc_unlock_res nlmsvc_proc_null +#define nlmsvc_proc_granted_res nlmsvc_proc_null + struct nlm_void { int dummy; }; #define PROC(name, xargt, xrest, argt, rest) \ @@ -533,10 +540,10 @@ PROC(unlock_msg, unlockargs, norep, args, void), PROC(granted_msg, testargs, norep, args, void), PROC(test_res, testres, norep, res, void), - PROC(lock_res, res, norep, res, void), - PROC(cancel_res, res, norep, res, void), - PROC(unlock_res, res, norep, res, void), - PROC(granted_res, res, norep, res, void), + PROC(lock_res, lockres, norep, res, void), + PROC(cancel_res, cancelres, norep, res, void), + PROC(unlock_res, unlockres, norep, res, void), + PROC(granted_res, grantedres, norep, res, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), diff -u --recursive --new-file v2.2.0-pre1/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c --- v2.2.0-pre1/linux/fs/lockd/svcsubs.c Sun Jul 26 11:57:18 1998 +++ linux/fs/lockd/svcsubs.c Tue Dec 29 11:42:25 1998 @@ -52,6 +52,8 @@ struct nlm_file *file; unsigned int hash; u32 nfserr; + uid_t saved_cr_uid; + struct svc_cred *cred; dprintk("lockd: nlm_file_lookup(%s/%u)\n", kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino); @@ -80,11 +82,19 @@ /* Open the file. Note that this must not sleep for too long, else * we would lock up lockd:-) So no NFS re-exports, folks. + * + * We have to make sure we have the right credential to open + * the file. */ + cred = &rqstp->rq_cred; + saved_cr_uid = cred->cr_uid; + cred->cr_uid = 0; if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) { dprintk("lockd: open failed (nfserr %ld)\n", ntohl(nfserr)); + cred->cr_uid = saved_cr_uid; goto out_free; } + cred->cr_uid = saved_cr_uid; file->f_next = nlm_files[hash]; nlm_files[hash] = file; diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/Makefile linux/fs/nfsd/Makefile --- v2.2.0-pre1/linux/fs/nfsd/Makefile Wed Jun 24 22:54:09 1998 +++ linux/fs/nfsd/Makefile Tue Dec 29 11:42:25 1998 @@ -9,11 +9,8 @@ O_TARGET := nfsd.o O_OBJS := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ - export.o auth.o lockd.o nfscache.o nfsxdr.o - -ifdef CONFIG_PROC_FS - O_OBJS += stats.o -endif + export.o auth.o lockd.o nfscache.o nfsxdr.o \ + stats.o M_OBJS := $(O_TARGET) diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/auth.c linux/fs/nfsd/auth.c --- v2.2.0-pre1/linux/fs/nfsd/auth.c Sun Nov 8 14:03:07 1998 +++ linux/fs/nfsd/auth.c Tue Dec 29 11:42:25 1998 @@ -50,11 +50,10 @@ current->ngroups = i; if ((cred->cr_uid)) { - cap_lower(current->cap_effective, CAP_DAC_OVERRIDE); - cap_lower(current->cap_effective, CAP_DAC_READ_SEARCH); + cap_t(current->cap_effective) &= ~CAP_FS_MASK; } else { - cap_raise(current->cap_effective, CAP_DAC_OVERRIDE); - cap_raise(current->cap_effective, CAP_DAC_READ_SEARCH); + cap_t(current->cap_effective) |= (CAP_FS_MASK & + current->cap_permitted); } rqstp->rq_userset = 1; diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/export.c linux/fs/nfsd/export.c --- v2.2.0-pre1/linux/fs/nfsd/export.c Sun Nov 8 14:03:07 1998 +++ linux/fs/nfsd/export.c Tue Dec 29 11:42:25 1998 @@ -615,6 +615,112 @@ return NULL; } +struct flags { + int flag; + char *name[2]; +} expflags[] = { + { NFSEXP_READONLY, {"ro", "rw"}}, + { NFSEXP_INSECURE_PORT, {"insecure", ""}}, + { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}}, + { NFSEXP_ALLSQUASH, {"all_squash", ""}}, + { NFSEXP_ASYNC, {"async", ""}}, + { NFSEXP_GATHERED_WRITES, {"wdelay", ""}}, + { NFSEXP_UIDMAP, {"uidmap", ""}}, + { NFSEXP_KERBEROS, { "kerberos", ""}}, + { NFSEXP_SUNSECURE, { "sunsecure", ""}}, + { NFSEXP_CROSSMNT, {"crossmnt", ""}}, + { 0, {"", ""}} +}; + +static int +exp_flags(char *buffer, int flag) +{ + int len = 0, first = 0; + struct flags *flg = expflags; + + for (;flg->flag;flg++) { + int state = (flg->flag & flag)?0:1; + if (!flg->flag) + break; + if (*flg->name[state]) { + len += sprintf(buffer + len, "%s%s", + first++?",":"", flg->name[state]); + } + } + return len; +} + +int +exp_procfs_exports(char *buffer, char **start, off_t offset, + int length, int *eof, void *data) +{ + struct svc_clnthash **hp, **head, *tmp; + struct svc_client *clp; + svc_export *exp; + off_t pos = 0; + off_t begin = 0; + int len = 0; + int i,j; + + len += sprintf(buffer, "# Version 1.0\n"); + len += sprintf(buffer+len, "# Path Client(Flags) # IPs\n"); + + for (clp = clients; clp; clp = clp->cl_next) { + for (i = 0; i < NFSCLNT_EXPMAX; i++) { + exp = clp->cl_export[i]; + while (exp) { + int first = 0; + len += sprintf(buffer+len, "%s\t", exp->ex_path); + len += sprintf(buffer+len, "%s", clp->cl_ident); + len += sprintf(buffer+len, "("); + + len += exp_flags(buffer+len, exp->ex_flags); + len += sprintf(buffer+len, ") # "); + for (j = 0; j < clp->cl_naddr; j++) { + struct in_addr addr = clp->cl_addr[j]; + + head = &clnt_hash[CLIENT_HASH(addr.s_addr)]; + for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) { + if (tmp->h_addr.s_addr == addr.s_addr) { + if (first++) len += sprintf(buffer+len, "%s", " "); + if (tmp->h_client != clp) + len += sprintf(buffer+len, "("); + len += sprintf(buffer+len, "%ld.%ld.%ld.%ld", + htonl(addr.s_addr) >> 24 & 0xff, + htonl(addr.s_addr) >> 16 & 0xff, + htonl(addr.s_addr) >> 8 & 0xff, + htonl(addr.s_addr) >> 0 & 0xff); + if (tmp->h_client != clp) + len += sprintf(buffer+len, ")"); + break; + } + } + } + exp = exp->ex_next; + + buffer[len++]='\n'; + + pos=begin+len; + if(pos offset + length) + goto done; + } + } + } + + *eof = 1; + +done: + *start = buffer + (offset - begin); + len -= (offset - begin); + if ( len > length ) + len = length; + return len; +} + /* * Add or modify a client. * Change requests may involve the list of host addresses. The list of diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/nfscache.c linux/fs/nfsd/nfscache.c --- v2.2.0-pre1/linux/fs/nfsd/nfscache.c Mon Apr 7 11:35:31 1997 +++ linux/fs/nfsd/nfscache.c Tue Dec 29 11:42:25 1998 @@ -314,8 +314,8 @@ data->len); return 0; } - memcpy(resp->buf, data->buf, data->len); - resp->buf += ((data->len + 3) >> 2); + memcpy(resp->buf, data->buf, data->len << 2); + resp->buf += data->len; resp->len += data->len; return 1; } diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c --- v2.2.0-pre1/linux/fs/nfsd/nfsctl.c Fri Oct 23 22:01:22 1998 +++ linux/fs/nfsd/nfsctl.c Tue Dec 29 11:42:25 1998 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,24 @@ static int initialized = 0; +#ifdef CONFIG_PROC_FS + +int exp_procfs_exports(char *buffer, char **start, off_t offset, + int length, int *eof, void *data); + +void proc_export_init(void) +{ + struct proc_dir_entry *nfs_export_ent = NULL; + + if (!(nfs_export_ent = create_proc_entry("fs/nfs", S_IFDIR, 0))) + return; + if (!(nfs_export_ent = create_proc_entry("fs/nfs/exports", 0, 0))) + return; + nfs_export_ent->read_proc = exp_procfs_exports; +} + +#endif + /* * Initialize nfsd */ @@ -66,8 +85,10 @@ nfsd_cache_init(); /* RPC reply cache */ nfsd_export_init(); /* Exports table */ nfsd_lockd_init(); /* lockd->nfsd callbacks */ - nfsd_racache_init(); /* Readahead param cache */ nfsd_fh_init(); /* FH table */ +#ifdef CONFIG_PROC_FS + proc_export_init(); +#endif initialized = 1; } @@ -290,6 +311,8 @@ nfsd_cache_shutdown(); nfsd_fh_free(); #ifdef CONFIG_PROC_FS + remove_proc_entry("fs/nfs/exports", NULL); + remove_proc_entry("fs/nfs", NULL); nfsd_stat_shutdown(); #endif nfsd_lockd_shutdown(); diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c --- v2.2.0-pre1/linux/fs/nfsd/nfsfh.c Mon Dec 28 15:00:53 1998 +++ linux/fs/nfsd/nfsfh.c Tue Dec 29 11:42:25 1998 @@ -1093,32 +1093,33 @@ /* * Security: Check that the export is valid for dentry */ + error = 0; if (fh->fh_dev != fh->fh_xdev) { printk("fh_verify: Security: export on other device" " (%d, %d).\n", fh->fh_dev, fh->fh_xdev); - goto out; + error = nfserr_stale; } else if (exp->ex_dentry != dentry) { struct dentry *tdentry = dentry; - int err2 = 0; - error = nfserr_stale; do { tdentry = tdentry->d_parent; - if (exp->ex_dentry == tdentry) { - error = 0; + if (exp->ex_dentry == tdentry) break; - } - if ((err2 = nfsd_permission(exp, tdentry, MAY_READ))) { - error = err2; -#ifdef NFSD_PARANOIA - goto out1; -#else - goto out; -#endif + /* executable only by root and we can't be root */ + if (current->fsuid && + !(tdentry->d_inode->i_uid && + (tdentry->d_inode->i_mode & S_IXUSR)) && + !(tdentry->d_inode->i_gid && + (tdentry->d_inode->i_mode & S_IXGRP)) && + !(tdentry->d_inode->i_mode & S_IXOTH) && + (exp->ex_flags & NFSEXP_ROOTSQUASH)) { + error = nfserr_stale; +dprintk("fh_verify: no root_squashed access.\n"); } } while ((tdentry != tdentry->d_parent)); - if (error) { - printk("fh_verify: Security: %s/%s bad export.\n", + if (exp->ex_dentry != tdentry) { + error = nfserr_stale; + printk("nfsd Security: %s/%s bad export.\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; @@ -1126,14 +1127,14 @@ } /* Finally, check access permissions. */ - error = nfsd_permission(exp, dentry, access); + if (!error) { + error = nfsd_permission(exp, dentry, access); + } #ifdef NFSD_PARANOIA -out1: if (error) printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, access, error); #endif - out: return error; } diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c --- v2.2.0-pre1/linux/fs/nfsd/nfssvc.c Sun Nov 8 14:03:07 1998 +++ linux/fs/nfsd/nfssvc.c Tue Dec 29 15:17:13 1998 @@ -44,6 +44,11 @@ struct timeval nfssvc_boot = { 0, 0 }; static int nfsd_active = 0; +/* + * Maximum number of nfsd processes + */ +#define NFSD_MAXSERVS 128 + int nfsd_svc(unsigned short port, int nrservs) { @@ -52,19 +57,30 @@ dprintk("nfsd: creating service\n"); error = -EINVAL; - if (nrservs < 0) + if (nrservs <= 0) goto out; if (nrservs > NFSD_MAXSERVS) nrservs = NFSD_MAXSERVS; + nfsd_nservers = nrservs; error = -ENOMEM; + nfsd_racache_init(); /* Readahead param cache */ + if (nfsd_nservers == 0) + goto out; + serv = svc_create(&nfsd_program, NFSD_BUFSIZE, NFSSVC_XDRSIZE); - if (serv == NULL) + if (serv == NULL) goto out; - if ((error = svc_makesock(serv, IPPROTO_UDP, port)) < 0 - || (error = svc_makesock(serv, IPPROTO_TCP, port)) < 0) + error = svc_makesock(serv, IPPROTO_UDP, port); + if (error < 0) + goto failure; + +#if 0 /* Don't even pretend that TCP works. It doesn't. */ + error = svc_makesock(serv, IPPROTO_TCP, port); + if (error < 0) goto failure; +#endif while (nrservs--) { error = svc_create_thread(nfsd, serv); @@ -93,6 +109,8 @@ exit_mm(current); current->session = 1; current->pgrp = 1; + /* Let svc_process check client's authentication. */ + rqstp->rq_auth = 1; sprintf(current->comm, "nfsd"); oldumask = current->fs->umask; /* Set umask to 0. */ @@ -127,22 +145,13 @@ * port probes on port 2049 by unauthorized clients. */ rqstp->rq_client = exp_getclient(&rqstp->rq_addr); - if (!rqstp->rq_client) { - printk(KERN_WARNING "nfsd: unauthenticated request " - "from (%08lx:%d)\n", - ntohl(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); - svc_drop(rqstp); - serv->sv_stats->rpcbadclnt++; - } else { - /* Process request with signals blocked. */ - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, ALLOWED_SIGS); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - svc_process(serv, rqstp); - } + /* Process request with signals blocked. */ + spin_lock_irq(¤t->sigmask_lock); + siginitsetinv(¤t->blocked, ALLOWED_SIGS); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + svc_process(serv, rqstp); /* Unlock export hash tables */ exp_unlock(); @@ -166,6 +175,8 @@ printk("nfsd: last server exiting\n"); /* revoke all exports */ nfsd_export_shutdown(); + /* release read-ahead cache */ + nfsd_racache_shutdown(); } /* Destroy the thread */ diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/stats.c linux/fs/nfsd/stats.c --- v2.2.0-pre1/linux/fs/nfsd/stats.c Mon Jan 12 14:39:48 1998 +++ linux/fs/nfsd/stats.c Tue Dec 29 11:42:25 1998 @@ -13,6 +13,7 @@ * Copyright (C) 1995, 1996, 1997 Olaf Kirch */ +#include #include #include #include @@ -26,6 +27,7 @@ struct nfsd_stats nfsdstats; struct svc_stat nfsd_svcstats = { &nfsd_program, }; +#ifdef CONFIG_PROC_FS static int nfsd_proc_read(char *buffer, char **start, off_t offset, int count, int *eof, void *data) @@ -88,3 +90,4 @@ { svc_proc_unregister("nfsd"); } +#endif /* CONFIG_PROC_FS */ diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.2.0-pre1/linux/fs/nfsd/vfs.c Tue Dec 22 14:16:57 1998 +++ linux/fs/nfsd/vfs.c Tue Dec 29 11:42:25 1998 @@ -73,9 +73,10 @@ p_rawin; }; -#define FILECACHE_MAX (2 * NFSD_MAXSERVS) -static struct raparms raparms[FILECACHE_MAX]; -static struct raparms * raparm_cache = 0; +int nfsd_nservers = 0; +#define FILECACHE_MAX (2 * nfsd_nservers) +static struct raparms * raparml = NULL; +static struct raparms * raparm_cache = NULL; /* * Lock a parent directory following the VFS locking protocol. @@ -148,16 +149,18 @@ dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name); /* Obtain dentry and export. */ - err = fh_verify(rqstp, fhp, S_IFDIR, MAY_NOP); + err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC); if (err) goto out; dparent = fhp->fh_dentry; exp = fhp->fh_export; +#if 0 err = nfsd_permission(exp, dparent, MAY_EXEC); if (err) goto out; +#endif err = nfserr_noent; if (fs_off_limits(dparent->d_sb)) goto out; @@ -232,13 +235,17 @@ dentry = fhp->fh_dentry; inode = dentry->d_inode; + err = inode_change_ok(inode, iap); + if (err) + goto out_nfserr; + /* The size case is special... */ if (iap->ia_valid & ATTR_SIZE) { if (!S_ISREG(inode->i_mode)) printk("nfsd_setattr: size change??\n"); if (iap->ia_size < inode->i_size) { err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC); - if (err != 0) + if (err) goto out; } err = get_write_access(inode); @@ -275,9 +282,17 @@ /* Change the attributes. */ if (iap->ia_valid) { + kernel_cap_t saved_cap; + iap->ia_valid |= ATTR_CTIME; iap->ia_ctime = CURRENT_TIME; + if (current->fsuid != 0) { + saved_cap = current->cap_effective; + cap_clear(current->cap_effective); + } err = notify_change(dentry, iap); + if (current->fsuid != 0) + current->cap_effective = saved_cap; if (err) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) @@ -493,6 +508,9 @@ struct inode *inode; mm_segment_t oldfs; int err = 0; +#ifdef CONFIG_QUOTA + uid_t saved_euid; +#endif if (!cnt) goto out; @@ -522,16 +540,31 @@ /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); +#ifdef CONFIG_QUOTA + /* This is for disk quota. */ + saved_euid = current->euid; + current->euid = current->fsuid; err = file.f_op->write(&file, buf, cnt, &file.f_pos); + current->euid = saved_euid; +#else + err = file.f_op->write(&file, buf, cnt, &file.f_pos); +#endif set_fs(oldfs); /* clear setuid/setgid flag after write */ if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) { struct iattr ia; + kernel_cap_t saved_cap; ia.ia_valid = ATTR_MODE; ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID); + if (current->fsuid != 0) { + saved_cap = current->cap_effective; + cap_clear(current->cap_effective); + } notify_change(dentry, &ia); + if (current->fsuid != 0) + current->cap_effective = saved_cap; } fh_unlock(fhp); /* unlock inode */ @@ -661,7 +694,14 @@ break; case S_IFCHR: case S_IFBLK: + /* The client is _NOT_ required to do security enforcement */ + if(!capable(CAP_SYS_ADMIN)) + { + err = -EPERM; + goto out; + } case S_IFIFO: + case S_IFSOCK: opfunc = dirp->i_op->mknod; break; } @@ -719,6 +759,7 @@ struct inode *inode; struct iattr newattrs; int err; + kernel_cap_t saved_cap; err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC); if (err) @@ -736,7 +777,13 @@ DQUOT_INIT(inode); newattrs.ia_size = size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + if (current->fsuid != 0) { + saved_cap = current->cap_effective; + cap_clear(current->cap_effective); + } err = notify_change(dentry, &newattrs); + if (current->fsuid != 0) + current->cap_effective = saved_cap; if (!err) { vmtruncate(inode, size); if (inode->i_op && inode->i_op->truncate) @@ -1235,11 +1282,11 @@ { struct inode *inode = dentry->d_inode; int err; + kernel_cap_t saved_cap; if (acc == MAY_NOP) return 0; - - /* +#if 0 dprintk("nfsd: permission 0x%x%s%s%s%s%s mode 0%o%s%s%s\n", acc, (acc & MAY_READ)? " read" : "", @@ -1253,8 +1300,7 @@ IS_RDONLY(inode)? " ro" : ""); dprintk(" owner %d/%d user %d/%d\n", inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); - */ - +#endif #ifndef CONFIG_NFSD_SUN if (dentry->d_mounts != dentry) { return nfserr_perm; @@ -1284,15 +1330,33 @@ if (inode->i_uid == current->fsuid /* && !(acc & MAY_TRUNC) */) return 0; + if (current->fsuid != 0) { + saved_cap = current->cap_effective; + cap_clear(current->cap_effective); + } + err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); /* Allow read access to binaries even when mode 111 */ - if (err == -EPERM && S_ISREG(inode->i_mode) && acc == MAY_READ) + if (err == -EACCES && S_ISREG(inode->i_mode) && acc == MAY_READ) err = permission(inode, MAY_EXEC); + if (current->fsuid != 0) + current->cap_effective = saved_cap; + return err? nfserrno(-err) : 0; } +void +nfsd_racache_shutdown(void) +{ + if (!raparm_cache) + return; + dprintk("nfsd: freeing %d readahead buffers.\n", FILECACHE_MAX); + kfree(raparml); + nfsd_nservers = 0; + raparm_cache = raparml = NULL; +} /* * Initialize readahead param cache */ @@ -1303,9 +1367,19 @@ if (raparm_cache) return; - memset(raparms, 0, sizeof(raparms)); - for (i = 0; i < FILECACHE_MAX - 1; i++) { - raparms[i].p_next = raparms + i + 1; + raparml = kmalloc(sizeof(struct raparms) * FILECACHE_MAX, GFP_KERNEL); + + if (raparml != NULL) { + dprintk("nfsd: allocating %d readahead buffers.\n", + FILECACHE_MAX); + memset(raparml, 0, sizeof(struct raparms) * FILECACHE_MAX); + for (i = 0; i < FILECACHE_MAX - 1; i++) { + raparml[i].p_next = raparml + i + 1; + } + raparm_cache = raparml; + } else { + printk(KERN_WARNING + "nfsd: Could not allocate memory read-ahead cache.\n"); + nfsd_nservers = 0; } - raparm_cache = raparms; } diff -u --recursive --new-file v2.2.0-pre1/linux/fs/open.c linux/fs/open.c --- v2.2.0-pre1/linux/fs/open.c Mon Dec 28 15:00:53 1998 +++ linux/fs/open.c Tue Dec 29 11:40:35 1998 @@ -523,19 +523,27 @@ newattrs.ia_gid = group; newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; /* - * If the owner has been changed, remove the setuid bit + * If the user or group of a non-directory has been changed by a + * non-root user, remove the setuid bit. + * 19981026 David C Niemi + * */ - if (inode->i_mode & S_ISUID) { + if ((inode->i_mode & S_ISUID) == S_ISUID && + !S_ISDIR(inode->i_mode) + && current->fsuid) + { newattrs.ia_mode &= ~S_ISUID; newattrs.ia_valid |= ATTR_MODE; } /* - * If the group has been changed, remove the setgid bit - * - * Don't remove the setgid bit if no group execute bit. - * This is a file marked for mandatory locking. + * Likewise, if the user or group of a non-directory has been changed + * by a non-root user, remove the setgid bit UNLESS there is no group + * execute bit (this would be a file marked for mandatory locking). + * 19981026 David C Niemi */ - if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) { + if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) + && !S_ISDIR(inode->i_mode) && current->fsuid) + { newattrs.ia_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE; } diff -u --recursive --new-file v2.2.0-pre1/linux/fs/sysv/CHANGES linux/fs/sysv/CHANGES --- v2.2.0-pre1/linux/fs/sysv/CHANGES Tue Dec 22 14:16:57 1998 +++ linux/fs/sysv/CHANGES Tue Dec 29 17:31:48 1998 @@ -38,3 +38,8 @@ Removed dead code - mknod is never asked to create a symlink or directory. Incidentially, it wouldn't do it right if it would be called. + +Sat Dec 26 1998 KGB + * inode.c (detect_sysv4): + Added detection of expanded s_type field (0x10, + 0x20 and 0x30). Forced read-only access in this case. diff -u --recursive --new-file v2.2.0-pre1/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v2.2.0-pre1/linux/fs/sysv/inode.c Thu Sep 17 17:53:38 1998 +++ linux/fs/sysv/inode.c Tue Dec 29 17:31:48 1998 @@ -15,6 +15,7 @@ * * sysv/inode.c * Copyright (C) 1993 Bruno Haible + * Copyright (C) 1997, 1998 Krzysztof G. Baranowski * * This file contains code for allocating/freeing inodes and for read/writing * the superblock. @@ -179,12 +180,25 @@ return NULL; if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */ return NULL; - if (sbd->s_type > 3 || sbd->s_type < 1) + if ((sbd->s_type > 3 || sbd->s_type < 1) && (sbd->s_type > 0x30 || sbd->s_type < 0x10)) return NULL; - detected_bs(sbd->s_type, sb); + + /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, + 0x20 or 0x30 indicates that symbolic links and the 14-character + filename limit is gone. Due to lack of information about this + feature read-only mode seems to be a reasonable approach... -KGB */ + + if (sbd->s_type >= 0x10) { + printk("SysV FS: can't handle long file names on %s, " + "forcing read-only mode.\n", kdevname(sb->s_dev)); + sb->s_flags |= MS_RDONLY; + } + + detected_bs(sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type, sb); sb->sv_type = FSTYPE_SYSV4; return "SystemV"; } + static struct super_block * detected_sysv4 (struct super_block *sb, struct buffer_head *bh) { struct sysv4_super_block * sbd; diff -u --recursive --new-file v2.2.0-pre1/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v2.2.0-pre1/linux/fs/sysv/namei.c Tue Dec 22 14:16:57 1998 +++ linux/fs/sysv/namei.c Tue Dec 29 17:31:48 1998 @@ -9,6 +9,7 @@ * * sysv/namei.c * Copyright (C) 1993 Bruno Haible + * Copyright (C) 1997, 1998 Krzysztof G. Baranowski */ diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/delay.h linux/include/asm-alpha/delay.h --- v2.2.0-pre1/linux/include/asm-alpha/delay.h Fri May 8 23:14:54 1998 +++ linux/include/asm-alpha/delay.h Tue Dec 29 13:56:15 1998 @@ -1,7 +1,7 @@ #ifndef __ALPHA_DELAY_H #define __ALPHA_DELAY_H -extern unsigned long loops_per_sec; +#include /* * Copyright (C) 1993 Linus Torvalds @@ -9,7 +9,8 @@ * Delay routines, using a pre-computed "loops_per_second" value. */ -extern __inline__ void __delay(unsigned long loops) +extern __inline__ void +__delay(unsigned long loops) { __asm__ __volatile__(".align 3\n" "1:\tsubq %0,1,%0\n\t" @@ -24,15 +25,46 @@ * lookup table, really, as the multiplications take much too long with * short delays. This is a "reasonable" implementation, though (and the * first constant multiplications gets optimized away if the delay is - * a constant) + * a constant). + * + * Optimize small constants further by exposing the second multiplication + * to the compiler. In addition, mulq is 2 cycles faster than umulh. */ -extern __inline__ void udelay(unsigned long usecs) + +extern __inline__ void +__udelay(unsigned long usecs, unsigned long lps) { + /* compute (usecs * 2**64 / 10**6) * loops_per_sec / 2**64 */ + usecs *= 0x000010c6f7a0b5edUL; /* 2**64 / 1000000 */ - __asm__("umulh %1,%2,%0" - :"=r" (usecs) - :"r" (usecs),"r" (loops_per_sec)); + __asm__("umulh %1,%2,%0" :"=r" (usecs) :"r" (usecs),"r" (lps)); + __delay(usecs); +} + +extern __inline__ void +__small_const_udelay(unsigned long usecs, unsigned long lps) +{ + /* compute (usecs * 2**32 / 10**6) * loops_per_sec / 2**32 */ + + usecs *= 0x10c6; /* 2^32 / 10^6 */ + usecs *= lps; + usecs >>= 32; __delay(usecs); } + +#ifdef __SMP__ +#define udelay(usecs) \ + (__builtin_constant_p(usecs) && usecs < 0x100000000UL \ + ? __small_const_udelay(usecs, \ + cpu_data[smp_processor_id()].loops_per_sec) \ + : __udelay(usecs, \ + cpu_data[smp_processor_id()].loops_per_sec)) +#else +#define udelay(usecs) \ + (__builtin_constant_p(usecs) && usecs < 0x100000000UL \ + ? __small_const_udelay(usecs, loops_per_sec) \ + : __udelay(usecs, loops_per_sec)) +#endif + #endif /* defined(__ALPHA_DELAY_H) */ diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/init.h linux/include/asm-alpha/init.h --- v2.2.0-pre1/linux/include/asm-alpha/init.h Tue Aug 18 22:02:07 1998 +++ linux/include/asm-alpha/init.h Tue Dec 29 13:56:15 1998 @@ -12,4 +12,6 @@ #define __FINIT .previous #define __INITDATA .section .data.init,"a" +#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES))) + #endif diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h --- v2.2.0-pre1/linux/include/asm-alpha/irq.h Tue Dec 22 14:16:57 1998 +++ linux/include/asm-alpha/irq.h Tue Dec 29 13:56:15 1998 @@ -93,6 +93,7 @@ extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); +struct pt_regs; extern void (*perf_irq)(unsigned long, struct pt_regs *); diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v2.2.0-pre1/linux/include/asm-alpha/pgtable.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/pgtable.h Tue Dec 29 13:56:15 1998 @@ -175,7 +175,7 @@ struct vm_area_struct * flush_vma; } p; unsigned long flush_addr; - /* unsigned long flush_end; */ /* not used by local_flush_tlb_range */ + unsigned long flush_end; }; extern struct ipi_msg_flush_tb_struct ipi_msg_flush_tb; diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h --- v2.2.0-pre1/linux/include/asm-alpha/smp.h Wed Sep 9 14:51:10 1998 +++ linux/include/asm-alpha/smp.h Tue Dec 29 13:56:15 1998 @@ -12,7 +12,8 @@ unsigned long *pgd_cache; unsigned long *pte_cache; unsigned long pgtable_cache_sz; -}; + unsigned long ipi_count; +} __attribute__((aligned(32))); extern struct cpuinfo_alpha cpu_data[NR_CPUS]; @@ -35,9 +36,6 @@ #define smp_processor_id() (current->processor) #define cpu_logical_map(cpu) (cpu) - -/* For the benefit of panic. */ -void smp_message_pass(int target, int msg, unsigned long data, int wait); #endif /* __SMP__ */ diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.2.0-pre1/linux/include/asm-alpha/system.h Tue Dec 22 14:16:57 1998 +++ linux/include/asm-alpha/system.h Tue Dec 29 13:56:15 1998 @@ -244,14 +244,14 @@ __asm__ __volatile__( "1: ldl_l %0,%2\n" - " bis %3,%3,%1\n" + " bis $31,%3,%1\n" " stl_c %1,%2\n" " beq %1,2f\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) - : "r" (val), "m" (*m)); + : "rI" (val), "m" (*m)); return val; } @@ -262,14 +262,14 @@ __asm__ __volatile__( "1: ldq_l %0,%2\n" - " bis %3,%3,%1\n" + " bis $31,%3,%1\n" " stq_c %1,%2\n" " beq %1,2f\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) - : "r" (val), "m" (*m)); + : "rI" (val), "m" (*m)); return val; } diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-alpha/timex.h linux/include/asm-alpha/timex.h --- v2.2.0-pre1/linux/include/asm-alpha/timex.h Fri May 8 23:14:54 1998 +++ linux/include/asm-alpha/timex.h Tue Dec 29 13:56:15 1998 @@ -8,4 +8,23 @@ #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +/* + * Standard way to access the cycle counter. + * Currently only used on SMP for scheduling. + * + * Only the low 32 bits are available as a continuously counting entity. + * But this only means we'll force a reschedule every 8 seconds or so, + * which isn't an evil thing. + */ + +typedef unsigned int cycles_t; +extern cycles_t cacheflush_time; + +static inline cycles_t get_cycles (void) +{ + cycles_t ret; + __asm__ __volatile__ ("rpcc %0" : "=r"(ret)); + return ret; +} + #endif diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h --- v2.2.0-pre1/linux/include/asm-i386/bugs.h Mon Oct 5 13:13:42 1998 +++ linux/include/asm-i386/bugs.h Tue Dec 29 17:20:33 1998 @@ -312,10 +312,50 @@ } } +/* + * Check wether we are able to run this kernel safely with this + * configuration. Various configs imply certain minimum requirements + * of the machine: + * + * - In order to run on a i386, we need to be compiled for i386 + * (for due to lack of "invlpg" and working WP on a i386) + * - In order to run on anything without a TSC, we need to be + * compiled for a i486. + * - In order to work on a Pentium/SMP machine, we need to be + * compiled for a Pentium or lower, as a PPro config implies + * a properly working local APIC without the need to do extra + * reads from the APIC. + */ +__initfunc(static void check_config(void)) +{ + /* Configuring for a i386 will boot on anything */ +#ifndef CONFIG_M386 + /* Configuring for an i486 only implies 'invlpg' and a working WP bit */ + if (boot_cpu_data.x86 == 3) + panic("Kernel requires i486+ for 'invlpg' and other features"); + +#ifndef CONFIG_M486 + /* Configuring for a Pentium implies having a TSC */ + if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC)) + panic("Kernel compiled for Pentium+, requires TSC"); + +#ifndef CONFIG_M586 + /* Configuring for a PPro implies that we have an IO-APIC without the read-before-write bug */ + +#ifdef __SMP__ + if (smp_found_config && boot_cpu_data.x86 <= 5) + panic("Kernel compiled for PPro+, assumes local APIC without read-before-write bug"); +#endif /* __SMP__ */ +#endif /* CONFIG_M586 */ +#endif /* CONFIG_M486 */ +#endif /* CONFIG_M386 */ +} + __initfunc(static void check_bugs(void)) { check_cyrix_cpu(); identify_cpu(&boot_cpu_data); + check_config(); #ifndef __SMP__ printk("CPU: "); print_cpu_info(&boot_cpu_data); diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v2.2.0-pre1/linux/include/asm-i386/pgtable.h Wed Sep 9 14:51:12 1998 +++ linux/include/asm-i386/pgtable.h Tue Dec 29 15:53:00 1998 @@ -218,18 +218,16 @@ * memory. */ #define _PAGE_PRESENT 0x001 -#define _PAGE_PROTNONE 0x002 /* If not present */ -#define _PAGE_RW 0x002 /* If present */ +#define _PAGE_RW 0x002 #define _PAGE_USER 0x004 #define _PAGE_WT 0x008 #define _PAGE_PCD 0x010 #define _PAGE_ACCESSED 0x020 #define _PAGE_DIRTY 0x040 -#define _PAGE_4M 0x080 /* 4 MB page, Pentium+.. */ +#define _PAGE_4M 0x080 /* 4 MB page, Pentium+, if present.. */ #define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */ -#define _PAGE_READABLE (_PAGE_PRESENT) -#define _PAGE_WRITABLE (_PAGE_PRESENT | _PAGE_RW) +#define _PAGE_PROTNONE 0x080 /* If not present */ #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) @@ -340,21 +338,17 @@ extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } - -/* - * These are harder, as writability is two bits, not one.. - */ -extern inline int pte_write(pte_t pte) { return (pte_val(pte) & _PAGE_WRITABLE) == _PAGE_WRITABLE; } -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~((pte_val(pte) & _PAGE_PRESENT) << 1); return pte; } extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } /* @@ -589,9 +583,9 @@ { } -#define SWP_TYPE(entry) (((entry) >> 2) & 0x3f) +#define SWP_TYPE(entry) (((entry) >> 1) & 0x3f) #define SWP_OFFSET(entry) ((entry) >> 8) -#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 8)) +#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) #define module_map vmalloc #define module_unmap vfree diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h --- v2.2.0-pre1/linux/include/asm-i386/smp.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-i386/smp.h Tue Dec 29 14:20:42 1998 @@ -159,6 +159,7 @@ extern unsigned long smp_alloc_memory(unsigned long mem_base); extern unsigned char boot_cpu_id; extern unsigned long cpu_present_map; +extern unsigned long cpu_online_map; extern volatile int cpu_number_map[NR_CPUS]; extern volatile unsigned long smp_invalidate_needed; extern void smp_flush_tlb(void); diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-i386/string.h linux/include/asm-i386/string.h --- v2.2.0-pre1/linux/include/asm-i386/string.h Wed Jun 24 22:54:10 1998 +++ linux/include/asm-i386/string.h Tue Dec 29 11:18:18 1998 @@ -30,20 +30,22 @@ #define __HAVE_ARCH_STRCPY extern inline char * strcpy(char * dest,const char *src) { +int d0, d1, d2; __asm__ __volatile__( "cld\n" "1:\tlodsb\n\t" "stosb\n\t" "testb %%al,%%al\n\t" "jne 1b" - : /* no output */ - :"S" (src),"D" (dest):"si","di","ax","memory"); + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); return dest; } #define __HAVE_ARCH_STRNCPY extern inline char * strncpy(char * dest,const char *src,size_t count) { +int d0, d1, d2, d3; __asm__ __volatile__( "cld\n" "1:\tdecl %2\n\t" @@ -55,14 +57,15 @@ "rep\n\t" "stosb\n" "2:" - : /* no output */ - :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory"); + : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) + :"0" (src),"1" (dest),"2" (count) : "memory"); return dest; } #define __HAVE_ARCH_STRCAT extern inline char * strcat(char * dest,const char * src) { +int d0, d1, d2, d3; __asm__ __volatile__( "cld\n\t" "repne\n\t" @@ -72,20 +75,21 @@ "stosb\n\t" "testb %%al,%%al\n\t" "jne 1b" - : /* no output */ - :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx"); + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); return dest; } #define __HAVE_ARCH_STRNCAT extern inline char * strncat(char * dest,const char * src,size_t count) { +int d0, d1, d2, d3; __asm__ __volatile__( "cld\n\t" "repne\n\t" "scasb\n\t" "decl %1\n\t" - "movl %4,%3\n" + "movl %8,%3\n" "1:\tdecl %3\n\t" "js 2f\n\t" "lodsb\n\t" @@ -94,15 +98,16 @@ "jne 1b\n" "2:\txorl %2,%2\n\t" "stosb" - : /* no output */ - :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) - :"si","di","ax","cx","memory"); + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) + : "memory"); return dest; } #define __HAVE_ARCH_STRCMP extern inline int strcmp(const char * cs,const char * ct) { +int d0, d1; register int __res; __asm__ __volatile__( "cld\n" @@ -116,7 +121,8 @@ "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" - :"=a" (__res):"S" (cs),"D" (ct):"si","di"); + :"=a" (__res), "=&S" (d0), "=&D" (d1) + :"1" (cs),"2" (ct)); return __res; } @@ -124,6 +130,7 @@ extern inline int strncmp(const char * cs,const char * ct,size_t count) { register int __res; +int d0, d1, d2; __asm__ __volatile__( "cld\n" "1:\tdecl %3\n\t" @@ -138,13 +145,15 @@ "3:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "4:" - :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx"); + :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + :"1" (cs),"2" (ct),"3" (count)); return __res; } #define __HAVE_ARCH_STRCHR extern inline char * strchr(const char * s, int c) { +int d0; register char * __res; __asm__ __volatile__( "cld\n\t" @@ -157,13 +166,14 @@ "movl $1,%1\n" "2:\tmovl %1,%0\n\t" "decl %0" - :"=a" (__res):"S" (s),"0" (c):"si"); + :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); return __res; } #define __HAVE_ARCH_STRRCHR extern inline char * strrchr(const char * s, int c) { +int d0, d1; register char * __res; __asm__ __volatile__( "cld\n\t" @@ -174,104 +184,24 @@ "leal -1(%%esi),%0\n" "2:\ttestb %%al,%%al\n\t" "jne 1b" - :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si"); -return __res; -} - -#define __HAVE_ARCH_STRSPN -extern inline size_t strspn(const char * cs, const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "je 1b\n" - "2:\tdecl %0" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); -return __res-cs; -} - -#define __HAVE_ARCH_STRCSPN -extern inline size_t strcspn(const char * cs, const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 1b\n" - "2:\tdecl %0" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); -return __res-cs; -} - -#define __HAVE_ARCH_STRPBRK -extern inline char * strpbrk(const char * cs,const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 1b\n\t" - "decl %0\n\t" - "jmp 3f\n" - "2:\txorl %0,%0\n" - "3:" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); + :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); return __res; } #define __HAVE_ARCH_STRSTR extern inline char * strstr(const char * cs,const char * ct) { +int d0, d1, d2, d3; register char * __res; __asm__ __volatile__( "cld\n\t" \ - "movl %4,%%edi\n\t" + "movl %8,%%edi\n\t" "repne\n\t" "scasb\n\t" "notl %%ecx\n\t" "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ "movl %%ecx,%%edx\n" - "1:\tmovl %4,%%edi\n\t" + "1:\tmovl %8,%%edi\n\t" "movl %%esi,%%eax\n\t" "movl %%edx,%%ecx\n\t" "repe\n\t" @@ -283,14 +213,14 @@ "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "2:" - :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) - :"cx","dx","di","si"); + :"=a" (__res), "=&c" (d0), "=&S" (d1), "=&d" (d2), "=&D" (d3) : "0" (0),"1" (0xffffffff),"2" (cs),"g" (ct)); return __res; } #define __HAVE_ARCH_STRLEN extern inline size_t strlen(const char * s) { +int d0; register int __res; __asm__ __volatile__( "cld\n\t" @@ -298,86 +228,26 @@ "scasb\n\t" "notl %0\n\t" "decl %0" - :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di"); -return __res; -} - -#define __HAVE_ARCH_STRTOK -extern inline char * strtok(char * s,const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "testl %1,%1\n\t" - "jne 1f\n\t" - "testl %0,%0\n\t" - "je 8f\n\t" - "movl %0,%1\n" - "1:\txorl %0,%0\n\t" - "movl $-1,%%ecx\n\t" - "xorl %%eax,%%eax\n\t" - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "je 7f\n\t" /* empty delimiter-string */ - "movl %%ecx,%%edx\n" - "2:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 7f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "je 2b\n\t" - "decl %1\n\t" - "cmpb $0,(%1)\n\t" - "je 7f\n\t" - "movl %1,%0\n" - "3:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 5f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 3b\n\t" - "decl %1\n\t" - "cmpb $0,(%1)\n\t" - "je 5f\n\t" - "movb $0,(%1)\n\t" - "incl %1\n\t" - "jmp 6f\n" - "5:\txorl %1,%1\n" - "6:\tcmpb $0,(%0)\n\t" - "jne 7f\n\t" - "xorl %0,%0\n" - "7:\ttestl %0,%0\n\t" - "jne 8f\n\t" - "movl %0,%1\n" - "8:" - :"=b" (__res),"=S" (___strtok) - :"0" (___strtok),"1" (s),"g" (ct) - :"ax","cx","dx","di","memory"); + :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); return __res; } extern inline void * __memcpy(void * to, const void * from, size_t n) { +int d0, d1, d2; __asm__ __volatile__( "cld\n\t" "rep ; movsl\n\t" - "testb $2,%b1\n\t" + "testb $2,%b4\n\t" "je 1f\n\t" "movsw\n" - "1:\ttestb $1,%b1\n\t" + "1:\ttestb $1,%b4\n\t" "je 2f\n\t" "movsb\n" "2:" - : /* no output */ - :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from) - : "cx","di","si","memory"); + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); return (to); } @@ -431,19 +301,23 @@ return to; } #define COMMON(x) \ -__asm__("cld\n\t" \ +__asm__ __volatile__( \ + "cld\n\t" \ "rep ; movsl" \ x \ - : /* no outputs */ \ - : "c" (n/4),"D" ((long) to),"S" ((long) from) \ - : "cx","di","si","memory"); - + : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ + : "0" (n/4),"1" ((long) to),"2" ((long) from) \ + : "memory"); +{ + int d0, d1, d2; switch (n % 4) { case 0: COMMON(""); return to; case 1: COMMON("\n\tmovsb"); return to; case 2: COMMON("\n\tmovsw"); return to; default: COMMON("\n\tmovsw\n\tmovsb"); return to; } +} + #undef COMMON } @@ -456,25 +330,26 @@ #define __HAVE_ARCH_MEMMOVE extern inline void * memmove(void * dest,const void * src, size_t n) { +int d0, d1, d2; if (destword79 = __le16_to_cpu(id->word79); id->word80 = __le16_to_cpu(id->word80); id->word81 = __le16_to_cpu(id->word81); - id->word82 = __le16_to_cpu(id->word82); + id->command_sets = __le16_to_cpu(id->command_sets); id->word83 = __le16_to_cpu(id->word83); id->word84 = __le16_to_cpu(id->word84); id->word85 = __le16_to_cpu(id->word85); id->word86 = __le16_to_cpu(id->word86); id->word87 = __le16_to_cpu(id->word87); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - for (i=0; i<167; i++) + id->word89 = __le16_to_cpu(id->word89); + id->word90 = __le16_to_cpu(id->word90); + id->word91 = __le16_to_cpu(id->word91); + id->word92 = __le16_to_cpu(id->word92); + id->word93 = __le16_to_cpu(id->word93); + id->word94 = __le16_to_cpu(id->word94); + id->word95 = __le16_to_cpu(id->word95); + id->word96 = __le16_to_cpu(id->word96); + id->word97 = __le16_to_cpu(id->word97); + id->word98 = __le16_to_cpu(id->word98); + id->word99 = __le16_to_cpu(id->word99); + id->word100 = __le16_to_cpu(id->word100); + id->word101 = __le16_to_cpu(id->word101); + id->word102 = __le16_to_cpu(id->word102); + id->word103 = __le16_to_cpu(id->word103); + id->word104 = __le16_to_cpu(id->word104); + id->word105 = __le16_to_cpu(id->word105); + id->word106 = __le16_to_cpu(id->word106); + id->word107 = __le16_to_cpu(id->word107); + id->word108 = __le16_to_cpu(id->word108); + id->word109 = __le16_to_cpu(id->word109); + id->word110 = __le16_to_cpu(id->word110); + id->word111 = __le16_to_cpu(id->word111); + id->word112 = __le16_to_cpu(id->word112); + id->word113 = __le16_to_cpu(id->word113); + id->word114 = __le16_to_cpu(id->word114); + id->word115 = __le16_to_cpu(id->word115); + id->word116 = __le16_to_cpu(id->word116); + id->word117 = __le16_to_cpu(id->word117); + id->word118 = __le16_to_cpu(id->word118); + id->word119 = __le16_to_cpu(id->word119); + id->word120 = __le16_to_cpu(id->word120); + id->word121 = __le16_to_cpu(id->word121); + id->word122 = __le16_to_cpu(id->word122); + id->word123 = __le16_to_cpu(id->word123); + id->word124 = __le16_to_cpu(id->word124); + id->word125 = __le16_to_cpu(id->word125); + id->word126 = __le16_to_cpu(id->word126); + id->word127 = __le16_to_cpu(id->word127); + id->security = __le16_to_cpu(id->security); + for (i=0; i<127; i++) id->reserved[i] = __le16_to_cpu(id->reserved[i]); } } diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h --- v2.2.0-pre1/linux/include/asm-ppc/init.h Fri May 8 23:14:56 1998 +++ linux/include/asm-ppc/init.h Tue Dec 29 10:48:24 1998 @@ -31,6 +31,9 @@ #define __FINIT .previous #define __INITDATA .section ".data.init",#alloc,#write +#define __cacheline_aligned __attribute__ \ + ((__section__ (".data.cacheline_aligned"))) + #else /* not egcs */ #define __init @@ -52,5 +55,7 @@ #define __openfirmware #define __openfirmwaredata #define __openfirmwarefunc(x) x + +#define __cacheline_aligned #endif /* egcs */ #endif diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h --- v2.2.0-pre1/linux/include/asm-ppc/termios.h Mon Oct 5 13:13:43 1998 +++ linux/include/asm-ppc/termios.h Tue Dec 29 11:18:18 1998 @@ -182,6 +182,8 @@ #define N_MASC 8 /* Reserved for Mobitex module */ #define N_R3964 9 /* Reserved for Simatic R3964 module */ #define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ +#define N_IRDA 11 /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */ +#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.2.0-pre1/linux/include/asm-ppc/timex.h linux/include/asm-ppc/timex.h --- v2.2.0-pre1/linux/include/asm-ppc/timex.h Fri May 8 23:14:56 1998 +++ linux/include/asm-ppc/timex.h Tue Dec 29 10:48:24 1998 @@ -12,4 +12,18 @@ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ << (SHIFT_SCALE-SHIFT_HZ)) / HZ) +typedef unsigned long long cycles_t; + +extern cycles_t cacheflush_time; + +static inline cycles_t get_cycles (void) +{ + cycles_t value; + + __asm__("rdtsc" + :"=a" (*(((int *)&value)+0)), + "=d" (*(((int *)&value)+1))); + return value; +} + #endif diff -u --recursive --new-file v2.2.0-pre1/linux/include/linux/arcdevice.h linux/include/linux/arcdevice.h --- v2.2.0-pre1/linux/include/linux/arcdevice.h Sun Jun 7 11:16:39 1998 +++ linux/include/linux/arcdevice.h Tue Dec 29 11:18:18 1998 @@ -192,7 +192,7 @@ -#define JIFFER(time) for (delayval=jiffies+time; jiffiessetuser OK */ - rq_secure : 1; /* secure port */ + rq_secure : 1, /* secure port */ + rq_auth : 1; /* check client */ void * rq_argp; /* decoded arguments */ void * rq_resp; /* xdr'd results */ diff -u --recursive --new-file v2.2.0-pre1/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.2.0-pre1/linux/include/linux/sysctl.h Tue Dec 22 14:16:58 1998 +++ linux/include/linux/sysctl.h Tue Dec 29 11:18:18 1998 @@ -112,7 +112,7 @@ VM_PAGECACHE=7, /* struct: Set cache memory thresholds */ VM_PAGERDAEMON=8, /* struct: Control kswapd behaviour */ VM_PGT_CACHE=9, /* struct: Set page table cache parameters */ - VM_PAGE_CLUSTER=10 /* int: set log2 number of pages to swap together */ + VM_PAGE_CLUSTER=10 /* int: set number of pages to swap together */ }; @@ -376,11 +376,12 @@ /* /proc/sys/net/decnet */ enum { - NET_DECNET_NODE_TYPE=1, - NET_DECNET_NODE_ADDRESS=2, - NET_DECNET_NODE_NAME=3, - NET_DECNET_DEFAULT_DEVICE=4, - NET_DECNET_DEBUG_LEVEL=255 + NET_DECNET_DEF_T3_BROADCAST=1, + NET_DECNET_DEF_T3_POINTTOPOINT=2, + NET_DECNET_DEF_T1=3, + NET_DECNET_DEF_BCT1=4, + NET_DECNET_CACHETIMEOUT=5, + NET_DECNET_DEBUG_LEVEL=6 }; /* CTL_PROC names: */ @@ -397,7 +398,7 @@ FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */ FS_DENTRY=8, FS_NRSUPER=9, /* int:current number of allocated super_blocks */ - FS_MAXSUPER=10 /* int:maximum number of super_blocks that can be allocated */ + FS_MAXSUPER=10 /* int:maximum number of super_blocks that can be allocated */ }; /* CTL_DEBUG names: */ diff -u --recursive --new-file v2.2.0-pre1/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h --- v2.2.0-pre1/linux/include/linux/sysv_fs.h Thu Sep 17 17:53:38 1998 +++ linux/include/linux/sysv_fs.h Tue Dec 29 17:31:48 1998 @@ -98,7 +98,9 @@ char s_fill[371]; s32 s_magic; /* version of file system */ s32 s_type; /* type of file system: 1 for 512 byte blocks - 2 for 1024 byte blocks */ + 2 for 1024 byte blocks + 3 for 2048 byte blocks */ + }; /* Xenix free list block on disk */ diff -u --recursive --new-file v2.2.0-pre1/linux/ipc/shm.c linux/ipc/shm.c --- v2.2.0-pre1/linux/ipc/shm.c Tue Dec 22 14:16:59 1998 +++ linux/ipc/shm.c Tue Dec 29 11:21:49 1998 @@ -624,6 +624,7 @@ unsigned int id, idx; id = SWP_OFFSET(code) & SHM_ID_MASK; +#ifdef DEBUG_SHM if (id != (SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK)) { printk ("shm_swap_in: code id = %d and shmd id = %ld differ\n", id, SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK); @@ -633,12 +634,17 @@ printk ("shm_swap_in: id=%d too big. proc mem corrupted\n", id); return BAD_PAGE; } +#endif shp = shm_segs[id]; + +#ifdef DEBUG_SHM if (shp == IPC_UNUSED || shp == IPC_NOID) { printk ("shm_swap_in: id=%d invalid. Race.\n", id); return BAD_PAGE; } +#endif idx = (SWP_OFFSET(code) >> SHM_IDX_SHIFT) & SHM_IDX_MASK; +#ifdef DEBUG_SHM if (idx != (offset >> PAGE_SHIFT)) { printk ("shm_swap_in: code idx = %u and shmd idx = %lu differ\n", idx, offset >> PAGE_SHIFT); @@ -648,6 +654,7 @@ printk ("shm_swap_in : too large page index. id=%d\n", id); return BAD_PAGE; } +#endif pte = __pte(shp->shm_pages[idx]); if (!pte_present(pte)) { diff -u --recursive --new-file v2.2.0-pre1/linux/kernel/acct.c linux/kernel/acct.c --- v2.2.0-pre1/linux/kernel/acct.c Fri Nov 27 13:09:29 1998 +++ linux/kernel/acct.c Tue Dec 29 17:32:38 1998 @@ -124,12 +124,12 @@ if (acct_active) { if (act < 0) { acct_active = 0; - printk(KERN_INFO "Process accounting paused\r\n"); + printk(KERN_INFO "Process accounting paused\n"); } } else { if (act > 0) { acct_active = 1; - printk(KERN_INFO "Process accounting resumed\r\n"); + printk(KERN_INFO "Process accounting resumed\n"); } } diff -u --recursive --new-file v2.2.0-pre1/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.2.0-pre1/linux/kernel/ksyms.c Mon Dec 28 15:00:53 1998 +++ linux/kernel/ksyms.c Tue Dec 29 13:52:45 1998 @@ -129,6 +129,7 @@ EXPORT_SYMBOL(get_empty_filp); EXPORT_SYMBOL(init_private_file); EXPORT_SYMBOL(fput); +EXPORT_SYMBOL(put_filp); EXPORT_SYMBOL(check_disk_change); EXPORT_SYMBOL(invalidate_buffers); EXPORT_SYMBOL(invalidate_inodes); diff -u --recursive --new-file v2.2.0-pre1/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.2.0-pre1/linux/kernel/sysctl.c Tue Dec 22 14:16:59 1998 +++ linux/kernel/sysctl.c Tue Dec 29 15:31:09 1998 @@ -28,7 +28,7 @@ #include #endif -#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) +#if defined(CONFIG_SYSCTL) /* External variables not in a header file. */ extern int panic_timeout; @@ -36,6 +36,8 @@ extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern char binfmt_java_interpreter[], binfmt_java_appletviewer[]; extern int sysctl_overcommit_memory; +extern int nr_queued_signals, max_queued_signals; + #ifdef CONFIG_KMOD extern char modprobe_path[]; #endif @@ -70,7 +72,9 @@ static ctl_table kern_table[]; static ctl_table vm_table[]; +#ifdef CONFIG_NET extern ctl_table net_table[]; +#endif static ctl_table proc_table[]; static ctl_table fs_table[]; static ctl_table debug_table[]; @@ -123,18 +127,20 @@ extern struct proc_dir_entry proc_sys_root; -extern int inodes_stat[]; -extern int dentry_stat[]; static void register_proc_table(ctl_table *, struct proc_dir_entry *); static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); #endif +extern int inodes_stat[]; +extern int dentry_stat[]; /* The default sysctl tables: */ static ctl_table root_table[] = { {CTL_KERN, "kernel", NULL, 0, 0555, kern_table}, {CTL_VM, "vm", NULL, 0, 0555, vm_table}, +#ifdef CONFIG_NET {CTL_NET, "net", NULL, 0, 0555, net_table}, +#endif {CTL_PROC, "proc", NULL, 0, 0555, proc_table}, {CTL_FS, "fs", NULL, 0, 0555, fs_table}, {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table}, @@ -195,6 +201,10 @@ {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int), 0644, NULL, &proc_dointvec}, #endif + {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int), + 0444, NULL, &proc_dointvec}, + {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int), + 0644, NULL, &proc_dointvec}, {0} }; @@ -868,14 +878,14 @@ #else /* CONFIG_PROC_FS */ -int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) +int proc_dostring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) { - return -ENOSYS; + return -ENOSYS; } -int proc_dostring(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) { return -ENOSYS; } @@ -1055,7 +1065,7 @@ } -#else /* CONFIG_PROC_FS && CONFIG_SYSCTL */ +#else /* CONFIG_SYSCTL */ extern asmlinkage int sys_sysctl(struct __sysctl_args *args) @@ -1111,7 +1121,4 @@ { } -#endif /* CONFIG_PROC_FS && CONFIG_SYSCTL */ - - - +#endif /* CONFIG_SYSCTL */ diff -u --recursive --new-file v2.2.0-pre1/linux/net/Config.in linux/net/Config.in --- v2.2.0-pre1/linux/net/Config.in Thu Sep 17 17:53:39 1998 +++ linux/net/Config.in Tue Dec 29 11:21:49 1998 @@ -54,11 +54,14 @@ bool 'Forwarding between high speed interfaces' CONFIG_NET_HW_FLOWCONTROL bool 'CPU is too slow to handle full bandwidth' CONFIG_CPU_IS_SLOW if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + mainmenu_option next_comment + comment 'QoS and/or fair queueing' bool 'QoS and/or fair queueing' CONFIG_NET_SCHED if [ "$CONFIG_NET_SCHED" = "y" ]; then source net/sched/Config.in fi # bool 'Network code profiler' CONFIG_NET_PROFILE + endmenu fi fi endmenu diff -u --recursive --new-file v2.2.0-pre1/linux/net/core/Makefile linux/net/core/Makefile --- v2.2.0-pre1/linux/net/core/Makefile Sat May 2 14:19:54 1998 +++ linux/net/core/Makefile Tue Dec 29 11:21:49 1998 @@ -12,7 +12,9 @@ O_OBJS := sock.o skbuff.o iovec.o datagram.o scm.o ifeq ($(CONFIG_SYSCTL),y) +ifeq ($(CONFIG_NET),y) O_OBJS += sysctl_net_core.o +endif endif ifdef CONFIG_FILTER diff -u --recursive --new-file v2.2.0-pre1/linux/net/core/firewall.c linux/net/core/firewall.c --- v2.2.0-pre1/linux/net/core/firewall.c Mon Feb 23 18:12:12 1998 +++ linux/net/core/firewall.c Tue Dec 29 11:21:49 1998 @@ -10,6 +10,7 @@ #include #include #include +#include #include struct semaphore firewall_sem = MUTEX; @@ -89,6 +90,7 @@ struct firewall_ops *f=fw->next; *nl = f; up(&firewall_sem); + synchronize_bh(); return 0; } nl=&((*nl)->next); diff -u --recursive --new-file v2.2.0-pre1/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c --- v2.2.0-pre1/linux/net/ipv4/devinet.c Sat Sep 5 16:46:42 1998 +++ linux/net/ipv4/devinet.c Tue Dec 29 17:33:35 1998 @@ -208,9 +208,16 @@ { struct in_ifaddr *ifa1, **ifap, **last_primary; - if (ifa->ifa_local == 0) { - inet_free_ifa(ifa); - return 0; + /* Allow 0.0.0.0, but it must be the only address to avoid + multiple matches. */ + if (in_dev->ifa_list) { + if (ifa->ifa_local == 0) { + inet_free_ifa(ifa); + return 0; + } + + if (in_dev->ifa_list->ifa_local == 0) + inet_del_ifa(in_dev, &in_dev->ifa_list, 1); } ifa->ifa_flags &= ~IFA_F_SECONDARY; @@ -1001,18 +1008,12 @@ __initfunc(int inet_add_bootp_addr(struct device *dev)) { - struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa; - if (!in_dev && !(in_dev = inetdev_init(dev))) - return -ENOBUFS; if (!(ifa = inet_alloc_ifa())) return -ENOBUFS; - ifa->ifa_dev = in_dev; - in_dev->ifa_list = ifa; - rtmsg_ifa(RTM_NEWADDR, ifa); - notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); - return 0; + + return inet_set_ifa(dev, ifa); } __initfunc(void inet_del_bootp_addr(struct device *dev)) diff -u --recursive --new-file v2.2.0-pre1/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c --- v2.2.0-pre1/linux/net/ipv4/fib_frontend.c Sat Sep 5 16:46:42 1998 +++ linux/net/ipv4/fib_frontend.c Tue Dec 29 17:33:35 1998 @@ -443,13 +443,13 @@ if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF) fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); - if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) && + if (!(ifa->ifa_flags&IFA_F_SECONDARY) && (prefix != addr || ifa->ifa_prefixlen < 32)) { fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim); /* Add network specific broadcasts, when it takes a sense */ - if (ifa->ifa_prefixlen < 31) { + if (!ZERONET(prefix) && ifa->ifa_prefixlen < 31) { fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim); fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim); } diff -u --recursive --new-file v2.2.0-pre1/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c --- v2.2.0-pre1/linux/net/ipv4/ipconfig.c Sun Nov 8 14:03:14 1998 +++ linux/net/ipv4/ipconfig.c Tue Dec 29 17:33:35 1998 @@ -411,96 +411,6 @@ static struct bootp_pkt *ic_recv_bootp __initdata = NULL; /* Packet being received */ /* - * Dirty tricks for BOOTP packet routing. We replace the standard lookup function - * for the local fib by our version which does fake lookups and returns our private - * fib entries. Ugly, but it seems to be the simplest way to do the job. - */ - -static void *ic_old_local_lookup __initdata = NULL; /* Old local routing table lookup function */ -static struct fib_info *ic_bootp_tx_fib __initdata = NULL; /* Our fake fib entries */ -static struct fib_info *ic_bootp_rx_fib __initdata = NULL; - -__initfunc(static int ic_bootp_route_lookup(struct fib_table *tb, const struct rt_key *key, - struct fib_result *res)) -{ - static u32 ic_brl_zero = 0; - - DBG(("BOOTP: Route lookup: %d:%08x -> %d:%08x: ", key->iif, key->src, key->oif, key->dst)); - res->scope = RT_SCOPE_UNIVERSE; - res->prefix = &ic_brl_zero; - res->prefixlen = 0; - res->nh_sel = 0; - if (key->src == 0 && key->dst == 0xffffffff && key->iif == loopback_dev.ifindex) { /* Packet output */ - DBG(("Output\n")); - res->type = RTN_UNICAST; - res->fi = ic_bootp_tx_fib; - } else if (key->iif && key->iif != loopback_dev.ifindex && key->oif == 0) { /* Packet input */ - DBG(("Input\n")); - res->type = RTN_LOCAL; - res->fi = ic_bootp_rx_fib; - } else if (!key->iif && !key->oif && !key->src) { /* Address check by inet_addr_type() */ - DBG(("Check\n")); - res->type = RTN_UNICAST; - res->fi = ic_bootp_tx_fib; - } else { - DBG(("Drop\n")); - return -EINVAL; - } - return 0; -} - -__initfunc(static int ic_set_bootp_route(struct ic_device *d)) -{ - struct fib_info *f = ic_bootp_tx_fib; - struct fib_nh *n = &f->fib_nh[0]; - - n->nh_dev = d->dev; - n->nh_oif = n->nh_dev->ifindex; - rt_cache_flush(0); - return 0; -} - -__initfunc(static int ic_bootp_route_init(void)) -{ - int size = sizeof(struct fib_info) + sizeof(struct fib_nh); - struct fib_info *rf, *tf; - struct fib_nh *nh; - - if (!(rf = ic_bootp_rx_fib = kmalloc(size, GFP_KERNEL)) || - !(tf = ic_bootp_tx_fib = kmalloc(size, GFP_KERNEL))) - return -1; - - memset(rf, 0, size); - rf->fib_nhs = 1; - nh = &rf->fib_nh[0]; - nh->nh_scope = RT_SCOPE_UNIVERSE; - - memset(tf, 0, size); - rf->fib_nhs = 1; - nh = &rf->fib_nh[0]; - nh->nh_dev = ic_first_dev->dev; - nh->nh_scope = RT_SCOPE_UNIVERSE; - nh->nh_oif = nh->nh_dev->ifindex; - - /* Dirty trick: replace standard routing table lookup by our function */ - ic_old_local_lookup = local_table->tb_lookup; - local_table->tb_lookup = ic_bootp_route_lookup; - - return 0; -} - -__initfunc(static void ic_bootp_route_cleanup(void)) -{ - if (ic_old_local_lookup) - local_table->tb_lookup = ic_old_local_lookup; - if (ic_bootp_rx_fib) - kfree_s(ic_bootp_rx_fib, sizeof(struct fib_info) + sizeof(struct fib_nh)); - if (ic_bootp_tx_fib) - kfree_s(ic_bootp_tx_fib, sizeof(struct fib_info) + sizeof(struct fib_nh)); -} - - -/* * Allocation and freeing of BOOTP packet buffers. */ __initfunc(static int ic_bootp_alloc(void)) @@ -677,10 +587,9 @@ /* Add fake zero addresses to all interfaces */ if (ic_bootp_addrs_add() < 0) return -1; - - /* Initialize BOOTP routing */ - if (ic_bootp_route_init() < 0) - return -1; + + /* Setting the addresses automatically creates appropriate + routes. */ /* Initialize common portion of BOOTP request */ memset(ic_xmit_bootp, 0, sizeof(struct bootp_pkt)); @@ -699,7 +608,6 @@ ic_bootp_xmit_sock->sk->broadcast = 1; ic_bootp_xmit_sock->sk->reuse = 1; ic_bootp_recv_sock->sk->reuse = 1; - ic_set_bootp_route(ic_first_dev); if (ic_udp_bind(ic_bootp_recv_sock, INADDR_ANY, 68) || ic_udp_bind(ic_bootp_xmit_sock, INADDR_ANY, 68) || ic_udp_connect(ic_bootp_xmit_sock, INADDR_BROADCAST, 67)) @@ -718,7 +626,6 @@ ic_udp_close(ic_bootp_recv_sock); ic_bootp_addrs_del(); ic_bootp_free(); - ic_bootp_route_cleanup(); } @@ -735,7 +642,6 @@ memset(b->hw_addr, 0, sizeof(b->hw_addr)); memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); b->secs = htons(jiffies / HZ); - ic_set_bootp_route(d); return ic_udp_send(ic_bootp_xmit_sock, b, sizeof(struct bootp_pkt)); } diff -u --recursive --new-file v2.2.0-pre1/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.2.0-pre1/linux/net/ipv4/route.c Mon Oct 5 13:13:48 1998 +++ linux/net/ipv4/route.c Tue Dec 29 17:33:35 1998 @@ -950,6 +950,10 @@ if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr)) goto martian_destination; + /* Accept anything arriving at 0.0.0.0 */ + if (in_dev->ifa_list && in_dev->ifa_list->ifa_local == 0) + goto local_input; + /* * Now we are ready to route packet. */ diff -u --recursive --new-file v2.2.0-pre1/linux/net/netsyms.c linux/net/netsyms.c --- v2.2.0-pre1/linux/net/netsyms.c Thu Nov 19 09:56:29 1998 +++ linux/net/netsyms.c Tue Dec 29 11:21:49 1998 @@ -11,17 +11,16 @@ #include #include #include -#include -#include -#include -#include #include -#include #include #include #include #include #include +#include +#include +#include +#include #ifdef CONFIG_BRIDGE #include @@ -29,6 +28,7 @@ #ifdef CONFIG_INET #include +#include #include #include #include @@ -38,19 +38,13 @@ #include #include #include +#include #include #include #include extern struct net_proto_family inet_family_ops; -#ifdef CONFIG_DLCI_MODULE -extern int (*dlci_ioctl_hook)(unsigned int, void *); -EXPORT_SYMBOL(dlci_ioctl_hook); -#endif - -#endif - #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include #include @@ -62,6 +56,7 @@ extern int tcp_tw_death_row_slot; #endif +#endif #include @@ -87,6 +82,10 @@ #ifdef CONFIG_ATALK_MODULE #include +#include +#include +#include +#include #endif #ifdef CONFIG_SYSCTL @@ -136,6 +135,9 @@ EXPORT_SYMBOL(sock_no_recvmsg); EXPORT_SYMBOL(sock_rfree); EXPORT_SYMBOL(sock_wfree); +EXPORT_SYMBOL(sock_wmalloc); +EXPORT_SYMBOL(sock_rmalloc); +EXPORT_SYMBOL(sock_rspace); EXPORT_SYMBOL(skb_recv_datagram); EXPORT_SYMBOL(skb_free_datagram); EXPORT_SYMBOL(skb_copy_datagram); @@ -222,6 +224,7 @@ EXPORT_SYMBOL(icmp_send); EXPORT_SYMBOL(ip_options_compile); EXPORT_SYMBOL(arp_send); +EXPORT_SYMBOL(arp_broken_ops); EXPORT_SYMBOL(ip_id_count); EXPORT_SYMBOL(ip_send_check); EXPORT_SYMBOL(ip_fragment); @@ -233,13 +236,16 @@ EXPORT_SYMBOL(inet_dgram_ops); EXPORT_SYMBOL(ip_cmsg_recv); EXPORT_SYMBOL(__release_sock); -EXPORT_SYMBOL(arp_find); -EXPORT_SYMBOL(ip_rcv); -EXPORT_SYMBOL(arp_rcv); /* needed for ip_gre -cw */ EXPORT_SYMBOL(ip_statistics); +#ifdef CONFIG_DLCI_MODULE +extern int (*dlci_ioctl_hook)(unsigned int, void *); +EXPORT_SYMBOL(dlci_ioctl_hook); +#endif + + #ifdef CONFIG_IPV6 EXPORT_SYMBOL(ipv6_addr_type); EXPORT_SYMBOL(icmpv6_send); @@ -273,7 +279,6 @@ EXPORT_SYMBOL(csum_partial_copy_fromiovecend); EXPORT_SYMBOL(net_timer); /* UDP/TCP exported functions for TCPv6 */ -EXPORT_SYMBOL(sock_rspace); EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_connect); EXPORT_SYMBOL(udp_sendmsg); @@ -370,8 +375,17 @@ EXPORT_SYMBOL(rtnl_lock); EXPORT_SYMBOL(rtnl_unlock); -EXPORT_SYMBOL(sock_wmalloc); -EXPORT_SYMBOL(sock_rmalloc); + +/* Used by at least ipip.c. */ +EXPORT_SYMBOL(ipv4_config); +EXPORT_SYMBOL(dev_open); + +EXPORT_SYMBOL(ip_rcv); +EXPORT_SYMBOL(arp_rcv); +EXPORT_SYMBOL(arp_tbl); +EXPORT_SYMBOL(arp_find); + +#endif /* CONFIG_INET */ #if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \ defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \ @@ -395,12 +409,6 @@ EXPORT_SYMBOL(init_trdev); EXPORT_SYMBOL(tr_freedev); #endif - -/* Used by at least ipip.c. */ -EXPORT_SYMBOL(ipv4_config); -EXPORT_SYMBOL(dev_open); - -#endif /* CONFIG_INET */ /* Device callback registration */ EXPORT_SYMBOL(register_netdevice_notifier); @@ -445,10 +453,11 @@ EXPORT_SYMBOL(dev_base); EXPORT_SYMBOL(dev_close); EXPORT_SYMBOL(dev_mc_add); +EXPORT_SYMBOL(dev_mc_delete); +EXPORT_SYMBOL(dev_mc_upload); EXPORT_SYMBOL(n_tty_ioctl); EXPORT_SYMBOL(tty_register_ldisc); EXPORT_SYMBOL(kill_fasync); -EXPORT_SYMBOL(dev_mc_delete); EXPORT_SYMBOL(if_port_text); diff -u --recursive --new-file v2.2.0-pre1/linux/net/sunrpc/auth.c linux/net/sunrpc/auth.c --- v2.2.0-pre1/linux/net/sunrpc/auth.c Mon Dec 28 15:00:53 1998 +++ linux/net/sunrpc/auth.c Tue Dec 29 11:42:25 1998 @@ -117,7 +117,7 @@ printk("RPC: rpcauth_gc_credcache looping!\n"); break; } - if (!cred->cr_count && time_after(jiffies, cred->cr_expire)) { + if (!cred->cr_count && time_before(cred->cr_expire, jiffies)) { *q = cred->cr_next; cred->cr_next = free; free = cred; @@ -160,7 +160,7 @@ nr = RPC_DO_ROOTOVERRIDE(task)? 0 : (current->uid % RPC_CREDCACHE_NR); - if (time_after(jiffies, auth->au_nextgc)) + if (time_before(auth->au_nextgc, jiffies)) rpcauth_gc_credcache(auth); q = &auth->au_credcache[nr]; diff -u --recursive --new-file v2.2.0-pre1/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c --- v2.2.0-pre1/linux/net/sunrpc/sched.c Sun Nov 8 14:03:16 1998 +++ linux/net/sunrpc/sched.c Tue Dec 29 11:42:25 1998 @@ -79,13 +79,16 @@ * improve overall performance. * Everyone else gets appended to the queue to ensure proper FIFO behavior. */ -void +int rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) { if (task->tk_rpcwait) { if (task->tk_rpcwait != queue) + { printk(KERN_WARNING "RPC: doubly enqueued task!\n"); - return; + return -EWOULDBLOCK; + } + return 0; } if (RPC_IS_SWAPPER(task)) rpc_insert_list(&queue->task, task); @@ -95,6 +98,8 @@ dprintk("RPC: %4d added to queue %p \"%s\"\n", task->tk_pid, queue, rpc_qname(queue)); + + return 0; } /* @@ -168,7 +173,13 @@ return; } if (RPC_IS_ASYNC(task)) { - rpc_add_wait_queue(&schedq, task); + int status; + status = rpc_add_wait_queue(&schedq, task); + if (status) + { + printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); + task->tk_status = status; + } wake_up(&rpciod_idle); } else { wake_up(&task->tk_wait); @@ -202,6 +213,7 @@ rpc_action action, rpc_action timer) { unsigned long oldflags; + int status; dprintk("RPC: %4d sleep_on(queue \"%s\" time %ld)\n", task->tk_pid, rpc_qname(q), jiffies); @@ -211,11 +223,20 @@ */ save_flags(oldflags); cli(); - rpc_add_wait_queue(q, task); - task->tk_callback = action; - if (task->tk_timeout) - rpc_add_timer(task, timer); - task->tk_flags &= ~RPC_TASK_RUNNING; + status = rpc_add_wait_queue(q, task); + if (status) + { + printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); + task->tk_status = status; + task->tk_flags |= RPC_TASK_RUNNING; + } + else + { + task->tk_callback = action; + if (task->tk_timeout) + rpc_add_timer(task, timer); + task->tk_flags &= ~RPC_TASK_RUNNING; + } restore_flags(oldflags); return; diff -u --recursive --new-file v2.2.0-pre1/linux/net/sunrpc/svc.c linux/net/sunrpc/svc.c --- v2.2.0-pre1/linux/net/sunrpc/svc.c Fri Dec 19 10:54:10 1997 +++ linux/net/sunrpc/svc.c Tue Dec 29 11:42:25 1998 @@ -244,6 +244,12 @@ argp->buf += 5; argp->len -= 5; + /* Used by nfsd to only allow the NULL procedure for amd. */ + if (rqstp->rq_auth && !rqstp->rq_client && proc) { + auth_stat = rpc_autherr_badcred; + goto err_bad_auth; + } + /* * Decode auth data, and add verifier to reply buffer. * We do this before anything else in order to get a decent diff -u --recursive --new-file v2.2.0-pre1/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c --- v2.2.0-pre1/linux/net/sunrpc/xprt.c Mon Dec 28 15:00:53 1998 +++ linux/net/sunrpc/xprt.c Tue Dec 29 11:42:25 1998 @@ -543,7 +543,7 @@ pkt_cnt++; pkt_len += req->rq_slen + copied; pkt_rtt += jiffies - req->rq_xtime; - if (time_after(jiffies, nextstat)) { + if (time_before(nextstat, jiffies)) { printk("RPC: %lu %ld cwnd\n", jiffies, xprt->cwnd); printk("RPC: %ld %ld %ld %ld stat\n", jiffies, pkt_cnt, pkt_len, pkt_rtt); @@ -936,6 +936,7 @@ struct rpc_timeout *timeo; struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; + int status; /*DEBUG*/int ac_debug=xprt->snd_sent; @@ -993,9 +994,17 @@ * the pending list now: */ start_bh_atomic(); - rpc_add_wait_queue(&xprt->pending, task); - task->tk_callback = NULL; + status = rpc_add_wait_queue(&xprt->pending, task); + if (!status) + task->tk_callback = NULL; end_bh_atomic(); + + if (status) + { + printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status); + task->tk_status = status; + return; + } /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have diff -u --recursive --new-file v2.2.0-pre1/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c --- v2.2.0-pre1/linux/net/wanrouter/wanmain.c Mon Dec 28 15:00:53 1998 +++ linux/net/wanrouter/wanmain.c Tue Dec 29 13:53:43 1998 @@ -87,10 +87,8 @@ * Global Data */ -#ifdef MODULE static char fullname[] = "WAN Router"; static char copyright[] = "(c) 1995-1997 Sangoma Technologies Inc."; -#endif static char modname[] = ROUTER_NAME; /* short module name */ wan_device_t * router_devlist = NULL; /* list of registered devices */ static int devcnt = 0;