diff -Naurp linux-2.4.20-wolk4.4-fullkernel/Documentation/Configure.help linux-2.4.20-wolk4.5-fullkernel/Documentation/Configure.help --- linux-2.4.20-wolk4.4-fullkernel/Documentation/Configure.help 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/Documentation/Configure.help 2003-08-04 21:45:26.000000000 +0200 @@ -7690,6 +7690,32 @@ CONFIG_KMOD replacement for kerneld.) Say Y here and read about configuring it in . +Kernel .config file saved in kernel image +CONFIG_IKCONFIG + This option enables the complete Linux kernel ".config" file + contents, information on compiler used to build the kernel, + kernel running when this kernel was built and kernel version + from Makefile to be saved in kernel. It provides documentation + of which kernel options are used in a running kernel or in an + on-disk kernel. This information can be extracted from the kernel + image file with the script scripts/extract-ikconfig and used as + input to rebuild the current kernel or to build another kernel. + It can also be extracted from a running kernel by reading + /proc/ikconfig/config and /proc/ikconfig/built_with, if enabled. + /proc/ikconfig/config will list the configuration that was used + to build the kernel and /proc/ikconfig/built_with will list + information on the compiler and host machine that was used to + build the kernel. Since the kernel image is zipped, using this + option adds approximately 8 KB to a kernel image file. + This option is not available as a module. If you want a separate + file to save the kernel's .config contents, use 'installkernel' or 'cp' + or a similar tool, or just save it in '/lib/modules/'. + +Enable access to .config through /proc/ikconfig +CONFIG_IKCONFIG_PROC + This option enables access to kernel configuration file and build + information through /proc/ikconfig. + ARP daemon support CONFIG_ARPD Normally, the kernel maintains an internal cache which maps IP @@ -9302,7 +9328,7 @@ SCSI tape drive support for Smart Array CONFIG_CISS_SCSI_TAPE When enabled (Y), this option allows SCSI tape drives and SCSI medium changers (tape robots) to be accessed via a Compaq 5xxx array - controller. (See Documentation/cciss.txt for more details.) + controller. (See for more details.) "SCSI support" and "SCSI tape support" must also be enabled for this option to work. @@ -9310,6 +9336,15 @@ CONFIG_CISS_SCSI_TAPE When this option is disabled (N), the SCSI portion of the driver is not compiled. +Enable monitor thread +CONFIG_CISS_MONITOR_THREAD + Intended for use with multipath configurations (see the md driver). + This option allows a per-adapter monitoring thread to periodically + poll the adapter to detect failure modes in which the processor + is unable to receive interrupts from the adapter, thus enabling + fail-over to an alternate adapter in such situations. See + for more details. + QuickNet Internet LineJack/PhoneJack support CONFIG_PHONE_IXJ Say M if you have a telephony card manufactured by Quicknet diff -Naurp linux-2.4.20-wolk4.4-fullkernel/Documentation/cciss.txt linux-2.4.20-wolk4.5-fullkernel/Documentation/cciss.txt --- linux-2.4.20-wolk4.4-fullkernel/Documentation/cciss.txt 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/Documentation/cciss.txt 2003-07-31 23:50:23.000000000 +0200 @@ -127,3 +127,55 @@ hardware and it is important to prevent access these devices too, as if the array controller were merely a SCSI controller in the same way that we are allowing it to access SCSI tape drives. +Monitor Threads +--------------- + +For multipath configurations (acheived via a higher level driver, such +as the "md" driver) it is important that failure of a controller is detected. +Ordinarily, the driver is entirely interrupt driven. If a failure occurs +in such a way that the processor cannot receive interrupts from an adapter, +the driver will wait forever for i/o's to complete. In a multipath +configuration this is undesirable, as the md driver relies on i/o's being +reported as failed by the low level driver to trigger failing over to an +alternate controller. The monitor threads allow the driver to detect such +situations and report outstanding i/o's as having failed so that recovery +actions such switching to an alternate controller can occur. The monitor +threads periodically sends a trivial "no-operation" command down to +the controllers and expect them to complete within a a reasonable (short) +time period. The firmware on the adapter is designed such that no matter +how busy the adapter is serving i/o, it can respond quickly to a +"no-operation" command. In the event that a deadline elapses before a no +operation command completes, all outstanding commands on that controller +are reported back to the upper layers as having failed, and any new commands +sent to the controller are immediately reported back as failed. + +To enable the monitor threads, the compile time option must be enabled +(via the usual linux kernel configuration) and the monitor thread must +be enabled at runtime as well. A system may have many adapters, but +perhaps only a single pair operating in a multipath configuration. +In this way, it is possible to run monitoring threads only for those +adapters which require it. + +To start a monitoring thread on the first cciss adapter, "cciss0" with +a polling interval of 30 seconds, execute the following command: + + echo "monitor 30" > /proc/driver/cciss/cciss0 + +To change the polling interval, to say, 60 seconds: + + echo "monitor 60" > /proc/driver/cciss/cciss0 + +(Note, the change will not take effect until the previous polling +interval elapses.) + +To disable the monitoring thread, set the polling interval to 0 seconds: + + echo "monitor 0" > /proc/driver/cciss/cciss0 + +(Again, the monitoring thread will not exit until the previous polling +interval elapses.) + +The minimum monitoring period is 10 seconds, and the maximum monitoring +period is 3600 seconds (1 hour). The no-operation command must complete +with 5 seconds of submission in all cases or the controller will be presumed +failed. diff -Naurp linux-2.4.20-wolk4.4-fullkernel/Makefile linux-2.4.20-wolk4.5-fullkernel/Makefile --- linux-2.4.20-wolk4.4-fullkernel/Makefile 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/Makefile 2003-08-04 23:03:47.000000000 +0200 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 20 -EXTRAVERSION = -wolk4.4s +EXTRAVERSION = -wolk4.5s KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -251,6 +251,7 @@ CLEAN_FILES = \ kernel/ksyms.lst include/linux/compile.h \ vmlinux System.map include/linux/config_data.h \ $(TMPPREFIX).tmp* \ + kernel/ikconfig.h \ drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \ drivers/char/conmakehash \ drivers/char/drm/*-mod.c \ @@ -297,6 +298,7 @@ MRPROPER_FILES = \ kdb/gen-kdb_cmds.c \ .hdepend scripts/mkdep scripts/split-include scripts/docproc scripts/bin2c \ $(TOPDIR)/include/linux/modversions.h \ + kernel/ikconfig.h \ kernel.spec # directories removed with 'make mrproper' diff -Naurp linux-2.4.20-wolk4.4-fullkernel/VERSION linux-2.4.20-wolk4.5-fullkernel/VERSION --- linux-2.4.20-wolk4.4-fullkernel/VERSION 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/VERSION 2003-08-04 23:03:51.000000000 +0200 @@ -1 +1 @@ -WOLK v4.4s "Server Edition" FINAL, based on 2.4.20 +WOLK v4.5s "Server Edition" FINAL, based on 2.4.20 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/WOLK-CHANGELOG linux-2.4.20-wolk4.5-fullkernel/WOLK-CHANGELOG --- linux-2.4.20-wolk4.4-fullkernel/WOLK-CHANGELOG 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/WOLK-CHANGELOG 2003-08-04 23:02:45.000000000 +0200 @@ -1,3 +1,32 @@ +Changelog from v4.4s -> v4.5s +----------------------------- +o added: ikconfig support (will be merged soon into 2.4-BK, finally!) +o added: kernel compilattion support for IBM's propolice gcc extension +o added: HP CISS: support for failover in multipath environments using + the md driver. For more informations, please read: + Documentation/cciss.txt: Monitor Threads +o fixed: CAN-2003-0464: A recent change in the RPC code set the reuse + flag on newly-created sockets. Olaf Kirch noticed that his + could allow normal users to bind to UDP ports used for + services such as nfsd. +o fixed: CAN-2003-0187: A vulnerability was reported in Netfilter in the + connection tracking function. On certain versions of the Linux + kernel, a remote user can cause denial of service conditions + on the target system. +o fixed: CAN-2003-0467: A vulnerability was reported in the network + address translation (NAT) implementation in Netfilter. A + remote user may be able to cause the target system to crash. ++ fixed: 3com 3c59x: static compile issue (Mike Bethune) ++ fixed: 3com 3c59x: module license missing (Michael Getsroither) +o fixed: Error out if no I/O elevator is selected and tell the user about +o fixed: AGPGART problem with 4GB RAM +o fixed: slab cache usage (it's broken in 2.4 mainline, too much wastage) +o fixed: irq handling of IO-APIC edge IRQs on UP +o updated: 3ware Driver v1.02.00.036 +o updated: LSI MegaRAID (driver series v1.18j) +o updated: LSI MegaRAID (driver series v2.00.7) + + Changelog from v4.3s -> v4.4s ----------------------------- o added: High Performance Packet Classification (nf-hipac) v0.8 rev2 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/WOLK-README linux-2.4.20-wolk4.5-fullkernel/WOLK-README --- linux-2.4.20-wolk4.4-fullkernel/WOLK-README 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/WOLK-README 2003-08-04 23:02:56.000000000 +0200 @@ -1,4 +1,4 @@ -Kernel - patched - WOLK v4.4s - Base: Linux kernel 2.4.20 +Kernel - patched - WOLK v4.5s - Base: Linux kernel 2.4.20 located at http://sf.net/projects/wolk by Marc-Christian Petersen -------------------------------------------------------------------------- diff -Naurp linux-2.4.20-wolk4.4-fullkernel/arch/all/Config-TWEAKS.in linux-2.4.20-wolk4.5-fullkernel/arch/all/Config-TWEAKS.in --- linux-2.4.20-wolk4.4-fullkernel/arch/all/Config-TWEAKS.in 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/arch/all/Config-TWEAKS.in 2003-08-01 15:35:52.000000000 +0200 @@ -2,7 +2,7 @@ # O(1) Scheduler, Low Latency, Low Latency Elevator, Max Throughput Elevator, Preempt, Memory Pools # mainmenu_option next_comment -comment 'Scheduler, Low Latency, Preempt - Tweaks' +comment 'Scheduler, Low Latency, Preempt, Elevator' # Scheduler int 'Scheduler - Maximum User Real-Time Priority' CONFIG_MAX_USER_RT_PRIO 100 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/arch/i386/kernel/io_apic.c linux-2.4.20-wolk4.5-fullkernel/arch/i386/kernel/io_apic.c --- linux-2.4.20-wolk4.4-fullkernel/arch/i386/kernel/io_apic.c 2003-08-04 23:06:34.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/arch/i386/kernel/io_apic.c 2003-07-31 01:41:58.000000000 +0200 @@ -199,6 +199,25 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } +#ifndef CONFIG_SMP + +void send_IPI_self(int vector) +{ + unsigned int cfg; + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); +} + +#endif /* CONFIG_SMP */ + static void set_ioapic_affinity (unsigned int irq, unsigned long mask) { unsigned long flags; diff -Naurp linux-2.4.20-wolk4.4-fullkernel/arch/i386/kernel/setup.c linux-2.4.20-wolk4.5-fullkernel/arch/i386/kernel/setup.c --- linux-2.4.20-wolk4.4-fullkernel/arch/i386/kernel/setup.c 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/arch/i386/kernel/setup.c 2003-08-01 14:59:00.000000000 +0200 @@ -128,6 +128,7 @@ char ignore_irq13; /* set if exception struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; unsigned long mmu_cr4_features; +EXPORT_SYMBOL(mmu_cr4_features); /* * Bus types .. diff -Naurp linux-2.4.20-wolk4.4-fullkernel/arch/x86_64/kernel/setup.c linux-2.4.20-wolk4.5-fullkernel/arch/x86_64/kernel/setup.c --- linux-2.4.20-wolk4.4-fullkernel/arch/x86_64/kernel/setup.c 2003-05-03 01:55:41.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/arch/x86_64/kernel/setup.c 2003-08-01 14:59:00.000000000 +0200 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ struct cpuinfo_x86 boot_cpu_data = { }; unsigned long mmu_cr4_features; +EXPORT_SYMBOL(mmu_cr4_features); /* For PCI or other memory-mapped resources */ unsigned long pci_mem_start = 0x10000000; diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/block/Config.in linux-2.4.20-wolk4.5-fullkernel/drivers/block/Config.in --- linux-2.4.20-wolk4.4-fullkernel/drivers/block/Config.in 2003-05-03 02:36:59.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/block/Config.in 2003-07-31 23:50:23.000000000 +0200 @@ -36,6 +36,7 @@ fi dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI dep_mbool ' SCSI tape drive support for Smart Array 5xxx' CONFIG_CISS_SCSI_TAPE $CONFIG_BLK_CPQ_CISS_DA $CONFIG_SCSI +dep_mbool ' Enable monitor thread' CONFIG_CISS_MONITOR_THREAD $CONFIG_BLK_CPQ_CISS_DA dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI dep_tristate 'Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)' CONFIG_BLK_DEV_UMEM $CONFIG_PCI $CONFIG_EXPERIMENTAL diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/block/cciss.c linux-2.4.20-wolk4.5-fullkernel/drivers/block/cciss.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/block/cciss.c 2003-08-04 23:06:37.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/block/cciss.c 2003-07-31 23:50:23.000000000 +0200 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,47) /* Embedded module documentation macros - see modules.h */ -MODULE_AUTHOR("Charles M. White III - Hewlett-Packard Company"); +MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.47"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"); MODULE_LICENSE("GPL"); @@ -109,8 +110,19 @@ static struct board_type products[] = { #define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFF /* 64 bit DMA */ +#ifdef CONFIG_CISS_MONITOR_THREAD +static int cciss_monitor(void *ctlr); +static int start_monitor_thread(ctlr_info_t *h, unsigned char *cmd, + unsigned long count, int (*cciss_monitor)(void *), int *rc); +#else +#define cciss_monitor(x) +#define kill_monitor_thead(x) +#endif + static ctlr_info_t *hba[MAX_CTLR]; +static u32 heartbeat_timer = 0; + static struct proc_dir_entry *proc_cciss; static void do_cciss_request(request_queue_t *q); @@ -188,7 +200,11 @@ static int cciss_proc_get_info(char *buf "Current # commands on controller: %d\n" "Max Q depth since init: %d\n" "Max # commands on controller since init: %d\n" - "Max SG entries since init: %d\n\n", + "Max SG entries since init: %d\n" + MONITOR_PERIOD_PATTERN + MONITOR_DEADLINE_PATTERN + MONITOR_STATUS_PATTERN + "\n", h->devname, h->product_name, (unsigned long)h->board_id, @@ -196,7 +212,10 @@ static int cciss_proc_get_info(char *buf (unsigned int)h->intr, h->num_luns, h->Qdepth, h->commands_outstanding, - h->maxQsinceinit, h->max_outstanding, h->maxSG); + h->maxQsinceinit, h->max_outstanding, h->maxSG, + MONITOR_PERIOD_VALUE(h), + MONITOR_DEADLINE_VALUE(h), + CTLR_STATUS(h)); pos += size; len += size; cciss_proc_tape_report(ctlr, buffer, &pos, &len); @@ -231,10 +250,8 @@ cciss_proc_write(struct file *file, cons { unsigned char cmd[80]; int len; -#ifdef CONFIG_CISS_SCSI_TAPE ctlr_info_t *h = (ctlr_info_t *) data; int rc; -#endif if (count > sizeof(cmd)-1) return -EINVAL; @@ -244,6 +261,7 @@ cciss_proc_write(struct file *file, cons len = strlen(cmd); if (cmd[len-1] == '\n') cmd[--len] = '\0'; + # ifdef CONFIG_CISS_SCSI_TAPE if (strcmp("engage scsi", cmd)==0) { rc = cciss_engage_scsi(h->ctlr); @@ -254,6 +272,10 @@ cciss_proc_write(struct file *file, cons /* might be nice to have "disengage" too, but it's not safely possible. (only 1 module use count, lock issues.) */ # endif + + if (START_MONITOR_THREAD(h, cmd, count, cciss_monitor, &rc) == 0) + return rc; + return -EINVAL; } @@ -407,7 +429,7 @@ static int cciss_open(struct inode *inod printk(KERN_DEBUG "cciss_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk); #endif /* CCISS_DEBUG */ - if (ctlr > MAX_CTLR || hba[ctlr] == NULL) + if (ctlr > MAX_CTLR || hba[ctlr] == NULL || !CTLR_IS_ALIVE(hba[ctlr])) return -ENXIO; /* * Root is allowed to open raw volume zero even if its not configured @@ -1107,7 +1129,8 @@ static int sendcmd_withirq(__u8 cmd, size_t size, unsigned int use_unit_num, unsigned int log_unit, - __u8 page_code ) + __u8 page_code, + __u8 cmdtype) { ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; @@ -1131,6 +1154,9 @@ static int sendcmd_withirq(__u8 cmd, } c->Header.Tag.lower = c->busaddr; /* tag is phys addr of cmd */ /* Fill in Request block */ + c->Request.CDB[0] = cmd; + c->Request.Type.Type = cmdtype; + if (cmdtype == TYPE_CMD) { switch (cmd) { case CISS_INQUIRY: /* If the logical unit number is 0 then, this is going @@ -1150,11 +1176,9 @@ static int sendcmd_withirq(__u8 cmd, c->Request.CDB[2] = page_code; } c->Request.CDBLen = 6; - c->Request.Type.Type = TYPE_CMD; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; /* Read */ c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = CISS_INQUIRY; c->Request.CDB[4] = size & 0xFF; break; case CISS_REPORT_LOG: @@ -1163,11 +1187,9 @@ static int sendcmd_withirq(__u8 cmd, So we have nothing to write. */ c->Request.CDBLen = 12; - c->Request.Type.Type = TYPE_CMD; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; /* Read */ c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = CISS_REPORT_LOG; c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */ c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0xFF; @@ -1178,18 +1200,38 @@ static int sendcmd_withirq(__u8 cmd, hba[ctlr]->drv[log_unit].LunID; c->Header.LUN.LogDev.Mode = 1; c->Request.CDBLen = 10; - c->Request.Type.Type = TYPE_CMD; /* It is a command. */ c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; /* Read */ c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = CCISS_READ_CAPACITY; break; default: printk(KERN_WARNING "cciss: Unknown Command 0x%x sent attempted\n", cmd); cmd_free(h, c, 1); return IO_ERROR; - }; + } + } else if (cmdtype == TYPE_MSG) { + switch (cmd) { + case 3: /* No-Op message */ + c->Request.CDBLen = 1; + c->Request.Type.Attribute = ATTR_SIMPLE; + c->Request.Type.Direction = XFER_WRITE; + c->Request.Timeout = 0; + c->Request.CDB[0] = cmd; + break; + default: + printk(KERN_WARNING + "cciss%d: unknown message type %d\n", + ctlr, cmd); + cmd_free(h, c, 1); + return IO_ERROR; + } + } else { + printk(KERN_WARNING + "cciss%d: unknown command type %d\n", ctlr, cmdtype); + cmd_free(h, c, 1); + return IO_ERROR; + } /* Fill in the scatter gather information */ if (size > 0) { @@ -1352,7 +1394,7 @@ static int register_new_disk(int ctlr, i } return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0 ); + sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD); if (return_code == IO_OK) { listlength = be32_to_cpu(*((__u32 *) &ld_buff->LUNListLength[0])); @@ -1451,7 +1493,7 @@ static int register_new_disk(int ctlr, i memset(size_buff, 0, sizeof(ReadCapdata_struct)); return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, sizeof(ReadCapdata_struct), 1, - logvol, 0 ); + logvol, 0, TYPE_CMD); if (return_code == IO_OK) { total_size = (0xff & (unsigned int) size_buff->total_size[0]) << 24; @@ -1482,7 +1524,7 @@ static int register_new_disk(int ctlr, i /* Execute the command to read the disk geometry */ memset(inq_buff, 0, sizeof(InquiryData_struct)); return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, - sizeof(InquiryData_struct), 1, logvol ,0xC1 ); + sizeof(InquiryData_struct), 1, logvol ,0xC1, TYPE_CMD); if (return_code == IO_OK) { if (inq_buff->data_byte[8] == 0xFF) { printk(KERN_WARNING @@ -1590,7 +1632,8 @@ static int cciss_rescan_disk(int ctlr, i } memset(size_buff, 0, sizeof(ReadCapdata_struct)); return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, - sizeof( ReadCapdata_struct), 1, logvol, 0 ); + sizeof( ReadCapdata_struct), 1, logvol, 0, + TYPE_CMD); if (return_code == IO_OK) { total_size = (0xff & (unsigned int)(size_buff->total_size[0])) << 24; @@ -1619,7 +1662,7 @@ static int cciss_rescan_disk(int ctlr, i /* Execute the command to read the disk geometry */ memset(inq_buff, 0, sizeof(InquiryData_struct)); return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, - sizeof(InquiryData_struct), 1, logvol ,0xC1 ); + sizeof(InquiryData_struct), 1, logvol ,0xC1, TYPE_CMD); if (return_code == IO_OK) { if (inq_buff->data_byte[8] == 0xFF) { printk(KERN_WARNING "cciss: reading geometry failed, " @@ -2236,6 +2279,15 @@ next: goto startio; } + /* make sure controller is alive. */ + if (!CTLR_IS_ALIVE(h)) { + printk(KERN_WARNING "cciss%d: I/O quit ", h->ctlr); + blkdev_dequeue_request(creq); + complete_buffers(creq->bh, 0); + end_that_request_last(creq); + return; + } + if (( c = cmd_alloc(h, 1)) == NULL) goto startio; @@ -2341,7 +2393,7 @@ static void do_cciss_intr(int irq, void /* Is this interrupt for us? */ - if (h->access.intr_pending(h) == 0) + if ((h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) return; /* @@ -2833,7 +2885,174 @@ static void free_hba(int i) kfree(hba[i]); hba[i]=NULL; } +#ifdef CONFIG_CISS_MONITOR_THREAD +static void fail_all_cmds(unsigned long ctlr) +{ + /* If we get here, the board is apparently dead. */ + ctlr_info_t *h = hba[ctlr]; + CommandList_struct *c; + unsigned long flags; + + printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); + h->alive = 0; /* the controller apparently died... */ + + spin_lock_irqsave(&io_request_lock, flags); + + pci_disable_device(h->pdev); /* Make sure it is really dead. */ + + /* move everything off the request queue onto the completed queue */ + while( (c = h->reqQ) != NULL ) { + removeQ(&(h->reqQ), c); + h->Qdepth--; + addQ (&(h->cmpQ), c); + } + + /* Now, fail everything on the completed queue with a HW error */ + while( (c = h->cmpQ) != NULL ) { + removeQ(&h->cmpQ, c); + c->err_info->CommandStatus = CMD_HARDWARE_ERR; + if (c->cmd_type == CMD_RWREQ) { + complete_command(h, c, 0); + } else if (c->cmd_type == CMD_IOCTL_PEND) + complete(c->waiting); +# ifdef CONFIG_CISS_SCSI_TAPE + else if (c->cmd_type == CMD_SCSI) + complete_scsi_command(c, 0, 0); +# endif + } + spin_unlock_irqrestore(&io_request_lock, flags); + return; +} +static int cciss_monitor(void *ctlr) +{ + /* If the board fails, we ought to detect that. So we periodically + send down a No-Op message and expect it to complete quickly. If it + doesn't, then we assume the board is dead, and fail all commands. + This is useful mostly in a multipath configuration, so that failover + will happen. */ + + int rc; + ctlr_info_t *h = (ctlr_info_t *) ctlr; + unsigned long flags; + u32 current_timer; + + daemonize(); + exit_files(current); + reparent_to_init(); + + printk("cciss%d: Monitor thread starting.\n", h->ctlr); + + /* only listen to signals if the HA was loaded as a module. */ +#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); + sprintf(current->comm, "ccissmon%d", h->ctlr); + h->monitor_thread = current; + + init_timer(&h->watchdog); + h->watchdog.function = fail_all_cmds; + h->watchdog.data = (unsigned long) h->ctlr; + while (1) { + /* check heartbeat timer */ + current_timer = readl(&h->cfgtable->HeartBeat); + current_timer &= 0x0fffffff; + if (heartbeat_timer == current_timer) { + fail_all_cmds(h->ctlr); + break; + } + else + heartbeat_timer = current_timer; + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(h->monitor_period * HZ); + h->watchdog.expires = jiffies + HZ * h->monitor_deadline; + add_timer(&h->watchdog); + /* send down a trivial command (no op message) to ctlr */ + rc = sendcmd_withirq(3, h->ctlr, NULL, 0, 0, 0, 0, TYPE_MSG); + del_timer(&h->watchdog); + if (!CTLR_IS_ALIVE(h)) + break; + if (signal_pending(current)) { + printk(KERN_WARNING "%s received signal.\n", + current->comm); + break; + } + if (h->monitor_period == 0) /* zero period means exit thread */ + break; + } + printk(KERN_INFO "%s exiting.\n", current->comm); + spin_lock_irqsave(&io_request_lock, flags); + h->monitor_started = 0; + h->monitor_thread = NULL; + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} +static int start_monitor_thread(ctlr_info_t *h, unsigned char *cmd, + unsigned long count, int (*cciss_monitor)(void *), int *rc) +{ + unsigned long flags; + unsigned int new_period, old_period, new_deadline, old_deadline; + + if (strncmp("monitor", cmd, 7) == 0) { + new_period = simple_strtol(cmd + 8, NULL, 10); + spin_lock_irqsave(&io_request_lock, flags); + new_deadline = h->monitor_deadline; + spin_unlock_irqrestore(&io_request_lock, flags); + } else if (strncmp("deadline", cmd, 8) == 0) { + new_deadline = simple_strtol(cmd + 9, NULL, 10); + spin_lock_irqsave(&io_request_lock, flags); + new_period = h->monitor_period; + spin_unlock_irqrestore(&io_request_lock, flags); + } else + return -1; + if (new_period != 0 && new_period < CCISS_MIN_PERIOD) + new_period = CCISS_MIN_PERIOD; + if (new_period > CCISS_MAX_PERIOD) + new_period = CCISS_MAX_PERIOD; + if (new_deadline >= new_period) { + new_deadline = new_period - 5; + printk(KERN_INFO "setting deadline to %d\n", new_deadline); + } + spin_lock_irqsave(&io_request_lock, flags); + if (h->monitor_started != 0) { + old_period = h->monitor_period; + old_deadline = h->monitor_deadline; + h->monitor_period = new_period; + h->monitor_deadline = new_deadline; + spin_unlock_irqrestore(&io_request_lock, flags); + if (new_period == 0) { + printk(KERN_INFO "cciss%d: stopping monitor thread\n", + h->ctlr); + *rc = count; + return 0; + } + if (new_period != old_period) + printk(KERN_INFO "cciss%d: adjusting monitor thread " + "period from %d to %d seconds\n", + h->ctlr, old_period, new_period); + if (new_deadline != old_deadline) + printk(KERN_INFO "cciss%d: adjusting monitor thread " + "deadline from %d to %d seconds\n", + h->ctlr, old_deadline, new_deadline); + *rc = count; + return 0; + } + h->monitor_started = 1; + h->monitor_period = new_period; + h->monitor_deadline = new_deadline; + spin_unlock_irqrestore(&io_request_lock, flags); + kernel_thread(cciss_monitor, h, 0); + *rc = count; + return 0; +} +static void kill_monitor_thread(ctlr_info_t *h) +{ + if (h->monitor_thread) + send_sig(SIGKILL, h->monitor_thread, 1); +} +#else +#define kill_monitor_thread(h) +#endif /* * This is it. Find all the controllers and register them. I really hate * stealing all these major device numbers. @@ -2861,6 +3080,7 @@ static int __init cciss_init_one(struct sprintf(hba[i]->devname, "cciss%d", i); hba[i]->ctlr = i; hba[i]->pdev = pdev; + ASSERT_CTLR_ALIVE(hba[i]); if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops)) { printk(KERN_ERR "cciss: Unable to get major number " @@ -2993,14 +3213,17 @@ static void __devexit cciss_remove_one ( "already be removed \n"); return; } - /* Turn board interrupts off and send the flush cache command */ - /* sendcmd will turn off interrupt, and send the flush... - * To write all data in the battery backed cache to disks */ + kill_monitor_thread(hba[i]); + /* no sense in trying to flush a dead board's cache. */ + if (CTLR_IS_ALIVE(hba[i])) { + /* Turn board interrupts off and flush the cache */ + /* write all data in the battery backed cache to disks */ memset(flush_buf, 0, 4); - return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4,0,0,0, NULL); - if (return_code != IO_OK) { + return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, + 4, 0, 0, 0, NULL); + if (return_code != IO_OK) printk(KERN_WARNING - "Error Flushing cache on controller %d\n", i); + "cciss%d: Error flushing cache\n", i); } free_irq(hba[i]->intr, hba[i]); pci_set_drvdata(pdev, NULL); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/block/cciss.h linux-2.4.20-wolk4.5-fullkernel/drivers/block/cciss.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/block/cciss.h 2003-05-03 03:03:09.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/block/cciss.h 2003-07-31 23:50:23.000000000 +0200 @@ -51,7 +51,7 @@ struct ctlr_info unsigned long io_mem_length; CfgTable_struct *cfgtable; int intr; - + int interrupts_enabled; int max_commands; int commands_outstanding; int max_outstanding; /* Debug */ @@ -91,6 +91,40 @@ struct ctlr_info #ifdef CONFIG_CISS_SCSI_TAPE void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ #endif +#ifdef CONFIG_CISS_MONITOR_THREAD + struct timer_list watchdog; + struct task_struct *monitor_thread; + unsigned int monitor_period; + unsigned int monitor_deadline; + unsigned char alive; + unsigned char monitor_started; +#define CCISS_MIN_PERIOD 10 +#define CCISS_MAX_PERIOD 3600 +#define CTLR_IS_ALIVE(h) (h->alive) +#define ASSERT_CTLR_ALIVE(h) { h->alive = 1; \ + h->monitor_period = 0; \ + h->monitor_started = 0; } +#define MONITOR_STATUS_PATTERN "Status: %s\n" +#define CTLR_STATUS(h) CTLR_IS_ALIVE(h) ? "operational" : "failed" +#define MONITOR_PERIOD_PATTERN "Monitor thread period: %d\n" +#define MONITOR_PERIOD_VALUE(h) (h->monitor_period) +#define MONITOR_DEADLINE_PATTERN "Monitor thread deadline: %d\n" +#define MONITOR_DEADLINE_VALUE(h) (h->monitor_deadline) +#define START_MONITOR_THREAD(h, cmd, count, cciss_monitor, rc) \ + start_monitor_thread(h, cmd, count, cciss_monitor, rc) +#else + +#define MONITOR_PERIOD_PATTERN "%s" +#define MONITOR_PERIOD_VALUE(h) "" +#define MONITOR_DEADLINE_PATTERN "%s" +#define MONITOR_DEADLINE_VALUE(h) "" +#define MONITOR_STATUS_PATTERN "%s\n" +#define CTLR_STATUS(h) "" +#define CTLR_IS_ALIVE(h) (1) +#define ASSERT_CTLR_ALIVE(h) +#define START_MONITOR_THREAD(a,b,c,d,rc) (*rc == 0) + +#endif }; /* Defining the diffent access_menthods */ @@ -139,9 +173,11 @@ static void SA5_intr_mask(ctlr_info_t *h { if (val) { /* Turn interrupts on */ + h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { + h->interrupts_enabled = 0; writel( SA5_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } @@ -155,9 +191,11 @@ static void SA5B_intr_mask(ctlr_info_t * { if (val) { /* Turn interrupts on */ + h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { + h->interrupts_enabled = 0; writel( SA5B_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/block/cpqarray.c linux-2.4.20-wolk4.5-fullkernel/drivers/block/cpqarray.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/block/cpqarray.c 2003-05-03 02:30:57.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/block/cpqarray.c 2003-08-01 18:49:06.000000000 +0200 @@ -41,13 +41,13 @@ #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.25)" -#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,25) +#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.26)" +#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,26) /* Embedded module documentation macros - see modules.h */ /* Original author Chris Frantz - Compaq Computer Corporation */ MODULE_AUTHOR("Compaq Computer Corporation"); -MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers version 2.4.25"); +MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers version 2.4.26"); MODULE_LICENSE("GPL"); #define MAJOR_NR COMPAQ_SMART2_MAJOR @@ -649,9 +649,8 @@ static void free_hba(int i) */ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev) { - ushort vendor_id, device_id, command; - unchar cache_line_size, latency_timer; - unchar irq, revision; + ushort subsystem_vendor_id, subsystem_device_id, command; + unchar irq; unsigned long addr[6]; __u32 board_id; @@ -665,10 +664,13 @@ static int cpqarray_pci_init(ctlr_info_t } c->pci_dev = pdev; - vendor_id = pdev->vendor; - device_id = pdev->device; + subsystem_vendor_id = pdev->subsystem_vendor; + subsystem_device_id = pdev->subsystem_device; irq = pdev->irq; + board_id = (((__u32) (subsystem_device_id) << 16) & 0xffff0000) | + (__u32) (subsystem_vendor_id); + for(i=0; i<6; i++) addr[i] = pci_resource_start(pdev, i); @@ -681,25 +683,6 @@ static int cpqarray_pci_init(ctlr_info_t return -1; } - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer); - - pci_read_config_dword(pdev, 0x2c, &board_id); - -DBGINFO( - printk("vendor_id = %x\n", vendor_id); - printk("device_id = %x\n", device_id); - printk("command = %x\n", command); - for(i=0; i<6; i++) - printk("addr[%d] = %lx\n", i, addr[i]); - printk("revision = %x\n", revision); - printk("irq = %x\n", irq); - printk("cache_line_size = %x\n", cache_line_size); - printk("latency_timer = %x\n", latency_timer); - printk("board_id = %x\n", board_id); -); - c->intr = irq; for(i=0; i<6; i++) { if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) { @@ -1644,9 +1627,10 @@ static int ida_ctlr_big_ioctl(int ctlr, /* Wait for completion */ wait_for_completion(&wait); /* Unmap the DMA */ - for(i=0; ireq.hdr.sg_cnt; i++) { + for (i=0; ireq.hdr.sg_cnt; i++) { pci_unmap_single(h->pci_dev, c->req.sg[i].addr, c->req.sg[i].size, PCI_DMA_BIDIRECTIONAL); + c->req.sg[i].addr = 0; } /* if we are reading data from the hardware copy it back to user */ @@ -1667,31 +1651,26 @@ static int ida_ctlr_big_ioctl(int ctlr, io->rcode = c->req.hdr.rcode; - if(scsi_param) { +ida_alloc_cleanup: + if (scsi_param) { pci_unmap_single(h->pci_dev, c->req.hdr.blk, sizeof(scsi_param_t), PCI_DMA_BIDIRECTIONAL); /* copy the scsi_params back to the user */ - if( copy_to_user(io->scsi_param, scsi_param, + if (error == 0 && + copy_to_user(io->scsi_param, scsi_param, sizeof(scsi_param_t))) { error = -EFAULT; } kfree(scsi_param); } - cmd_free(h, c, 0); - return(error); -ida_alloc_cleanup: - if(scsi_param) { - pci_unmap_single(h->pci_dev, c->req.hdr.blk, - sizeof(scsi_param_t), PCI_DMA_BIDIRECTIONAL); - kfree(scsi_param); - } for (i=0; ipci_dev, c->req.sg[i].addr, - buff_size[sg_used], PCI_DMA_BIDIRECTIONAL); - kfree(buff[sg_used]); - } + if (c->req.sg[i].addr != 0) + pci_unmap_single(h->pci_dev, c->req.sg[i].addr, + buff_size[i], PCI_DMA_BIDIRECTIONAL); + + if (buff[i] != NULL) + kfree(buff[i]); } cmd_free(h, c, 0); return(error); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/char/agp/agp.h linux-2.4.20-wolk4.5-fullkernel/drivers/char/agp/agp.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/char/agp/agp.h 2003-08-04 23:06:30.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/char/agp/agp.h 2003-07-30 16:13:31.000000000 +0200 @@ -202,6 +202,12 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_INTEL_860_0 #define PCI_DEVICE_ID_INTEL_860_0 0x2531 #endif +#ifndef PCI_DEVICE_ID_INTEL_7205_0 +#define PCI_DEVICE_ID_INTEL_7205_0 0x255d +#endif +#ifndef PCI_DEVICE_ID_INTEL_7505_0 +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 +#endif #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0 #define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122 #endif @@ -323,6 +329,10 @@ struct agp_bridge_data { #define INTEL_I860_MCHCFG 0x50 #define INTEL_I860_ERRSTS 0xc8 +/* intel i7505 registers */ +#define INTEL_I7505_MCHCFG 0x50 +#define INTEL_I7505_ERRSTS 0x42 + /* intel i810 registers */ #define I810_GMADDR 0x10 #define I810_MMADDR 0x14 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/char/agp/agpgart_be.c linux-2.4.20-wolk4.5-fullkernel/drivers/char/agp/agpgart_be.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/char/agp/agpgart_be.c 2003-08-04 23:06:30.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/char/agp/agpgart_be.c 2003-07-30 16:21:33.000000000 +0200 @@ -1774,6 +1774,37 @@ static int intel_860_configure(void) } +static int intel_7505_configure(void) +{ + u32 temp; + u16 temp2; + aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* mcgcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_I7505_MCHCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_I7505_MCHCFG, + temp2 | (1 << 9)); + return 0; +} + + static unsigned long intel_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ @@ -2083,6 +2114,38 @@ static int __init intel_860_setup (struc (void) pdev; /* unused */ } +static int __init intel_7505_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_7505_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_VIA @@ -4882,6 +4945,18 @@ static struct { "Intel", "i860", intel_860_setup }, + { PCI_DEVICE_ID_INTEL_7205_0, + PCI_VENDOR_ID_INTEL, + INTEL_I7205, + "Intel", + "i7205", + intel_7505_setup }, + { PCI_DEVICE_ID_INTEL_7505_0, + PCI_VENDOR_ID_INTEL, + INTEL_I7505, + "Intel", + "i7505", + intel_7505_setup }, { 0, PCI_VENDOR_ID_INTEL, INTEL_GENERIC, @@ -5378,7 +5453,11 @@ static int __init agp_find_max (void) { long memory, index, result; - memory = (num_physpages << PAGE_SHIFT) >> 20; +#if PAGE_SHIFT < 20 + memory = num_physpages >> (20 - PAGE_SHIFT); +#else + memory = num_physpages << (PAGE_SHIFT - 20); +#endif index = 1; while ((memory > maxes_table[index].mem) && diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/char/tty_io.c linux-2.4.20-wolk4.5-fullkernel/drivers/char/tty_io.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/char/tty_io.c 2003-08-04 23:06:30.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/char/tty_io.c 2003-08-01 14:57:21.000000000 +0200 @@ -1975,9 +1975,11 @@ static void __do_SAK(void *arg) for_each_task(p) { if ((p->tty == tty) || ((session > 0) && (p->session == session))) { +#ifdef CONFIG_GRKERNSEC_DMESG printk(KERN_NOTICE "SAK: killed process %d" " (%s): p->session==tty->session\n", p->pid, p->comm); +#endif send_sig(SIGKILL, p, 1); continue; } @@ -1988,9 +1990,11 @@ static void __do_SAK(void *arg) filp = fcheck_files(p->files, i); if (filp && (filp->f_op == &tty_fops) && (filp->private_data == tty)) { +#ifdef CONFIG_GRKERNSEC_DMESG printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", p->pid, p->comm, i); +#endif send_sig(SIGKILL, p, 1); break; } diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/net/3c59x.c linux-2.4.20-wolk4.5-fullkernel/drivers/net/3c59x.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/net/3c59x.c 2003-08-04 23:06:38.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/net/3c59x.c 2003-07-31 21:25:18.000000000 +0200 @@ -724,11 +724,6 @@ struct driver_operations vortex_ops = { #if defined(MODULE) || (LINUX_VERSION_CODE >= 0x020400) -#if ! defined(MODULE) /* Must be a 2.4 kernel */ -module_init(init_module); -module_exit(cleanup_module); -#endif - int init_module(void) { printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); @@ -769,6 +764,12 @@ int tc59x_probe(struct net_device *dev) printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return retval; } + +#if ! defined(MODULE) /* Must be a 2.4 kernel */ +module_init(init_module); +module_exit(cleanup_module); +#endif + #endif /* not MODULE */ #if ! defined(CARDBUS) && ! defined(USE_MEM_OPS) diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/net/3c90x.c linux-2.4.20-wolk4.5-fullkernel/drivers/net/3c90x.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/net/3c90x.c 2003-08-04 23:06:30.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/net/3c90x.c 2003-08-03 16:44:46.000000000 +0200 @@ -105,6 +105,7 @@ MODULE_PARM(downpoll, "1-" __MODULE_STRI MODULE_PARM(flowcontrol, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(media_select, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_LICENSE("GPL"); #endif // MODULE && LINUX_VERSION_CODE diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/3w-xxxx.c linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/3w-xxxx.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/3w-xxxx.c 2003-05-03 02:36:58.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/3w-xxxx.c 2003-07-31 21:15:01.000000000 +0200 @@ -165,6 +165,14 @@ Add support for "twe" character device for ioctls. Clean up request_id queueing code. Fix tw_scsi_queue() spinlocks. + 1.02.00.033 - Fix tw_aen_complete() to not queue 'queue empty' AEN's. + Initialize queues correctly when loading with no valid units. + 1.02.00.034 - Fix tw_decode_bits() to handle multiple errors. + Add support for user configurable cmd_per_lun. + Add support for sht->select_queue_depths. + 1.02.00.035 - Improve tw_allocate_memory() memory allocation. + Fix tw_chrdev_ioctl() to sleep correctly. + 1.02.00.036 - Increase character ioctl timeout to 60 seconds. */ #include @@ -232,7 +240,7 @@ static struct file_operations tw_fops = }; /* Globals */ -char *tw_driver_version="1.02.00.032"; +char *tw_driver_version="1.02.00.036"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; static int twe_major = -1; @@ -271,25 +279,24 @@ int tw_aen_complete(TW_Device_Extension printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen); } } - if (aen != 0x0) + if (aen != TW_AEN_QUEUE_EMPTY) { tw_dev->aen_count++; - /* Now queue the code */ - tw_dev->aen_queue[tw_dev->aen_tail] = aen; - if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { - tw_dev->aen_tail = TW_Q_START; - } else { - tw_dev->aen_tail = tw_dev->aen_tail + 1; - } - if (tw_dev->aen_head == tw_dev->aen_tail) { - if (tw_dev->aen_head == TW_Q_LENGTH - 1) { - tw_dev->aen_head = TW_Q_START; + /* Now queue the code */ + tw_dev->aen_queue[tw_dev->aen_tail] = aen; + if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { + tw_dev->aen_tail = TW_Q_START; } else { - tw_dev->aen_head = tw_dev->aen_head + 1; + tw_dev->aen_tail = tw_dev->aen_tail + 1; + } + if (tw_dev->aen_head == tw_dev->aen_tail) { + if (tw_dev->aen_head == TW_Q_LENGTH - 1) { + tw_dev->aen_head = TW_Q_START; + } else { + tw_dev->aen_head = tw_dev->aen_head + 1; + } } - } - if (aen != TW_AEN_QUEUE_EMPTY) { error = tw_aen_read_queue(tw_dev, request_id); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no); @@ -556,34 +563,33 @@ int tw_allocate_memory(TW_Device_Extensi else imax = TW_Q_LENGTH; - for (i=0;itw_pci_dev, size, &dma_handle); - if (cpu_addr == NULL) { - printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); - return 1; - } + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*imax, &dma_handle); + if (cpu_addr == NULL) { + printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); + return 1; + } - if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { - printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); - pci_free_consistent(tw_dev->tw_pci_dev, size, cpu_addr, dma_handle); - return 1; - } + if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { + printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); + pci_free_consistent(tw_dev->tw_pci_dev, size*imax, cpu_addr, dma_handle); + return 1; + } + + memset(cpu_addr, 0, size*imax); + for (i=0;icommand_packet_virtual_address[i] = cpu_addr; - tw_dev->command_packet_physical_address[i] = dma_handle; - memset(tw_dev->command_packet_virtual_address[i], 0, size); + tw_dev->command_packet_physical_address[i] = dma_handle+(i*size); + tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; case 1: - tw_dev->alignment_virtual_address[i] = cpu_addr; - tw_dev->alignment_physical_address[i] = dma_handle; - memset(tw_dev->alignment_virtual_address[i], 0, size); + tw_dev->alignment_physical_address[i] = dma_handle+(i*size); + tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; case 2: - tw_dev->bounce_buffer[i] = cpu_addr; - tw_dev->bounce_buffer_phys[i] = dma_handle; - memset(tw_dev->bounce_buffer[i], 0, size); + tw_dev->bounce_buffer_phys[i] = dma_handle+(i*size); + tw_dev->bounce_buffer[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; default: printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n"); @@ -631,11 +637,11 @@ static int tw_chrdev_ioctl(struct inode int error, request_id; dma_addr_t dma_handle; unsigned short tw_aen_code; - unsigned long before; unsigned long flags; unsigned int data_buffer_length = 0; unsigned long data_buffer_length_adjusted = 0; unsigned long *cpu_addr; + long timeout; TW_New_Ioctl *tw_ioctl; TW_Passthru *passthru; TW_Device_Extension *tw_dev = tw_device_extension_list[MINOR(inode->i_rdev)]; @@ -735,30 +741,30 @@ static int tw_chrdev_ioctl(struct inode tw_post_command_packet(tw_dev, request_id); spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ; + /* Now wait for the command to complete */ - before = jiffies; + tw_wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); - while (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { - /* FIXME: we need to sleep here */ - udelay(10); - if (time_after(jiffies, before + HZ *TW_IOCTL_CHRDEV_TIMEOUT)) { - /* Now we need to reset the board */ + /* Check if we timed out, got a signal, or didn't get + an interrupt */ + if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) { + /* Now we need to reset the board */ + if (timeout == -ERESTARTSYS) { + retval = timeout; + } else { printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd); - spin_lock_irqsave(&tw_dev->tw_lock, flags); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); - tw_dev->posted_request_count--; - if (tw_reset_device_extension(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); - } - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); - if (signal_pending(current)) - retval = -EINTR; - else - retval = -EIO; - goto out2; + retval = -EIO; + } + spin_lock_irqsave(&tw_dev->tw_lock, flags); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; + if (tw_reset_device_extension(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); } + spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + goto out2; } /* Now copy in the command packet response */ @@ -886,30 +892,33 @@ int tw_decode_bits(TW_Device_Extension * else host[0] = '\0'; - switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) { - case TW_STATUS_PCI_PARITY_ERROR: + if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) { printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr); - break; - case TW_STATUS_MICROCONTROLLER_ERROR: - if (tw_dev->reset_print == 0) { - printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); - tw_dev->reset_print = 1; - } - return 1; - case TW_STATUS_PCI_ABORT: + } + + if (status_reg_value & TW_STATUS_PCI_ABORT) { printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host); outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr); pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); - break; - case TW_STATUS_QUEUE_ERROR: + } + + if (status_reg_value & TW_STATUS_QUEUE_ERROR) { printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr); - break; - case TW_STATUS_SBUF_WRITE_ERROR: + } + + if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr); - break; + } + + if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { + if (tw_dev->reset_print == 0) { + printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); + tw_dev->reset_print = 1; + } + return 1; } return 0; @@ -1143,19 +1152,24 @@ int tw_findcards(Scsi_Host_Template *tw_ tw_dev->online = 1; /* Calculate max cmds per lun, and setup queues */ - if (tw_dev->num_units > 0) { - if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { - tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1; - } else { - /* Use SHT cmd_per_lun here */ + if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1; + } else { + /* Check for user configured cmd_per_lun */ +#ifdef CONFIG_3W_XXXX_CMD_PER_LUN + tw_host->cmd_per_lun = CONFIG_3W_XXXX_CMD_PER_LUN; + if (tw_host->cmd_per_lun > TW_MAX_CMDS_PER_LUN) tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->free_wrap = TW_Q_LENGTH - 1; - } +#else + /* Use SHT cmd_per_lun default */ + tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; +#endif + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->free_wrap = TW_Q_LENGTH - 1; } /* Register the card with the kernel SCSI layer */ @@ -1184,6 +1198,8 @@ int tw_findcards(Scsi_Host_Template *tw_ host->max_sectors = TW_MAX_SECTORS; #endif + host->select_queue_depths = tw_select_queue_depths; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) scsi_set_pci_device(host, tw_pci_dev); #endif @@ -1198,6 +1214,10 @@ int tw_findcards(Scsi_Host_Template *tw_ if (host->hostdata) { tw_dev2 = (TW_Device_Extension *)host->hostdata; memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension)); + /* Need to init the sem/wqueue after the copy */ + init_MUTEX(&tw_dev2->ioctl_sem); + init_waitqueue_head(&tw_dev2->ioctl_wqueue); + tw_device_extension_list[tw_device_extension_count] = tw_dev2; numcards++; tw_device_extension_count = numcards; @@ -1254,22 +1274,17 @@ int tw_findcards(Scsi_Host_Template *tw_ /* This function will free up device extension resources */ void tw_free_device_extension(TW_Device_Extension *tw_dev) { - int i; - dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n"); + /* Free command packet and generic buffer memory */ - for (i=0;icommand_packet_virtual_address[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->command_packet_virtual_address[i], tw_dev->command_packet_physical_address[i]); + if (tw_dev->command_packet_physical_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]); - if (tw_dev->alignment_virtual_address[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->alignment_virtual_address[i], tw_dev->alignment_physical_address[i]); + if (tw_dev->alignment_physical_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]); - } - for (i=0;ibounce_buffer[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS, tw_dev->bounce_buffer[i], tw_dev->bounce_buffer_phys[i]); - } + if (tw_dev->bounce_buffer[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS*TW_MAX_BOUNCEBUF, tw_dev->bounce_buffer[0], tw_dev->bounce_buffer_phys[0]); } /* End tw_free_device_extension() */ /* Clean shutdown routine */ @@ -1379,8 +1394,6 @@ int tw_initialize_device_extension(TW_De tw_dev->pending_tail = TW_Q_START; spin_lock_init(&tw_dev->tw_lock); tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - init_waitqueue_head(&tw_dev->ioctl_wqueue); - init_MUTEX(&tw_dev->ioctl_sem); return 0; } /* End tw_initialize_device_extension() */ @@ -1720,6 +1733,7 @@ static void tw_interrupt(int irq, void * } } else { tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + wake_up(&tw_dev->ioctl_wqueue); } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { @@ -3403,6 +3417,31 @@ int tw_scsiop_test_unit_ready_complete(T return 0; } /* End tw_scsiop_test_unit_ready_complete() */ +/* This function will select queue depths for a target */ +void tw_select_queue_depths(struct Scsi_Host *host, Scsi_Device *dev) +{ + Scsi_Device *ptr; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + dprintk(KERN_WARNING "3w-xxxx: tw_select_queue_depths()\n"); + + for (ptr = dev; ptr != NULL; ptr = ptr->next) { + if (ptr->host == host) { + if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + ptr->queue_depth = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; + } else { +#ifdef CONFIG_3W_XXXX_CMD_PER_LUN + ptr->queue_depth = CONFIG_3W_XXXX_CMD_PER_LUN; + if (ptr->queue_depth > TW_MAX_CMDS_PER_LUN) + ptr->queue_depth = TW_MAX_CMDS_PER_LUN; +#else + ptr->queue_depth = TW_MAX_CMDS_PER_LUN; +#endif + } + } + } +} /* End tw_select_queue_depths() */ + /* Set a value in the features table */ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val) diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/3w-xxxx.h linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/3w-xxxx.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/3w-xxxx.h 2003-05-03 03:31:45.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/3w-xxxx.h 2003-07-31 21:15:01.000000000 +0200 @@ -115,10 +115,10 @@ static unsigned char tw_sense_table[][4] {0xd0, 0x0b, 0x00, 0x00}, // Device busy Aborted command {0xd1, 0x0b, 0x00, 0x00}, // Device busy Aborted command {0x37, 0x02, 0x04, 0x00}, // Unit offline Not ready + {0x09, 0x02, 0x04, 0x00}, // Unrecovered disk error Not ready /* Codes for older firmware */ // 3ware Error SCSI Error - {0x09, 0x0b, 0x00, 0x00}, // Unrecovered disk error Aborted command {0x51, 0x0b, 0x00, 0x00} // Unspecified Aborted command }; @@ -238,7 +238,7 @@ static unsigned char tw_sense_table[][4] #define TW_ISR_DONT_COMPLETE 2 #define TW_ISR_DONT_RESULT 3 #define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ -#define TW_IOCTL_CHRDEV_TIMEOUT 25 /* 25 seconds */ +#define TW_IOCTL_CHRDEV_TIMEOUT 60 /* 60 seconds */ #define TW_IOCTL_CHRDEV_FREE -1 /* Macros */ @@ -249,6 +249,30 @@ static unsigned char tw_sense_table[][4] (x & TW_STATUS_MICROCONTROLLER_ERROR)) && \ (x & TW_STATUS_MICROCONTROLLER_READY)) +/* This was taken from 2.5 kernel */ +#define tw_wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + #ifdef TW_DEBUG #define dprintk(msg...) printk(msg) #else @@ -498,6 +522,7 @@ int tw_scsiop_request_sense(TW_Device_Ex int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id); +void tw_select_queue_depths(struct Scsi_Host *host, Scsi_Device *dev); int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val); int tw_setup_irq(TW_Device_Extension *tw_dev); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/Config.in linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/Config.in --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/Config.in 2003-05-03 02:27:41.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/Config.in 2003-07-30 17:22:02.000000000 +0200 @@ -1,6 +1,8 @@ if [ "$CONFIG_SCSI_AIC7XXX_OLD" != "y" ]; then dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then + bool ' Do not use MMAPIO (does not work with PCI-X (64-bit PCI)' \ + CONFIG_SCSI_AIC7XXX_MMAPIO int ' Maximum number of TCQ commands per device' \ CONFIG_AIC7XXX_CMDS_PER_DEVICE 32 int ' Initial bus reset delay in milli-seconds' \ @@ -19,6 +21,8 @@ if [ "$CONFIG_SCSI_AIC7XXX_OLD" != "y" ] fi dep_tristate 'Adaptec AIC79xx support' CONFIG_SCSI_AIC79XX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC79XX" != "n" ]; then + bool ' Do not use MMAPIO (does not work with PCI-X (64-bit PCI)' \ + CONFIG_SCSI_AIC79XX_MMAPIO int ' Maximum number of TCQ commands per device' \ CONFIG_AIC79XX_CMDS_PER_DEVICE 32 int ' Initial bus reset delay in milli-seconds' \ diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/aic79xx_osm.h 2003-07-30 17:22:02.000000000 +0200 @@ -591,9 +591,11 @@ ahd_delay(long usec) /***************************** Low Level I/O **********************************/ +#ifndef CONFIG_SCSI_AIC79XX_MMAPIO #if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) #define MMAPIO #endif +#endif /* CONFIG_SCSI_AIC7XXX_MMAPIO */ static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port); static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/aic7xxx/aic7xxx_osm.h 2003-07-30 17:22:02.000000000 +0200 @@ -596,9 +596,11 @@ ahc_delay(long usec) /***************************** Low Level I/O **********************************/ +#ifndef CONFIG_SCSI_AIC7XXX_MMAPIO #if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) #define MMAPIO #endif +#endif /* CONFIG_SCSI_AIC7XXX_MMAPIO */ static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port); static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid.c linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid.c 2003-08-04 23:06:38.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid.c 2003-08-02 02:19:53.000000000 +0200 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version : v1.18i (June 20, 2003) + * Version : v1.18j (July 7, 2003) * * Description: Linux device driver for LSI Logic MegaRAID controller * @@ -539,6 +539,17 @@ * Prevent memory leak in cases when data transfer from/to application fails * and ioctl is failing. * + * Set the PCI dma_mask to default value of 0xFFFFFFFF when we get a handle to + * it. The previous value of 64-bit might be sticky and would cause the memory + * for mailbox and scatter lists to be allocated beyond 4GB. This was observed + * on an Itenium + * + * Version 1.18j + * Mon Jul 7 14:39:55 EDT 2003 - Atul Mukker + * + * Disable /proc/megaraid/stat file to prevent buffer overflow error during + * read of this file. + * * Add support for ioctls on AMD-64 bit platforms * - Sreenivas Bagalkote * @@ -2974,6 +2985,13 @@ static int mega_findCard (Scsi_Host_Temp pciBus = pdev->bus->number; pciDevFun = pdev->devfn; #endif + + /* + * Set the dma_mask to default value. It might be sticky from previous + * insmod-rmmod sequence + */ + pdev->dma_mask = 0xFFFFFFFF; + did_mem_map_f = 0; did_io_map_f = 0; did_scsi_register_f = 0; @@ -3028,6 +3046,7 @@ static int mega_findCard (Scsi_Host_Temp if( (subsysvid != AMI_SUBSYS_ID) && (subsysvid != DELL_SUBSYS_ID) && (subsysvid != LSI_SUBSYS_ID) && + (subsysvid != INTEL_SUBSYS_ID) && (subsysvid != HP_SUBSYS_ID) ) continue; } @@ -4273,6 +4292,11 @@ static int proc_read_stat (char *page, c proc_printf (megaCfg, "Interrupts Collected = %lu\n", megaCfg->nInterrupts); + proc_printf (megaCfg, "INTERFACE DISABLED\n"); + COPY_BACK; + return count; + +#if 0 // can cause buffer overrun with 40 logical drives and IO information for (i = 0; i < megaCfg->numldrv; i++) { proc_printf (megaCfg, "Logical Drive %d:\n", i); @@ -4288,6 +4312,7 @@ static int proc_read_stat (char *page, c COPY_BACK; return count; +#endif } static int proc_read_status (char *page, char **start, off_t offset, diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid.h linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid.h 2003-08-04 23:06:38.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid.h 2003-08-02 02:19:53.000000000 +0200 @@ -30,7 +30,7 @@ #define M_RD_IOCTL_CMD_NEW 0x81 #define M_RD_DRIVER_IOCTL_INTERFACE 0x82 -#define MEGARAID_VERSION "v1.18i (Release Date: Fri Jun 20 07:39:05 EDT 2003)\n" +#define MEGARAID_VERSION "v1.18j (Release Date: Mon Jul 7 14:39:55 EDT 2003)\n" #define MEGARAID_IOCTL_VERSION 114 @@ -191,6 +191,7 @@ #define AMI_SUBSYS_ID 0x101E #define DELL_SUBSYS_ID 0x1028 #define HP_SUBSYS_ID 0x103C +#define INTEL_SUBSYS_ID 0x8086 #define AMI_SIGNATURE 0x3344 #define AMI_SIGNATURE_471 0xCCCC diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid2.c linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid2.c --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid2.c 2003-05-03 02:30:56.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid2.c 2003-08-02 02:40:22.000000000 +0200 @@ -2,7 +2,7 @@ * * Linux MegaRAID device driver * - * Copyright © 2002 LSI Logic Corporation. + * Copyright (c) 2002 LSI Logic Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -14,7 +14,7 @@ * - speed-ups (list handling fixes, issued_list, optimizations.) * - lots of cleanups. * - * Version : v2.00.5 (Apr 24, 2003) - Atul Mukker + * Version : v2.00.7 (Aug 01, 2003) - Atul Mukker * * Description: Linux device driver for LSI Logic MegaRAID controller * @@ -73,7 +73,9 @@ MODULE_PARM_DESC(max_mbox_busy_wait, "Ma static int hba_count; static adapter_t *hba_soft_state[MAX_CONTROLLERS]; +#ifdef CONFIG_PROC_FS static struct proc_dir_entry *mega_proc_dir_entry; +#endif static struct notifier_block mega_notifier = { .notifier_call = megaraid_reboot_notify @@ -255,6 +257,16 @@ mega_find_card(Scsi_Host_Template *host_ while((pdev = pci_find_device(pci_vendor, pci_device, pdev))) { + // reset flags for all controllers in this class + did_ioremap_f = 0; + did_req_region_f = 0; + did_scsi_reg_f = 0; + got_ipdev_f = 0; + alloc_int_buf_f = 0; + alloc_scb_f = 0; + got_irq_f = 0; + did_setup_mbox_f = 0; + if(pci_enable_device (pdev)) continue; pci_bus = pdev->bus->number; @@ -290,6 +302,7 @@ mega_find_card(Scsi_Host_Template *host_ if( subsysvid && (subsysvid != AMI_SUBSYS_VID) && (subsysvid != DELL_SUBSYS_VID) && (subsysvid != HP_SUBSYS_VID) && + (subsysvid != INTEL_SUBSYS_VID) && (subsysvid != LSI_SUBSYS_VID) ) continue; @@ -381,7 +394,8 @@ mega_find_card(Scsi_Host_Template *host_ adapter->flag = flag; spin_lock_init(&adapter->lock); - host->lock = &adapter->lock; + + adapter->host_lock = &io_request_lock; host->cmd_per_lun = max_cmd_per_lun; host->max_sectors = max_sectors_per_io; @@ -1625,7 +1639,7 @@ issue_scb(adapter_t *adapter, scb_t *scb /* * Increment the pending queue counter */ - atomic_inc(&adapter->pend_cmds); + atomic_inc((atomic_t *)&adapter->pend_cmds); switch (mbox->cmd) { case MEGA_MBOXCMD_LREAD64: @@ -1710,6 +1724,9 @@ issue_scb_block(adapter_t *adapter, u_ch mbox->numstatus = 0xFF; + while((volatile u8)mbox->status == 0xFF) + cpu_relax(); + while( (volatile u8)mbox->poll != 0x77 ) cpu_relax(); @@ -1759,7 +1776,7 @@ megaraid_isr_iomapped(int irq, void *dev unsigned long flags; - spin_lock_irqsave(&adapter->lock, flags); + spin_lock_irqsave(adapter->host_lock, flags); megaraid_iombox_ack_sequence(adapter); @@ -1768,7 +1785,7 @@ megaraid_isr_iomapped(int irq, void *dev mega_runpendq(adapter); } - spin_unlock_irqrestore(&adapter->lock, flags); + spin_unlock_irqrestore(adapter->host_lock, flags); return; } @@ -1805,12 +1822,13 @@ megaraid_iombox_ack_sequence(adapter_t * cpu_relax(); adapter->mbox->numstatus = 0xFF; - status = adapter->mbox->status; + while((status = (volatile u8)adapter->mbox->status) == 0xFF) + cpu_relax(); /* * decrement the pending queue counter */ - atomic_sub(nstatus, &adapter->pend_cmds); + atomic_sub(nstatus, (atomic_t *)&adapter->pend_cmds); memcpy(completed, (void *)adapter->mbox->completed, nstatus); @@ -1840,7 +1858,7 @@ megaraid_isr_memmapped(int irq, void *de unsigned long flags; - spin_lock_irqsave(&adapter->lock, flags); + spin_lock_irqsave(adapter->host_lock, flags); megaraid_memmbox_ack_sequence(adapter); @@ -1849,7 +1867,7 @@ megaraid_isr_memmapped(int irq, void *de mega_runpendq(adapter); } - spin_unlock_irqrestore(&adapter->lock, flags); + spin_unlock_irqrestore(adapter->host_lock, flags); return; } @@ -1884,17 +1902,18 @@ megaraid_memmbox_ack_sequence(adapter_t } WROUTDOOR(adapter, 0x10001234); - while((nstatus = adapter->mbox->numstatus) == 0xFF) { + while((nstatus = (volatile u8)adapter->mbox->numstatus) + == 0xFF) cpu_relax(); - } adapter->mbox->numstatus = 0xFF; - status = adapter->mbox->status; + while((status = (volatile u8)adapter->mbox->status) == 0xFF) + cpu_relax(); /* * decrement the pending queue counter */ - atomic_sub(nstatus, &adapter->pend_cmds); + atomic_sub(nstatus, (atomic_t *)&adapter->pend_cmds); memcpy(completed, (void *)adapter->mbox->completed, nstatus); @@ -2396,7 +2415,9 @@ megaraid_release(struct Scsi_Host *host) adapter_t *adapter; mbox_t *mbox; u_char raw_mbox[16]; +#ifdef CONFIG_PROC_FS char buf[12] = { 0 }; +#endif adapter = (adapter_t *)host->hostdata; mbox = (mbox_t *)raw_mbox; @@ -2598,7 +2619,7 @@ megaraid_abort(Scsi_Cmnd *scp) adapter = (adapter_t *)scp->host->hostdata; - ASSERT( spin_is_locked(&adapter->lock) ); + ASSERT( spin_is_locked(adapter->host_lock) ); printk("megaraid: aborting-%ld cmd=%x \n", scp->serial_number, scp->cmnd[0], scp->channel, scp->target, @@ -2641,8 +2662,7 @@ megaraid_abort(Scsi_Cmnd *scp) * completed by the firmware */ iter = 0; - while( !list_empty(&adapter->pending_list) ) { - + while( atomic_read(&adapter->pend_cmds) > 0 ) { /* * Perform the ack sequence, since interrupts are not * available right now! @@ -2695,7 +2715,7 @@ megaraid_reset(Scsi_Cmnd *cmd) adapter = (adapter_t *)cmd->host->hostdata; - ASSERT( spin_is_locked(&adapter->lock) ); + ASSERT( spin_is_locked(adapter->host_lock) ); printk("megaraid: reset-%ld cmd=%x \n", cmd->serial_number, cmd->cmnd[0], cmd->channel, cmd->target, @@ -2706,7 +2726,7 @@ megaraid_reset(Scsi_Cmnd *cmd) mc.cmd = MEGA_CLUSTER_CMD; mc.opcode = MEGA_RESET_RESERVATIONS; - spin_unlock_irq(&adapter->lock); + spin_unlock_irq(adapter->host_lock); if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) { printk(KERN_WARNING "megaraid: reservation reset failed.\n"); @@ -2714,7 +2734,7 @@ megaraid_reset(Scsi_Cmnd *cmd) else { printk(KERN_INFO "megaraid: reservation reset.\n"); } - spin_lock_irq(&adapter->lock); + spin_lock_irq(adapter->host_lock); #endif /* @@ -2722,8 +2742,7 @@ megaraid_reset(Scsi_Cmnd *cmd) * firmware */ iter = 0; - while( !list_empty(&adapter->pending_list) ) { - + while( atomic_read(&adapter->pend_cmds) > 0 ) { /* * Perform the ack sequence, since interrupts are not * available right now! @@ -3565,6 +3584,7 @@ proc_rdrv(adapter_t *adapter, char *page u32 array_sz; int len = 0; int i; + u8 span8_flag = 1; pdev = adapter->ipdev; @@ -3586,6 +3606,7 @@ proc_rdrv(adapter_t *adapter, char *page memset(&mc, 0, sizeof(megacmd_t)); if( adapter->flag & BOARD_40LD ) { + array_sz = sizeof(disk_array_40ld); rdrv_state = ((mega_inquiry3 *)inquiry)->ldrv_state; @@ -3593,7 +3614,12 @@ proc_rdrv(adapter_t *adapter, char *page num_ldrv = ((mega_inquiry3 *)inquiry)->num_ldrv; } else { - array_sz = sizeof(disk_array_8ld); + /* + * 'array_sz' is either the size of diskarray_span4_t or the + * size of disk_array_span8_t. We use span8_t's size because + * it is bigger of the two. + */ + array_sz = sizeof( diskarray_span8_t ); rdrv_state = ((mraid_ext_inquiry *)inquiry)-> raid_inq.logdrv_info.ldrv_state; @@ -3633,10 +3659,17 @@ proc_rdrv(adapter_t *adapter, char *page } else { + /* + * Try 8-Span "read config" command + */ mc.cmd = NEW_READ_CONFIG_8LD; if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) ) { + /* + * 8-Span command failed; try 4-Span command + */ + span8_flag = 0; mc.cmd = READ_CONFIG_8LD; if( mega_internal_command(adapter, LOCK_INT, &mc, @@ -3663,8 +3696,14 @@ proc_rdrv(adapter_t *adapter, char *page &((disk_array_40ld *)disk_array)->ldrv[i].lparam; } else { - lparam = - &((disk_array_8ld *)disk_array)->ldrv[i].lparam; + if( span8_flag ) { + lparam = (logdrv_param*) &((diskarray_span8_t*) + (disk_array))->log_drv[i]; + } + else { + lparam = (logdrv_param*) &((diskarray_span4_t*) + (disk_array))->log_drv[i]; + } } /* @@ -4706,7 +4745,7 @@ mega_is_bios_enabled(adapter_t *adapter) mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(mbox)); + memset(mbox, 0, 16); memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE); @@ -4739,7 +4778,7 @@ mega_enum_raid_scsi(adapter_t *adapter) mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(mbox)); + memset(mbox, 0, 16); /* * issue command to find out what channels are raid/scsi @@ -4860,7 +4899,7 @@ mega_support_random_del(adapter_t *adapt mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof(mbox)); + memset(mbox, 0, 16); /* * issue command @@ -4889,7 +4928,7 @@ mega_support_ext_cdb(adapter_t *adapter) mbox = (mbox_t *)raw_mbox; - memset(mbox, 0, sizeof (mbox)); + memset(mbox, 0, 16); /* * issue command to find out if controller supports extended CDBs. */ @@ -4918,7 +4957,7 @@ mega_del_logdrv(adapter_t *adapter, int scb_t *scb; int rval; - ASSERT( !spin_is_locked(&adapter->lock) ); + ASSERT( !spin_is_locked(adapter->host_lock) ); /* * Stop sending commands to the controller, queue them internally. @@ -4938,7 +4977,7 @@ mega_del_logdrv(adapter_t *adapter, int rval = mega_do_del_logdrv(adapter, logdrv); - spin_lock_irqsave(&adapter->lock, flags); + spin_lock_irqsave(adapter->host_lock, flags); /* * If delete operation was successful, add 0x80 to the logical drive @@ -4957,7 +4996,7 @@ mega_del_logdrv(adapter_t *adapter, int mega_runpendq(adapter); - spin_unlock_irqrestore(&adapter->lock, flags); + spin_unlock_irqrestore(adapter->host_lock, flags); return rval; } @@ -5319,6 +5358,7 @@ mega_swap_hosts (struct Scsi_Host *shone +#ifdef CONFIG_PROC_FS /** * mega_adapinq() * @adapter - pointer to our soft state @@ -5441,6 +5481,7 @@ mega_internal_dev_inquiry(adapter_t *ada return rval; } +#endif // #ifdef CONFIG_PROC_FS /** @@ -5505,11 +5546,11 @@ mega_internal_command(adapter_t *adapter /* * Get the lock only if the caller has not acquired it already */ - if( ls == LOCK_INT ) spin_lock_irqsave(&adapter->lock, flags); + if( ls == LOCK_INT ) spin_lock_irqsave(adapter->host_lock, flags); megaraid_queue(scmd, mega_internal_done); - if( ls == LOCK_INT ) spin_unlock_irqrestore(&adapter->lock, flags); + if( ls == LOCK_INT ) spin_unlock_irqrestore(adapter->host_lock, flags); /* * Wait till this command finishes. Do not use diff -Naurp linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid2.h linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid2.h --- linux-2.4.20-wolk4.4-fullkernel/drivers/scsi/megaraid2.h 2003-05-03 03:31:34.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/drivers/scsi/megaraid2.h 2003-08-02 02:35:04.000000000 +0200 @@ -6,7 +6,7 @@ #define MEGARAID_VERSION \ - "v2.00.5 (Release Date: Thu Apr 24 14:06:55 EDT 2003)\n" + "v2.00.7 (Release Date: Fri Aug 1 11:01:11 EDT 2003)\n" /* * Driver features - change the values to enable or disable features in the @@ -83,6 +83,7 @@ #define DELL_SUBSYS_VID 0x1028 #define HP_SUBSYS_VID 0x103C #define LSI_SUBSYS_VID 0x1000 +#define INTEL_SUBSYS_VID 0x8086 #define HBA_SIGNATURE 0x3344 #define HBA_SIGNATURE_471 0xCCCC @@ -509,6 +510,70 @@ typedef struct { phys_drv pdrv[MAX_PHYSICAL_DRIVES]; }__attribute__ ((packed)) disk_array_8ld; +/* + * FW Definitions & Data Structures for 8LD 4-Span and 8-Span Controllers + */ +#define MAX_STRIPES 8 +#define SPAN4_DEPTH 4 +#define SPAN8_DEPTH 8 +#define MAX_PHYDRVS 5 * 16 /* 5 Channels * 16 Targets */ + +typedef struct { + unsigned char channel; + unsigned char target; +}__attribute__ ((packed)) device_t; + +typedef struct { + unsigned long start_blk; + unsigned long total_blks; + device_t device[ MAX_STRIPES ]; +}__attribute__ ((packed)) span_t; + +typedef struct { + unsigned char type; + unsigned char curr_status; + unsigned char tag_depth; + unsigned char resvd1; + unsigned long size; +}__attribute__ ((packed)) phydrv_t; + +typedef struct { + unsigned char span_depth; + unsigned char raid; + unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ + unsigned char stripe_sz; + unsigned char status; + unsigned char write_policy; /* 0=wrthru,1=wrbak */ + unsigned char direct_io; /* 1=directio,0=cached */ + unsigned char no_stripes; + span_t span[ SPAN4_DEPTH ]; +}__attribute__ ((packed)) ld_span4_t; + +typedef struct { + unsigned char span_depth; + unsigned char raid; + unsigned char read_ahead; /* 0=No rdahead,1=RDAHEAD,2=adaptive */ + unsigned char stripe_sz; + unsigned char status; + unsigned char write_policy; /* 0=wrthru,1=wrbak */ + unsigned char direct_io; /* 1=directio,0=cached */ + unsigned char no_stripes; + span_t span[ SPAN8_DEPTH ]; +}__attribute__ ((packed)) ld_span8_t; + +typedef struct { + unsigned char no_log_drives; + unsigned char pad[3]; + ld_span4_t log_drv[ MAX_LOGICAL_DRIVES_8LD ]; + phydrv_t phys_drv[ MAX_PHYDRVS ]; +}__attribute__ ((packed)) diskarray_span4_t; + +typedef struct { + unsigned char no_log_drives; + unsigned char pad[3]; + ld_span8_t log_drv[ MAX_LOGICAL_DRIVES_8LD ]; + phydrv_t phys_drv[ MAX_PHYDRVS ]; +}__attribute__ ((packed)) diskarray_span8_t; /* * User ioctl structure. @@ -847,8 +912,8 @@ typedef struct { u8 max_cmds; scb_t *scb_list; - atomic_t pend_cmds; /* maintain a counter for pending - commands in firmware */ + volatile atomic_t pend_cmds; /* maintain a counter for + pending commands in firmware */ #if MEGA_HAVE_STATS u32 nreads[MAX_LOGICAL_DRIVES_40LD]; @@ -899,6 +964,7 @@ typedef struct { sending requests to the hba till delete operation is completed */ spinlock_t lock; + spinlock_t *host_lock; // pointer to appropriate lock u8 logdrv_chan[MAX_CHANNELS+NVIRT_CHAN]; /* logical drive are on what channels. */ @@ -1049,7 +1115,6 @@ static int megaraid_command (Scsi_Cmnd * static int megaraid_abort(Scsi_Cmnd *); static int megaraid_reset(Scsi_Cmnd *); static int megaraid_biosparam (Disk *, kdev_t, int *); -static int mega_print_inquiry(char *, char *); static int mega_build_sglist (adapter_t *adapter, scb_t *scb, u32 *buffer, u32 *length); @@ -1092,12 +1157,13 @@ static int proc_rdrv_20(char *, char **, static int proc_rdrv_30(char *, char **, off_t, int, int *, void *); static int proc_rdrv_40(char *, char **, off_t, int, int *, void *); static int proc_rdrv(adapter_t *, char *, int, int); -#endif static int mega_adapinq(adapter_t *, dma_addr_t); static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t); static inline caddr_t mega_allocate_inquiry(dma_addr_t *, struct pci_dev *); static inline void mega_free_inquiry(caddr_t, dma_addr_t, struct pci_dev *); +static int mega_print_inquiry(char *, char *); +#endif static int mega_support_ext_cdb(adapter_t *); static mega_passthru* mega_prepare_passthru(adapter_t *, scb_t *, diff -Naurp linux-2.4.20-wolk4.4-fullkernel/evfs/Makefile linux-2.4.20-wolk4.5-fullkernel/evfs/Makefile --- linux-2.4.20-wolk4.4-fullkernel/evfs/Makefile 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/evfs/Makefile 2003-07-30 15:37:15.000000000 +0200 @@ -1,4 +1,4 @@ -CFLAGS=-Wall -O6 -fomit-frame-pointer -funroll-all-loops +CFLAGS+=-Wall -O6 -fomit-frame-pointer -funroll-all-loops .c.o: gcc $(CFLAGS) -c $< diff -Naurp linux-2.4.20-wolk4.4-fullkernel/fs/Config.in linux-2.4.20-wolk4.5-fullkernel/fs/Config.in --- linux-2.4.20-wolk4.4-fullkernel/fs/Config.in 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/fs/Config.in 2003-08-04 21:45:26.000000000 +0200 @@ -64,6 +64,8 @@ bool '/proc file system support' CONFIG_ if [ "$CONFIG_PROC_FS" = "y" ] ; then bool ' /proc/config.gz (Kernel Configuration)' CONFIG_PROC_CONFIG + bool ' Kernel .config support' CONFIG_IKCONFIG + dep_bool ' Enable access to .config through /proc/ikconfig' CONFIG_IKCONFIG_PROC $CONFIG_IKCONFIG fi dep_bool '/dev file system support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL dep_bool ' Automatically mount at boot' CONFIG_DEVFS_MOUNT $CONFIG_DEVFS_FS diff -Naurp linux-2.4.20-wolk4.4-fullkernel/fs/aio.c linux-2.4.20-wolk4.5-fullkernel/fs/aio.c --- linux-2.4.20-wolk4.4-fullkernel/fs/aio.c 2003-08-04 23:06:27.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/fs/aio.c 2003-08-04 21:04:12.000000000 +0200 @@ -11,6 +11,7 @@ #include #include #include +#include #include //#define DEBUG 1 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/fs/mbcache.c linux-2.4.20-wolk4.5-fullkernel/fs/mbcache.c --- linux-2.4.20-wolk4.4-fullkernel/fs/mbcache.c 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/fs/mbcache.c 2003-08-03 22:47:07.000000000 +0200 @@ -60,19 +60,19 @@ MODULE_DESCRIPTION("Meta block cache (fo MODULE_LICENSE("GPL"); -EXPORT_SYMBOL_GPL(mb_cache_create); -EXPORT_SYMBOL_GPL(mb_cache_shrink); -EXPORT_SYMBOL_GPL(mb_cache_destroy); -EXPORT_SYMBOL_GPL(mb_cache_entry_alloc); -EXPORT_SYMBOL_GPL(mb_cache_entry_insert); -EXPORT_SYMBOL_GPL(mb_cache_entry_release); -EXPORT_SYMBOL_GPL(mb_cache_entry_takeout); -EXPORT_SYMBOL_GPL(mb_cache_entry_free); -EXPORT_SYMBOL_GPL(mb_cache_entry_dup); -EXPORT_SYMBOL_GPL(mb_cache_entry_get); +EXPORT_SYMBOL(mb_cache_create); +EXPORT_SYMBOL(mb_cache_shrink); +EXPORT_SYMBOL(mb_cache_destroy); +EXPORT_SYMBOL(mb_cache_entry_alloc); +EXPORT_SYMBOL(mb_cache_entry_insert); +EXPORT_SYMBOL(mb_cache_entry_release); +EXPORT_SYMBOL(mb_cache_entry_takeout); +EXPORT_SYMBOL(mb_cache_entry_free); +EXPORT_SYMBOL(mb_cache_entry_dup); +EXPORT_SYMBOL(mb_cache_entry_get); #if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -EXPORT_SYMBOL_GPL(mb_cache_entry_find_first); -EXPORT_SYMBOL_GPL(mb_cache_entry_find_next); +EXPORT_SYMBOL(mb_cache_entry_find_first); +EXPORT_SYMBOL(mb_cache_entry_find_next); #endif diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/asm-i386/hw_irq.h linux-2.4.20-wolk4.5-fullkernel/include/asm-i386/hw_irq.h --- linux-2.4.20-wolk4.4-fullkernel/include/asm-i386/hw_irq.h 2003-05-13 12:18:45.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/asm-i386/hw_irq.h 2003-08-03 15:57:00.000000000 +0200 @@ -232,7 +232,7 @@ static inline void x86_do_profile (unsig atomic_inc((atomic_t *)&prof_buffer[eip]); } -#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ +#if defined(CONFIG_X86_IO_APIC) static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { if (IO_APIC_IRQ(i)) send_IPI_self(IO_APIC_VECTOR(i)); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/asm-i386/processor.h linux-2.4.20-wolk4.5-fullkernel/include/asm-i386/processor.h --- linux-2.4.20-wolk4.4-fullkernel/include/asm-i386/processor.h 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/asm-i386/processor.h 2003-07-31 23:11:48.000000000 +0200 @@ -341,9 +341,9 @@ struct i387_soft_struct { long foo; long fos; long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ - unsigned char ftop, changed, lookahead, no_update, rm, alimit; struct info *info; unsigned long entry_eip; + unsigned char ftop, changed, lookahead, no_update, rm, alimit; }; union i387_union { @@ -397,11 +397,12 @@ struct thread_struct { unsigned long debugreg[8]; /* %%db0-7 debug registers */ /* fault info */ unsigned long cr2, trap_no, error_code; +/* virtual 86 mode info part #1 */ + unsigned long screen_bitmap; /* floating point info */ union i387_union i387; -/* virtual 86 mode info */ +/* virtual 86 mode info part #2 */ struct vm86_struct * vm86_info; - unsigned long screen_bitmap; unsigned long v86flags, v86mask, saved_esp0; unsigned int saved_fs, saved_gs; /* IO permissions */ @@ -416,9 +417,9 @@ struct thread_struct { 0, \ 0, 0, 0, 0, \ { [0 ... 7] = 0 }, /* debugging registers */ \ - 0, 0, 0, \ + 0, 0, 0, 0, \ { { 0, }, }, /* 387 state */ \ - 0,0,0,0,0, \ + 0,0,0,0, \ 0,{~0,} /* io permissions */ \ } diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/agp_backend.h linux-2.4.20-wolk4.5-fullkernel/include/linux/agp_backend.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/agp_backend.h 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/agp_backend.h 2003-07-30 16:13:31.000000000 +0200 @@ -53,6 +53,8 @@ enum chipset_type { INTEL_I845, INTEL_I850, INTEL_I860, + INTEL_I7205, + INTEL_I7505, VIA_GENERIC, VIA_VP3, VIA_MVP3, diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/blkdev.h linux-2.4.20-wolk4.5-fullkernel/include/linux/blkdev.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/blkdev.h 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/blkdev.h 2003-08-01 15:35:52.000000000 +0200 @@ -305,6 +305,11 @@ extern char * blkdev_varyio[MAX_BLKDEV]; # define MAX_NR_REQUESTS 16 /* 8k when in 16 units, normally min is 16k in 1k units */ #endif +#if !defined (MAX_QUEUE_SECTORS) && !defined (MAX_NR_REQUESTS) +# error You should select an I/O elevator in the kernel configuration menu! +# error Go back and select one and try the compilation again :p +#endif + #define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK) diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/brlock.h linux-2.4.20-wolk4.5-fullkernel/include/linux/brlock.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/brlock.h 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/brlock.h 2003-08-02 23:17:43.000000000 +0200 @@ -37,6 +37,7 @@ enum brlock_indices { BR_AIO_REQ_LOCK, BR_LRU_LOCK, BR_HIPAC_LOCK, + BR_PAGECACHE_LOCK, __BR_END }; diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/kernel.h linux-2.4.20-wolk4.5-fullkernel/include/linux/kernel.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/kernel.h 2003-05-13 12:18:44.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/kernel.h 2003-08-02 23:18:47.000000000 +0200 @@ -89,6 +89,9 @@ extern unsigned long long memparse(char extern void dev_probe_lock(void); extern void dev_probe_unlock(void); +extern int __guard; +extern void __stack_smash_handler(int, char []); + extern int session_of_pgrp(int pgrp); #ifdef CONFIG_WLI_EARLY_PRINTK diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.20-wolk4.5-fullkernel/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/netfilter_ipv4/ip_conntrack.h 2003-05-13 12:39:24.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/netfilter_ipv4/ip_conntrack.h 2003-08-04 20:52:57.000000000 +0200 @@ -6,6 +6,7 @@ #include #include +#include #include enum ip_conntrack_info @@ -41,6 +42,10 @@ enum ip_conntrack_status { /* Conntrack should never be early-expired. */ IPS_ASSURED_BIT = 2, IPS_ASSURED = (1 << IPS_ASSURED_BIT), + + /* Connection is confirmed: originating packet has left box */ + IPS_CONFIRMED_BIT = 3, + IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT), }; #include @@ -163,7 +168,7 @@ struct ip_conntrack struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; /* Have we seen traffic both ways yet? (bitset) */ - volatile unsigned long status; + unsigned long status; /* Timer function; drops refcnt when it goes off. */ struct timer_list timeout; @@ -261,7 +266,7 @@ ip_ct_selective_cleanup(int (*kill)(cons /* It's confirmed if it is, or has been in the hash table. */ static inline int is_confirmed(struct ip_conntrack *ct) { - return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL; + return test_bit(IPS_CONFIRMED_BIT, &ct->status); } extern unsigned int ip_conntrack_htable_size; diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/proc_fs.h linux-2.4.20-wolk4.5-fullkernel/include/linux/proc_fs.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/proc_fs.h 2003-05-13 12:18:56.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/proc_fs.h 2003-08-01 15:55:12.000000000 +0200 @@ -142,6 +142,7 @@ extern struct proc_dir_entry *proc_symli struct proc_dir_entry *, const char *); extern struct proc_dir_entry *proc_mknod(const char *,mode_t, struct proc_dir_entry *,kdev_t); +extern struct proc_dir_entry *proc_mkdir_mode(const char *,mode_t,struct proc_dir_entry *); extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *); #ifdef CONFIG_GRKERNSEC_PROC extern struct proc_dir_entry *proc_priv_mkdir(const char *, struct proc_dir_entry *); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/include/linux/swap.h linux-2.4.20-wolk4.5-fullkernel/include/linux/swap.h --- linux-2.4.20-wolk4.4-fullkernel/include/linux/swap.h 2003-08-04 23:06:31.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/include/linux/swap.h 2003-08-02 23:17:43.000000000 +0200 @@ -3,6 +3,7 @@ #include #include +#include #define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ #define SWAP_FLAG_PRIO_MASK 0x7fff @@ -95,8 +96,32 @@ extern unsigned int freeable_lowmem(void extern atomic_t page_cache_size; extern atomic_t buffermem_pages; +#if 1 + +static inline void + lock_pagecache(void) { br_write_lock(BR_PAGECACHE_LOCK); } +static inline void + unlock_pagecache(void) { br_write_unlock(BR_PAGECACHE_LOCK); } +static inline void + lock_pagecache_readonly(void) { br_read_lock(BR_PAGECACHE_LOCK); } +static inline void + unlock_pagecache_readonly(void) { br_read_unlock(BR_PAGECACHE_LOCK); } + +#else + extern spinlock_cacheline_t pagecache_lock_cacheline; -#define pagecache_lock (pagecache_lock_cacheline.lock) +#define __pagecache_lock (pagecache_lock_cacheline.lock) + +static inline void + lock_pagecache(void) { spin_lock(&__pagecache_lock); } +static inline void + unlock_pagecache(void) { spin_unlock(&__pagecache_lock); } +static inline void + lock_pagecache_readonly(void) { spin_lock(&__pagecache_lock); } +static inline void + unlock_pagecache_readonly(void) { spin_unlock(&__pagecache_lock); } + +#endif extern void __remove_inode_page(struct page *); @@ -110,6 +135,7 @@ struct zone_t; /* linux/mm/rmap.c */ struct pte_chain; extern int FASTCALL(page_referenced(struct page *, int *)); +extern int FASTCALL(page_referenced_lock(struct page *, int *)); extern struct pte_chain * FASTCALL(page_add_rmap(struct page *, pte_t *, struct pte_chain *)); extern void FASTCALL(page_remove_rmap(struct page *, pte_t *)); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/init/version.c linux-2.4.20-wolk4.5-fullkernel/init/version.c --- linux-2.4.20-wolk4.4-fullkernel/init/version.c 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/init/version.c 2003-08-04 23:03:09.000000000 +0200 @@ -26,7 +26,7 @@ struct new_utsname system_utsname = { }; const char *wolk_banner = - "WOLK - Working Overloaded Linux Kernel - v4.4 - Server Edition""\n\n"; + "WOLK - Working Overloaded Linux Kernel - v4.5 - Server Edition""\n\n"; const char *linux_banner = "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" diff -Naurp linux-2.4.20-wolk4.4-fullkernel/kernel/Makefile linux-2.4.20-wolk4.5-fullkernel/kernel/Makefile --- linux-2.4.20-wolk4.4-fullkernel/kernel/Makefile 2003-08-04 23:06:27.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/kernel/Makefile 2003-08-04 21:45:26.000000000 +0200 @@ -23,6 +23,7 @@ obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_EVLOG) += evl_buf.o evl_cmd.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_IKCONFIG) += configs.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is @@ -34,3 +35,10 @@ CFLAGS_sched.o := $(PROFILING) -fno-omit endif include $(TOPDIR)/Rules.make + +ikconfig.h: $(TOPDIR)/scripts/mkconfigs $(TOPDIR)/.config $(TOPDIR)/Makefile + $(CONFIG_SHELL) $(TOPDIR)/scripts/mkconfigs $(TOPDIR)/.config $(TOPDIR)/Makefile > ikconfig.h + +configs.o: ikconfig.h configs.c \ + $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h + diff -Naurp linux-2.4.20-wolk4.4-fullkernel/kernel/configs.c linux-2.4.20-wolk4.5-fullkernel/kernel/configs.c --- linux-2.4.20-wolk4.4-fullkernel/kernel/configs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/kernel/configs.c 2003-08-04 21:45:26.000000000 +0200 @@ -0,0 +1,189 @@ +/* + * kernel/configs.c + * Echo the kernel .config file used to build the kernel + * + * Copyright (C) 2002 Khalid Aziz + * Copyright (C) 2002 Randy Dunlap + * Copyright (C) 2002 Al Stone + * Copyright (C) 2002 Hewlett-Packard Company + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +/**************************************************/ +/* the actual current config file */ + +#include "ikconfig.h" + +#ifdef CONFIG_IKCONFIG_PROC + +/**************************************************/ +/* globals and useful constants */ + +static char *IKCONFIG_NAME = "ikconfig"; +static char *IKCONFIG_VERSION = "0.5"; + +static int ikconfig_current_size = 0; +static struct proc_dir_entry *ikconfig_dir, *current_config, *built_with; + +static int +ikconfig_permission_current(struct inode *inode, int op) +{ + /* anyone can read the device, no one can write to it */ + return (op == MAY_READ) ? 0 : -EACCES; +} + +static ssize_t +ikconfig_output_current(struct file *file, char *buf, + size_t len, loff_t * offset) +{ + int i, limit; + int cnt; + + limit = (ikconfig_current_size > len) ? len : ikconfig_current_size; + for (i = file->f_pos, cnt = 0; + i < ikconfig_current_size && cnt < limit; i++, cnt++) { + if (put_user(ikconfig_config[i], buf + cnt)) + return -EFAULT; + } + file->f_pos = i; + return cnt; +} + +static int +ikconfig_open_current(struct inode *inode, struct file *file) +{ + if (file->f_mode & FMODE_READ) { + inode->i_size = ikconfig_current_size; + file->f_pos = 0; + } + return 0; +} + +static int +ikconfig_close_current(struct inode *inode, struct file *file) +{ + return 0; +} + +static struct file_operations ikconfig_file_ops = { + .read = ikconfig_output_current, + .open = ikconfig_open_current, + .release = ikconfig_close_current, +}; + +static struct inode_operations ikconfig_inode_ops = { + .permission = ikconfig_permission_current, +}; + +/***************************************************/ +/* proc_read_built_with: let people read the info */ +/* we have on the tools used to build this kernel */ + +static int +proc_read_built_with(char *page, char **start, + off_t off, int count, int *eof, void *data) +{ + *eof = 1; + return sprintf(page, + "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", + ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE); +} + +/***************************************************/ +/* ikconfig_init: start up everything we need to */ + +int __init +ikconfig_init(void) +{ + int result = 0; + + printk(KERN_INFO "ikconfig %s with /proc/ikconfig\n", + IKCONFIG_VERSION); + + /* create the ikconfig directory */ + ikconfig_dir = proc_mkdir(IKCONFIG_NAME, NULL); + if (ikconfig_dir == NULL) { + result = -ENOMEM; + goto leave; + } + ikconfig_dir->owner = THIS_MODULE; + + /* create the current config file */ + current_config = create_proc_entry("config", S_IFREG | S_IRUGO, + ikconfig_dir); + if (current_config == NULL) { + result = -ENOMEM; + goto leave2; + } + current_config->proc_iops = &ikconfig_inode_ops; + current_config->proc_fops = &ikconfig_file_ops; + current_config->owner = THIS_MODULE; + ikconfig_current_size = strlen(ikconfig_config); + current_config->size = ikconfig_current_size; + + /* create the "built with" file */ + built_with = create_proc_read_entry("built_with", 0444, ikconfig_dir, + proc_read_built_with, NULL); + if (built_with == NULL) { + result = -ENOMEM; + goto leave3; + } + built_with->owner = THIS_MODULE; + goto leave; + +leave3: + /* remove the file from proc */ + remove_proc_entry("config", ikconfig_dir); + +leave2: + /* remove the ikconfig directory */ + remove_proc_entry(IKCONFIG_NAME, NULL); + +leave: + return result; +} + +/***************************************************/ +/* cleanup_ikconfig: clean up our mess */ + +static void +cleanup_ikconfig(void) +{ + /* remove the files */ + remove_proc_entry("config", ikconfig_dir); + remove_proc_entry("built_with", ikconfig_dir); + + /* remove the ikconfig directory */ + remove_proc_entry(IKCONFIG_NAME, NULL); +} + +module_init(ikconfig_init); +module_exit(cleanup_ikconfig); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Randy Dunlap"); +MODULE_DESCRIPTION("Echo the kernel .config file used to build the kernel"); + +#endif /* CONFIG_IKCONFIG_PROC */ diff -Naurp linux-2.4.20-wolk4.4-fullkernel/kernel/ksyms.c linux-2.4.20-wolk4.5-fullkernel/kernel/ksyms.c --- linux-2.4.20-wolk4.4-fullkernel/kernel/ksyms.c 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/kernel/ksyms.c 2003-08-04 22:09:11.000000000 +0200 @@ -129,8 +129,8 @@ EXPORT_SYMBOL(kmem_cache_shrink); EXPORT_SYMBOL(kmem_cache_alloc); EXPORT_SYMBOL(kmem_cache_free); EXPORT_SYMBOL(kmem_cache_size); -EXPORT_SYMBOL_GPL(register_cache); -EXPORT_SYMBOL_GPL(unregister_cache); +EXPORT_SYMBOL(register_cache); +EXPORT_SYMBOL(unregister_cache); EXPORT_SYMBOL(kmalloc); EXPORT_SYMBOL(kfree); EXPORT_SYMBOL(vfree); @@ -604,6 +604,8 @@ EXPORT_SYMBOL(single_open); EXPORT_SYMBOL(single_release); extern int disable_all_usb; EXPORT_SYMBOL(disable_all_usb); +EXPORT_SYMBOL_NOVERS(__guard); +EXPORT_SYMBOL_NOVERS(__stack_smash_handler); /* Program loader interfaces */ EXPORT_SYMBOL(setup_arg_pages); @@ -700,7 +702,6 @@ EXPORT_SYMBOL(set_fs_pwd); EXPORT_SYMBOL(set_fs_root); /* evfs */ -#ifdef CONFIG_EVFS_FS extern void sys_rename(); extern void sys_readlink(); extern void sys_unlink(); @@ -718,4 +719,3 @@ EXPORT_SYMBOL(sys_mknod); EXPORT_SYMBOL(sys_mkdir); EXPORT_SYMBOL(sys_rmdir); EXPORT_SYMBOL(sys_link); -#endif diff -Naurp linux-2.4.20-wolk4.4-fullkernel/kernel/panic.c linux-2.4.20-wolk4.5-fullkernel/kernel/panic.c --- linux-2.4.20-wolk4.4-fullkernel/kernel/panic.c 2003-05-03 02:37:14.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/kernel/panic.c 2003-08-04 21:09:22.000000000 +0200 @@ -250,12 +250,16 @@ NORET_TYPE void panic(const char * fmt, if (panic_timeout > 0) { + int i; /* * Delay timeout seconds before rebooting the machine. * We can't use the "normal" timers since we just panicked.. */ printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout); - mdelay(panic_timeout*1000); + for (i = 0; i < panic_timeout; i++) { + touch_nmi_watchdog(); + mdelay(1000); + } /* * Should we run the reboot notifier. For the moment Im * choosing not too. It might crash, be corrupt or do diff -Naurp linux-2.4.20-wolk4.4-fullkernel/lib/Makefile linux-2.4.20-wolk4.5-fullkernel/lib/Makefile --- linux-2.4.20-wolk4.4-fullkernel/lib/Makefile 2002-12-18 01:04:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/lib/Makefile 2003-08-02 23:18:47.000000000 +0200 @@ -11,7 +11,7 @@ L_TARGET := lib.a export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o rbtree.o obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \ - bust_spinlocks.o rbtree.o dump_stack.o + bust_spinlocks.o rbtree.o dump_stack.o propolice.o obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o diff -Naurp linux-2.4.20-wolk4.4-fullkernel/lib/propolice.c linux-2.4.20-wolk4.5-fullkernel/lib/propolice.c --- linux-2.4.20-wolk4.4-fullkernel/lib/propolice.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/lib/propolice.c 2003-08-02 23:18:47.000000000 +0200 @@ -0,0 +1,13 @@ + /* + * linux/lib/errno.c + * + * + */ + + int __guard = '\0\0\n\777'; + + void __stack_smash_handler (int damaged, char func[]) + { + static char *message = "propolice detects %x at function %s.\n" ; + panic (message, damaged, func); +} diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/filemap.c linux-2.4.20-wolk4.5-fullkernel/mm/filemap.c --- linux-2.4.20-wolk4.4-fullkernel/mm/filemap.c 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/filemap.c 2003-08-02 23:17:43.000000000 +0200 @@ -138,9 +138,9 @@ void remove_inode_page(struct page *page if (!PageLocked(page)) PAGE_BUG(page); - spin_lock(&pagecache_lock); + lock_pagecache(); __remove_inode_page(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); } static inline int sync_page(struct page *page) @@ -161,13 +161,13 @@ void set_page_dirty(struct page *page) struct address_space *mapping = page->mapping; if (mapping) { - spin_lock(&pagecache_lock); + lock_pagecache(); mapping = page->mapping; if (mapping) { /* may have been truncated */ list_del(&page->list); list_add(&page->list, &mapping->dirty_pages); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); if (mapping && mapping->host) mark_inode_dirty_pages(mapping->host); @@ -191,7 +191,7 @@ void invalidate_inode_pages(struct inode head = &inode->i_mapping->clean_pages; lru_lock(ALL_ZONES); - spin_lock(&pagecache_lock); + lock_pagecache(); curr = head->next; while (curr != head) { @@ -223,7 +223,7 @@ unlock: continue; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_unlock(ALL_ZONES); } @@ -295,7 +295,7 @@ static int truncate_list_pages(struct li /* Restart on this page */ list_add(head, curr); - spin_unlock(&pagecache_lock); + unlock_pagecache(); unlocked = 1; if (!failed) { @@ -312,7 +312,7 @@ static int truncate_list_pages(struct li page_cache_release(page); cond_resched(); - spin_lock(&pagecache_lock); + lock_pagecache(); goto restart; } curr = curr->prev; @@ -336,14 +336,14 @@ void truncate_inode_pages(struct address unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); int unlocked; - spin_lock(&pagecache_lock); + lock_pagecache(); do { unlocked = truncate_list_pages(&mapping->clean_pages, start, &partial); unlocked |= truncate_list_pages(&mapping->dirty_pages, start, &partial); unlocked |= truncate_list_pages(&mapping->locked_pages, start, &partial); } while (unlocked); /* Traversed all three lists without dropping the lock */ - spin_unlock(&pagecache_lock); + unlock_pagecache(); } static inline int invalidate_this_page2(struct page * page, @@ -362,7 +362,7 @@ static inline int invalidate_this_page2( list_add_tail(head, curr); page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); truncate_complete_page(page); } else { if (page->buffers) { @@ -371,7 +371,7 @@ static inline int invalidate_this_page2( list_add_tail(head, curr); page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); block_invalidate_page(page); } else unlocked = 0; @@ -411,7 +411,7 @@ static int invalidate_list_pages2(struct list_add(head, curr); page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); unlocked = 1; wait_on_page(page); } @@ -419,7 +419,7 @@ static int invalidate_list_pages2(struct page_cache_release(page); cond_resched(); - spin_lock(&pagecache_lock); + lock_pagecache(); goto restart; } return unlocked; @@ -434,13 +434,13 @@ void invalidate_inode_pages2(struct addr { int unlocked; - spin_lock(&pagecache_lock); + lock_pagecache(); do { unlocked = invalidate_list_pages2(&mapping->clean_pages); unlocked |= invalidate_list_pages2(&mapping->dirty_pages); unlocked |= invalidate_list_pages2(&mapping->locked_pages); } while (unlocked); - spin_unlock(&pagecache_lock); + unlock_pagecache(); } static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page) @@ -452,6 +452,9 @@ static inline struct page * __find_page_ inside: if (!page) goto not_found; + + prefetch(page->next_hash); + if (page->mapping != mapping) continue; if (page->index == offset) @@ -468,7 +471,7 @@ static int do_buffer_fdatasync(struct li struct page *page; int retval = 0; - spin_lock(&pagecache_lock); + lock_pagecache(); curr = head->next; while (curr != head) { page = list_entry(curr, struct page, list); @@ -481,7 +484,7 @@ static int do_buffer_fdatasync(struct li continue; page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lock_page(page); /* The buffers could have been free'd while we waited for the page lock */ @@ -489,11 +492,11 @@ static int do_buffer_fdatasync(struct li retval |= fn(page); UnlockPage(page); - spin_lock(&pagecache_lock); + lock_pagecache(); curr = page->list.next; page_cache_release(page); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); return retval; } @@ -560,7 +563,7 @@ int filemap_fdatasync(struct address_spa int ret = 0; int (*writepage)(struct page *) = mapping->a_ops->writepage; - spin_lock(&pagecache_lock); + lock_pagecache(); while (!list_empty(&mapping->dirty_pages)) { struct page *page = list_entry(mapping->dirty_pages.prev, struct page, list); @@ -572,7 +575,7 @@ int filemap_fdatasync(struct address_spa continue; page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lock_page(page); @@ -587,9 +590,9 @@ int filemap_fdatasync(struct address_spa page_cache_release(page); cond_resched(); - spin_lock(&pagecache_lock); + lock_pagecache(); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); return ret; } @@ -604,7 +607,7 @@ int filemap_fdatawait(struct address_spa { int ret = 0; - spin_lock(&pagecache_lock); + lock_pagecache(); while (!list_empty(&mapping->locked_pages)) { struct page *page = list_entry(mapping->locked_pages.next, struct page, list); @@ -616,16 +619,16 @@ int filemap_fdatawait(struct address_spa continue; page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); ___wait_on_page(page); if (PageError(page)) ret = -EIO; page_cache_release(page); - spin_lock(&pagecache_lock); + lock_pagecache(); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); return ret; } @@ -642,10 +645,10 @@ void add_to_page_cache_locked(struct pag page->index = index; page_cache_get(page); - spin_lock(&pagecache_lock); + lock_pagecache(); add_page_to_inode_queue(mapping, page); add_page_to_hash_queue(page, page_hash(mapping, index)); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_cache_add(page); } @@ -670,9 +673,9 @@ static inline void __add_to_page_cache(s void add_to_page_cache(struct page * page, struct address_space * mapping, unsigned long offset) { - spin_lock(&pagecache_lock); + lock_pagecache(); __add_to_page_cache(page, mapping, offset, page_hash(mapping, offset)); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_cache_add(page); } @@ -683,7 +686,7 @@ int add_to_page_cache_unique(struct page int err; struct page *alias; - spin_lock(&pagecache_lock); + lock_pagecache(); alias = __find_page_nolock(mapping, offset, *hash); err = 1; @@ -692,7 +695,7 @@ int add_to_page_cache_unique(struct page err = 0; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); if (!err) lru_cache_add(page); return err; @@ -711,9 +714,9 @@ static int page_cache_read(struct file * cond_resched(); - spin_lock(&pagecache_lock); + lock_pagecache_readonly(); page = __find_page_nolock(mapping, offset, *hash); - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); if (page) return 0; @@ -971,11 +974,11 @@ struct page * __find_get_page(struct add * We scan the hash list read-only. Addition to and removal from * the hash-list needs a held write-lock. */ - spin_lock(&pagecache_lock); + lock_pagecache_readonly(); page = __find_page_nolock(mapping, offset, *hash); if (page) page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); return page; } @@ -987,13 +990,13 @@ struct page *find_trylock_page(struct ad struct page *page; struct page **hash = page_hash(mapping, offset); - spin_lock(&pagecache_lock); + lock_pagecache_readonly(); page = __find_page_nolock(mapping, offset, *hash); if (page) { if (TryLockPage(page)) page = NULL; } - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); return page; } @@ -1017,9 +1020,39 @@ repeat: if (page) { page_cache_get(page); if (TryLockPage(page)) { - spin_unlock(&pagecache_lock); + unlock_pagecache(); lock_page(page); - spin_lock(&pagecache_lock); + lock_pagecache(); + + /* Has the page been re-allocated while we slept? */ + if (page->mapping != mapping || page->index != offset) { + UnlockPage(page); + page_cache_release(page); + goto repeat; + } + } + } + return page; +} + +static struct page * FASTCALL(__find_lock_page_helper_readonly(struct address_space *, unsigned long, struct page *)); +static struct page * __find_lock_page_helper_readonly(struct address_space *mapping, + unsigned long offset, struct page *hash) +{ + struct page *page; + + /* + * We scan the hash list read-only. Addition to and removal from + * the hash-list needs a held write-lock. + */ +repeat: + page = __find_page_nolock(mapping, offset, hash); + if (page) { + page_cache_get(page); + if (TryLockPage(page)) { + unlock_pagecache_readonly(); + lock_page(page); + lock_pagecache_readonly(); /* Has the page been re-allocated while we slept? */ if (page->mapping != mapping || page->index != offset) { @@ -1041,9 +1074,9 @@ struct page * __find_lock_page (struct a { struct page *page; - spin_lock(&pagecache_lock); - page = __find_lock_page_helper(mapping, offset, *hash); - spin_unlock(&pagecache_lock); + lock_pagecache_readonly(); + page = __find_lock_page_helper_readonly(mapping, offset, *hash); + unlock_pagecache_readonly(); return page; } @@ -1055,20 +1088,20 @@ struct page * find_or_create_page(struct struct page *page; struct page **hash = page_hash(mapping, index); - spin_lock(&pagecache_lock); - page = __find_lock_page_helper(mapping, index, *hash); - spin_unlock(&pagecache_lock); + lock_pagecache_readonly(); + page = __find_lock_page_helper_readonly(mapping, index, *hash); + unlock_pagecache_readonly(); if (!page) { struct page *newpage = alloc_page(gfp_mask); if (newpage) { - spin_lock(&pagecache_lock); + lock_pagecache(); page = __find_lock_page_helper(mapping, index, *hash); if (likely(!page)) { page = newpage; __add_to_page_cache(page, mapping, index, hash); newpage = NULL; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); if (newpage == NULL) lru_cache_add(page); else @@ -1395,7 +1428,7 @@ static unsigned long shrink_list(struct unsigned long nr_shrunk = 0; lru_lock(ALL_ZONES); - spin_lock(&pagecache_lock); + lock_pagecache(); while ((curr != list)) { struct page *page = list_entry(curr, struct page, list); @@ -1429,7 +1462,7 @@ static unsigned long shrink_list(struct nr_shrunk++; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_unlock(ALL_ZONES); return nr_shrunk; @@ -1535,7 +1568,7 @@ void __do_generic_file_read(struct file } for (;;) { - struct page *page, **hash; + struct page *page, **hash, **next_hash; unsigned long end_index, nr, ret; loff_t i_size = i_size_read(inode); @@ -1560,15 +1593,18 @@ void __do_generic_file_read(struct file * Try to find the data in the page cache.. */ hash = page_hash(mapping, index); + prefetch(*hash); + if (likely(hash + 1 != page_hash_table + PAGE_HASH_SIZE)) + prefetch(*(hash + 1)); - spin_lock(&pagecache_lock); + lock_pagecache_readonly(); page = __find_page_nolock(mapping, index, *hash); if (!page) goto no_cached_page; -found_page: page_cache_get(page); - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); +found_page: if (!Page_Uptodate(page)) { if (nonblock) { page_cache_release(page); @@ -1602,17 +1638,10 @@ page_ok: index += offset >> PAGE_CACHE_SHIFT; offset &= ~PAGE_CACHE_MASK; - lru_lock(page_zone(page)); - pte_chain_lock(page); - if (PageFresh(page) && page->age <= INITIAL_AGE && - !page_referenced(page, &dummy)) { - pte_chain_unlock(page); + if (PageFresh(page) && page->age <= INITIAL_AGE && !page_referenced_lock(page, &dummy) ) { ClearPageFresh(page); - deactivate_page_nolock(page); - lru_unlock(page_zone(page)); + deactivate_page(page); } else { - pte_chain_unlock(page); - lru_unlock(page_zone(page)); /* * Mark the page accessed if we read the beginning or * we just did an lseek, in order to prevent a series @@ -1678,7 +1707,7 @@ readpage: no_cached_page: if (nonblock) { - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); desc->error = -EWOULDBLOCKIO; break; } @@ -1689,21 +1718,25 @@ no_cached_page: * We get here with the page cache lock held. */ if (!cached_page) { - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); cached_page = page_cache_alloc(mapping); if (!cached_page) { desc->error = -ENOMEM; break; } + } else + unlock_pagecache_readonly(); - /* - * Somebody may have added the page while we - * dropped the page cache lock. Check for that. - */ - spin_lock(&pagecache_lock); - page = __find_page_nolock(mapping, index, *hash); - if (page) - goto found_page; + /* + * Somebody may have added the page while we + * dropped the page cache lock. Check for that. + */ + lock_pagecache(); + page = __find_page_nolock(mapping, index, *hash); + if (page) { + page_cache_get(page); + unlock_pagecache(); + goto found_page; } /* @@ -1712,7 +1745,7 @@ no_cached_page: page = cached_page; __add_to_page_cache(page, mapping, index, hash); SetPageFresh(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_cache_add(page); cached_page = NULL; @@ -2896,11 +2929,11 @@ static unsigned char mincore_page(struct struct address_space * as = vma->vm_file->f_dentry->d_inode->i_mapping; struct page * page, ** hash = page_hash(as, pgoff); - spin_lock(&pagecache_lock); + lock_pagecache_readonly(); page = __find_page_nolock(as, pgoff, *hash); if ((page) && (Page_Uptodate(page))) present = 1; - spin_unlock(&pagecache_lock); + unlock_pagecache_readonly(); return present; } @@ -3535,7 +3568,7 @@ static int address_space_map(struct addr ret = 0; - spin_lock(&pagecache_lock); + lock_pagecache(); while (nr > 0) { struct page **hash = page_hash(as, index); @@ -3554,16 +3587,16 @@ got_page: if (cached_page) { __add_to_page_cache(cached_page, as, index, hash); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_cache_add(cached_page); - spin_lock(&pagecache_lock); + lock_pagecache(); nr_new++; *new_pages++ = page = cached_page; cached_page = NULL; goto got_page; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); cached_page = page_cache_alloc(as); if (!cached_page) @@ -3571,10 +3604,10 @@ got_page: /* Okay, we now have an allocated page. Retry * the search and add. */ - spin_lock(&pagecache_lock); + lock_pagecache(); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); out: if (cached_page) diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/page_alloc.c linux-2.4.20-wolk4.5-fullkernel/mm/page_alloc.c --- linux-2.4.20-wolk4.4-fullkernel/mm/page_alloc.c 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/page_alloc.c 2003-08-04 22:39:19.000000000 +0200 @@ -175,6 +175,8 @@ static void __free_pages_ok (struct page if (PageInactiveClean(page)) BUG(); if (page->pte.direct) + printk(KERN_WARNING "There's a BUG() with PaX's ET_EXEC vs. RMAP. Someone has to fix this up!\n"); + printk(KERN_WARNING "Please write to 'pageexec@freemail.hu' and ask, if they'll do RMAP support please.\n"); BUG(); #ifdef CONFIG_MXT diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/rmap.c linux-2.4.20-wolk4.5-fullkernel/mm/rmap.c --- linux-2.4.20-wolk4.4-fullkernel/mm/rmap.c 2003-08-04 23:06:35.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/rmap.c 2003-08-02 23:17:43.000000000 +0200 @@ -205,6 +205,17 @@ int page_referenced(struct page * page, return referenced; } +int page_referenced_lock(struct page * page, int * rsslimit) +{ + int ret; + + pte_chain_lock(page); + ret = page_referenced(page, rsslimit); + pte_chain_unlock(page); + + return ret; +} + /** * page_add_rmap - add reverse mapping entry to a page * @page: the page to add the mapping to diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/slab.c linux-2.4.20-wolk4.5-fullkernel/mm/slab.c --- linux-2.4.20-wolk4.4-fullkernel/mm/slab.c 2003-08-04 23:06:32.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/slab.c 2003-07-31 23:10:47.000000000 +0200 @@ -75,6 +75,7 @@ #include #include #include +#include #include /* @@ -401,7 +402,7 @@ static void kmem_cache_estimate (unsigne base = sizeof(slab_t); extra = sizeof(kmem_bufctl_t); } - i = (wastage - base) / (size + extra); + i = (wastage - base) / (size + extra); while (i*size + L1_CACHE_ALIGN(base+i*extra) <= wastage) i++; if (i > 0) @@ -1502,17 +1503,21 @@ static inline void __kmem_cache_free (km CHECK_PAGE(virt_to_page(objp)); if (cc) { - int batchcount; + int tofree; if (cc->avail < cc->limit) { STATS_INC_FREEHIT(cachep); cc_entry(cc)[cc->avail++] = objp; return; } STATS_INC_FREEMISS(cachep); - batchcount = cachep->batchcount; - cc->avail -= batchcount; - free_block(cachep, - &cc_entry(cc)[cc->avail],batchcount); + tofree = cachep->batchcount; + cc->avail -= tofree; + /* + * True LIFO - zap the cache-cold entries: + */ + free_block(cachep, &cc_entry(cc)[0],tofree); + memmove(&cc_entry(cc)[0], + &cc_entry(cc)[tofree],sizeof(void*)*cc->avail); cc_entry(cc)[cc->avail++] = objp; return; } else { @@ -1698,19 +1703,26 @@ oom: static void enable_cpucache (kmem_cache_t *cachep) { int err; - int limit; + int limit, scale; - /* FIXME: optimize */ + /* higher-order objects are rare. */ if (cachep->objsize > PAGE_SIZE) return; + /* + * Up to 256 MB of lowmem RAM we use a scale of 1, + * then for the next 256 MB of RAM a scale of 2 ... + * 4 GB lowmem means a scale of 16. + */ + scale = min(max_low_pfn, num_physpages) / (256*1024*1024 / PAGE_SIZE) + 1; + if (cachep->objsize > 1024) - limit = 60; + limit = 60 * scale; else if (cachep->objsize > 256) - limit = 124; + limit = 124 * scale; else - limit = 252; + limit = 252 * scale; - err = kmem_tune_cpucache(cachep, limit, limit/2); + err = kmem_tune_cpucache(cachep, limit, limit/4); if (err) printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n", cachep->name, -err); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/swap_state.c linux-2.4.20-wolk4.5-fullkernel/mm/swap_state.c --- linux-2.4.20-wolk4.4-fullkernel/mm/swap_state.c 2003-05-03 02:10:38.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/swap_state.c 2003-08-02 23:17:43.000000000 +0200 @@ -153,9 +153,9 @@ void delete_from_swap_cache(struct page entry.val = page->index; - spin_lock(&pagecache_lock); + lock_pagecache(); __delete_from_swap_cache(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); swap_free(entry); page_cache_release(page); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/swapfile.c linux-2.4.20-wolk4.5-fullkernel/mm/swapfile.c --- linux-2.4.20-wolk4.4-fullkernel/mm/swapfile.c 2003-08-04 23:06:35.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/swapfile.c 2003-08-02 23:17:43.000000000 +0200 @@ -243,10 +243,10 @@ static int exclusive_swap_page(struct pa /* Is the only swap cache user the cache itself? */ if (p->swap_map[SWP_OFFSET(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ - spin_lock(&pagecache_lock); + lock_pagecache(); if (page_count(page) - !!page->buffers == 2) retval = 1; - spin_unlock(&pagecache_lock); + unlock_pagecache(); } swap_info_put(p); } @@ -311,12 +311,12 @@ int remove_exclusive_swap_page(struct pa retval = 0; if (p->swap_map[SWP_OFFSET(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ - spin_lock(&pagecache_lock); + lock_pagecache(); if (page_count(page) - !!page->buffers == 2) { __delete_from_swap_cache(page); retval = 1; } - spin_unlock(&pagecache_lock); + unlock_pagecache(); } swap_info_put(p); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/mm/vmscan.c linux-2.4.20-wolk4.5-fullkernel/mm/vmscan.c --- linux-2.4.20-wolk4.4-fullkernel/mm/vmscan.c 2003-08-04 23:06:40.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/mm/vmscan.c 2003-08-02 23:17:43.000000000 +0200 @@ -157,7 +157,7 @@ struct page * reclaim_page(zone_t * zone * reclaim_page() doesn't race with other pagecache users */ lru_lock(zone); - spin_lock(&pagecache_lock); + lock_pagecache(); maxscan = zone->inactive_clean_pages; while (maxscan-- && !list_empty(&zone->inactive_clean_list)) { page_lru = zone->inactive_clean_list.prev; @@ -208,7 +208,7 @@ struct page * reclaim_page(zone_t * zone pte_chain_unlock(page); UnlockPage(page); } - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_unlock(zone); return NULL; @@ -216,7 +216,7 @@ struct page * reclaim_page(zone_t * zone found_page: __lru_cache_del(page); pte_chain_unlock(page); - spin_unlock(&pagecache_lock); + unlock_pagecache(); lru_unlock(zone); if (entry.val) swap_free(entry); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_core.c --- linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_core.c 2003-08-04 23:06:27.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_core.c 2003-08-04 20:52:57.000000000 +0200 @@ -295,9 +295,6 @@ clean_from_lists(struct ip_conntrack *ct { DEBUGP("clean_from_lists(%p)\n", ct); MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); - /* Remove from both hash lists: must not NULL out next ptrs, - otherwise we'll look unconfirmed. Fortunately, LIST_DELETE - doesn't do this. --RR */ LIST_DELETE(&ip_conntrack_hash [hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)], &ct->tuplehash[IP_CT_DIR_ORIGINAL]); @@ -474,6 +471,7 @@ __ip_conntrack_confirm(struct nf_ct_info ct->timeout.expires += jiffies; add_timer(&ct->timeout); atomic_inc(&ct->ct_general.use); + set_bit(IPS_CONFIRMED_BIT, &ct->status); WRITE_UNLOCK(&ip_conntrack_lock); return NF_ACCEPT; } @@ -592,7 +590,7 @@ icmp_error_track(struct sk_buff *skb, connection. Too bad: we're in trouble anyway. */ static inline int unreplied(const struct ip_conntrack_tuple_hash *i) { - return !(i->ctrack->status & IPS_ASSURED); + return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status)); } static int early_drop(struct list_head *chain) @@ -731,7 +729,7 @@ init_conntrack(const struct ip_conntrack conntrack, expected); /* Welcome, Mr. Bond. We've been expecting you... */ IP_NF_ASSERT(master_ct(conntrack)); - conntrack->status = IPS_EXPECTED; + __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = expected; expected->sibling = conntrack; LIST_DELETE(&ip_conntrack_expect_list, expected); @@ -780,11 +778,11 @@ resolve_normal_ct(struct sk_buff *skb, *set_reply = 1; } else { /* Once we've had two way comms, always ESTABLISHED. */ - if (h->ctrack->status & IPS_SEEN_REPLY) { + if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) { DEBUGP("ip_conntrack_in: normal packet for %p\n", h->ctrack); *ctinfo = IP_CT_ESTABLISHED; - } else if (h->ctrack->status & IPS_EXPECTED) { + } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) { DEBUGP("ip_conntrack_in: related packet for %p\n", h->ctrack); *ctinfo = IP_CT_RELATED; diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_tcp.c --- linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-05-03 02:36:04.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-08-04 20:52:57.000000000 +0200 @@ -829,7 +829,7 @@ static int tcp_packet(struct ip_conntrac ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state]; WRITE_UNLOCK(&tcp_lock); - if (!(conntrack->status & IPS_SEEN_REPLY)) { + if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { /* If only reply is a RST, we can consider ourselves not to have an established connection: this is a fairly common problem case, so we can delete the conntrack diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_udp.c --- linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-05-03 02:36:02.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-08-04 20:52:57.000000000 +0200 @@ -51,7 +51,7 @@ static int udp_packet(struct ip_conntrac { /* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ - if (conntrack->status & IPS_SEEN_REPLY) { + if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream); /* Also, more likely to be important, and not a probe */ set_bit(IPS_ASSURED_BIT, &conntrack->status); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-05-03 02:36:03.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-08-04 20:52:57.000000000 +0200 @@ -81,7 +81,7 @@ print_expect(char *buffer, const struct } static unsigned int -print_conntrack(char *buffer, const struct ip_conntrack *conntrack) +print_conntrack(char *buffer, struct ip_conntrack *conntrack) { unsigned int len; struct ip_conntrack_protocol *proto @@ -99,12 +99,12 @@ print_conntrack(char *buffer, const stru len += print_tuple(buffer + len, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, proto); - if (!(conntrack->status & IPS_SEEN_REPLY)) + if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status))) len += sprintf(buffer + len, "[UNREPLIED] "); len += print_tuple(buffer + len, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple, proto); - if (conntrack->status & IPS_ASSURED) + if (test_bit(IPS_ASSURED_BIT, &conntrack->status)) len += sprintf(buffer + len, "[ASSURED] "); len += sprintf(buffer + len, "use=%u ", atomic_read(&conntrack->ct_general.use)); diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_nat_helper.c --- linux-2.4.20-wolk4.4-fullkernel/net/ipv4/netfilter/ip_nat_helper.c 2003-05-03 02:36:02.000000000 +0200 +++ linux-2.4.20-wolk4.5-fullkernel/net/ipv4/netfilter/ip_nat_helper.c 2003-08-04 20:37:27.000000000 +0200 @@ -366,54 +366,49 @@ sack_adjust(struct tcphdr *tcph, } -/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */ -static inline int +/* TCP SACK sequence number adjustment. */ +static inline void ip_nat_sack_adjust(struct sk_buff *skb, - struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo) + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) { - struct iphdr *iph; struct tcphdr *tcph; - unsigned char *ptr; - int length, dir, sack_adjusted = 0; + unsigned char *ptr, *optend; + unsigned int dir; - iph = skb->nh.iph; - tcph = (void *)iph + iph->ihl*4; - length = (tcph->doff*4)-sizeof(struct tcphdr); + tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4; + optend = (unsigned char *)tcph + tcph->doff*4; ptr = (unsigned char *)(tcph+1); dir = CTINFO2DIR(ctinfo); - while (length > 0) { - int opcode = *ptr++; + while (ptr < optend) { + int opcode = ptr[0]; int opsize; switch (opcode) { case TCPOPT_EOL: - return !sack_adjusted; + return; case TCPOPT_NOP: - length--; + ptr++; continue; default: - opsize = *ptr++; - if (opsize > length) /* no partial opts */ - return !sack_adjusted; + opsize = ptr[1]; + /* no partial opts */ + if (ptr + opsize > optend || opsize < 2) + return; if (opcode == TCPOPT_SACK) { /* found SACK */ if((opsize >= (TCPOLEN_SACK_BASE +TCPOLEN_SACK_PERBLOCK)) && !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK)) - sack_adjust(tcph, ptr-2, + sack_adjust(tcph, ptr, &ct->nat.info.seq[!dir]); - - sack_adjusted = 1; } - ptr += opsize-2; - length -= opsize; + ptr += opsize; } } - return !sack_adjusted; } /* TCP sequence number adjustment */ diff -Naurp linux-2.4.20-wolk4.4-fullkernel/net/sunrpc/svcsock.c linux-2.4.20-wolk4.5-fullkernel/net/sunrpc/svcsock.c --- linux-2.4.20-wolk4.4-fullkernel/net/sunrpc/svcsock.c 2002-12-18 01:04:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/net/sunrpc/svcsock.c 2003-08-01 12:12:19.000000000 +0200 @@ -1229,7 +1229,8 @@ svc_create_socket(struct svc_serv *serv, return error; if (sin != NULL) { - sock->sk->reuse = 1; /* allow address reuse */ + if (type == SOCK_STREAM) + sock->sk->reuse = 1; /* allow address reuse */ error = sock->ops->bind(sock, (struct sockaddr *) sin, sizeof(*sin)); if (error < 0) diff -Naurp linux-2.4.20-wolk4.4-fullkernel/scripts/binoffset.c linux-2.4.20-wolk4.5-fullkernel/scripts/binoffset.c --- linux-2.4.20-wolk4.4-fullkernel/scripts/binoffset.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/scripts/binoffset.c 2003-08-04 21:45:26.000000000 +0200 @@ -0,0 +1,163 @@ +/*************************************************************************** + * binoffset.c + * (C) 2002 Randy Dunlap + * +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# binoffset.c: +# - searches a (binary) file for a specified (binary) pattern +# - returns the offset of the located pattern or ~0 if not found +# - exits with exit status 0 normally or non-0 if pattern is not found +# or any other error occurs. + +****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "0.1" +#define BUF_SIZE (16 * 1024) +#define PAT_SIZE 100 + +char *progname; +char *inputname; +int inputfd; +int bix; /* buf index */ +unsigned char patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */ +int pat_len; /* actual number of pattern bytes */ +unsigned char *madr; /* mmap address */ +size_t filesize; +int num_matches = 0; +off_t firstloc = 0; + +void usage (void) +{ + fprintf (stderr, "%s ver. %s\n", progname, VERSION); + fprintf (stderr, "usage: %s filename pattern_bytes\n", + progname); + fprintf (stderr, " [prints location of pattern_bytes in file]\n"); + exit (1); +} + +int get_pattern (int pat_count, char *pats []) +{ + int ix, err, tmp; + +#ifdef DEBUG + fprintf (stderr,"get_pattern: count = %d\n", pat_count); + for (ix = 0; ix < pat_count; ix++) + fprintf (stderr, " pat # %d: [%s]\n", ix, pats[ix]); +#endif + + for (ix = 0; ix < pat_count; ix++) { + tmp = 0; + err = sscanf (pats[ix], "%5i", &tmp); + if (err != 1 || tmp > 0xff) { + fprintf (stderr, "pattern or value error in pattern # %d [%s]\n", + ix, pats[ix]); + usage (); + } + patterns [ix] = tmp; + } + pat_len = pat_count; +} + +int search_pattern (void) +{ + for (bix = 0; bix < filesize; bix++) { + if (madr[bix] == patterns[0]) { + if (memcmp (&madr[bix], patterns, pat_len) == 0) { + if (num_matches == 0) + firstloc = bix; + num_matches++; + } + } + } +} + +#ifdef NOTDEF +size_t get_filesize (int fd) +{ + off_t end_off = lseek (fd, 0, SEEK_END); + lseek (fd, 0, SEEK_SET); + return (size_t) end_off; +} +#endif + +size_t get_filesize (int fd) +{ + int err; + struct stat stat; + + err = fstat (fd, &stat); + fprintf (stderr, "filesize: %d\n", err < 0 ? err : stat.st_size); + if (err < 0) + return err; + return (size_t) stat.st_size; +} + +int main (int argc, char *argv []) +{ + progname = argv[0]; + + if (argc < 3) + usage (); + + get_pattern (argc - 2, argv + 2); + + inputname = argv[1]; + + inputfd = open (inputname, O_RDONLY); + if (inputfd == -1) { + fprintf (stderr, "%s: cannot open '%s'\n", + progname, inputname); + exit (3); + } + + filesize = get_filesize (inputfd); + + madr = mmap (0, filesize, PROT_READ, MAP_PRIVATE, inputfd, 0); + if (madr == MAP_FAILED) { + fprintf (stderr, "mmap error = %d\n", errno); + close (inputfd); + exit (4); + } + + search_pattern (); + + if (munmap (madr, filesize)) + fprintf (stderr, "munmap error = %d\n", errno); + + if (close (inputfd)) + fprintf (stderr, "%s: error %d closing '%s'\n", + progname, errno, inputname); + + fprintf (stderr, "number of pattern matches = %d\n", num_matches); + if (num_matches == 0) + firstloc = ~0; + printf ("%d\n", firstloc); + fprintf (stderr, "%d\n", firstloc); + + exit (num_matches ? 0 : 2); +} + +/* end binoffset.c */ diff -Naurp linux-2.4.20-wolk4.4-fullkernel/scripts/extract-ikconfig linux-2.4.20-wolk4.5-fullkernel/scripts/extract-ikconfig --- linux-2.4.20-wolk4.4-fullkernel/scripts/extract-ikconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/scripts/extract-ikconfig 2003-08-04 21:45:26.000000000 +0200 @@ -0,0 +1,66 @@ +#! /bin/sh +# extracts .config info from a [b]zImage file +# uses: binoffset (new), dd, zcat, strings, grep +# $arg1 is [b]zImage filename + +TMPFILE="" + +usage() +{ + echo " usage: extract-ikconfig [b]zImage_filename" +} + +clean_up() +{ + if [ -z $ISCOMP ] + then + rm -f $TMPFILE + fi +} + +if [ $# -lt 1 ] +then + usage + exit +fi + +image=$1 + +# There are two gzip headers, as well as arches which don't compress their +# kernel. +GZHDR="0x1f 0x8b 0x08 0x00" +if [ `binoffset $image $GZHDR >/dev/null 2>&1 ; echo $?` -ne 0 ] +then + GZHDR="0x1f 0x8b 0x08 0x08" + if [ `binoffset $image $GZHDR >/dev/null 2>&1 ; echo $?` -ne 0 ] + then + ISCOMP=0 + fi +fi + +PID=$$ + +# Extract and uncompress the kernel image if necessary +if [ -z $ISCOMP ] +then + TMPFILE="/tmp/`basename $image`.vmlin.$PID" + dd if=$image bs=1 skip=`binoffset $image $GZHDR` 2> /dev/null | zcat > $TMPFILE +else + TMPFILE=$image +fi + +# Look for strings. +strings $TMPFILE | grep "CONFIG_BEGIN=n" > /dev/null +if [ $? -eq 0 ] +then + strings $TMPFILE | awk "/CONFIG_BEGIN=n/,/CONFIG_END=n/" > $image.oldconfig.$PID +else + echo "ERROR: Unable to extract kernel configuration information." + echo " This kernel image may not have the config info." + clean_up + exit 1 +fi + +echo "Kernel configuration written to $image.oldconfig.$PID" +clean_up +exit 0 diff -Naurp linux-2.4.20-wolk4.4-fullkernel/scripts/mkconfigs linux-2.4.20-wolk4.5-fullkernel/scripts/mkconfigs --- linux-2.4.20-wolk4.4-fullkernel/scripts/mkconfigs 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.20-wolk4.5-fullkernel/scripts/mkconfigs 2003-08-04 21:45:26.000000000 +0200 @@ -0,0 +1,81 @@ +#!/bin/sh +# +# Copyright (C) 2002 Khalid Aziz +# Copyright (C) 2002 Randy Dunlap +# Copyright (C) 2002 Al Stone +# Copyright (C) 2002 Hewlett-Packard Company +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# Rules to generate ikconfig.h from linux/.config: +# - Retain lines that begin with "CONFIG_" +# - Retain lines that begin with "# CONFIG_" +# - lines that use double-quotes must \\-escape-quote them + + +kernel_version() +{ + KERNVER="`grep VERSION $1 | head -1 | cut -f3 -d' '`.`grep PATCHLEVEL $1 | head -1 | cut -f3 -d' '`.`grep SUBLEVEL $1 | head -1 | cut -f3 -d' '``grep EXTRAVERSION $1 | head -1 | cut -f3 -d' '`" +} + +if [ $# -lt 2 ] +then + echo "Usage: `basename $0` " + exit 1 +fi + +config=$1 +makefile=$2 + +echo "#ifndef _IKCONFIG_H" +echo "#define _IKCONFIG_H" +echo \ +"/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * + * This file is generated automatically by scripts/mkconfigs. Do not edit. + * + */" + +echo "static char *ikconfig_built_with =" +echo " \"`uname -s` `uname -r` `uname -v` `uname -m`\";" +echo +kernel_version $makefile +echo "#ifdef CONFIG_IKCONFIG_PROC" +echo "static char *ikconfig_config = " +echo "#else" +echo "static char *ikconfig_config __initdata __attribute__((unused)) = " +echo "#endif" +echo "\"CONFIG_BEGIN=n\\n\\" +echo "`cat $config | sed 's/\"/\\\\\"/g' | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `" +echo "CONFIG_END=n\\n\";" +echo "#endif /* _IKCONFIG_H */"