diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle --- a/Documentation/CodingStyle Mon Feb 17 14:57:27 2003 +++ b/Documentation/CodingStyle Mon Feb 17 14:57:27 2003 @@ -173,7 +173,7 @@ user helper that "GNU emacs" automatically formats the C sources for you, and you've noticed that yes, it does do that, but the defaults it uses are less than desirable (in fact, they are worse than random -typing - a infinite number of monkeys typing into GNU emacs would never +typing - an infinite number of monkeys typing into GNU emacs would never make a good program). So, you can either get rid of GNU emacs, or change it to use saner diff -Nru a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt --- a/Documentation/cli-sti-removal.txt Mon Feb 17 14:57:27 2003 +++ b/Documentation/cli-sti-removal.txt Mon Feb 17 14:57:27 2003 @@ -121,9 +121,8 @@ another related change is that synchronize_irq() now takes a parameter: synchronize_irq(irq). This change too has the purpose of making SMP -to make the transition easier, we've still kept the cli(), sti(), -save_flags() and restore_flags() macros defined on UP systems - but -their usage will be phased out until the 2.6 kernel is released. +synchronization more lightweight - this way you can wait for your own +interrupt handler to finish, no need to wait for other IRQ sources. why were these changes done? The main reason was the architectural burden diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking --- a/Documentation/filesystems/Locking Mon Feb 17 14:57:28 2003 +++ b/Documentation/filesystems/Locking Mon Feb 17 14:57:28 2003 @@ -21,7 +21,7 @@ dcache_lock may block d_revalidate: no yes d_hash no yes -d_compare: yes no +d_compare: no no d_delete: yes no d_release: no yes d_iput: no yes diff -Nru a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt --- a/Documentation/s390/Debugging390.txt Mon Feb 17 14:57:27 2003 +++ b/Documentation/s390/Debugging390.txt Mon Feb 17 14:57:27 2003 @@ -10,7 +10,7 @@ This document is intended to give an good overview of how to debug Linux for s/390 & z/Architecture it isn't intended as a complete reference & not a tutorial on the fundamentals of C & assembly, it dosen't go into -390 IO in any detail. It is intended to compliment the documents in the +390 IO in any detail. It is intended to complement the documents in the reference section below & any other worthwhile references you get. It is intended like the Enterprise Systems Architecture/390 Reference Summary diff -Nru a/Makefile b/Makefile --- a/Makefile Mon Feb 17 14:57:26 2003 +++ b/Makefile Mon Feb 17 14:57:26 2003 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 61 +SUBLEVEL = 62 EXTRAVERSION = # *DOCUMENTATION* @@ -405,30 +405,17 @@ .PHONY: prepare prepare: include/linux/version.h include/asm include/config/MARKER -ifdef CONFIG_MODVERSIONS ifdef KBUILD_MODULES ifeq ($(origin SUBDIRS),file) $(Q)rm -rf $(MODVERDIR) - $(Q)mkdir $(MODVERDIR) else @echo '*** Warning: Overriding SUBDIRS on the command line can cause' - @echo '*** inconsistencies with module symbol versions' -endif + @echo '*** inconsistencies' endif + $(Q)mkdir -p $(MODVERDIR) endif @echo ' Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)' -# We need to build init/vermagic.o before descending since all modules -# (*.ko) need it already - -ifdef CONFIG_MODULES - -prepare: init/vermagic.o - -init/vermagic.o: include/linux/version.h - -endif - # This can be used by arch/$ARCH/Makefile to preprocess # their vmlinux.lds.S file @@ -518,21 +505,15 @@ # Build modules -.PHONY: modules __modversions -modules: $(SUBDIRS) __modversions - -ifdef CONFIG_MODVERSIONS - -__modversions: vmlinux $(SUBDIRS) - @echo ' Recording module symbol versions.'; - $(Q)$(MAKE) -rR -f scripts/Makefile.modver - -endif +.PHONY: modules +modules: $(SUBDIRS) $(if $(CONFIG_MODVERSIONS),vmlinux) + @echo ' Building modules, stage 2.'; + $(Q)$(MAKE) -rR -f scripts/Makefile.modpost # Install modules .PHONY: modules_install -modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post +modules_install: _modinst_ _modinst_post .PHONY: _modinst_ _modinst_: @@ -540,6 +521,7 @@ @rm -f $(MODLIB)/build @mkdir -p $(MODLIB)/kernel @ln -s $(TOPDIR) $(MODLIB)/build + $(Q)$(MAKE) -rR -f scripts/Makefile.modinst # If System.map exists, run depmod. This deliberately does not have a # dependency on System.map since that would run the dependency tree on @@ -552,13 +534,9 @@ depmod_opts := -b $(INSTALL_MOD_PATH) -r endif .PHONY: _modinst_post -_modinst_post: +_modinst_post: _modinst_ if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi -.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS)) -$(patsubst %, _modinst_%, $(SUBDIRS)) : - $(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$(patsubst _modinst_%,%,$@) - else # CONFIG_MODULES # Modules not configured @@ -726,8 +704,8 @@ $(call cmd,rmclean) @find . $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ - -o -name '.*.d' -o -name '.*.tmp' \) -type f \ - -print | xargs rm -f + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ + -type f -print | xargs rm -f # mrproper - delete configuration + modules + core files # diff -Nru a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c --- a/arch/alpha/kernel/asm-offsets.c Mon Feb 17 14:57:28 2003 +++ b/arch/alpha/kernel/asm-offsets.c Mon Feb 17 14:57:28 2003 @@ -7,6 +7,7 @@ #include #include #include +#include #include #define DEFINE(sym, val) \ diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c --- a/arch/alpha/kernel/core_marvel.c Mon Feb 17 14:57:26 2003 +++ b/arch/alpha/kernel/core_marvel.c Mon Feb 17 14:57:26 2003 @@ -1058,10 +1058,10 @@ } } - printk("MARVEL - using hose %d as AGP\n", hose->index); - if (!hose || !hose->sg_pci) return NULL; + + printk("MARVEL - using hose %d as AGP\n", hose->index); /* * Get the csrs from the hose. diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Mon Feb 17 14:57:26 2003 +++ b/arch/alpha/kernel/pci.c Mon Feb 17 14:57:26 2003 @@ -57,12 +57,6 @@ */ static void __init -quirk_eisa_bridge(struct pci_dev *dev) -{ - dev->class = PCI_CLASS_BRIDGE_EISA << 8; -} - -static void __init quirk_isa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_ISA << 8; @@ -125,8 +119,6 @@ } struct pci_fixup pcibios_fixups[] __initdata = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, - quirk_eisa_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, diff -Nru a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c --- a/arch/alpha/kernel/sys_marvel.c Mon Feb 17 14:57:28 2003 +++ b/arch/alpha/kernel/sys_marvel.c Mon Feb 17 14:57:28 2003 @@ -223,7 +223,7 @@ */ val = io7->csrs->PO7_LSI_CTL[which].csr; val &= ~(0x1ffUL << 14); /* clear the target pid */ - val |= ((unsigned long)where << 14); /* set teh new target pid */ + val |= ((unsigned long)where << 14); /* set the new target pid */ io7->csrs->PO7_LSI_CTL[which].csr = val; mb(); @@ -240,7 +240,7 @@ */ val = io7->csrs->PO7_MSI_CTL[which].csr; val &= ~(0x1ffUL << 14); /* clear the target pid */ - val |= ((unsigned long)where << 14); /* set teh new target pid */ + val |= ((unsigned long)where << 14); /* set the new target pid */ io7->csrs->PO7_MSI_CTL[which].csr = val; mb(); diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S --- a/arch/alpha/kernel/systbls.S Mon Feb 17 14:57:27 2003 +++ b/arch/alpha/kernel/systbls.S Mon Feb 17 14:57:27 2003 @@ -432,6 +432,7 @@ .quad sys_remap_file_pages /* 410 */ .quad sys_set_tid_address .quad sys_restart_syscall + .quad sys_fadvise64 .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff -Nru a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S --- a/arch/alpha/lib/csum_ipv6_magic.S Mon Feb 17 14:57:27 2003 +++ b/arch/alpha/lib/csum_ipv6_magic.S Mon Feb 17 14:57:27 2003 @@ -84,7 +84,7 @@ extwl $0,2,$1 # e0 : fold 17-bit value zapnot $0,3,$0 # .. e1 : addq $0,$1,$0 # e0 : - not $0,$0 # e1 : and compliment. + not $0,$0 # e1 : and complement. zapnot $0,3,$0 # e0 : ret # .. e1 : diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c --- a/arch/alpha/mm/numa.c Mon Feb 17 14:57:26 2003 +++ b/arch/alpha/mm/numa.c Mon Feb 17 14:57:26 2003 @@ -64,6 +64,7 @@ unsigned long bootmap_size, bootmap_pages, bootmap_start; unsigned long start, end; unsigned long node_pfn_start, node_pfn_end; + unsigned long node_min_pfn, node_max_pfn; int i; unsigned long node_datasz = PFN_UP(sizeof(pg_data_t)); int show_init = 0; @@ -76,8 +77,9 @@ memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb); - /* find the bounds of this node (min_low_pfn/max_low_pfn) */ - min_low_pfn = ~0UL; + /* find the bounds of this node (node_min_pfn/node_max_pfn) */ + node_min_pfn = ~0UL; + node_max_pfn = 0UL; for_each_mem_cluster(memdesc, cluster, i) { /* Bit 0 is console/PALcode reserved. Bit 1 is non-volatile memory -- we might want to mark @@ -104,42 +106,48 @@ if (end > node_pfn_end) end = node_pfn_end; - if (start < min_low_pfn) - min_low_pfn = start; - if (end > max_low_pfn) - max_pfn = max_low_pfn = end; + if (start < node_min_pfn) + node_min_pfn = start; + if (end > node_max_pfn) + node_max_pfn = end; } - if (mem_size_limit && max_low_pfn > mem_size_limit) { + if (mem_size_limit && node_max_pfn > mem_size_limit) { static int msg_shown = 0; if (!msg_shown) { msg_shown = 1; printk("setup: forcing memory size to %ldK (from %ldK).\n", mem_size_limit << (PAGE_SHIFT - 10), - max_low_pfn << (PAGE_SHIFT - 10)); + node_max_pfn << (PAGE_SHIFT - 10)); } - max_low_pfn = mem_size_limit; + node_max_pfn = mem_size_limit; } - if (min_low_pfn >= max_low_pfn) + if (node_min_pfn >= node_max_pfn) return; - num_physpages += max_low_pfn - min_low_pfn; + /* Update global {min,max}_low_pfn from node information. */ + if (node_min_pfn < min_low_pfn) + min_low_pfn = node_min_pfn; + if (node_max_pfn > max_low_pfn) + max_pfn = max_low_pfn = node_max_pfn; + + num_physpages += node_max_pfn - node_min_pfn; #if 0 /* we'll try this one again in a little while */ /* Cute trick to make sure our local node data is on local memory */ - node_data[nid] = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT)); + node_data[nid] = (pg_data_t *)(__va(node_min_pfn << PAGE_SHIFT)); #endif /* Quasi-mark the pg_data_t as in-use */ - min_low_pfn += node_datasz; - if (min_low_pfn >= max_low_pfn) { + node_min_pfn += node_datasz; + if (node_min_pfn >= node_max_pfn) { printk(" not enough mem to reserve NODE_DATA"); return; } NODE_DATA(nid)->bdata = &node_bdata[nid]; printk(" Detected node memory: start %8lu, end %8lu\n", - min_low_pfn, max_low_pfn); + node_min_pfn, node_max_pfn); DBGDCONT(" DISCONTIG: node_data[%d] is at 0x%p\n", nid, NODE_DATA(nid)); DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata); @@ -149,15 +157,15 @@ end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); bootmap_start = -1; - if (!nid && (max_low_pfn < end_kernel_pfn || min_low_pfn > start_kernel_pfn)) + if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn)) panic("kernel loaded out of ram"); /* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned */ - min_low_pfn = (min_low_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1); + node_min_pfn = (node_min_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1); /* We need to know how many physically contiguous pages we'll need for the bootmap. */ - bootmap_pages = bootmem_bootmap_pages(max_low_pfn-min_low_pfn); + bootmap_pages = bootmem_bootmap_pages(node_max_pfn-node_min_pfn); /* Now find a good region where to allocate the bootmap. */ for_each_mem_cluster(memdesc, cluster, i) { @@ -167,13 +175,13 @@ start = cluster->start_pfn; end = start + cluster->numpages; - if (start >= max_low_pfn || end <= min_low_pfn) + if (start >= node_max_pfn || end <= node_min_pfn) continue; - if (end > max_low_pfn) - end = max_low_pfn; - if (start < min_low_pfn) - start = min_low_pfn; + if (end > node_max_pfn) + end = node_max_pfn; + if (start < node_min_pfn) + start = node_min_pfn; if (start < start_kernel_pfn) { if (end > end_kernel_pfn @@ -195,7 +203,7 @@ /* Allocate the bootmap and mark the whole MM as reserved. */ bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start, - min_low_pfn, max_low_pfn); + node_min_pfn, node_max_pfn); DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n", bootmap_start, bootmap_size, bootmap_pages); @@ -207,13 +215,13 @@ start = cluster->start_pfn; end = cluster->start_pfn + cluster->numpages; - if (start >= max_low_pfn || end <= min_low_pfn) + if (start >= node_max_pfn || end <= node_min_pfn) continue; - if (end > max_low_pfn) - end = max_low_pfn; - if (start < min_low_pfn) - start = min_low_pfn; + if (end > node_max_pfn) + end = node_max_pfn; + if (start < node_min_pfn) + start = node_min_pfn; if (start < start_kernel_pfn) { if (end > end_kernel_pfn) { @@ -249,6 +257,9 @@ show_mem_layout(); numnodes = 0; + + min_low_pfn = ~0UL; + max_low_pfn = 0UL; for (nid = 0; nid < MAX_NUMNODES; nid++) setup_memory_node(nid, kernel_end); diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Mon Feb 17 14:57:27 2003 +++ b/arch/arm/Kconfig Mon Feb 17 14:57:27 2003 @@ -539,8 +539,8 @@ depends on CPU_FREQ default y -config CPU_FREQ_26_API - bool +config CPU_FREQ_PROC_INTF + tristate depends on CPU_FREQ default y diff -Nru a/arch/arm/common/sa1111-pcibuf.c b/arch/arm/common/sa1111-pcibuf.c --- a/arch/arm/common/sa1111-pcibuf.c Mon Feb 17 14:57:26 2003 +++ b/arch/arm/common/sa1111-pcibuf.c Mon Feb 17 14:57:26 2003 @@ -54,7 +54,7 @@ dma_addr_t safe_dma_addr; }; -LIST_HEAD(safe_buffers); +static LIST_HEAD(safe_buffers); #define SIZE_SMALL 1024 diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/common/sa1111.c Mon Feb 17 14:57:28 2003 @@ -218,7 +218,7 @@ * be triggered. In fact, its very difficult, if not impossible to get * INTSET to re-trigger the interrupt. */ -static void sa1111_rerun_lowirq(unsigned int irq) +static int sa1111_retrigger_lowirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_LO(irq); int i; @@ -233,6 +233,7 @@ if (i == 8) printk(KERN_ERR "Danger Will Robinson: failed to " "re-trigger IRQ%d\n", irq); + return i == 8 ? -1 : 0; } static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) @@ -270,7 +271,7 @@ .ack = sa1111_ack_irq, .mask = sa1111_mask_lowirq, .unmask = sa1111_unmask_lowirq, - .rerun = sa1111_rerun_lowirq, + .retrigger = sa1111_retrigger_lowirq, .type = sa1111_type_lowirq, .wake = sa1111_wake_lowirq, }; @@ -292,7 +293,7 @@ * be triggered. In fact, its very difficult, if not impossible to get * INTSET to re-trigger the interrupt. */ -static void sa1111_rerun_highirq(unsigned int irq) +static int sa1111_retrigger_highirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_HI(irq); int i; @@ -307,6 +308,7 @@ if (i == 8) printk(KERN_ERR "Danger Will Robinson: failed to " "re-trigger IRQ%d\n", irq); + return i == 8 ? -1 : 0; } static int sa1111_type_highirq(unsigned int irq, unsigned int flags) @@ -344,7 +346,7 @@ .ack = sa1111_ack_irq, .mask = sa1111_mask_highirq, .unmask = sa1111_unmask_highirq, - .rerun = sa1111_rerun_highirq, + .retrigger = sa1111_retrigger_highirq, .type = sa1111_type_highirq, .wake = sa1111_wake_highirq, }; diff -Nru a/arch/arm/def-configs/epxa10db b/arch/arm/def-configs/epxa10db --- a/arch/arm/def-configs/epxa10db Mon Feb 17 14:57:27 2003 +++ b/arch/arm/def-configs/epxa10db Mon Feb 17 14:57:27 2003 @@ -1,27 +1,31 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y +CONFIG_SWAP=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set + +# +# General setup +# +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 # # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_KMOD is not set # @@ -33,6 +37,7 @@ # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set CONFIG_ARCH_CAMELOT=y # CONFIG_ARCH_FOOTBRIDGE is not set @@ -46,106 +51,71 @@ # # Archimedes/A5000 Implementations # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set + +# +# Archimedes/A5000 Implementations (select only ONE) +# + +# +# CLPS711X/EP721X Implementations +# + +# +# Epxa10db +# + +# +# PLD hotswap support +# +CONFIG_PLD=y +# CONFIG_PLD_HOTSWAP is not set # # Footbridge Implementations # -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set + +# +# IOP310 Implementation Options +# + +# +# IOP310 Chipset Features +# + +# +# Intel PXA250/210 Implementations +# # # SA11x0 Implementations # -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_H3XXX is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_H3600_SLEEVE is not set # -# CLPS711X/EP721X Implementations +# Processor Type # -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set CONFIG_CPU_ARM922T=y -CONFIG_CPU_ARM922_CPU_IDLE=y -CONFIG_CPU_ARM922_I_CACHE_ON=y -CONFIG_CPU_ARM922_D_CACHE_ON=y -# CONFIG_CPU_ARM922_WRITETHROUGH is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -# CONFIG_XSCALE_PMU is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# # CONFIG_ARM_THUMB is not set -# CONFIG_DISCONTIGMEM is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set # # General setup # -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_FIQ is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y + +# +# At least one math emulation must be selected +# CONFIG_FPE_NWFPE=y # CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y @@ -154,7 +124,7 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set -# CONFIG_APM is not set +# CONFIG_PREEMPT is not set # CONFIG_ARTHUR is not set CONFIG_CMDLINE="mem=32M console=ttyUA0,38400 root=/dev/mtdblock0 rw" CONFIG_ALIGNMENT_TRAP=y @@ -171,9 +141,14 @@ CONFIG_MTD_DEBUG=y CONFIG_MTD_DEBUG_VERBOSE=0 CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_BOOTLDR_PARTS=y +# CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set @@ -192,9 +167,6 @@ # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set # CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set # # Mapping drivers for chip access @@ -202,24 +174,23 @@ # CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_NORA is not set # CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set CONFIG_MTD_EPXA10DB=y -# CONFIG_MTD_PCI is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_UCLINUX is not set # # Self-contained MTD device drivers # -# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# # CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set # # NAND Flash Device Drivers @@ -227,21 +198,14 @@ # CONFIG_MTD_NAND is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -252,23 +216,22 @@ # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -278,19 +241,26 @@ # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_XFRM_USER is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -303,54 +273,27 @@ # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set CONFIG_ETHER00=m -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set CONFIG_PPP=y CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y # CONFIG_PPP_DEFLATE is not set @@ -364,11 +307,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -377,21 +317,19 @@ # CONFIG_WAN is not set # -# Amateur Radio support +# IrDA (infrared) support # -# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set # -# IrDA (infrared) support +# Amateur Radio support # -# CONFIG_IRDA is not set +# CONFIG_HAMRADIO is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI support @@ -402,59 +340,48 @@ # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # -# Input core support +# Input device support # # CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# # # Character devices # -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_UART00=y CONFIG_SERIAL_UART00_CONSOLE=y -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_ATOMWIDE_SERIAL is not set -# CONFIG_DUALSP_SERIAL is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y @@ -466,33 +393,36 @@ # CONFIG_I2C is not set # +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# + +# # L3 serial bus support # # CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set -# CONFIG_L3_SA1111 is not set -# CONFIG_BIT_SA1100_GPIO is not set # # Mice # # CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Joysticks +# IPMI # -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -503,6 +433,7 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -516,50 +447,39 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set # CONFIG_CRAMFS is not set CONFIG_TMPFS=y CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set CONFIG_ROMFS_FS=y CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set # # Network File Systems @@ -568,107 +488,52 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set # CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Misc devices +# # # Multimedia Capabilities Port drivers # # CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set + +# +# Console Switches +# +# CONFIG_SWITCHES is not set # # USB support # -# CONFIG_USB is not set -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set # # Bluetooth support @@ -681,19 +546,21 @@ CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_NO_PGT_CACHE is not set # CONFIG_DEBUG_KERNEL is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_ERRORS is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set # # Library routines # # CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c --- a/arch/arm/kernel/init_task.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/kernel/init_task.c Mon Feb 17 14:57:28 2003 @@ -13,6 +13,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Mon Feb 17 14:57:26 2003 +++ b/arch/arm/kernel/irq.c Mon Feb 17 14:57:26 2003 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ static volatile unsigned long irq_err_count; static spinlock_t irq_controller_lock; +static LIST_HEAD(irq_pending); struct irqdesc irq_desc[NR_IRQS]; void (*init_arch_irq)(void) __initdata = NULL; @@ -69,9 +71,10 @@ }; static struct irqdesc bad_irq_desc = { - .chip = &bad_chip, - .handle = do_bad_IRQ, - .depth = 1, + .chip = &bad_chip, + .handle = do_bad_IRQ, + .pend = LIST_HEAD_INIT(bad_irq_desc.pend), + .disable_depth = 1, }; /** @@ -90,6 +93,7 @@ spin_lock_irqsave(&irq_controller_lock, flags); desc->disable_depth++; + list_del_init(&desc->pend); spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -122,9 +126,11 @@ * from here since the caller might be in an * interrupt-protected region. */ - if (desc->pending) { + if (desc->pending && list_empty(&desc->pend)) { desc->pending = 0; - desc->chip->rerun(irq); + if (!desc->chip->retrigger || + desc->chip->retrigger(irq)) + list_add(&desc->pend, &irq_pending); } } spin_unlock_irqrestore(&irq_controller_lock, flags); @@ -346,6 +352,40 @@ } } +static void do_pending_irqs(struct pt_regs *regs) +{ + struct list_head head, *l, *n; + + do { + struct irqdesc *desc; + + /* + * First, take the pending interrupts off the list. + * The act of calling the handlers may add some IRQs + * back onto the list. + */ + head = irq_pending; + INIT_LIST_HEAD(&irq_pending); + head.next->prev = &head; + head.prev->next = &head; + + /* + * Now run each entry. We must delete it from our + * list before calling the handler. + */ + list_for_each_safe(l, n, &head) { + desc = list_entry(l, struct irqdesc, pend); + list_del_init(&desc->pend); + desc->handle(desc - irq_desc, desc, regs); + } + + /* + * The list must be empty. + */ + BUG_ON(!list_empty(&head)); + } while (!list_empty(&irq_pending)); +} + /* * do_IRQ handles all hardware IRQ's. Decoded IRQs should not * come via this function. Instead, they should provide their @@ -365,6 +405,13 @@ irq_enter(); spin_lock(&irq_controller_lock); desc->handle(irq, desc, regs); + + /* + * Now re-run any pending interrupts. + */ + if (!list_empty(&irq_pending)) + do_pending_irqs(regs); + spin_unlock(&irq_controller_lock); irq_exit(); } @@ -740,8 +787,10 @@ extern void init_dma(void); int irq; - for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) + for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { *desc = bad_irq_desc; + INIT_LIST_HEAD(&desc->pend); + } init_arch_irq(); init_dma(); diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c --- a/arch/arm/kernel/ptrace.c Mon Feb 17 14:57:26 2003 +++ b/arch/arm/kernel/ptrace.c Mon Feb 17 14:57:26 2003 @@ -446,7 +446,7 @@ * Ensure no single-step breakpoint is pending. Returns non-zero * value if child was being single-stepped. */ -void __ptrace_cancel_bpt(struct task_struct *child) +void ptrace_cancel_bpt(struct task_struct *child) { int i, nsaved = child->thread.debug.nsaved; @@ -468,7 +468,8 @@ */ void ptrace_disable(struct task_struct *child) { - __ptrace_cancel_bpt(child); + child->ptrace &= ~PT_SINGLESTEP; + ptrace_cancel_bpt(child); } /* @@ -486,7 +487,7 @@ if (tsk->thread.debug.nsaved == 0) printk(KERN_ERR "ptrace: bogus breakpoint trap\n"); - __ptrace_cancel_bpt(tsk); + ptrace_cancel_bpt(tsk); info.si_signo = SIGTRAP; info.si_errno = 0; @@ -637,7 +638,8 @@ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; /* make sure single-step breakpoint is gone. */ - __ptrace_cancel_bpt(child); + child->ptrace &= ~PT_SINGLESTEP; + ptrace_cancel_bpt(child); wake_up_process(child); ret = 0; break; @@ -649,7 +651,8 @@ */ case PTRACE_KILL: /* make sure single-step breakpoint is gone. */ - __ptrace_cancel_bpt(child); + child->ptrace &= ~PT_SINGLESTEP; + ptrace_cancel_bpt(child); if (child->state != TASK_ZOMBIE) { child->exit_code = SIGKILL; wake_up_process(child); @@ -664,7 +667,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->thread.debug.nsaved = -1; + child->ptrace |= PT_SINGLESTEP; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; /* give it a chance to run. */ diff -Nru a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h --- a/arch/arm/kernel/ptrace.h Mon Feb 17 14:57:27 2003 +++ b/arch/arm/kernel/ptrace.h Mon Feb 17 14:57:27 2003 @@ -1,26 +1,12 @@ /* * linux/arch/arm/kernel/ptrace.h * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 2000-2003 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -extern void __ptrace_cancel_bpt(struct task_struct *); +extern void ptrace_cancel_bpt(struct task_struct *); extern void ptrace_set_bpt(struct task_struct *); extern void ptrace_break(struct task_struct *, struct pt_regs *); - -/* - * Clear a breakpoint, if one exists. - */ -static inline int ptrace_cancel_bpt(struct task_struct *tsk) -{ - int nsaved = tsk->thread.debug.nsaved; - - if (nsaved) - __ptrace_cancel_bpt(tsk); - - return nsaved; -} - diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c --- a/arch/arm/kernel/signal.c Mon Feb 17 14:57:26 2003 +++ b/arch/arm/kernel/signal.c Mon Feb 17 14:57:26 2003 @@ -216,8 +216,10 @@ goto badframe; /* Send SIGTRAP if we're single-stepping */ - if (ptrace_cancel_bpt(current)) + if (current->ptrace & PT_SINGLESTEP) { + ptrace_cancel_bpt(current); send_sig(SIGTRAP, current, 1); + } return regs->ARM_r0; @@ -256,8 +258,10 @@ goto badframe; /* Send SIGTRAP if we're single-stepping */ - if (ptrace_cancel_bpt(current)) + if (current->ptrace & PT_SINGLESTEP) { + ptrace_cancel_bpt(current); send_sig(SIGTRAP, current, 1); + } return regs->ARM_r0; @@ -441,19 +445,48 @@ return err; } +static inline void restart_syscall(struct pt_regs *regs) +{ + regs->ARM_r0 = regs->ARM_ORIG_r0; + regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; +} + /* * OK, we're invoking a handler */ static void -handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, int syscall) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; + struct k_sigaction *ka = &tsk->sighand->action[sig-1]; int usig = sig; int ret; /* + * If we were from a system call, check for system call restarting... + */ + if (syscall) { + switch (regs->ARM_r0) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = + do_no_restart_syscall; + case -ERESTARTNOHAND: + regs->ARM_r0 = -EINTR; + break; + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->ARM_r0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + restart_syscall(regs); + } + } + + /* * translate the signal */ if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) @@ -504,7 +537,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { siginfo_t info; - int single_stepping; + int signr; /* * We want the common case to go fast, which @@ -515,130 +548,14 @@ if (!user_mode(regs)) return 0; - single_stepping = ptrace_cancel_bpt(current); - - for (;;) { - unsigned long signr = 0; - struct k_sigaction *ka; - - spin_lock_irq(¤t->sighand->siglock); - signr = dequeue_signal(current, ¤t->blocked, &info); - spin_unlock_irq(¤t->sighand->siglock); - - if (!signr) - break; + if (current->ptrace & PT_SINGLESTEP) + ptrace_cancel_bpt(current); - if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { - /* Let the debugger run. */ - current->exit_code = signr; - set_current_state(TASK_STOPPED); - notify_parent(current, SIGCHLD); - schedule(); - single_stepping |= ptrace_cancel_bpt(current); - - /* We're back. Did the debugger cancel the sig? */ - signr = current->exit_code; - if (signr == 0) - continue; - current->exit_code = 0; - - /* The debugger continued. Ignore SIGSTOP. */ - if (signr == SIGSTOP) - continue; - - /* Update the siginfo structure. Is this good? */ - if (signr != info.si_signo) { - info.si_signo = signr; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->parent->pid; - info.si_uid = current->parent->uid; - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(¤t->blocked, signr)) { - send_sig_info(signr, &info, current); - continue; - } - } - - ka = ¤t->sig->action[signr-1]; - if (ka->sa.sa_handler == SIG_IGN) { - if (signr != SIGCHLD) - continue; - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; - continue; - } - - if (ka->sa.sa_handler == SIG_DFL) { - int exit_code = signr; - - /* Init gets no signals it doesn't want. */ - if (current->pid == 1) - continue; - - switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: - continue; - - case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) - continue; - /* FALLTHRU */ - - case SIGSTOP: { - struct signal_struct *sig; - set_current_state(TASK_STOPPED); - current->exit_code = signr; - sig = current->parent->sig; - if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) - notify_parent(current, SIGCHLD); - schedule(); - single_stepping |= ptrace_cancel_bpt(current); - continue; - } - - case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGABRT: case SIGFPE: case SIGSEGV: - case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: - if (do_coredump(signr, exit_code, regs)) - exit_code |= 0x80; - /* FALLTHRU */ - - default: - sig_exit(signr, exit_code, &info); - /* NOTREACHED */ - } - } - - /* Are we from a system call? */ - if (syscall) { - /* If so, check system call restarting.. */ - switch (regs->ARM_r0) { - case -ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = - do_no_restart_syscall; - case -ERESTARTNOHAND: - regs->ARM_r0 = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->ARM_r0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - regs->ARM_r0 = regs->ARM_ORIG_r0; - regs->ARM_pc -= 4; - } - } - /* Whee! Actually deliver the signal. */ - handle_signal(signr, ka, &info, oldset, regs); - if (single_stepping) - ptrace_set_bpt(current); + signr = get_signal_to_deliver(&info, regs, NULL); + if (signr > 0) { + handle_signal(signr, &info, oldset, regs, syscall); + if (current->ptrace & PT_SINGLESTEP) + ptrace_set_bpt(current); return 1; } @@ -668,11 +585,10 @@ if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { - regs->ARM_r0 = regs->ARM_ORIG_r0; - regs->ARM_pc -= 4; + restart_syscall(regs); } } - if (single_stepping) + if (current->ptrace & PT_SINGLESTEP) ptrace_set_bpt(current); return 0; } diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c --- a/arch/arm/kernel/traps.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/kernel/traps.c Mon Feb 17 14:57:27 2003 @@ -52,9 +52,14 @@ void dump_backtrace_entry(unsigned long where, unsigned long from) { +#ifdef CONFIG_KALLSYMS + printk("[<%08lx>] ", where); + print_symbol("(%s) ", where); + printk("from [<%08lx>] ", from); + print_symbol("(%s)\n", from); +#else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); - print_symbol(" %s", where); - printk("\n"); +#endif } /* @@ -503,11 +508,11 @@ die_if_kernel("unknown data abort code", regs, instr); } -void __bug(const char *file, int line, void *data) +volatile void __bug(const char *file, int line, void *data) { printk(KERN_CRIT"kernel BUG at %s:%d!", file, line); if (data) - printk(KERN_CRIT" - extra data = %p", data); + printk(" - extra data = %p", data); printk("\n"); *(int *)0 = 0; } diff -Nru a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S --- a/arch/arm/lib/backtrace.S Mon Feb 17 14:57:27 2003 +++ b/arch/arm/lib/backtrace.S Mon Feb 17 14:57:27 2003 @@ -82,11 +82,20 @@ teq r3, r2 bleq .Ldumpstm - teq frame, next - movne frame, next - teqne frame, #0 - bne 3b - LOADREGS(fd, sp!, {r4 - r8, pc}) + /* + * A zero next framepointer means we're done. + */ + teq next, #0 + LOADREGS(eqfd, sp!, {r4 - r8, pc}) + + /* + * The next framepointer must be above the + * current framepointer. + */ + cmp next, frame + mov frame, next + bhi 3b + b 1007f /* * Fixup for LDMDB diff -Nru a/arch/arm/mach-epxa10db/irq.c b/arch/arm/mach-epxa10db/irq.c --- a/arch/arm/mach-epxa10db/irq.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/mach-epxa10db/irq.c Mon Feb 17 14:57:27 2003 @@ -19,6 +19,9 @@ */ #include #include +#include +#include +#include #include #include #include diff -Nru a/arch/arm/mach-footbridge/irq.c b/arch/arm/mach-footbridge/irq.c --- a/arch/arm/mach-footbridge/irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mach-footbridge/irq.c Mon Feb 17 14:57:28 2003 @@ -15,6 +15,7 @@ * 16-Mar-1999 RMK Added autodetect of ISA PICs */ #include +#include #include #include diff -Nru a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c --- a/arch/arm/mach-footbridge/isa-irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mach-footbridge/isa-irq.c Mon Feb 17 14:57:28 2003 @@ -16,6 +16,7 @@ */ #include #include +#include #include #include diff -Nru a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c --- a/arch/arm/mach-iop310/iop310-irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mach-iop310/iop310-irq.c Mon Feb 17 14:57:28 2003 @@ -15,6 +15,7 @@ */ #include #include +#include #include #include diff -Nru a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c --- a/arch/arm/mach-iop310/iop310-pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/mach-iop310/iop310-pci.c Mon Feb 17 14:57:27 2003 @@ -360,6 +360,8 @@ if (!res) panic("PCI: unable to alloc resources"); + memset(res, 0, sizeof(struct resource) * 2); + switch (nr) { case 0: res[0].start = IOP310_PCIPRI_LOWER_IO + 0x6e000000; diff -Nru a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c --- a/arch/arm/mach-iop310/iq80310-irq.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/mach-iop310/iq80310-irq.c Mon Feb 17 14:57:27 2003 @@ -15,6 +15,7 @@ * Fixes for various revision boards - DS */ #include +#include #include #include diff -Nru a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c --- a/arch/arm/mach-iop310/xs80200-irq.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/mach-iop310/xs80200-irq.c Mon Feb 17 14:57:27 2003 @@ -11,6 +11,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c --- a/arch/arm/mach-pxa/irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mach-pxa/irq.c Mon Feb 17 14:57:28 2003 @@ -86,19 +86,6 @@ } /* - * Since we can't actually physically mask edge triggered interrupts - * without the risk of missing transitions, we therefore logically mask - * them and defer their processing through tis function. - */ - -static void pxa_manual_rerun(unsigned int irq) -{ - struct pt_regs regs; - memset(®s, 0, sizeof(regs)); - irq_desc[irq].handle(irq, &irq_desc[irq], ®s); -} - -/* * GPIO IRQs must be acknoledged. This is for GPIO 0 and 1. */ @@ -111,7 +98,6 @@ .ack = pxa_ack_low_gpio, .mask = pxa_mask_irq, .unmask = pxa_unmask_irq, - .rerun = pxa_manual_rerun, .type = pxa_gpio_irq_type, }; diff -Nru a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c --- a/arch/arm/mach-rpc/irq.c Mon Feb 17 14:57:26 2003 +++ b/arch/arm/mach-rpc/irq.c Mon Feb 17 14:57:26 2003 @@ -1,4 +1,5 @@ #include +#include #include #include diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c --- a/arch/arm/mach-sa1100/irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mach-sa1100/irq.c Mon Feb 17 14:57:28 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -24,20 +25,12 @@ /* * SA1100 GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, or both. - * This must be called *before* the appropriate IRQ is registered. * Use this instead of directly setting GRER/GFER. */ static int GPIO_IRQ_rising_edge; static int GPIO_IRQ_falling_edge; static int GPIO_IRQ_mask = (1 << 11) - 1; -static void sa1100_manual_rerun(unsigned int irq) -{ - struct pt_regs regs; - memset(®s, 0, sizeof(regs)); - irq_desc[irq].handle(irq, &irq_desc[irq], ®s); -} - /* * To get the GPIO number from an IRQ number */ @@ -105,7 +98,6 @@ .ack = sa1100_low_gpio_ack, .mask = sa1100_low_gpio_mask, .unmask = sa1100_low_gpio_unmask, - .rerun = sa1100_manual_rerun, .type = sa1100_gpio_type, .wake = sa1100_low_gpio_wake, }; @@ -189,7 +181,6 @@ .ack = sa1100_high_gpio_ack, .mask = sa1100_high_gpio_mask, .unmask = sa1100_high_gpio_unmask, - .rerun = sa1100_manual_rerun, .type = sa1100_gpio_type, .wake = sa1100_high_gpio_wake, }; @@ -212,7 +203,6 @@ .ack = sa1100_mask_irq, .mask = sa1100_mask_irq, .unmask = sa1100_unmask_irq, - /* rerun should never be called */ }; static struct resource irq_resource = { @@ -267,10 +257,4 @@ */ set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip); set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); - - /* - * We generally don't want the LCD IRQ being - * enabled as soon as we request it. - */ - set_irq_flags(IRQ_LCD, IRQF_VALID/* | IRQF_NOAUTOEN*/); } diff -Nru a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c --- a/arch/arm/mach-sa1100/xp860.c Mon Feb 17 14:57:27 2003 +++ b/arch/arm/mach-sa1100/xp860.c Mon Feb 17 14:57:27 2003 @@ -15,9 +15,9 @@ #include #include #include +#include #include "generic.h" -#include "sa1111.h" static void xp860_power_off(void) diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c --- a/arch/arm/mm/consistent.c Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mm/consistent.c Mon Feb 17 14:57:28 2003 @@ -83,7 +83,7 @@ struct vm_region *c; printk("Consistent Allocation Map (%s):\n", fn); - list_for_each_entry(c, &head->list, vm_list) { + list_for_each_entry(c, &head->vm_list, vm_list) { printk(" %p: %08lx - %08lx (0x%08x)\n", c, c->vm_start, c->vm_end, c->vm_end - c->vm_start); } diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S --- a/arch/arm/mm/proc-xscale.S Mon Feb 17 14:57:28 2003 +++ b/arch/arm/mm/proc-xscale.S Mon Feb 17 14:57:28 2003 @@ -678,7 +678,7 @@ mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes mrc p15, 0, r0, c1, c0, 0 @ get control register bic r0, r0, #0x0200 @ .... ..R. .... .... - bic r0, r0, #0x0082 @ .... .... B... ..A. + bic r0, r0, #0x0002 @ .... .... .... ..A. orr r0, r0, #0x0005 @ .... .... .... .C.M orr r0, r0, #0x3900 @ ..VI Z..S .... .... mov pc, lr diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in --- a/arch/arm/vmlinux-armv.lds.in Mon Feb 17 14:57:27 2003 +++ b/arch/arm/vmlinux-armv.lds.in Mon Feb 17 14:57:27 2003 @@ -7,7 +7,11 @@ OUTPUT_ARCH(arm) ENTRY(stext) +#ifndef __ARMEB__ jiffies = jiffies_64; +#else +jiffies = jiffies_64 + 4; +#endif SECTIONS { . = TEXTADDR; diff -Nru a/arch/cris/drivers/eeprom.c b/arch/cris/drivers/eeprom.c --- a/arch/cris/drivers/eeprom.c Mon Feb 17 14:57:27 2003 +++ b/arch/cris/drivers/eeprom.c Mon Feb 17 14:57:27 2003 @@ -207,7 +207,7 @@ * it will mirror the address space: * 1. We read two locations (that are mirrored), * if the content differs * it's a 16kB EEPROM. - * 2. if it doesn't differ - write diferent value to one of the locations, + * 2. if it doesn't differ - write different value to one of the locations, * check the other - if content still is the same it's a 2k EEPROM, * restore original data. */ diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Mon Feb 17 14:57:27 2003 +++ b/arch/i386/Kconfig Mon Feb 17 14:57:27 2003 @@ -969,7 +969,7 @@ If in doubt, say N. config CPU_FREQ_PROC_INTF - bool "/proc/cpufreq interface (DEPRECATED)" + tristate "/proc/cpufreq interface (DEPRECATED)" depends on CPU_FREQ && PROC_FS help This enables the /proc/cpufreq interface for controlling @@ -994,9 +994,19 @@ If in doubt, say N. +config CPU_FREQ_TABLE + tristate "CPU frequency table helpers" + depends on CPU_FREQ + default y + help + Many CPUFreq drivers use these helpers, so only say N here if + the CPUFreq driver of your choice doesn't need these helpers. + + If in doubt, say Y. + config X86_ACPI_CPUFREQ tristate "ACPI Processor P-States driver" - depends on CPU_FREQ && ACPI_PROCESSOR + depends on CPU_FREQ_TABLE && ACPI_PROCESSOR help This driver adds a CPUFreq driver which utilizes the ACPI Processor Performance States. @@ -1007,7 +1017,7 @@ config X86_POWERNOW_K6 tristate "AMD Mobile K6-2/K6-3 PowerNow!" - depends on CPU_FREQ + depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for mobile AMD K6-2+ and mobile AMD K6-3+ processors. @@ -1018,7 +1028,7 @@ config X86_POWERNOW_K7 tristate "AMD Mobile Athlon/Duron PowerNow!" - depends on CPU_FREQ + depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for mobile AMD K7 mobile processors. @@ -1028,7 +1038,7 @@ config ELAN_CPUFREQ tristate "AMD Elan" - depends on CPU_FREQ && MELAN + depends on CPU_FREQ_TABLE && MELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 processors. @@ -1055,7 +1065,7 @@ config X86_SPEEDSTEP tristate "Intel Speedstep" - depends on CPU_FREQ + depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for certain mobile Intel Pentium III (Coppermine), all mobile Intel Pentium III-M (Tulatin) and all @@ -1067,7 +1077,7 @@ config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" - depends on CPU_FREQ + depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for Intel Pentium 4 / XEON processors. diff -Nru a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c --- a/arch/i386/kernel/cpu/mtrr/generic.c Mon Feb 17 14:57:27 2003 +++ b/arch/i386/kernel/cpu/mtrr/generic.c Mon Feb 17 14:57:27 2003 @@ -83,15 +83,13 @@ if (!mask) return; if (mask & MTRR_CHANGE_MASK_FIXED) - printk - ("mtrr: your CPUs had inconsistent fixed MTRR settings\n"); + printk(KERN_WARNING "mtrr: your CPUs had inconsistent fixed MTRR settings\n"); if (mask & MTRR_CHANGE_MASK_VARIABLE) - printk - ("mtrr: your CPUs had inconsistent variable MTRR settings\n"); + printk(KERN_WARNING "mtrr: your CPUs had inconsistent variable MTRR settings\n"); if (mask & MTRR_CHANGE_MASK_DEFTYPE) - printk - ("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); - printk("mtrr: probably your BIOS does not setup all CPUs\n"); + printk(KERN_WARNING "mtrr: your CPUs had inconsistent MTRRdefType settings\n"); + printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n"); + printk(KERN_INFO "mtrr: corrected configuration.\n"); } @@ -338,23 +336,19 @@ boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_mask <= 7) { if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) { - printk(KERN_WARNING - "mtrr: base(0x%lx000) is not 4 MiB aligned\n", - base); + printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); return -EINVAL; } if (!(base + size < 0x70000000 || base > 0x7003FFFF) && (type == MTRR_TYPE_WRCOMB || type == MTRR_TYPE_WRBACK)) { - printk(KERN_WARNING - "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); + printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); return -EINVAL; } } if (base + size < 0x100) { - printk(KERN_WARNING - "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n", + printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n", base, size); return -EINVAL; } @@ -364,8 +358,7 @@ for (lbase = base; !(lbase & 1) && (last & 1); lbase = lbase >> 1, last = last >> 1) ; if (lbase != last) { - printk(KERN_WARNING - "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", + printk(KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size); return -EINVAL; } diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Mon Feb 17 14:57:27 2003 +++ b/arch/i386/kernel/io_apic.c Mon Feb 17 14:57:27 2003 @@ -668,7 +668,9 @@ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA || - mp_bus_id_to_type[lbus] == MP_BUS_MCA) && + mp_bus_id_to_type[lbus] == MP_BUS_MCA || + mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + ) && (mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_srcbusirq == irq)) @@ -762,6 +764,12 @@ #define default_MCA_trigger(idx) (1) #define default_MCA_polarity(idx) (0) +/* NEC98 interrupts are always polarity zero edge triggered, + * when listed as conforming in the MP table. */ + +#define default_NEC98_trigger(idx) (0) +#define default_NEC98_polarity(idx) (0) + static int __init MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; @@ -796,6 +804,11 @@ polarity = default_MCA_polarity(idx); break; } + case MP_BUS_NEC98: /* NEC 98 pin */ + { + polarity = default_NEC98_polarity(idx); + break; + } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -865,6 +878,11 @@ trigger = default_MCA_trigger(idx); break; } + case MP_BUS_NEC98: /* NEC 98 pin */ + { + trigger = default_NEC98_trigger(idx); + break; + } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -926,6 +944,7 @@ case MP_BUS_ISA: /* ISA pin */ case MP_BUS_EISA: case MP_BUS_MCA: + case MP_BUS_NEC98: { irq = mp_irqs[idx].mpc_srcbusirq; break; @@ -1133,8 +1152,9 @@ void __init UNEXPECTED_IO_APIC(void) { - printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n"); - printk(KERN_WARNING " to linux-smp@vger.kernel.org\n"); + printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n"); + printk(KERN_WARNING " http://bugzilla.kernel.org\n"); + printk(KERN_WARNING " if your kernel is less than 3 months old.\n"); } void __init print_IO_APIC(void) diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Mon Feb 17 14:57:27 2003 +++ b/arch/i386/kernel/mpparse.c Mon Feb 17 14:57:27 2003 @@ -169,7 +169,7 @@ num_processors++; if (m->mpc_apicid > MAX_APICS) { - printk("Processor #%d INVALID. (Max ID: %d).\n", + printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); --num_processors; return; @@ -182,7 +182,7 @@ * Validate version */ if (ver == 0x0) { - printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); + printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); ver = 0x10; } apic_version[m->mpc_apicid] = ver; @@ -209,8 +209,10 @@ mp_current_pci_id++; } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; + } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98; } else { - printk("Unknown bustype %s - ignoring\n", str); + printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); } } @@ -219,10 +221,10 @@ if (!(m->mpc_flags & MPC_APIC_USABLE)) return; - printk("I/O APIC #%d Version %d at 0x%lX.\n", + printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n", m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); if (nr_ioapics >= MAX_IO_APICS) { - printk("Max # of I/O APICs (%d) exceeded (found %d).\n", + printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n", MAX_IO_APICS, nr_ioapics); panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); } @@ -272,10 +274,10 @@ #ifdef CONFIG_X86_NUMAQ static void __init MP_translation_info (struct mpc_config_translation *m) { - printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); + printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); if (mpc_record >= MAX_MPC_ENTRY) - printk("MAX_MPC_ENTRY exceeded!\n"); + printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); else translation_table[mpc_record] = m; /* stash this for later */ if (m->trans_quad+1 > numnodes) @@ -293,10 +295,10 @@ unsigned char *oemptr = ((unsigned char *)oemtable)+count; mpc_record = 0; - printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable); + printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4)) { - printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n", + printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", oemtable->oem_signature[0], oemtable->oem_signature[1], oemtable->oem_signature[2], @@ -305,7 +307,7 @@ } if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length)) { - printk("SMP oem mptable: checksum error!\n"); + printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); return; } while (count < oemtable->oem_length) { @@ -322,7 +324,7 @@ } default: { - printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr); + printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr); return; } } @@ -364,7 +366,7 @@ } memcpy(oem,mpc->mpc_oem,8); oem[8]=0; - printk("OEM ID: %s ",oem); + printk(KERN_INFO "OEM ID: %s ",oem); memcpy(str,mpc->mpc_productid,12); str[12]=0; @@ -479,12 +481,12 @@ * If it does, we assume it's valid. */ if (mpc_default_type == 5) { - printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); + printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13)) - printk("ELCR contains invalid data... not using ELCR\n"); + printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n"); else { - printk("Using ELCR to identify PCI interrupts\n"); + printk(KERN_INFO "Using ELCR to identify PCI interrupts\n"); ELCR_fallback = 1; } } @@ -559,7 +561,8 @@ bus.mpc_busid = 0; switch (mpc_default_type) { default: - printk("???\nUnknown standard configuration %d\n", + printk("???\n"); + printk(KERN_ERR "Unknown standard configuration %d\n", mpc_default_type); /* fall through */ case 1: @@ -628,12 +631,12 @@ else if (acpi_lapic) printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); - printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); + printk("KERN_INFO Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { - printk(" IMCR and PIC compatibility mode.\n"); + printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); pic_mode = 1; } else { - printk(" Virtual Wire compatibility mode.\n"); + printk(KERN_INFO " Virtual Wire compatibility mode.\n"); pic_mode = 0; } @@ -642,7 +645,7 @@ */ if (mpf->mpf_feature1 != 0) { - printk("Default MP configuration #%d\n", mpf->mpf_feature1); + printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1); construct_default_ISA_mptable(mpf->mpf_feature1); } else if (mpf->mpf_physptr) { @@ -665,7 +668,7 @@ if (!mp_irq_entries) { struct mpc_config_bus bus; - printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); + printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); bus.mpc_type = MP_BUS; bus.mpc_busid = 0; @@ -678,7 +681,7 @@ } else BUG(); - printk("Processors: %d\n", num_processors); + printk(KERN_INFO "Processors: %d\n", num_processors); /* * Only use the first configuration found. */ @@ -702,7 +705,7 @@ || (mpf->mpf_specification == 4)) ) { smp_found_config = 1; - printk("found SMP MP-table at %08lx\n", + printk(KERN_INFO "found SMP MP-table at %08lx\n", virt_to_phys(mpf)); reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); if (mpf->mpf_physptr) @@ -752,8 +755,6 @@ address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; smp_scan_config(address, 0x400); - if (smp_found_config) - printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n"); } diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Mon Feb 17 14:57:26 2003 +++ b/arch/i386/kernel/process.c Mon Feb 17 14:57:26 2003 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c Mon Feb 17 14:57:26 2003 +++ b/arch/i386/kernel/smp.c Mon Feb 17 14:57:26 2003 @@ -452,9 +452,11 @@ void flush_tlb_all(void) { + preempt_disable(); smp_call_function (flush_tlb_all_ipi,0,1,1); do_flush_tlb_all_local(); + preempt_enable(); } /* diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Mon Feb 17 14:57:27 2003 +++ b/arch/i386/kernel/traps.c Mon Feb 17 14:57:27 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef CONFIG_EISA #include diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Mon Feb 17 14:57:26 2003 +++ b/arch/i386/kernel/vm86.c Mon Feb 17 14:57:26 2003 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c --- a/arch/i386/mach-voyager/voyager_thread.c Mon Feb 17 14:57:27 2003 +++ b/arch/i386/mach-voyager/voyager_thread.c Mon Feb 17 14:57:27 2003 @@ -57,7 +57,7 @@ } static int -execute_helper(void *string) +execute(const char *string) { int ret; @@ -74,20 +74,11 @@ NULL, }; - if((ret = exec_usermodehelper(argv[0], argv, envp)) < 0) { - printk(KERN_ERR "Voyager failed to execute \"%s\"\n", - (char *)string); + if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) { + printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", + string, ret); } return ret; -} - -static void -execute(char *string) -{ - if(kernel_thread(execute_helper, (void *)string, CLONE_VFORK | SIGCHLD) < 0) { - printk(KERN_ERR "Voyager failed to fork before exec of \"%s\"\n", - string); - } } static void diff -Nru a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c --- a/arch/i386/math-emu/fpu_entry.c Mon Feb 17 14:57:28 2003 +++ b/arch/i386/math-emu/fpu_entry.c Mon Feb 17 14:57:28 2003 @@ -25,6 +25,7 @@ +---------------------------------------------------------------------------*/ #include +#include #include #include diff -Nru a/arch/ia64/sn/io/io.c b/arch/ia64/sn/io/io.c --- a/arch/ia64/sn/io/io.c Mon Feb 17 14:57:27 2003 +++ b/arch/ia64/sn/io/io.c Mon Feb 17 14:57:27 2003 @@ -631,7 +631,7 @@ } /* - * Check that an address is in teh real small window widget 0 space + * Check that an address is in the real small window widget 0 space * or else in the big window we're using to emulate small window 0 * in the kernel. */ @@ -708,7 +708,7 @@ /* * hub_setup_prb(nasid, prbnum, credits, conveyor) * - * Put a PRB into fire-and-forget mode if conveyor isn't set. Otehrwise, + * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, * put it into conveyor belt mode with the specified number of credits. */ void diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c --- a/arch/m68k/kernel/traps.c Mon Feb 17 14:57:28 2003 +++ b/arch/m68k/kernel/traps.c Mon Feb 17 14:57:28 2003 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c --- a/arch/m68knommu/kernel/asm-offsets.c Mon Feb 17 14:57:28 2003 +++ b/arch/m68knommu/kernel/asm-offsets.c Mon Feb 17 14:57:28 2003 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c --- a/arch/m68knommu/kernel/traps.c Mon Feb 17 14:57:27 2003 +++ b/arch/m68knommu/kernel/traps.c Mon Feb 17 14:57:27 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/mips/ddb5xxx/common/nile4.c b/arch/mips/ddb5xxx/common/nile4.c --- a/arch/mips/ddb5xxx/common/nile4.c Mon Feb 17 14:57:27 2003 +++ b/arch/mips/ddb5xxx/common/nile4.c Mon Feb 17 14:57:27 2003 @@ -109,7 +109,7 @@ * When programming a PDAR, the register should be read immediately * after writing it. This ensures that address decoders are properly * configured. - * [jsun] is this really necesary? + * [jsun] is this really necessary? */ ddb_in32(pdar); ddb_in32(pdar + 4); diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c --- a/arch/mips/kernel/irixsig.c Mon Feb 17 14:57:28 2003 +++ b/arch/mips/kernel/irixsig.c Mon Feb 17 14:57:28 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c --- a/arch/mips/kernel/sysmips.c Mon Feb 17 14:57:27 2003 +++ b/arch/mips/kernel/sysmips.c Mon Feb 17 14:57:27 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c --- a/arch/parisc/hpux/fs.c Mon Feb 17 14:57:27 2003 +++ b/arch/parisc/hpux/fs.c Mon Feb 17 14:57:27 2003 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c --- a/arch/parisc/kernel/sys_parisc32.c Mon Feb 17 14:57:27 2003 +++ b/arch/parisc/kernel/sys_parisc32.c Mon Feb 17 14:57:27 2003 @@ -53,6 +53,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S --- a/arch/parisc/kernel/syscall.S Mon Feb 17 14:57:28 2003 +++ b/arch/parisc/kernel/syscall.S Mon Feb 17 14:57:28 2003 @@ -320,7 +320,8 @@ #ifdef __LP64__ /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific - * implementation is required on wide palinux. + * implementation is required on wide palinux. Use ENTRY_COMP where + * the compatability layer has a useful 32-bit implementation. */ #define ENTRY_SAME(_name_) .dword sys_##_name_ #define ENTRY_DIFF(_name_) .dword sys32_##_name_ @@ -597,7 +598,7 @@ ENTRY_SAME(ni_syscall) /* tkill */ ENTRY_SAME(sendfile64) - ENTRY_SAME(futex) /* 210 */ + ENTRY_COMP(futex) /* 210 */ ENTRY_SAME(sched_setaffinity) ENTRY_SAME(sched_getaffinity) ENTRY_SAME(set_thread_area) diff -Nru a/arch/ppc/boot/common/cpc700_memory.c b/arch/ppc/boot/common/cpc700_memory.c --- a/arch/ppc/boot/common/cpc700_memory.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/common/cpc700_memory.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dan Cox * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c --- a/arch/ppc/boot/common/misc-common.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/common/misc-common.c Mon Feb 17 14:57:27 2003 @@ -9,7 +9,7 @@ * Derived from arch/ppc/boot/prep/misc.c * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/common/mpc10x_memory.c b/arch/ppc/boot/common/mpc10x_memory.c --- a/arch/ppc/boot/common/mpc10x_memory.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/common/mpc10x_memory.c Mon Feb 17 14:57:27 2003 @@ -10,7 +10,7 @@ * mgreer@mvista.com * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S --- a/arch/ppc/boot/common/util.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/common/util.S Mon Feb 17 14:57:28 2003 @@ -15,7 +15,7 @@ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h --- a/arch/ppc/boot/include/mpc10x.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/include/mpc10x.h Mon Feb 17 14:57:27 2003 @@ -13,7 +13,7 @@ * mgreer@mvista.com * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile --- a/arch/ppc/boot/simple/Makefile Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/boot/simple/Makefile Mon Feb 17 14:57:26 2003 @@ -4,7 +4,7 @@ # Author: Tom Rini # # 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under -# the terms of the GNU General Public License version 2.1. This program +# the terms of the GNU General Public License version 2. This program # is licensed "as is" without any warranty of any kind, whether express # or implied. # diff -Nru a/arch/ppc/boot/simple/gt64260_tty.c b/arch/ppc/boot/simple/gt64260_tty.c --- a/arch/ppc/boot/simple/gt64260_tty.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/simple/gt64260_tty.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S --- a/arch/ppc/boot/simple/head.S Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/simple/head.S Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/misc-ev64260.S b/arch/ppc/boot/simple/misc-ev64260.S --- a/arch/ppc/boot/simple/misc-ev64260.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/simple/misc-ev64260.S Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * Author: Mark Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c --- a/arch/ppc/boot/simple/misc-spruce.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/simple/misc-spruce.c Mon Feb 17 14:57:27 2003 @@ -9,7 +9,7 @@ * Derived from arch/ppc/boot/prep/misc.c * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c --- a/arch/ppc/boot/simple/misc.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/simple/misc.c Mon Feb 17 14:57:28 2003 @@ -11,7 +11,7 @@ * Derived from arch/ppc/boot/prep/misc.c * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S --- a/arch/ppc/boot/simple/relocate.S Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/simple/relocate.S Mon Feb 17 14:57:27 2003 @@ -10,7 +10,7 @@ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h --- a/arch/ppc/boot/simple/rw4/ppc_40x.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h Mon Feb 17 14:57:27 2003 @@ -41,9 +41,9 @@ #define dbsr 0x3f0 /* debug status register */ #define dccr 0x3fa /* data cache control reg. */ #define dcwr 0x3ba /* data cache write-thru reg */ -#define dear 0x3d5 /* data exeption address reg */ -#define esr 0x3d4 /* execption syndrome registe */ -#define evpr 0x3d6 /* exeption vector prefix reg */ +#define dear 0x3d5 /* data exception address reg */ +#define esr 0x3d4 /* exception syndrome registe */ +#define evpr 0x3d6 /* exception vector prefix reg */ #define iccr 0x3fb /* instruction cache cntrl re */ #define icdbdr 0x3d3 /* instr cache dbug data reg */ #define lrreg 0x008 /* link register */ diff -Nru a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c --- a/arch/ppc/boot/utils/addnote.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/utils/addnote.c Mon Feb 17 14:57:28 2003 @@ -14,6 +14,7 @@ * Usage: addnote zImage */ #include +#include #include #include #include diff -Nru a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c --- a/arch/ppc/boot/utils/hack-coff.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/utils/hack-coff.c Mon Feb 17 14:57:27 2003 @@ -11,8 +11,10 @@ * 2 of the License, or (at your option) any later version. */ #include +#include #include #include +#include #include "rs6000.h" #define AOUT_MAGIC 0x010b diff -Nru a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c --- a/arch/ppc/boot/utils/mkbugboot.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/boot/utils/mkbugboot.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c --- a/arch/ppc/boot/utils/mknote.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/boot/utils/mknote.c Mon Feb 17 14:57:28 2003 @@ -11,6 +11,7 @@ */ #include +#include #define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff ); diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/kernel/head.S Mon Feb 17 14:57:27 2003 @@ -1337,7 +1337,7 @@ blr /* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some - * erratas we work around here. + * errata we work around here. * Moto MPC710CE.pdf describes them, those are errata * #3, #4 and #5 * Note that we assume the firmware didn't choose to diff -Nru a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S --- a/arch/ppc/kernel/head_4xx.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/head_4xx.S Mon Feb 17 14:57:28 2003 @@ -923,6 +923,8 @@ ori r3,r3,KERNELBASE@l tophys(r4,r3) /* Load the kernel physical address */ + iccci r0,r3 /* Invalidate the i-cache before use */ + /* Load the kernel PID. */ li r0,0 diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/irq.c Mon Feb 17 14:57:28 2003 @@ -20,7 +20,7 @@ * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit * mask register (of which only 16 are defined), hence the weird shifting - * and compliment of the cached_irq_mask. I want to be able to stuff + * and complement of the cached_irq_mask. I want to be able to stuff * this right into the SIU SMASK register. * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx * to reduce code space and undefined function references. diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/misc.S Mon Feb 17 14:57:28 2003 @@ -1273,8 +1273,8 @@ .long sys_io_getevents .long sys_io_submit /* 230 */ .long sys_io_cancel - .long sys_ni_syscall /* reserved for alloc_hugepages */ - .long sys_ni_syscall /* reserved for free_hugepages */ + .long sys_set_tid_address + .long sys_fadvise64 .long sys_exit_group .long sys_lookup_dcookie /* 235 */ .long sys_epoll_create diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/ppc_ksyms.c Mon Feb 17 14:57:28 2003 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -69,8 +70,6 @@ long long __lshrdi3(long long, int); int abs(int); -extern unsigned char __res[]; - extern unsigned long mm_ptov (unsigned long paddr); EXPORT_SYMBOL(clear_page); @@ -180,6 +179,7 @@ EXPORT_SYMBOL(consistent_alloc); EXPORT_SYMBOL(consistent_free); EXPORT_SYMBOL(consistent_sync); +EXPORT_SYMBOL(flush_dcache_all); #endif EXPORT_SYMBOL(open); @@ -269,6 +269,8 @@ #endif /* CONFIG_NVRAM */ EXPORT_SYMBOL(to_tm); +EXPORT_SYMBOL(pm_power_off); + EXPORT_SYMBOL_NOVERS(__ashrdi3); EXPORT_SYMBOL_NOVERS(__ashldi3); EXPORT_SYMBOL_NOVERS(__lshrdi3); @@ -329,10 +331,12 @@ #endif #ifdef CONFIG_8xx -EXPORT_SYMBOL(__res); EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); #endif /* CONFIG_8xx */ +#if defined(CONFIG_8xx) || defined(CONFIG_4xx) +EXPORT_SYMBOL(__res); +#endif #if defined(CONFIG_8xx) || defined(CONFIG_8260) EXPORT_SYMBOL(request_8xxirq); #endif diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/kernel/process.c Mon Feb 17 14:57:27 2003 @@ -54,6 +54,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* this is 8kB-aligned so we can get to the thread_info struct diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c --- a/arch/ppc/kernel/ptrace.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/kernel/ptrace.c Mon Feb 17 14:57:27 2003 @@ -369,11 +369,9 @@ if (!test_thread_flag(TIF_SYSCALL_TRACE) || !(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); + /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/setup.c Mon Feb 17 14:57:28 2003 @@ -129,6 +129,8 @@ ppc_md.halt(); } +void (*pm_power_off)(void) = machine_power_off; + #ifdef CONFIG_TAU extern u32 cpu_temp(unsigned long cpu); extern u32 cpu_temp_both(unsigned long cpu); diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c --- a/arch/ppc/kernel/signal.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/kernel/signal.c Mon Feb 17 14:57:28 2003 @@ -389,7 +389,7 @@ { struct sigcontext *sc; struct rt_sigframe *rt_sf; - struct k_sigaction *ka = ¤t->sig->action[sig-1]; + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; if (TRAP(regs) == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || @@ -486,7 +486,7 @@ signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - ka = ¤t->sig->action[signr-1]; + ka = ¤t->sighand->action[signr-1]; if ( (ka->sa.sa_flags & SA_ONSTACK) && (! on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); diff -Nru a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c --- a/arch/ppc/platforms/4xx/ash.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ash.c Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Armin Kuster * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h --- a/arch/ppc/platforms/4xx/ash.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ash.h Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/cedar.c b/arch/ppc/platforms/4xx/cedar.c --- a/arch/ppc/platforms/4xx/cedar.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/cedar.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/cedar.h b/arch/ppc/platforms/4xx/cedar.h --- a/arch/ppc/platforms/4xx/cedar.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/cedar.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c --- a/arch/ppc/platforms/4xx/ep405.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ep405.c Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * Author: Matthew Locke * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h --- a/arch/ppc/platforms/4xx/ep405.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ep405.h Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * Author: Matthew Locke * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c --- a/arch/ppc/platforms/4xx/ibm405gp.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibm405gp.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h --- a/arch/ppc/platforms/4xx/ibm405gp.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ibm405gp.h Mon Feb 17 14:57:26 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster akuster@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c --- a/arch/ppc/platforms/4xx/ibm405gpr.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibm405gpr.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h --- a/arch/ppc/platforms/4xx/ibm405gpr.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibm405gpr.h Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c --- a/arch/ppc/platforms/4xx/ibmnp405h.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/ibmnp405h.c Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h --- a/arch/ppc/platforms/4xx/ibmnp405h.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmnp405h.h Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp405l.c b/arch/ppc/platforms/4xx/ibmnp405l.c --- a/arch/ppc/platforms/4xx/ibmnp405l.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmnp405l.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp405l.h b/arch/ppc/platforms/4xx/ibmnp405l.h --- a/arch/ppc/platforms/4xx/ibmnp405l.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmnp405l.h Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp4gs.c b/arch/ppc/platforms/4xx/ibmnp4gs.c --- a/arch/ppc/platforms/4xx/ibmnp4gs.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmnp4gs.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmnp4gs.h b/arch/ppc/platforms/4xx/ibmnp4gs.h --- a/arch/ppc/platforms/4xx/ibmnp4gs.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmnp4gs.h Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstb3.c b/arch/ppc/platforms/4xx/ibmstb3.c --- a/arch/ppc/platforms/4xx/ibmstb3.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ibmstb3.c Mon Feb 17 14:57:26 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstb3.h b/arch/ppc/platforms/4xx/ibmstb3.h --- a/arch/ppc/platforms/4xx/ibmstb3.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/ibmstb3.h Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * Authors: Armin Kuster , Tom Rini * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c --- a/arch/ppc/platforms/4xx/ibmstb4.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/ibmstb4.c Mon Feb 17 14:57:26 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h --- a/arch/ppc/platforms/4xx/ibmstb4.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/ibmstb4.h Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c --- a/arch/ppc/platforms/4xx/ibmstbx25.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmstbx25.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h --- a/arch/ppc/platforms/4xx/ibmstbx25.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/ibmstbx25.h Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood.c b/arch/ppc/platforms/4xx/redwood.c --- a/arch/ppc/platforms/4xx/redwood.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/redwood.c Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * Author: Frank Rowand , or source@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood.h b/arch/ppc/platforms/4xx/redwood.h --- a/arch/ppc/platforms/4xx/redwood.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/redwood.h Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * Author: Frank Rowand , or source@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c --- a/arch/ppc/platforms/4xx/redwood5.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/redwood5.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h --- a/arch/ppc/platforms/4xx/redwood5.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/4xx/redwood5.h Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c --- a/arch/ppc/platforms/4xx/redwood6.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/4xx/redwood6.c Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h --- a/arch/ppc/platforms/4xx/redwood6.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/redwood6.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c --- a/arch/ppc/platforms/4xx/sycamore.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/sycamore.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h --- a/arch/ppc/platforms/4xx/sycamore.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/sycamore.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * Author: Armin Kuster * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c --- a/arch/ppc/platforms/4xx/walnut.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/walnut.c Mon Feb 17 14:57:27 2003 @@ -9,7 +9,7 @@ * Copyright(c) 1999-2000 Grant Erickson * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h --- a/arch/ppc/platforms/4xx/walnut.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/4xx/walnut.h Mon Feb 17 14:57:27 2003 @@ -11,7 +11,7 @@ * Copyright (c) 1999 Grant Erickson * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h --- a/arch/ppc/platforms/ev64260.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/ev64260.h Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/ev64260_setup.c b/arch/ppc/platforms/ev64260_setup.c --- a/arch/ppc/platforms/ev64260_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/ev64260_setup.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h --- a/arch/ppc/platforms/k2.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/k2.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/k2_pci.c b/arch/ppc/platforms/k2_pci.c --- a/arch/ppc/platforms/k2_pci.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/k2_pci.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/k2_setup.c b/arch/ppc/platforms/k2_setup.c --- a/arch/ppc/platforms/k2_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/k2_setup.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/lopec_pci.c b/arch/ppc/platforms/lopec_pci.c --- a/arch/ppc/platforms/lopec_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/lopec_pci.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * danc@mvista.com (or, alternately, source@mvista.com) * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/lopec_serial.h b/arch/ppc/platforms/lopec_serial.h --- a/arch/ppc/platforms/lopec_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/lopec_serial.h Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * danc@mvista.com (or, alternately, source@mvista.com) * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c --- a/arch/ppc/platforms/lopec_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/lopec_setup.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * danc@mvista.com * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h --- a/arch/ppc/platforms/mcpn765.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/mcpn765.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mcpn765_pci.c b/arch/ppc/platforms/mcpn765_pci.c --- a/arch/ppc/platforms/mcpn765_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/mcpn765_pci.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mcpn765_serial.h b/arch/ppc/platforms/mcpn765_serial.h --- a/arch/ppc/platforms/mcpn765_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/mcpn765_serial.h Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mcpn765_setup.c b/arch/ppc/platforms/mcpn765_setup.c --- a/arch/ppc/platforms/mcpn765_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/mcpn765_setup.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/menf1.h b/arch/ppc/platforms/menf1.h --- a/arch/ppc/platforms/menf1.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/menf1.h Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/menf1_pci.c b/arch/ppc/platforms/menf1_pci.c --- a/arch/ppc/platforms/menf1_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/menf1_pci.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c --- a/arch/ppc/platforms/menf1_setup.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/menf1_setup.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h --- a/arch/ppc/platforms/mvme5100.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/mvme5100.h Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mvme5100_pci.c b/arch/ppc/platforms/mvme5100_pci.c --- a/arch/ppc/platforms/mvme5100_pci.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/mvme5100_pci.c Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mvme5100_serial.h b/arch/ppc/platforms/mvme5100_serial.h --- a/arch/ppc/platforms/mvme5100_serial.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/mvme5100_serial.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c --- a/arch/ppc/platforms/mvme5100_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/mvme5100_setup.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h --- a/arch/ppc/platforms/pal4.h Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/pal4.h Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Dan Cox * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c --- a/arch/ppc/platforms/pal4_pci.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/pal4_pci.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dan Cox * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h --- a/arch/ppc/platforms/pal4_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/pal4_serial.h Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dan Cox * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c --- a/arch/ppc/platforms/pal4_setup.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/pal4_setup.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dan Cox * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h --- a/arch/ppc/platforms/pcore.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/pcore.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pcore_pci.c b/arch/ppc/platforms/pcore_pci.c --- a/arch/ppc/platforms/pcore_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/pcore_pci.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c --- a/arch/ppc/platforms/pcore_setup.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/pcore_setup.c Mon Feb 17 14:57:26 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c --- a/arch/ppc/platforms/powerpmc250.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/powerpmc250.c Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h --- a/arch/ppc/platforms/powerpmc250.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/powerpmc250.h Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * Borrowed heavily from prpmc750.h by Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/powerpmc250_serial.h b/arch/ppc/platforms/powerpmc250_serial.h --- a/arch/ppc/platforms/powerpmc250_serial.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/powerpmc250_serial.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Troy Benjegerdes * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pplus_pci.c b/arch/ppc/platforms/pplus_pci.c --- a/arch/ppc/platforms/pplus_pci.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/pplus_pci.c Mon Feb 17 14:57:28 2003 @@ -10,7 +10,7 @@ * Troy Benjegerdes. * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c --- a/arch/ppc/platforms/pplus_setup.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/pplus_setup.c Mon Feb 17 14:57:28 2003 @@ -10,7 +10,7 @@ * Troy Benjegerdes. * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc750_pci.c b/arch/ppc/platforms/prpmc750_pci.c --- a/arch/ppc/platforms/prpmc750_pci.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/prpmc750_pci.c Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc750_serial.h b/arch/ppc/platforms/prpmc750_serial.h --- a/arch/ppc/platforms/prpmc750_serial.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/prpmc750_serial.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc750_setup.c b/arch/ppc/platforms/prpmc750_setup.c --- a/arch/ppc/platforms/prpmc750_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/prpmc750_setup.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h --- a/arch/ppc/platforms/prpmc800.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/prpmc800.h Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dale Farnsworth * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc800_pci.c b/arch/ppc/platforms/prpmc800_pci.c --- a/arch/ppc/platforms/prpmc800_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/prpmc800_pci.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Dale Farnsworth * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc800_serial.h b/arch/ppc/platforms/prpmc800_serial.h --- a/arch/ppc/platforms/prpmc800_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/prpmc800_serial.h Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Dale Farnsworth dale.farnsworth@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/prpmc800_setup.c b/arch/ppc/platforms/prpmc800_setup.c --- a/arch/ppc/platforms/prpmc800_setup.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/prpmc800_setup.c Mon Feb 17 14:57:27 2003 @@ -3,7 +3,7 @@ * Author: Dale Farnsworth * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h --- a/arch/ppc/platforms/sandpoint.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/sandpoint.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/sandpoint_pci.c b/arch/ppc/platforms/sandpoint_pci.c --- a/arch/ppc/platforms/sandpoint_pci.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/sandpoint_pci.c Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/sandpoint_serial.h b/arch/ppc/platforms/sandpoint_serial.h --- a/arch/ppc/platforms/sandpoint_serial.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/sandpoint_serial.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c --- a/arch/ppc/platforms/sandpoint_setup.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/sandpoint_setup.c Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/spruce.h b/arch/ppc/platforms/spruce.h --- a/arch/ppc/platforms/spruce.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/spruce.h Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * jpeters@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/spruce_pci.c b/arch/ppc/platforms/spruce_pci.c --- a/arch/ppc/platforms/spruce_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/spruce_pci.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * jpeters@mvista.com * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/spruce_serial.h b/arch/ppc/platforms/spruce_serial.h --- a/arch/ppc/platforms/spruce_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/spruce_serial.h Mon Feb 17 14:57:28 2003 @@ -8,7 +8,7 @@ * jpeters@mvista.com * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c --- a/arch/ppc/platforms/spruce_setup.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/spruce_setup.c Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * Matt Porter * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/zx4500.h b/arch/ppc/platforms/zx4500.h --- a/arch/ppc/platforms/zx4500.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/platforms/zx4500.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/zx4500_pci.c b/arch/ppc/platforms/zx4500_pci.c --- a/arch/ppc/platforms/zx4500_pci.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/zx4500_pci.c Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/zx4500_serial.h b/arch/ppc/platforms/zx4500_serial.h --- a/arch/ppc/platforms/zx4500_serial.h Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/platforms/zx4500_serial.h Mon Feb 17 14:57:28 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c --- a/arch/ppc/platforms/zx4500_setup.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/platforms/zx4500_setup.c Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h --- a/arch/ppc/syslib/cpc700.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/cpc700.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c --- a/arch/ppc/syslib/cpc700_pic.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/cpc700_pic.c Mon Feb 17 14:57:27 2003 @@ -9,7 +9,7 @@ * jpeters@mvista.com * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h --- a/arch/ppc/syslib/cpc710.h Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/cpc710.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/gt64260_common.c b/arch/ppc/syslib/gt64260_common.c --- a/arch/ppc/syslib/gt64260_common.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/syslib/gt64260_common.c Mon Feb 17 14:57:26 2003 @@ -8,7 +8,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c --- a/arch/ppc/syslib/gt64260_pic.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/gt64260_pic.c Mon Feb 17 14:57:27 2003 @@ -9,7 +9,7 @@ * Based on sources from Rabeeh Khoury / Galileo Technology * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c --- a/arch/ppc/syslib/harrier.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/harrier.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * dale.farnsworth@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c --- a/arch/ppc/syslib/mpc10x_common.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/mpc10x_common.c Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/pci_auto.c b/arch/ppc/syslib/pci_auto.c --- a/arch/ppc/syslib/pci_auto.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/pci_auto.c Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Matt Porter * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c --- a/arch/ppc/syslib/ppc405_pci.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/ppc405_pci.c Mon Feb 17 14:57:27 2003 @@ -4,7 +4,7 @@ * Further modifications by Armin Kuster * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c --- a/arch/ppc/syslib/ppc4xx_dma.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/syslib/ppc4xx_dma.c Mon Feb 17 14:57:28 2003 @@ -4,7 +4,7 @@ * arch/ppc/kernel/ppc405_dma.c * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/arch/ppc/syslib/ppc4xx_pm.c b/arch/ppc/syslib/ppc4xx_pm.c --- a/arch/ppc/syslib/ppc4xx_pm.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/syslib/ppc4xx_pm.c Mon Feb 17 14:57:26 2003 @@ -2,7 +2,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/arch/ppc/syslib/ppc4xx_serial.c b/arch/ppc/syslib/ppc4xx_serial.c --- a/arch/ppc/syslib/ppc4xx_serial.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc/syslib/ppc4xx_serial.c Mon Feb 17 14:57:26 2003 @@ -9,7 +9,7 @@ * be merged with other similar processor/boards. -- Dan * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/arch/ppc/syslib/pplus_common.c b/arch/ppc/syslib/pplus_common.c --- a/arch/ppc/syslib/pplus_common.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc/syslib/pplus_common.c Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c --- a/arch/ppc/syslib/todc_time.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc/syslib/todc_time.c Mon Feb 17 14:57:28 2003 @@ -8,7 +8,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/Kconfig Mon Feb 17 14:57:27 2003 @@ -128,6 +128,10 @@ tristate "Firmware flash interface" depends on !PPC_ISERIES +config SCANLOG + tristate "Scanlog dump interface" + depends on !PPC_ISERIES + config PPC_RTAS bool "Proc interface to RTAS" depends on !PPC_ISERIES @@ -186,9 +190,6 @@ ELF (Executable and Linkable Format) is a format for libraries and executables used across different architectures and operating systems. - -config BINFMT_ELF32 - tristate "Kernel support for 32-bit ELF binaries" config BINFMT_MISC tristate "Kernel support for MISC binaries" diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig --- a/arch/ppc64/defconfig Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/defconfig Mon Feb 17 14:57:27 2003 @@ -26,7 +26,12 @@ # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set # # Platform support @@ -256,6 +261,7 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_MII=y # CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set @@ -452,6 +458,7 @@ # CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=y +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/Makefile Mon Feb 17 14:57:28 2003 @@ -30,3 +30,4 @@ obj-$(CONFIG_PROFILING) += profile.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PPC_RTAS) += rtas-proc.o +obj-$(CONFIG_SCANLOG) += scanlog.o diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/align.c Mon Feb 17 14:57:28 2003 @@ -237,8 +237,12 @@ dsisr = regs->dsisr; /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) - dsisr = make_dsisr( *((unsigned *)regs->nip) ); + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + unsigned int real_instr; + if (__get_user(real_instr, (unsigned int *)regs->nip)) + return 0; + dsisr = make_dsisr(real_instr); + } /* extract the operation and registers from the dsisr */ reg = (dsisr >> 5) & 0x1f; /* source/dest register */ diff -Nru a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c --- a/arch/ppc64/kernel/binfmt_elf32.c Mon Feb 17 14:57:26 2003 +++ b/arch/ppc64/kernel/binfmt_elf32.c Mon Feb 17 14:57:26 2003 @@ -74,12 +74,6 @@ #define init_elf_binfmt init_elf32_binfmt #undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif +#define CONFIG_BINFMT_ELF 1 #include "../../../fs/binfmt_elf.c" diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Mon Feb 17 14:57:26 2003 +++ b/arch/ppc64/kernel/entry.S Mon Feb 17 14:57:26 2003 @@ -102,7 +102,6 @@ * Need to vector to 32 Bit or default sys_call_table here, * based on caller's run-mode / personality. */ -#ifdef CONFIG_BINFMT_ELF32 andi. r11,r10,_TIF_32BIT beq- 15f ld r10,.SYS_CALL_TABLE32@toc(2) @@ -118,7 +117,6 @@ clrldi r8,r8,32 b 17f 15: -#endif ld r10,.SYS_CALL_TABLE@toc(2) 17: slwi r0,r0,3 ldx r10,r10,r0 /* Fetch system call handler [ptr] */ @@ -171,7 +169,6 @@ * Need to vector to 32 Bit or default sys_call_table here, * based on caller's run-mode / personality. */ -#ifdef CONFIG_BINFMT_ELF32 clrrdi r10,r1,THREAD_SHIFT ld r10,TI_FLAGS(r10) andi. r11,r10,_TIF_32BIT @@ -189,7 +186,6 @@ clrldi r8,r8,32 b 57f 55: -#endif ld r10,.SYS_CALL_TABLE@toc(2) 57: slwi r0,r0,3 diff -Nru a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c --- a/arch/ppc64/kernel/i8259.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/i8259.c Mon Feb 17 14:57:28 2003 @@ -11,10 +11,11 @@ #include #include #include -#include -#include "i8259.h" #include +#include +#include #include +#include "i8259.h" unsigned char cached_8259[2] = { 0xff, 0xff }; #define cached_A1 (cached_8259[0]) diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/ioctl32.c Mon Feb 17 14:57:28 2003 @@ -3656,6 +3656,7 @@ COMPATIBLE_IOCTL(TCSETAW), COMPATIBLE_IOCTL(TCSETAF), COMPATIBLE_IOCTL(TCSBRK), +COMPATIBLE_IOCTL(TCSBRKP), COMPATIBLE_IOCTL(TCXONC), COMPATIBLE_IOCTL(TCFLSH), COMPATIBLE_IOCTL(TCGETS), @@ -4495,7 +4496,7 @@ { int i; if (!additional_ioctls) { - additional_ioctls = get_zeroed_page(GFP_KERNEL); + additional_ioctls = (struct ioctl_trans *)get_zeroed_page(GFP_KERNEL); if (!additional_ioctls) return -ENOMEM; } diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/misc.S Mon Feb 17 14:57:28 2003 @@ -499,7 +499,6 @@ SYSCALL(execve) SYSCALL(waitpid) -#ifdef CONFIG_BINFMT_ELF32 /* Why isn't this a) automatic, b) written in 'C'? */ .balign 8 _GLOBAL(sys_call_table32) @@ -631,8 +630,8 @@ .llong .sys_mprotect /* 125 */ .llong .compat_sys_sigprocmask .llong .sys_ni_syscall /* old create_module syscall */ - .llong .sys32_init_module - .llong .sys32_delete_module + .llong .sys_init_module + .llong .sys_delete_module .llong .sys_ni_syscall /* 130 old get_kernel_syms syscall */ .llong .sys_quotactl .llong .sys32_getpgid @@ -666,7 +665,7 @@ .llong .sys32_sched_get_priority_min /* 160 */ .llong .sys32_sched_rr_get_interval .llong .compat_sys_nanosleep - .llong .sys32_mremap + .llong .sys_mremap .llong .sys_setresuid .llong .sys_getresuid /* 165 */ .llong .sys_ni_syscall /* old query_module syscall */ @@ -724,7 +723,7 @@ .llong .sys_removexattr .llong .sys_lremovexattr .llong .sys_fremovexattr /* 220 */ - .llong .sys_futex + .llong .compat_sys_futex .llong .sys32_sched_setaffinity .llong .sys32_sched_getaffinity .llong .sys_ni_syscall @@ -735,10 +734,10 @@ .llong .sys_ni_syscall /* reserved for sys_io_getevents */ .llong .sys_ni_syscall /* 230 - reserved for sys_io_submit */ .llong .sys_ni_syscall /* reserved for sys_io_cancel */ - .llong .sys_ni_syscall /* reserved for alloc_hugepages */ - .llong .sys_ni_syscall /* reserved for free_hugepages */ + .llong .sys_set_tid_address + .llong .ppc32_fadvise64 .llong .sys_exit_group - .llong .sys32_lookup_dcookie /* 245 */ + .llong .ppc32_lookup_dcookie /* 245 */ .llong .sys_epoll_create .llong .sys_epoll_ctl .llong .sys_epoll_wait @@ -747,7 +746,6 @@ .rept NR_syscalls-239 .llong .sys_ni_syscall .endr -#endif .balign 8 _GLOBAL(sys_call_table) @@ -983,8 +981,8 @@ .llong .sys_io_getevents .llong .sys_io_submit /* 230 */ .llong .sys_io_cancel - .llong .sys_ni_syscall - .llong .sys_ni_syscall + .llong .sys_set_tid_address + .llong .sys_fadvise64 .llong .sys_exit_group .llong .sys_lookup_dcookie /* 235 */ .llong .sys_epoll_create diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/kernel/process.c Mon Feb 17 14:57:27 2003 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c --- a/arch/ppc64/kernel/ptrace.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/ptrace.c Mon Feb 17 14:57:28 2003 @@ -292,11 +292,11 @@ return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + /* the 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); + /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/kernel/rtas.c Mon Feb 17 14:57:27 2003 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,9 @@ extern unsigned long reloc_offset(void); +spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED; +char rtas_data_buf[RTAS_DATA_BUF_SIZE]; + void phys_call_rtas(int token, int nargs, int nret, ...) { @@ -278,3 +282,10 @@ rtas_flash_bypass_warning(); rtas_power_off(); } + +EXPORT_SYMBOL(rtas_proc_dir); +EXPORT_SYMBOL(rtas_firmware_flash_list); +EXPORT_SYMBOL(rtas_token); +EXPORT_SYMBOL(rtas_call); +EXPORT_SYMBOL(rtas_data_buf); +EXPORT_SYMBOL(rtas_data_buf_lock); diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c --- a/arch/ppc64/kernel/rtasd.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/kernel/rtasd.c Mon Feb 17 14:57:27 2003 @@ -147,8 +147,8 @@ { int error; - error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN, - 0, SURVEILLANCE_TIMEOUT); + error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, + SURVEILLANCE_TOKEN, 0, SURVEILLANCE_TIMEOUT); if (error) { printk(KERN_ERR "rtasd: could not enable surveillance\n"); @@ -243,11 +243,13 @@ } while(error == 0); - /* Check all cpus for pending events before sleeping*/ - if (!first_pass) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ*60/rtas_event_scan_rate) / 2); - } + /* + * Check all cpus for pending events quickly, sleeping for + * at least one second since some machines have problems + * if we call event-scan too quickly + */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2); } if (first_pass && surveillance_requested) { @@ -255,10 +257,9 @@ if (enable_surveillance()) goto error_vfree; DEBUG("surveillance enabled\n"); - } else { - first_pass = 0; } + first_pass = 0; goto repeat; error_vfree: diff -Nru a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/scanlog.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,249 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * 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. + * + * scan-log-data driver for PPC64 Todd Inglett + * + * When ppc64 hardware fails the service processor dumps internal state + * of the system. After a reboot the operating system can access a dump + * of this data using this driver. A dump exists if the device-tree + * /chosen/ibm,scan-log-data property exists. + * + * This driver exports /proc/ppc64/scan-log-dump which can be read. + * The driver supports only sequential reads. + * + * The driver looks at a write to the driver for the single word "reset". + * If given, the driver will reset the scanlog so the platform can free it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_VERSION "1.0" +#define MODULE_NAME "scanlog" + +/* Status returns from ibm,scan-log-dump */ +#define SCANLOG_COMPLETE 0 +#define SCANLOG_HWERROR -1 +#define SCANLOG_CONTINUE 1 + +#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0) + +static int scanlog_debug; +static unsigned int ibm_scan_log_dump; /* RTAS token */ +static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ + +extern struct proc_dir_entry *proc_rtas; + + +static ssize_t scanlog_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + struct proc_dir_entry *dp; + unsigned int *data; + unsigned long status; + unsigned long len, off; + unsigned int wait_time; + + dp = PDE(inode); + data = (unsigned int *)dp->data; + + if (!data) { + printk(KERN_ERR "scanlog: read failed no data\n"); + return -EIO; + } + + if (count > RTAS_DATA_BUF_SIZE) + count = RTAS_DATA_BUF_SIZE; + + if (count < 1024) { + /* This is the min supported by this RTAS call. Rather + * than do all the buffering we insist the user code handle + * larger reads. As long as cp works... :) + */ + printk(KERN_ERR "scanlog: cannot perform a small read (%ld)\n", count); + return -EINVAL; + } + + if (verify_area(VERIFY_WRITE, buf, count)) + return -EFAULT; + + for (;;) { + wait_time = HZ/2; /* default wait if no data */ + spin_lock(&rtas_data_buf_lock); + memcpy(rtas_data_buf, data, RTAS_DATA_BUF_SIZE); + status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, + __pa(rtas_data_buf), count); + memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE); + spin_unlock(&rtas_data_buf_lock); + + DEBUG("status=%ld, data[0]=%x, data[1]=%x, data[2]=%x\n", + status, data[0], data[1], data[2]); + switch (status) { + case SCANLOG_COMPLETE: + DEBUG("hit eof\n"); + return 0; + case SCANLOG_HWERROR: + DEBUG("hardware error reading scan log data\n"); + return -EIO; + case SCANLOG_CONTINUE: + /* We may or may not have data yet */ + len = data[1]; + off = data[2]; + if (len > 0) { + if (copy_to_user(buf, ((char *)data)+off, len)) + return -EFAULT; + return len; + } + /* Break to sleep default time */ + break; + default: + if (status > 9900 && status <= 9905) { + /* No data. RTAS is hinting at a delay required + * between 1-100000 milliseconds + */ + int ms = 1; + for (; status > 9900; status--) + ms = ms * 10; + /* Use microseconds for reasonable accuracy */ + ms *= 1000; + wait_time = ms / (1000000/HZ); /* round down is fine */ + /* Fall through to sleep */ + } else { + printk(KERN_ERR "scanlog: unknown error from rtas: %ld\n", status); + return -EIO; + } + } + /* Apparently no data yet. Wait and try again. */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(wait_time); + } + /*NOTREACHED*/ +} + +static ssize_t scanlog_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long status; + + if (buf) { + if (strncmp(buf, "reset", 5) == 0) { + DEBUG("reset scanlog\n"); + status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, NULL, 0); + DEBUG("rtas returns %ld\n", status); + } else if (strncmp(buf, "debugon", 7) == 0) { + printk(KERN_ERR "scanlog: debug on\n"); + scanlog_debug = 1; + } else if (strncmp(buf, "debugoff", 8) == 0) { + printk(KERN_ERR "scanlog: debug off\n"); + scanlog_debug = 0; + } + } + return count; +} + +static int scanlog_open(struct inode * inode, struct file * file) +{ + struct proc_dir_entry *dp = PDE(inode); + unsigned int *data = (unsigned int *)dp->data; + + if (!data) { + printk(KERN_ERR "scanlog: open failed no data\n"); + return -EIO; + } + + if (data[0] != 0) { + /* This imperfect test stops a second copy of the + * data (or a reset while data is being copied) + */ + return -EBUSY; + } + + data[0] = 0; /* re-init so we restart the scan */ + + return 0; +} + +static int scanlog_release(struct inode * inode, struct file * file) +{ + struct proc_dir_entry *dp = PDE(inode); + unsigned int *data = (unsigned int *)dp->data; + + if (!data) { + printk(KERN_ERR "scanlog: release failed no data\n"); + return -EIO; + } + data[0] = 0; + + return 0; +} + +struct file_operations scanlog_fops = { + owner: THIS_MODULE, + read: scanlog_read, + write: scanlog_write, + open: scanlog_open, + release: scanlog_release, +}; + +int __init scanlog_init(void) +{ + struct proc_dir_entry *ent; + + ibm_scan_log_dump = rtas_token("ibm,scan-log-dump"); + if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) { + printk(KERN_ERR "scan-log-dump not implemented on this system\n"); + return -EIO; + } + + if (proc_rtas == NULL) + proc_rtas = proc_mkdir("rtas", 0); + + if (proc_rtas == NULL) { + printk(KERN_ERR "Failed to create /proc/rtas in scanlog_init\n"); + return -EIO; + } + + ent = create_proc_entry("scan-log-dump", S_IRUSR, proc_rtas); + if (ent) { + ent->proc_fops = &scanlog_fops; + /* Ideally we could allocate a buffer < 4G */ + ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); + if (!ent->data) { + printk(KERN_ERR "Failed to allocate a buffer\n"); + remove_proc_entry("scan-log-dump", ent->parent); + return -ENOMEM; + } + ((unsigned int *)ent->data)[0] = 0; + } else { + printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n"); + return -EIO; + } + proc_ppc64_scan_log_dump = ent; + + return 0; +} + +void __exit scanlog_cleanup(void) +{ + if (proc_ppc64_scan_log_dump) { + if (proc_ppc64_scan_log_dump->data) + kfree(proc_ppc64_scan_log_dump->data); + remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent); + } +} + +module_init(scanlog_init); +module_exit(scanlog_cleanup); +MODULE_LICENSE("GPL"); diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/signal32.c Mon Feb 17 14:57:28 2003 @@ -750,6 +750,8 @@ return ret; } +extern int do_signal(sigset_t *oldset, struct pt_regs *regs); + int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) { diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/smp.c Mon Feb 17 14:57:28 2003 @@ -63,7 +63,6 @@ extern int cpu_idle(void *unused); void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -static unsigned long iSeries_smp_message[NR_CPUS]; void xics_setup_cpu(void); void xics_cause_IPI(int cpu); @@ -87,6 +86,8 @@ } #ifdef CONFIG_PPC_ISERIES +static unsigned long iSeries_smp_message[NR_CPUS]; + void iSeries_smp_message_recv( struct pt_regs * regs ) { int cpu = smp_processor_id(); @@ -563,8 +564,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { - int i; - /* Fixup boot cpu */ smp_store_cpu_info(smp_processor_id()); cpu_callin_map[smp_processor_id()] = 1; diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S --- a/arch/ppc64/kernel/sys32.S Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/sys32.S Mon Feb 17 14:57:28 2003 @@ -289,8 +289,7 @@ li r3,-EFAULT blr - .data - .align 8 + .balign 8 _GLOBAL(socketcall_table_begin) .llong .do_sys_socket .llong .do_sys_bind diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Mon Feb 17 14:57:27 2003 @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -607,10 +608,6 @@ } /* end of readdir & getdents */ - - -/* 32-bit timeval and related flotsam. */ - /* * Ooo, nasty. We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. @@ -768,13 +765,9 @@ return ret; } -/* Note: it is necessary to treat n as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x) +int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x) { + /* sign extend n */ return sys32_select((int)n, inp, outp, exp, tvp_x); } @@ -819,45 +812,6 @@ return sys_sysfs((int)option, arg1, arg2); } - - - -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, - unsigned long flags, u32 __new_addr) -{ - unsigned long ret = -EINVAL; - unsigned long new_addr = AA(__new_addr); - - if (old_len > 0xf0000000UL || new_len > 0xf0000000UL) - goto out; - if (addr > 0xf0000000UL - old_len) - goto out; - down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (new_addr > 0xf0000000UL - new_len) - goto out_sem; - } else if (addr > 0xf0000000UL - new_len) { - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - new_addr = get_unmapped_area (NULL, addr, new_len, 0, 0); - if (!new_addr) - goto out_sem; - flags |= MREMAP_FIXED; - } - ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - - - /* Handle adjtimex compatability. */ struct timex32 { u32 modes; @@ -934,38 +888,6 @@ return ret; } -#ifdef CONFIG_MODULES - -extern asmlinkage long sys_init_module(void *, unsigned long, const char *); - -asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs) -{ - return sys_init_module(umod, len, uargs); -} - -extern asmlinkage long sys_delete_module(const char *, unsigned int); - -asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags) -{ - return sys_delete_module(name_user, flags); -} - -#else /* CONFIG_MODULES */ - -asmlinkage int -sys32_init_module(const char *name_user, struct module *mod_user) -{ - return -ENOSYS; -} - -asmlinkage int -sys32_delete_module(const char *name_user) -{ - return -ENOSYS; -} - -#endif /* CONFIG_MODULES */ - /* Stuff for NFS server syscalls... */ struct nfsctl_svc32 { u16 svc32_port; @@ -3097,9 +3019,9 @@ return retval; } -asmlinkage long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs *regs) +long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs *regs) { int error; char * filename; @@ -3348,9 +3270,6 @@ return sys_getsid((int)pid); } - - - extern asmlinkage long sys_kill(int pid, int sig); /* Note: it is necessary to treat pid and sig as unsigned ints, @@ -3402,16 +3321,11 @@ return sys_msync(start, len, (int)flags); } - extern asmlinkage long sys_nice(int increment); -/* Note: it is necessary to treat increment as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_nice(u32 increment) +long sys32_nice(u32 increment) { + /* sign extend increment */ return sys_nice((int)increment); } @@ -3564,13 +3478,9 @@ extern asmlinkage long sys_sethostname(char *name, int len); -/* Note: it is necessary to treat len as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ asmlinkage long sys32_sethostname(char *name, u32 len) { + /* sign extend len */ return sys_sethostname(name, (int)len); } @@ -3590,17 +3500,12 @@ extern asmlinkage long sys_setpriority(int which, int who, int niceval); -/* Note: it is necessary to treat which, who, and niceval as unsigned ints, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_setpriority(u32 which, u32 who, u32 niceval) +long sys32_setpriority(u32 which, u32 who, u32 niceval) { + /* sign extend which, who and niceval */ return sys_setpriority((int)which, (int)who, (int)niceval); } - extern asmlinkage long sys_ssetmask(int newmask); /* Note: it is necessary to treat newmask as an unsigned int, @@ -3613,17 +3518,12 @@ return sys_ssetmask((int) newmask); } - extern asmlinkage long sys_syslog(int type, char * buf, int len); -/* Note: it is necessary to treat type and len as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_syslog(u32 type, char * buf, u32 len) +long sys32_syslog(u32 type, char * buf, u32 len) { - return sys_syslog((int)type, buf, (int)len); + /* sign extend len */ + return sys_syslog(type, buf, (int)len); } @@ -3652,51 +3552,6 @@ return sys_umount(name, (int)flags); } - -extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count, - loff_t pos); - -extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, - loff_t pos); - -compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count, - u32 reg6, u32 poshi, u32 poslo) -{ - return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); -} - -compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf, compat_size_t count, - u32 reg6, u32 poshi, u32 poslo) -{ - return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); -} - -extern ssize_t sys_readahead(int fd, loff_t offset, size_t count); - -compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count) -{ - return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, AA(count)); -} - -extern asmlinkage long sys_truncate(const char * path, unsigned long length); -extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); - -asmlinkage int sys32_truncate64(const char * path, u32 reg4, unsigned long high, unsigned long low) -{ - if ((int)high < 0) - return -EINVAL; - else - return sys_truncate(path, (high << 32) | low); -} - -asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, unsigned long low) -{ - if ((int)high < 0) - return -EINVAL; - else - return sys_ftruncate(fd, (high << 32) | low); -} - asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) { if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) @@ -3845,6 +3700,7 @@ return error; } + extern unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, off_t offset); @@ -3857,11 +3713,65 @@ return sys_mmap(addr, len, prot, flags, fd, pgoff << 12); } +/* + * long long munging: + * The 32 bit ABI passes long longs in an odd even register pair. + */ +extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count, + loff_t pos); + +extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, + loff_t pos); + +compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count, + u32 reg6, u32 poshi, u32 poslo) +{ + return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo); +} + +compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf, compat_size_t count, + u32 reg6, u32 poshi, u32 poslo) +{ + return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo); +} + +extern ssize_t sys_readahead(int fd, loff_t offset, size_t count); + +compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count) +{ + return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count); +} + +extern asmlinkage long sys_truncate(const char * path, unsigned long length); +extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); + +asmlinkage int sys32_truncate64(const char * path, u32 reg4, + unsigned long high, unsigned long low) +{ + return sys_truncate(path, (high << 32) | low); +} + +asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, + unsigned long low) +{ + return sys_ftruncate(fd, (high << 32) | low); +} + extern int sys_lookup_dcookie(u64 cookie64, char *buf, size_t len); -long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, +long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len) { return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, buf, len); } + +extern int sys_fadvise64(int fd, loff_t offset, size_t len, int advice); + +long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low, + size_t len, int advice) +{ + return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len, + advice); +} + diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/kernel/time.c Mon Feb 17 14:57:28 2003 @@ -267,7 +267,6 @@ unsigned long cur_tb; struct paca_struct *lpaca = get_paca(); unsigned long cpu = lpaca->xPacaIndex; - struct ItLpQueue * lpq; irq_enter(); @@ -301,9 +300,11 @@ set_dec(next_dec); #ifdef CONFIG_PPC_ISERIES - lpq = lpaca->lpQueuePtr; - if (lpq && ItLpQueue_isLpIntPending(lpq)) - lpEvent_count += ItLpQueue_process(lpq, regs); + { + struct ItLpQueue *lpq = lpaca->lpQueuePtr; + if (lpq && ItLpQueue_isLpIntPending(lpq)) + lpEvent_count += ItLpQueue_process(lpq, regs); + } #endif irq_exit(); diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Mon Feb 17 14:57:27 2003 +++ b/arch/ppc64/kernel/traps.c Mon Feb 17 14:57:27 2003 @@ -151,61 +151,87 @@ /* What should we do here? We could issue a shutdown or hard reset. */ } -static int power4_handle_mce(struct pt_regs *regs) +/* + * See if we can recover from a machine check exception. + * This is only called on power4 (or above) and only via + * the Firmware Non-Maskable Interrupts (fwnmi) handler + * which provides the error analysis for us. + * + * Return 1 if corrected (or delivered a signal). + * Return 0 if there is nothing we can do. + */ +static int recover_mce(struct pt_regs *regs, struct rtas_error_log err) { + siginfo_t info; + + if (err.disposition == DISP_FULLY_RECOVERED) { + /* Platform corrected itself */ + return 1; + } else if ((regs->msr & MSR_RI) && + user_mode(regs) && + err.severity == SEVERITY_ERROR_SYNC && + err.disposition == DISP_NOT_RECOVERED && + err.target == TARGET_MEMORY && + err.type == TYPE_ECC_UNCORR && + !(current->pid == 0 || current->pid == 1)) { + /* Kill off a user process with an ECC error */ + info.si_signo = SIGBUS; + info.si_errno = 0; + /* XXX something better for ECC error? */ + info.si_code = BUS_ADRERR; + info.si_addr = (void *)regs->nip; + printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n", + current->pid); + _exception(SIGBUS, &info, regs); + return 1; + } return 0; } +/* + * Handle a machine check. + * + * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi) + * should be present. If so the handler which called us tells us if the + * error was recovered (never true if RI=0). + * + * On hardware prior to Power 4 these exceptions were asynchronous which + * means we can't tell exactly where it occurred and so we can't recover. + * + * Note that the debugger should test RI=0 and warn the user that system + * state has been corrupted. + */ void MachineCheckException(struct pt_regs *regs) { - siginfo_t info; + struct rtas_error_log err, *errp; if (fwnmi_active) { - struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs); - if (errhdr) { - /* ToDo: attempt to recover from some errors here */ - } - FWNMI_release_errinfo(); + errp = FWNMI_get_errinfo(regs); + if (errp) + err = *errp; + FWNMI_release_errinfo(); /* frees errp */ + if (errp && recover_mce(regs, err)) + return; } - if (!user_mode(regs)) { - /* Attempt to recover if the interrupt is recoverable */ - if (regs->msr & MSR_RI) { - if ((__is_processor(PV_POWER4) || - __is_processor(PV_POWER4p)) && - power4_handle_mce(regs)) - return; - } - #ifdef CONFIG_DEBUG_KERNEL - if (debugger_fault_handler) { - debugger_fault_handler(regs); - return; - } - if (debugger) - debugger(regs); -#endif - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - printk("Machine check in kernel mode.\n"); - printk("Caused by (from SRR1=%lx): ", regs->msr); - show_regs(regs); - bust_spinlocks(0); - spin_unlock_irq(&die_lock); - panic("Unrecoverable Machine Check"); + if (debugger_fault_handler) { + debugger_fault_handler(regs); + return; } - - /* - * XXX we should check RI bit on exception exit and kill the - * task if it was cleared - */ - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *)regs->nip; - _exception(SIGSEGV, &info, regs); + if (debugger) + debugger(regs); +#endif + console_verbose(); + spin_lock_irq(&die_lock); + bust_spinlocks(1); + printk("Machine check in kernel mode.\n"); + printk("Caused by (from SRR1=%lx): ", regs->msr); + show_regs(regs); + bust_spinlocks(0); + spin_unlock_irq(&die_lock); + panic("Unrecoverable Machine Check"); } void diff -Nru a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c --- a/arch/ppc64/xmon/start.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/xmon/start.c Mon Feb 17 14:57:28 2003 @@ -17,7 +17,6 @@ #include extern void xmon_printf(const char *fmt, ...); -static int xmon_expect(const char *str, unsigned int timeout); #define TB_SPEED 25000000 @@ -120,32 +119,6 @@ static char line[256]; static char *lineptr; static int lineleft; - -int xmon_expect(const char *str, unsigned int timeout) -{ - int c; - unsigned int t0; - - timeout *= TB_SPEED; - t0 = readtb(); - do { - lineptr = line; - for (;;) { - c = xmon_read_poll(); - if (c == -1) { - if (readtb() - t0 > timeout) - return 0; - continue; - } - if (c == '\n') - break; - if (c != '\r' && lineptr < &line[sizeof(line) - 1]) - *lineptr++ = c; - } - *lineptr = 0; - } while (strstr(line, str) == NULL); - return 1; -} int xmon_getchar(void) diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Mon Feb 17 14:57:28 2003 +++ b/arch/ppc64/xmon/xmon.c Mon Feb 17 14:57:28 2003 @@ -2072,6 +2072,10 @@ int instr; int num_parms; + /* dont look for traceback table in userspace */ + if (codeaddr < PAGE_OFFSET) + return 0; + if (tab == NULL) return 0; memset(tab, 0, sizeof(tab)); diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Mon Feb 17 14:57:27 2003 +++ b/arch/s390x/kernel/entry.S Mon Feb 17 14:57:27 2003 @@ -629,7 +629,7 @@ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper) /* 235 */ .long SYSCALL(sys_gettid,sys_gettid) .long SYSCALL(sys_tkill,sys_tkill) - .long SYSCALL(sys_futex,sys32_futex_wrapper) + .long SYSCALL(sys_futex,compat_sys_futex_wrapper) .long SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper) .long SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Mon Feb 17 14:57:27 2003 +++ b/arch/s390x/kernel/linux32.c Mon Feb 17 14:57:27 2003 @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -4045,28 +4046,6 @@ if (put_user(kernel_mask, user_mask_ptr)) ret = -EFAULT; } - - return ret; -} - -asmlinkage int -sys_futex(void *uaddr, int op, int val, struct timespec *utime); - -asmlinkage int -sys32_futex(void *uaddr, int op, int val, - struct compat_timespec *timeout32) -{ - struct timespec tmp; - mm_segment_t old_fs; - int ret; - - if (timeout32 && get_compat_timespec(&tmp, timeout32)) - return -EINVAL; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_futex(uaddr, op, val, timeout32 ? &tmp : NULL); - set_fs(old_fs); return ret; } diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S --- a/arch/s390x/kernel/wrapper32.S Mon Feb 17 14:57:28 2003 +++ b/arch/s390x/kernel/wrapper32.S Mon Feb 17 14:57:28 2003 @@ -1088,13 +1088,13 @@ llgfr %r4,%r4 # long jg sys32_fstat64 # branch to system call - .globl sys32_futex_wrapper -sys32_futex_wrapper: - llgtr %r2,%r2 # void * + .globl compat_sys_futex_wrapper +compat_sys_futex_wrapper: + llgtr %r2,%r2 # u32 * lgfr %r3,%r3 # int lgfr %r4,%r4 # int - llgtr %r5,%r5 # struct timespec * - jg sys32_futex # branch to system call + llgtr %r5,%r5 # struct compat_timespec * + jg compat_sys_futex # branch to system call .globl sys32_setxattr_wrapper sys32_setxattr_wrapper: diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c --- a/arch/sh/kernel/process.c Mon Feb 17 14:57:27 2003 +++ b/arch/sh/kernel/process.c Mon Feb 17 14:57:27 2003 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Mon Feb 17 14:57:28 2003 +++ b/arch/sparc64/Kconfig Mon Feb 17 14:57:28 2003 @@ -151,7 +151,7 @@ If in doubt, say N. config CPU_FREQ_PROC_INTF - bool "/proc/cpufreq interface (DEPRECATED)" + tristate "/proc/cpufreq interface (DEPRECATED)" depends on CPU_FREQ && PROC_FS help This enables the /proc/cpufreq interface for controlling @@ -162,9 +162,14 @@ If in doubt, say N. +config CPU_FREQ_TABLE + tristate + default y + + config US3_FREQ tristate "UltraSPARC-III CPU Frequency driver" - depends on CPU_FREQ + depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for UltraSPARC-III processors. diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Mon Feb 17 14:57:27 2003 +++ b/arch/sparc64/kernel/sys_sparc32.c Mon Feb 17 14:57:27 2003 @@ -54,6 +54,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c --- a/arch/um/kernel/exec_kern.c Mon Feb 17 14:57:27 2003 +++ b/arch/um/kernel/exec_kern.c Mon Feb 17 14:57:27 2003 @@ -5,6 +5,7 @@ #include "linux/slab.h" #include "linux/smp_lock.h" +#include "linux/ptrace.h" #include "asm/ptrace.h" #include "asm/pgtable.h" #include "asm/tlbflush.h" diff -Nru a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c --- a/arch/um/kernel/signal_kern.c Mon Feb 17 14:57:27 2003 +++ b/arch/um/kernel/signal_kern.c Mon Feb 17 14:57:27 2003 @@ -14,6 +14,7 @@ #include "linux/slab.h" #include "linux/tty.h" #include "linux/binfmts.h" +#include "linux/ptrace.h" #include "asm/signal.h" #include "asm/uaccess.h" #include "asm/unistd.h" diff -Nru a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c --- a/arch/um/kernel/skas/process_kern.c Mon Feb 17 14:57:27 2003 +++ b/arch/um/kernel/skas/process_kern.c Mon Feb 17 14:57:27 2003 @@ -5,6 +5,7 @@ #include "linux/sched.h" #include "linux/slab.h" +#include "linux/ptrace.h" #include "kern_util.h" #include "time_user.h" #include "signal_user.h" diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c --- a/arch/um/kernel/tt/process_kern.c Mon Feb 17 14:57:28 2003 +++ b/arch/um/kernel/tt/process_kern.c Mon Feb 17 14:57:28 2003 @@ -7,6 +7,7 @@ #include "linux/signal.h" #include "linux/kernel.h" #include "linux/interrupt.h" +#include "linux/ptrace.h" #include "asm/system.h" #include "asm/pgalloc.h" #include "asm/ptrace.h" diff -Nru a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c --- a/arch/um/kernel/tt/syscall_kern.c Mon Feb 17 14:57:26 2003 +++ b/arch/um/kernel/tt/syscall_kern.c Mon Feb 17 14:57:26 2003 @@ -6,6 +6,7 @@ #include "linux/types.h" #include "linux/utime.h" #include "linux/sys.h" +#include "linux/ptrace.h" #include "asm/unistd.h" #include "asm/ptrace.h" #include "asm/uaccess.h" diff -Nru a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c --- a/arch/v850/kernel/asm-consts.c Mon Feb 17 14:57:27 2003 +++ b/arch/v850/kernel/asm-consts.c Mon Feb 17 14:57:27 2003 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S Mon Feb 17 14:57:27 2003 +++ b/arch/x86_64/ia32/ia32entry.S Mon Feb 17 14:57:27 2003 @@ -440,7 +440,7 @@ .quad sys_fremovexattr .quad sys_tkill /* 238 */ .quad sys_sendfile64 - .quad sys32_futex /* 240 */ + .quad compat_sys_futex /* 240 */ .quad sys32_sched_setaffinity .quad sys32_sched_getaffinity .quad sys_set_thread_area diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Mon Feb 17 14:57:27 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Mon Feb 17 14:57:27 2003 @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -2197,26 +2198,6 @@ if (err > 0) err = put_user((u32)mask, new_mask_ptr); return err; -} - -extern int sys_futex(unsigned long uaddr, int op, int val, struct timespec *t); - -asmlinkage long -sys32_futex(unsigned long uaddr, int op, int val, struct compat_timespec *utime32) -{ - struct timespec t; - mm_segment_t oldfs = get_fs(); - int err; - - if (utime32 && get_compat_timespec(&t, utime32)) - return -EFAULT; - - /* the set_fs is safe because futex doesn't use the seg limit - for valid page checking of uaddr. */ - set_fs(KERNEL_DS); - err = sys_futex(uaddr, op, val, utime32 ? &t : NULL); - set_fs(oldfs); - return err; } extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx); diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Mon Feb 17 14:57:28 2003 +++ b/drivers/Makefile Mon Feb 17 14:57:28 2003 @@ -45,3 +45,4 @@ obj-$(CONFIG_ISDN_BOOL) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ +obj-$(CONFIG_CPU_FREQ) += cpufreq/ diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Mon Feb 17 14:57:27 2003 +++ b/drivers/acorn/block/fd1772.c Mon Feb 17 14:57:27 2003 @@ -336,7 +336,7 @@ */ static int Probing = 0; -/* This flag is set when a dummy seek is necesary to make the WP +/* This flag is set when a dummy seek is necessary to make the WP * status bit accessible. */ static int NeedSeek = 0; diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c --- a/drivers/acorn/scsi/acornscsi.c Mon Feb 17 14:57:27 2003 +++ b/drivers/acorn/scsi/acornscsi.c Mon Feb 17 14:57:27 2003 @@ -116,7 +116,7 @@ #ifdef DEBUG_TARGET #define DBG(cmd,xxx...) \ - if (cmd->target == DEBUG_TARGET) { \ + if (cmd->device->id == DEBUG_TARGET) { \ xxx; \ } #else @@ -575,7 +575,7 @@ char acornscsi_target(AS_Host *host) { if (host->SCpnt) - return '0' + host->SCpnt->target; + return '0' + host->SCpnt->device->id; return 'H'; } @@ -742,7 +742,7 @@ * In this case, we don't want to write to the registers */ if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { - sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target); + sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->device->id); sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN); } @@ -759,7 +759,7 @@ #if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT)) DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n", - host->host->host_no, '0' + SCpnt->target, + host->host->host_no, '0' + SCpnt->device->id, SCpnt->cmnd[0])); #endif @@ -775,7 +775,7 @@ SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); + set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); host->stats.removes += 1; @@ -868,7 +868,7 @@ host->host->host_no, SCpnt->result); print_command(SCpnt->cmnd); acornscsi_dumpdma(host, "done"); - acornscsi_dumplog(host, SCpnt->target); + acornscsi_dumplog(host, SCpnt->device->id); SCpnt->result &= 0xffff; SCpnt->result |= DID_ERROR << 16; } @@ -878,7 +878,7 @@ if (!SCpnt->scsi_done) panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); - clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); SCpnt->scsi_done(SCpnt); } else @@ -1035,7 +1035,7 @@ if (direction == DMA_OUT) { #if (DEBUG & DEBUG_NO_WRITE) - if (NO_WRITE & (1 << host->SCpnt->target)) { + if (NO_WRITE & (1 << host->SCpnt->device->id)) { printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n", host->host->host_no, acornscsi_target(host)); return; @@ -1511,7 +1511,7 @@ if (host->scsi.phase != PHASE_STATUSIN) { printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", host->host->host_no, acornscsi_target(host)); - acornscsi_dumplog(host, host->SCpnt->target); + acornscsi_dumplog(host, host->SCpnt->device->id); } host->scsi.phase = PHASE_DONE; host->scsi.SCp.Message = message[0]; @@ -1567,8 +1567,8 @@ * transfer. Re-initiate sync transfer negociation now, and if * we got a REJECT in response to SDTR, then it'll be set to DONE. */ - if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) - host->device[host->SCpnt->target].sync_state = SYNC_NEGOCIATE; + if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) + host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE; #endif /* @@ -1591,7 +1591,7 @@ printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", host->host->host_no, acornscsi_target(host)); host->SCpnt->device->tagged_queue = 0; - set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, host->busyluns); + set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); break; #endif case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): @@ -1600,9 +1600,9 @@ */ printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n", host->host->host_no, acornscsi_target(host)); - host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA; - host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS; - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA; + host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS; + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; default: @@ -1625,18 +1625,18 @@ switch (message[2]) { #ifdef CONFIG_SCSI_ACORNSCSI_SYNC case EXTENDED_SDTR: - if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) { + if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) { /* * We requested synchronous transfers. This isn't quite right... * We can only say if this succeeded if we proceed on to execute the * command from this message. If we get a MESSAGE PARITY ERROR, * and the target retries fail, then we fallback to asynchronous mode */ - host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED; + host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED; printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n", host->host->host_no, acornscsi_target(host), message[4], message[3] * 4); - host->device[host->SCpnt->target].sync_xfer = + host->device[host->SCpnt->device->id].sync_xfer = calc_sync_xfer(message[3] * 4, message[4]); } else { unsigned char period, length; @@ -1649,10 +1649,10 @@ length = min_t(unsigned int, message[4], sdtr_size); msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, period, length); - host->device[host->SCpnt->target].sync_xfer = + host->device[host->SCpnt->device->id].sync_xfer = calc_sync_xfer(period * 4, length); } - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; #else /* We do not accept synchronous transfers. Respond with a @@ -1738,8 +1738,8 @@ #endif msgqueue_addmsg(&host->scsi.msgs, 1, - IDENTIFY(host->device[host->SCpnt->target].disconnect_ok, - host->SCpnt->lun)); + IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok, + host->SCpnt->device->lun)); #if 0 /* does the device need the current command aborted */ @@ -1764,8 +1764,8 @@ #endif #ifdef CONFIG_SCSI_ACORNSCSI_SYNC - if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) { - host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST; + if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) { + host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST; msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, sdtr_period / 4, sdtr_size); @@ -1792,7 +1792,7 @@ residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); sbic_arm_writenext(host->scsi.io_port, residual >> 16); sbic_arm_writenext(host->scsi.io_port, residual >> 8); sbic_arm_writenext(host->scsi.io_port, residual); @@ -1828,7 +1828,7 @@ if (host->SCpnt && !host->scsi.disconnectable) { printk(KERN_ERR "scsi%d.%d: reconnected while command in " "progress to target %d?\n", - host->host->host_no, target, host->SCpnt->target); + host->host->host_no, target, host->SCpnt->device->id); host->SCpnt = NULL; } @@ -1839,7 +1839,7 @@ host->scsi.reconnected.tag = 0; if (host->scsi.disconnectable && host->SCpnt && - host->SCpnt->target == target && host->SCpnt->lun == lun) + host->SCpnt->device->id == target && host->SCpnt->device->lun == lun) ok = 1; if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun)) @@ -1876,9 +1876,9 @@ { if (host->scsi.disconnectable && host->SCpnt) { host->scsi.disconnectable = 0; - if (host->SCpnt->target == host->scsi.reconnected.target && - host->SCpnt->lun == host->scsi.reconnected.lun && - host->SCpnt->tag == host->scsi.reconnected.tag) { + if (host->SCpnt->device->id == host->scsi.reconnected.target && + host->SCpnt->device->lun == host->scsi.reconnected.lun && + host->SCpnt->tag == host->scsi.reconnected.tag) { #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) DBG(host->SCpnt, printk("scsi%d.%c: reconnected", host->host->host_no, acornscsi_target(host))); @@ -1992,7 +1992,7 @@ ADD_STATUS(8, ssr, host->scsi.phase, in_irq); if (host->SCpnt && !host->scsi.disconnectable) - ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq); + ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); switch (ssr) { case 0x00: /* reset state - not advanced */ @@ -2030,7 +2030,7 @@ break; ssr = sbic_arm_read(host->scsi.io_port, SSR); ADD_STATUS(8, ssr, host->scsi.phase, 1); - ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1); + ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1); goto connected; case 0x42: /* select timed out */ @@ -2049,7 +2049,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); acornscsi_abortcmd(host, host->SCpnt->tag); } return INTR_PROCESSING; @@ -2085,7 +2085,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); acornscsi_abortcmd(host, host->SCpnt->tag); } return INTR_PROCESSING; @@ -2123,7 +2123,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2168,7 +2168,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2181,7 +2181,7 @@ } else { printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_NEXT_COMMAND; @@ -2191,7 +2191,7 @@ else { printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2206,7 +2206,7 @@ */ if (ssr != 0x8f && !acornscsi_reconnect_finish(host)) return INTR_IDLE; - ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq); + ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); switch (ssr) { case 0x88: /* data out phase */ /* -> PHASE_DATAOUT */ @@ -2251,7 +2251,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2300,7 +2300,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2352,7 +2352,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2373,7 +2373,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2396,14 +2396,14 @@ case 0x85: printk("scsi%d.%c: strange message in disconnection\n", host->host->host_no, acornscsi_target(host)); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); acornscsi_done(host, &host->SCpnt, DID_ERROR); break; default: printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2421,7 +2421,7 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; @@ -2447,14 +2447,14 @@ default: printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; default: printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n", host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); } return INTR_PROCESSING; } @@ -2531,9 +2531,9 @@ } #if (DEBUG & DEBUG_NO_WRITE) - if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) { + if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) { printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n", - SCpnt->host->host_no, '0' + SCpnt->target); + SCpnt->host->host_no, '0' + SCpnt->device->id); SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; @@ -2708,7 +2708,7 @@ printk(KERN_WARNING "acornscsi_abort: "); print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog(host, SCpnt->target); + acornscsi_dumplog(host, SCpnt->device->id); } #endif @@ -2724,7 +2724,7 @@ //#if (DEBUG & DEBUG_ABORT) printk("clear "); //#endif - clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); /* * We found the command, and cleared it out. Either @@ -2758,7 +2758,7 @@ */ default: case res_not_running: - acornscsi_dumplog(host, SCpnt->target); + acornscsi_dumplog(host, SCpnt->device->id); #if (DEBUG & DEBUG_ABORT) result = SCSI_ABORT_SNOOZE; #else @@ -2796,7 +2796,7 @@ printk(KERN_WARNING "acornscsi_reset: "); print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog(host, SCpnt->target); + acornscsi_dumplog(host, SCpnt->device->id); } #endif diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c --- a/drivers/acorn/scsi/fas216.c Mon Feb 17 14:57:27 2003 +++ b/drivers/acorn/scsi/fas216.c Mon Feb 17 14:57:27 2003 @@ -96,6 +96,47 @@ static int level_mask = LOG_ERROR; +static int __init fas216_log_setup(char *str) +{ + char *s; + + level_mask = 0; + + while ((s = strsep(&str, ",")) != NULL) { + switch (s[0]) { + case 'a': + if (strcmp(s, "all") == 0) + level_mask |= -1; + break; + case 'b': + if (strncmp(s, "bus", 3) == 0) + level_mask |= LOG_BUSSERVICE; + if (strncmp(s, "buf", 3) == 0) + level_mask |= LOG_BUFFER; + break; + case 'c': + level_mask |= LOG_CONNECT; + break; + case 'e': + level_mask |= LOG_ERROR; + break; + case 'm': + level_mask |= LOG_MESSAGES; + break; + case 'n': + if (strcmp(s, "none") == 0) + level_mask = 0; + break; + case 's': + level_mask |= LOG_FUNCTIONDONE; + break; + } + } + return 1; +} + +__setup("fas216_logging=", fas216_log_setup); + static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg) { unsigned int off = reg << info->scsi.io_shift; @@ -244,7 +285,7 @@ static char fas216_target(FAS216_Info *info) { if (info->SCpnt) - return '0' + info->SCpnt->target; + return '0' + info->SCpnt->device->id; else return 'H'; } @@ -267,7 +308,7 @@ return; va_start(args, fmt); - fas216_do_log(info, '0' + SCpnt->target, fmt, args); + fas216_do_log(info, '0' + SCpnt->device->id, fmt, args); va_end(args); printk(" CDB: "); @@ -495,7 +536,7 @@ */ static void fas216_handlesync(FAS216_Info *info, char *msg) { - struct fas216_device *dev = &info->device[info->SCpnt->target]; + struct fas216_device *dev = &info->device[info->SCpnt->device->id]; enum { sync, async, none, reject } res = none; #ifdef SCSI2_SYNC @@ -578,7 +619,7 @@ dev->period = msg[3]; dev->sof = msg[4]; dev->stp = fas216_syncperiod(info, msg[3] * 4); - fas216_set_sync(info, info->SCpnt->target); + fas216_set_sync(info, info->SCpnt->device->id); break; case reject: @@ -591,7 +632,7 @@ dev->period = info->ifcfg.asyncperiod / 4; dev->sof = 0; dev->stp = info->scsi.async_stp; - fas216_set_sync(info, info->SCpnt->target); + fas216_set_sync(info, info->SCpnt->device->id); break; case none: @@ -608,7 +649,7 @@ */ static void fas216_handlewide(FAS216_Info *info, char *msg) { - struct fas216_device *dev = &info->device[info->SCpnt->target]; + struct fas216_device *dev = &info->device[info->SCpnt->device->id]; enum { wide, bit8, none, reject } res = none; #ifdef SCSI2_WIDE @@ -725,7 +766,7 @@ bytes_transferred -= SCp->this_residual; if (!next_SCp(SCp) && bytes_transferred) { printk(KERN_WARNING "scsi%d.%c: out of buffers\n", - info->host->host_no, '0' + info->SCpnt->target); + info->host->host_no, '0' + info->SCpnt->device->id); return; } } @@ -848,7 +889,7 @@ * use DMA mode. If we are using asynchronous transfers, we may * use DMA mode or PIO mode. */ - if (info->device[info->SCpnt->target].sof) + if (info->device[info->SCpnt->device->id].sof) dmatype = fasdma_real_all; else dmatype = fasdma_pio; @@ -1023,10 +1064,10 @@ info->origSCpnt = SCpnt; info->SCpnt = NULL; - if (info->device[SCpnt->target].wide_state == neg_inprogress) - info->device[SCpnt->target].wide_state = neg_wait; - if (info->device[SCpnt->target].sync_state == neg_inprogress) - info->device[SCpnt->target].sync_state = neg_wait; + if (info->device[SCpnt->device->id].wide_state == neg_inprogress) + info->device[SCpnt->device->id].wide_state = neg_wait; + if (info->device[SCpnt->device->id].sync_state == neg_inprogress) + info->device[SCpnt->device->id].sync_state = neg_wait; } fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase); @@ -1073,7 +1114,7 @@ ok = 0; if (info->scsi.disconnectable && info->SCpnt && - info->SCpnt->target == target && info->SCpnt->lun == identify_msg) + info->SCpnt->device->id == target && info->SCpnt->device->lun == identify_msg) ok = 1; if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) @@ -1118,15 +1159,15 @@ fas216_checkmagic(info); fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x", - info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag, + info->SCpnt->device->id, info->SCpnt->device->lun, info->SCpnt->tag, info->scsi.reconnected.target, info->scsi.reconnected.lun, info->scsi.reconnected.tag); if (info->scsi.disconnectable && info->SCpnt) { info->scsi.disconnectable = 0; - if (info->SCpnt->target == info->scsi.reconnected.target && - info->SCpnt->lun == info->scsi.reconnected.lun && - info->SCpnt->tag == info->scsi.reconnected.tag) { + if (info->SCpnt->device->id == info->scsi.reconnected.target && + info->SCpnt->device->lun == info->scsi.reconnected.lun && + info->SCpnt->tag == info->scsi.reconnected.tag) { fas216_log(info, LOG_CONNECT, "reconnected"); } else { queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); @@ -1617,13 +1658,13 @@ * set of messages. If we have more than one byte to * send, we need to assert ATN again. */ - if (info->device[info->SCpnt->target].parity_check) { + if (info->device[info->SCpnt->device->id].parity_check) { /* * We were testing... good, the device * supports parity checking. */ - info->device[info->SCpnt->target].parity_check = 0; - info->device[info->SCpnt->target].parity_enabled = 1; + info->device[info->SCpnt->device->id].parity_check = 0; + info->device[info->SCpnt->device->id].parity_enabled = 1; fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); } @@ -1831,11 +1872,11 @@ fas216_cmd(info, CMD_FLUSHFIFO); /* load bus-id and timeout */ - fas216_writeb(info, REG_SDID, BUSID(SCpnt->target)); + fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id)); fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); /* synchronous transfers */ - fas216_set_sync(info, SCpnt->target); + fas216_set_sync(info, SCpnt->device->id); tot_msglen = msgqueue_msglength(&info->scsi.msgs); @@ -1845,7 +1886,7 @@ int msgnr = 0, i; printk("scsi%d.%c: message out: ", - info->host->host_no, '0' + SCpnt->target); + info->host->host_no, '0' + SCpnt->device->id); while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { printk("{ "); for (i = 0; i < msg->length; i++) @@ -1923,7 +1964,7 @@ info->SCpnt = SCpnt; info->dma.transfer_type = fasdma_none; - if (parity_test(info, SCpnt->target)) + if (parity_test(info, SCpnt->device->id)) fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE); else fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); @@ -1932,13 +1973,13 @@ * Don't allow request sense commands to disconnect. */ disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE && - info->device[SCpnt->target].disconnect_ok; + info->device[SCpnt->device->id].disconnect_ok; /* * build outgoing message bytes */ msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->lun)); + msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun)); /* * add tag message if required @@ -1948,8 +1989,8 @@ do { #ifdef SCSI2_WIDE - if (info->device[SCpnt->target].wide_state == neg_wait) { - info->device[SCpnt->target].wide_state = neg_inprogress; + if (info->device[SCpnt->device->id].wide_state == neg_wait) { + info->device[SCpnt->device->id].wide_state = neg_inprogress; msgqueue_addmsg(&info->scsi.msgs, 4, EXTENDED_MESSAGE, 2, EXTENDED_WDTR, info->ifcfg.wide_max_size); @@ -1957,11 +1998,11 @@ } #endif #ifdef SCSI2_SYNC - if ((info->device[SCpnt->target].sync_state == neg_wait || - info->device[SCpnt->target].sync_state == neg_complete) && + if ((info->device[SCpnt->device->id].sync_state == neg_wait || + info->device[SCpnt->device->id].sync_state == neg_complete) && (SCpnt->cmnd[0] == REQUEST_SENSE || SCpnt->cmnd[0] == INQUIRY)) { - info->device[SCpnt->target].sync_state = neg_inprogress; + info->device[SCpnt->device->id].sync_state = neg_inprogress; msgqueue_addmsg(&info->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, 1000 / info->ifcfg.clockrate, @@ -1988,7 +2029,7 @@ SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); info->stats.removes += 1; switch (SCpnt->cmnd[0]) { @@ -2033,11 +2074,11 @@ fas216_cmd(info, CMD_FLUSHFIFO); /* load bus-id and timeout */ - fas216_writeb(info, REG_SDID, BUSID(SCpnt->target)); + fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id)); fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); /* synchronous transfers */ - fas216_set_sync(info, SCpnt->target); + fas216_set_sync(info, SCpnt->device->id); msg = msgqueue_getmsg(&info->scsi.msgs, 0); @@ -2102,7 +2143,7 @@ if (info->scsi.disconnectable && info->SCpnt) { fas216_log(info, LOG_CONNECT, "moved command for %d to disconnected queue", - info->SCpnt->target); + info->SCpnt->device->id); queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); info->scsi.disconnectable = 0; info->SCpnt = NULL; @@ -2155,7 +2196,7 @@ static void fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) { - fas216_log_target(info, LOG_CONNECT, SCpnt->target, + fas216_log_target(info, LOG_CONNECT, SCpnt->device->id, "request sense complete, result=0x%04x%02x%02x", result, SCpnt->SCp.Message, SCpnt->SCp.Status); @@ -2166,7 +2207,7 @@ * confuse the higher levels. */ memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); -//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->target); +//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id); //{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); } /* * Note that we don't set SCpnt->result, since that should @@ -2235,7 +2276,7 @@ default: printk(KERN_ERR "scsi%d.%c: incomplete data transfer " "detected: res=%08X ptr=%p len=%X CDB: ", - info->host->host_no, '0' + SCpnt->target, + info->host->host_no, '0' + SCpnt->device->id, SCpnt->result, info->scsi.SCp.ptr, info->scsi.SCp.this_residual); print_command(SCpnt->cmnd); @@ -2259,11 +2300,11 @@ if (SCpnt->cmnd[0] == REQUEST_SENSE) goto done; - fas216_log_target(info, LOG_CONNECT, SCpnt->target, + fas216_log_target(info, LOG_CONNECT, SCpnt->device->id, "requesting sense"); memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); SCpnt->cmnd[0] = REQUEST_SENSE; - SCpnt->cmnd[1] = SCpnt->lun << 5; + SCpnt->cmnd[1] = SCpnt->device->lun << 5; SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); SCpnt->SCp.buffer = NULL; @@ -2285,7 +2326,7 @@ */ if (info->reqSCpnt) printk(KERN_WARNING "scsi%d.%c: loosing request command\n", - info->host->host_no, '0' + SCpnt->target); + info->host->host_no, '0' + SCpnt->device->id); info->reqSCpnt = SCpnt; } @@ -2324,7 +2365,7 @@ if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) { printk("scsi%d.%c: zero bytes left to transfer, but " "buffer pointer still valid: ptr=%p len=%08x CDB: ", - info->host->host_no, '0' + SCpnt->target, + info->host->host_no, '0' + SCpnt->device->id, info->scsi.SCp.ptr, info->scsi.SCp.this_residual); info->scsi.SCp.ptr = NULL; print_command(SCpnt->cmnd); @@ -2335,8 +2376,8 @@ * the sense information, fas216_kick will re-assert the busy * status. */ - info->device[SCpnt->target].parity_check = 0; - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + info->device[SCpnt->device->id].parity_check = 0; + clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; fn(info, SCpnt, result); @@ -2365,7 +2406,7 @@ */ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; int result; fas216_checkmagic(info); @@ -2412,7 +2453,7 @@ */ static void fas216_internal_done(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; fas216_checkmagic(info); @@ -2429,7 +2470,7 @@ */ int fas216_command(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; fas216_checkmagic(info); @@ -2555,7 +2596,7 @@ * been set. */ info->origSCpnt = NULL; - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); printk("waiting for execution "); res = res_success; } else @@ -2574,7 +2615,7 @@ */ int fas216_eh_abort(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; int result = FAILED; fas216_checkmagic(info); @@ -2631,9 +2672,9 @@ */ int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; unsigned long flags; - int i, res = FAILED, target = SCpnt->target; + int i, res = FAILED, target = SCpnt->device->id; fas216_log(info, LOG_ERROR, "device reset for target %d", target); @@ -2647,7 +2688,7 @@ * and we need a bus reset. */ if (info->SCpnt && !info->scsi.disconnectable && - info->SCpnt->target == SCpnt->target) + info->SCpnt->device->id == SCpnt->device->id) break; /* @@ -2658,9 +2699,9 @@ */ queue_remove_all_target(&info->queues.issue, target); queue_remove_all_target(&info->queues.disconnected, target); - if (info->origSCpnt && info->origSCpnt->target == target) + if (info->origSCpnt && info->origSCpnt->device->id == target) info->origSCpnt = NULL; - if (info->reqSCpnt && info->reqSCpnt->target == target) + if (info->reqSCpnt && info->reqSCpnt->device->id == target) info->reqSCpnt = NULL; for (i = 0; i < 8; i++) clear_bit(target * 8 + i, info->busyluns); @@ -2712,7 +2753,7 @@ */ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; unsigned long flags; Scsi_Device *SDpnt; @@ -2750,9 +2791,9 @@ queue_remove_all_target(&info->queues.issue, SDpnt->id); queue_remove_all_target(&info->queues.disconnected, SDpnt->id); - if (info->origSCpnt && info->origSCpnt->target == SDpnt->id) + if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id) info->origSCpnt = NULL; - if (info->reqSCpnt && info->reqSCpnt->target == SDpnt->id) + if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id) info->reqSCpnt = NULL; info->SCpnt = NULL; @@ -2809,12 +2850,12 @@ */ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) { - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; fas216_checkmagic(info); printk("scsi%d.%c: %s: resetting host\n", - info->host->host_no, '0' + SCpnt->target, __FUNCTION__); + info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__); /* * Reset the SCSI chip. diff -Nru a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c --- a/drivers/acorn/scsi/queue.c Mon Feb 17 14:57:26 2003 +++ b/drivers/acorn/scsi/queue.c Mon Feb 17 14:57:26 2003 @@ -170,7 +170,7 @@ spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (!test_bit(q->SCpnt->target * 8 + q->SCpnt->lun, exclude)) { + if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) { SCpnt = __queue_remove(queue, l); break; } @@ -217,7 +217,7 @@ spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->target == target && q->SCpnt->lun == lun && + if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun && q->SCpnt->tag == tag) { SCpnt = __queue_remove(queue, l); break; @@ -243,7 +243,7 @@ spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->target == target) + if (q->SCpnt->device->id == target) __queue_remove(queue, l); } spin_unlock_irqrestore(&queue->queue_lock, flags); @@ -267,7 +267,7 @@ spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->target == target && q->SCpnt->lun == lun) { + if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun) { found = 1; break; } diff -Nru a/drivers/acorn/scsi/scsi.h b/drivers/acorn/scsi/scsi.h --- a/drivers/acorn/scsi/scsi.h Mon Feb 17 14:57:27 2003 +++ b/drivers/acorn/scsi/scsi.h Mon Feb 17 14:57:27 2003 @@ -92,8 +92,8 @@ if (SCpnt->request_bufflen != len) printk(KERN_WARNING "scsi%d.%c: bad request buffer " - "length %d, should be %ld\n", SCpnt->host->host_no, - '0' + SCpnt->target, SCpnt->request_bufflen, len); + "length %d, should be %ld\n", SCpnt->device->host->host_no, + '0' + SCpnt->device->id, SCpnt->request_bufflen, len); SCpnt->request_bufflen = len; #endif } else { diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c Mon Feb 17 14:57:28 2003 +++ b/drivers/acpi/thermal.c Mon Feb 17 14:57:28 2003 @@ -436,7 +436,7 @@ envp[0] = "HOME=/"; envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - call_usermodehelper(argv[0], argv, envp); + call_usermodehelper(argv[0], argv, envp, 0); return_VALUE(0); } diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c --- a/drivers/base/hotplug.c Mon Feb 17 14:57:26 2003 +++ b/drivers/base/hotplug.c Mon Feb 17 14:57:26 2003 @@ -114,7 +114,7 @@ pr_debug ("%s: %s %s %s %s %s %s\n", __FUNCTION__, argv [0], argv[1], envp[0], envp[1], envp[2], envp[3]); - retval = call_usermodehelper (argv [0], argv, envp); + retval = call_usermodehelper (argv [0], argv, envp, 0); if (retval) pr_debug ("%s - call_usermodehelper returned %d\n", __FUNCTION__, retval); diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Mon Feb 17 14:57:28 2003 +++ b/drivers/block/cciss.c Mon Feb 17 14:57:28 2003 @@ -114,6 +114,9 @@ static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c); static void start_io( ctlr_info_t *h); +static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, + unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, + unsigned char *scsi3addr); #ifdef CONFIG_PROC_FS static int cciss_proc_get_info(char *buffer, char **start, off_t offset, @@ -353,7 +356,7 @@ * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (inode->i_bdev->bd_inode->i_size == 0) { + if (hba[ctlr]->drv[dsk].nr_blocks == 0) { if (minor(inode->i_rdev) != 0) return -ENXIO; if (!capable(CAP_SYS_ADMIN)) @@ -809,6 +812,7 @@ /* zero out the disk size info */ h->drv[logvol].nr_blocks = 0; h->drv[logvol].block_size = 0; + h->drv[logvol].cylinders = 0; h->drv[logvol].LunID = 0; return(0); } @@ -1002,6 +1006,73 @@ return(return_status); } +static void cciss_geometry_inquiry(int ctlr, int logvol, + int withirq, unsigned int total_size, + unsigned int block_size, InquiryData_struct *inq_buff, + drive_info_struct *drv) +{ + int return_code; + memset(inq_buff, 0, sizeof(InquiryData_struct)); + if (withirq) + return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, + inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1); + else + return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, + sizeof(*inq_buff), 1, logvol ,0xC1, NULL); + if (return_code == IO_OK) { + if(inq_buff->data_byte[8] == 0xFF) { + printk(KERN_WARNING + "cciss: reading geometry failed, volume " + "does not support reading geometry\n"); + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = 255; + drv->sectors = 32; // Sectors per track + drv->cylinders = total_size / 255 / 32; + } else { + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = inq_buff->data_byte[6]; + drv->sectors = inq_buff->data_byte[7]; + drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8; + drv->cylinders += inq_buff->data_byte[5]; + } + } else { /* Get geometry failed */ + printk(KERN_WARNING "cciss: reading geometry failed, " + "continuing with default geometry\n"); + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = 255; + drv->sectors = 32; // Sectors per track + drv->cylinders = total_size / 255 / 32; + } + printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", + drv->heads, drv->sectors, drv->cylinders); +} +static void +cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, + int withirq, unsigned int *total_size, unsigned int *block_size) +{ + int return_code; + memset(buf, 0, sizeof(*buf)); + if (withirq) + return_code = sendcmd_withirq(CCISS_READ_CAPACITY, + ctlr, buf, sizeof(*buf), 1, logvol, 0 ); + else + return_code = sendcmd(CCISS_READ_CAPACITY, + ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL ); + if (return_code == IO_OK) { + *total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1; + *block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0])); + } else { /* read capacity command failed */ + printk(KERN_WARNING "cciss: read capacity failed\n"); + *total_size = 0; + *block_size = BLOCK_SIZE; + } + printk(KERN_INFO " blocks= %d block_size= %d\n", + *total_size, *block_size); + return; +} static int register_new_disk(int ctlr) { struct gendisk *disk; @@ -1013,9 +1084,9 @@ int new_lun_index = 0; int free_index_found = 0; int free_index = 0; - ReportLunData_struct *ld_buff; - ReadCapdata_struct *size_buff; - InquiryData_struct *inq_buff; + ReportLunData_struct *ld_buff = NULL; + ReadCapdata_struct *size_buff = NULL; + InquiryData_struct *inq_buff = NULL; int return_code; int listlength = 0; __u32 lunid = 0; @@ -1030,26 +1101,14 @@ ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); if (ld_buff == NULL) - { - printk(KERN_ERR "cciss: out of memory\n"); - return -1; - } + goto mem_msg; memset(ld_buff, 0, sizeof(ReportLunData_struct)); size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); if (size_buff == NULL) - { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return -1; - } + goto mem_msg; inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) - { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - kfree(size_buff); - return -1; - } + goto mem_msg; return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, sizeof(ReportLunData_struct), 0, 0, 0 ); @@ -1068,7 +1127,7 @@ printk(KERN_WARNING "cciss: report logical volume" " command failed\n"); listlength = 0; - return -1; + goto free_err; } num_luns = listlength / 8; // 8 bytes pre entry if (num_luns > CISS_MAX_LUN) @@ -1119,7 +1178,7 @@ if (!new_lun_found) { printk(KERN_WARNING "cciss: New Logical Volume not found\n"); - return -1; + goto free_err; } /* Now find the free index */ for(i=0; i highest_lun < lunid) hba[ctlr]->highest_lun = logvol; - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, - sizeof( ReadCapdata_struct), 1, logvol, 0 ); - if (return_code == IO_OK) - { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; // command returns highest block address - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else /* read capacity command failed */ - { - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = 0; - block_size = BLOCK_SIZE; - } - printk(KERN_INFO " blocks= %u block_size= %d\n", - total_size, block_size); - /* 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 ); - if (return_code == IO_OK) - { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: reading geometry failed, " - "volume does not support reading geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track - hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32; - } else - { - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = - inq_buff->data_byte[6]; - hba[ctlr]->drv[logvol].sectors = - inq_buff->data_byte[7]; - hba[ctlr]->drv[logvol].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[ctlr]->drv[logvol].cylinders += - inq_buff->data_byte[5]; - } - } - else /* Get geometry failed */ - { - - printk(KERN_WARNING "cciss: reading geometry failed, " - "continuing with default geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track - hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32; - } - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", - hba[ctlr]->drv[logvol].heads, - hba[ctlr]->drv[logvol].sectors, - hba[ctlr]->drv[logvol].cylinders); + cciss_read_capacity(ctlr, logvol, size_buff, 1, + &total_size, &block_size); + cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, + inq_buff, &hba[ctlr]->drv[logvol]); hba[ctlr]->drv[logvol].usage_count = 0; ++hba[ctlr]->num_luns; /* setup partitions per disk */ disk = hba[ctlr]->gendisk[logvol]; set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks); add_disk(disk); - +freeret: kfree(ld_buff); kfree(size_buff); kfree(inq_buff); return (logvol); +mem_msg: + printk(KERN_ERR "cciss: out of memory\n"); +free_err: + logvol = -1; + goto freeret; } /* * Wait polling for a command to complete. * The memory mapped FIFO is polled for the completion. - * Used only at init time, interrupts disabled. + * Used only at init time, interrupts from the HBA are disabled. */ static unsigned long pollcomplete(int ctlr) { - unsigned long done; - int i; + unsigned long done; + int i; - /* Wait (up to 2 seconds) for a command to complete */ + /* Wait (up to 20 seconds) for a command to complete */ - for (i = 200000; i > 0; i--) { - done = hba[ctlr]->access.command_completed(hba[ctlr]); - if (done == FIFO_EMPTY) { - udelay(10); /* a short fixed delay */ - } else - return (done); - } - /* Invalid address to tell caller we ran out of time */ - return 1; + for (i = 20 * HZ; i > 0; i--) { + done = hba[ctlr]->access.command_completed(hba[ctlr]); + if (done == FIFO_EMPTY) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } else + return (done); + } + /* Invalid address to tell caller we ran out of time */ + return 1; } /* * Send a command to the controller, and wait for it to complete. @@ -2174,83 +2164,10 @@ ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); #endif /* CCISS_DEBUG */ - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, - sizeof( ReadCapdata_struct), 1, i, 0, NULL ); - if (return_code == IO_OK) - { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; // command returns highest block address - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else /* read capacity command failed */ - { - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = 0; - block_size = BLOCK_SIZE; - } - printk(KERN_INFO " blocks= %d block_size= %d\n", - total_size, block_size); - - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 1, i ,0xC1, NULL ); - if (return_code == IO_OK) - { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: reading geometry failed, volume does not support reading geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; // Sectors per track - hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; } else - { - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = - inq_buff->data_byte[6]; - hba[cntl_num]->drv[i].sectors = - inq_buff->data_byte[7]; - hba[cntl_num]->drv[i].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[cntl_num]->drv[i].cylinders += - inq_buff->data_byte[5]; - } - } - else /* Get geometry failed */ - { - printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; // Sectors per track - hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; - } - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", - hba[cntl_num]->drv[i].heads, - hba[cntl_num]->drv[i].sectors, - hba[cntl_num]->drv[i].cylinders); - + cciss_read_capacity(cntl_num, i, size_buff, 0, + &total_size, &block_size); + cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size, + inq_buff, &hba[cntl_num]->drv[i]); } kfree(ld_buff); kfree(size_buff); @@ -2408,7 +2325,7 @@ cciss_getgeometry(i); - cciss_find_non_disk_devices(i); /* find our tape drives, if any */ + cciss_scsi_setup(i); /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); @@ -2446,9 +2363,6 @@ set_capacity(disk, drv->nr_blocks); add_disk(disk); } - - cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */ - return(1); } diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c --- a/drivers/block/cciss_scsi.c Mon Feb 17 14:57:27 2003 +++ b/drivers/block/cciss_scsi.c Mon Feb 17 14:57:27 2003 @@ -89,8 +89,10 @@ working even with the SCSI system. It's so scsi_unregister_host will differentiate the controllers. When register_scsi_module is called, each host template is - customized (name change) in cciss_register_scsi() - (that's called from cciss.c:cciss_init_one()) */ + customized (name change) in cciss_register_scsi() (that's + called from cciss_engage_scsi, called from + cciss.c:cciss_proc_write(), on "engage scsi" being received + from user space.) */ static Scsi_Host_Template driver_template[MAX_CTLR] = @@ -199,14 +201,12 @@ } static int -scsi_cmd_stack_setup(int ctlr) +scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa) { int i; - struct cciss_scsi_adapter_data_t *sa; struct cciss_scsi_cmd_stack_t *stk; size_t size; - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; stk = &sa->cmd_stack; size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; @@ -535,126 +535,24 @@ return -1; } - static void -cciss_find_non_disk_devices(int cntl_num) +cciss_scsi_setup(int cntl_num) { - ReportLunData_struct *ld_buff; - InquiryData_struct *inq_buff; - int return_code; - int i; - int listlength = 0; - int num_luns; - unsigned char scsi3addr[8]; - unsigned long flags; - int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; - - hba[cntl_num]->scsi_ctlr = (void *) - kmalloc(sizeof(struct cciss_scsi_adapter_data_t), - GFP_KERNEL); - if (hba[cntl_num]->scsi_ctlr == NULL) - return; - - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->scsi_host = NULL; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->registered = 0; + struct cciss_scsi_adapter_data_t * shba; - if (scsi_cmd_stack_setup(cntl_num) != 0) { - printk("Trouble, returned non-zero!\n"); - return; - } - - ld_buff = kmalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } - - /* Get the physical luns */ - return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff, - reportlunsize, 0, 0, 0, NULL ); - - if( return_code == IO_OK) { - unsigned char *c = &ld_buff->LUNListLength[0]; - listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; - } - else { /* getting report of physical luns failed */ - printk(KERN_WARNING "cciss: report physical luns" - " command failed\n"); - listlength = 0; - } - - CPQ_TAPE_LOCK(cntl_num, flags); ccissscsi[cntl_num].ndevices = 0; - num_luns = listlength / 8; // 8 bytes pre entry - /* printk("Found %d LUNs\n", num_luns); */ - - if (num_luns > CISS_MAX_PHYS_LUN) - { - printk(KERN_WARNING - "cciss: Maximum physical LUNs (%d) exceeded. " - "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, - num_luns - CISS_MAX_PHYS_LUN); - num_luns = CISS_MAX_PHYS_LUN; - } - - for(i=0; iLUN[i], 8); /* ugly... */ - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr ); - if (return_code == IO_OK) { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: inquiry failed\n"); - } else { - int devtype; - - /* printk("Inquiry...\n"); - print_bytes((unsigned char *) inq_buff, 36, 1, 1); */ - devtype = (inq_buff->data_byte[0] & 0x1f); - - switch (devtype) - { - case 0x01: /* sequential access, (tape) */ - case 0x08: /* medium changer */ - /* this is the only kind of dev */ - /* we want to expose here. */ - if (cciss_scsi_add_entry(cntl_num, -1, - (unsigned char *) ld_buff->LUN[i], - devtype) != 0) - i=num_luns; // leave loop - break; - default: - break; - } - - } - } - else printk("cciss: inquiry failed.\n"); + shba = (struct cciss_scsi_adapter_data_t *) + kmalloc(sizeof(*shba), GFP_KERNEL); + if (shba == NULL) + return; + shba->scsi_host = NULL; + shba->lock = SPIN_LOCK_UNLOCKED; + shba->registered = 0; + if (scsi_cmd_stack_setup(cntl_num, shba) != 0) { + kfree(shba); + shba = NULL; } -#if 0 - for (i=0;iscsi_ctlr = (void *) shba; return; } @@ -913,7 +811,7 @@ memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memcpy(cp->Request.CDB, cdb, cdblen); - cp->Request.Timeout = 1000; // guarantee completion. + cp->Request.Timeout = 0; cp->Request.CDBLen = cdblen; cp->Request.Type.Type = TYPE_CMD; cp->Request.Type.Attribute = ATTR_SIMPLE; @@ -1208,6 +1106,12 @@ { case 0x01: /* sequential access, (tape) */ case 0x08: /* medium changer */ + if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { + printk(KERN_INFO "cciss%d: %s ignored, " + "too many devices.\n", cntl_num, + DEVICETYPE(devtype)); + break; + } memcpy(¤tsd[ncurrent].scsi3addr[0], &scsi3addr[0], 8); currentsd[ncurrent].devtype = devtype; @@ -1262,7 +1166,6 @@ int buflen, datalen; struct Scsi_Host *sh; - int found; ctlr_info_t *ci; int cntl_num; @@ -1379,11 +1282,11 @@ // Get the ptr to our adapter structure (hba[i]) out of cmd->host. // We violate cmd->host privacy here. (Is there another way?) - c = (ctlr_info_t **) &cmd->device->host->hostdata[0]; + c = (ctlr_info_t **) &cmd->device->host->hostdata[0]; ctlr = (*c)->ctlr; - rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, cmd->device->lun, - scsi3addr); + rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, + cmd->device->lun, scsi3addr); if (rc != 0) { /* the scsi nexus does not match any that we presented... */ /* pretend to mid layer that we got selection timeout */ @@ -1428,7 +1331,7 @@ // Fill in the request block... - cp->Request.Timeout = 1000; // guarantee completion + cp->Request.Timeout = 0; memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); cp->Request.CDBLen = cmd->cmd_len; @@ -1531,7 +1434,7 @@ } static int -cciss_register_scsi(int ctlr, int this_is_init_time) +cciss_register_scsi(int ctlr) { unsigned long flags; @@ -1541,15 +1444,10 @@ driver_template[ctlr].module = THIS_MODULE;; /* Since this is really a block driver, the SCSI core may not be - initialized yet, in which case, calling scsi_register_host - would hang. instead, we will do it later, via /proc filesystem + initialized at init time, in which case, calling scsi_register_host + would hang. Instead, we do it later, via /proc filesystem and rc scripts, when we know SCSI core is good to go. */ - if (this_is_init_time) { - CPQ_TAPE_UNLOCK(ctlr, flags); - return 0; - } - /* Only register if SCSI devices are detected. */ if (ccissscsi[ctlr].ndevices != 0) { ((struct cciss_scsi_adapter_data_t *) @@ -1583,7 +1481,7 @@ } spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); cciss_update_non_disk_devices(ctlr, -1); - cciss_register_scsi(ctlr, 0); + cciss_register_scsi(ctlr); return 0; } @@ -1607,9 +1505,9 @@ /* If no tape support, then these become defined out of existence */ -#define cciss_find_non_disk_devices(cntl_num) +#define cciss_scsi_setup(cntl_num) #define cciss_unregister_scsi(ctlr) -#define cciss_register_scsi(ctlr, this_is_init_time) +#define cciss_register_scsi(ctlr) #define cciss_proc_tape_report(ctlr, buffer, pos, len) #endif /* CONFIG_CISS_SCSI_TAPE */ diff -Nru a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c --- a/drivers/block/deadline-iosched.c Mon Feb 17 14:57:28 2003 +++ b/drivers/block/deadline-iosched.c Mon Feb 17 14:57:28 2003 @@ -98,6 +98,8 @@ unsigned long expires; }; +static inline void deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq); + static kmem_cache_t *drq_pool; #define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) @@ -189,26 +191,22 @@ return 0; } -static int +static void deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) { struct deadline_rq *__alias; drq->rb_key = rq_rb_key(drq->request); +retry: __alias = __deadline_add_drq_rb(dd, drq); if (!__alias) { rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); - return 0; + return; } - /* - * this should not typically happen, but if it does simply chain - * the two requests. then they will be moved to the dispatch list - * at the same time - */ - list_add(&drq->request->queuelist, &__alias->request->queuelist); - return 1; + deadline_move_to_dispatch(dd, __alias); + goto retry; } static inline void @@ -276,13 +274,12 @@ { const int data_dir = rq_data_dir(drq->request); - if (!deadline_add_drq_rb(dd, drq)) { - /* - * set expire time (only used for reads) and add to fifo list - */ - drq->expires = jiffies + dd->fifo_expire[data_dir]; - list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); - } + deadline_add_drq_rb(dd, drq); + /* + * set expire time (only used for reads) and add to fifo list + */ + drq->expires = jiffies + dd->fifo_expire[data_dir]; + list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); } /* @@ -300,6 +297,9 @@ deadline_del_drq_rb(dd, drq); } + if (q->last_merge == &rq->queuelist) + q->last_merge = NULL; + list_del_init(&rq->queuelist); } @@ -425,8 +425,9 @@ static inline void deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) { - deadline_del_drq_rb(dd, drq); - list_del_init(&drq->fifo); + request_queue_t *q = drq->request->q; + + deadline_remove_request(q, drq->request); list_add_tail(&drq->request->queuelist, dd->dispatch); } diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c --- a/drivers/block/elevator.c Mon Feb 17 14:57:28 2003 +++ b/drivers/block/elevator.c Mon Feb 17 14:57:28 2003 @@ -399,7 +399,7 @@ elevator_t *e = &q->elevator; if (e->elevator_former_req_fn) - return e->elevator_latter_req_fn(q, rq); + return e->elevator_former_req_fn(q, rq); prev = rq->queuelist.prev; if (prev != &q->queue_head && prev != &rq->queuelist) diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Mon Feb 17 14:57:26 2003 +++ b/drivers/block/ll_rw_blk.c Mon Feb 17 14:57:26 2003 @@ -1358,11 +1358,19 @@ generic_unplug_device(q); do { + int block = 0; + prepare_to_wait_exclusive(&rl->wait, &wait, TASK_UNINTERRUPTIBLE); + spin_lock_irq(q->queue_lock); if (!rl->count) + block = 1; + spin_unlock_irq(q->queue_lock); + + if (block) io_schedule(); finish_wait(&rl->wait, &wait); + spin_lock_irq(q->queue_lock); rq = get_request(q, rw); spin_unlock_irq(q->queue_lock); @@ -1596,13 +1604,9 @@ DEFINE_WAIT(wait); struct congestion_state *cs = &congestion_states[rw]; - if (!atomic_read(&cs->nr_active_queues)) - return; - blk_run_queues(); prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(&cs->nr_active_queues)) - io_schedule_timeout(timeout); + io_schedule_timeout(timeout); finish_wait(&cs->wqh, &wait); } diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c --- a/drivers/bluetooth/bt3c_cs.c Mon Feb 17 14:57:28 2003 +++ b/drivers/bluetooth/bt3c_cs.c Mon Feb 17 14:57:28 2003 @@ -24,18 +24,14 @@ #include #include -#define __KERNEL_SYSCALLS__ - #include #include #include #include #include #include -#include #include #include -#include #include #include #include @@ -405,7 +401,6 @@ - /* ======================== HCI interface ======================== */ @@ -489,65 +484,23 @@ #define FW_LOADER "/sbin/bluefw" -static int errno; - - -static int bt3c_fw_loader_exec(void *dev) -{ - char *argv[] = { FW_LOADER, "pccard", dev, NULL }; - char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - int err; - - err = exec_usermodehelper(FW_LOADER, argv, envp); - if (err) - printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev); - - return err; -} static int bt3c_firmware_load(bt3c_info_t *info) { - sigset_t tmpsig; char dev[16]; - pid_t pid; - int result; + int err; - /* Check if root fs is mounted */ - if (!current->fs->root) { - printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n"); - return -EPERM; - } + char *argv[] = { FW_LOADER, "pccard", dev, NULL }; + char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; sprintf(dev, "%04x", info->link.io.BasePort1); - pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0); - if (pid < 0) { - printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid); - return pid; - } - - /* Block signals, everything but SIGKILL/SIGSTOP */ - spin_lock_irq(¤t->sighand->siglock); - tmpsig = current->blocked; - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - result = waitpid(pid, NULL, __WCLONE); - - /* Allow signals again */ - spin_lock_irq(¤t->sighand->siglock); - current->blocked = tmpsig; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (result != pid) { - printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result); - return -result; - } + err = call_usermodehelper(FW_LOADER, argv, envp, 1); + if (err) + printk(KERN_WARNING "bt3c_cs: Failed to run \"%s pccard %s\" (errno=%d).\n", FW_LOADER, dev, err); - return 0; + return err; } diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c Mon Feb 17 14:57:27 2003 +++ b/drivers/cdrom/cdrom.c Mon Feb 17 14:57:27 2003 @@ -2542,33 +2542,81 @@ /* Place files in /proc/sys/dev/cdrom */ ctl_table cdrom_table[] = { - {DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info, - CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info}, - {DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check, - sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, - {0} - }; + { + .ctl_name = DEV_CDROM_INFO, + .procname = "info", + .data = &cdrom_sysctl_settings.info, + .maxlen = CDROM_STR_SIZE, + .mode = 0444, + .proc_handler = &cdrom_sysctl_info, + }, + { + .ctl_name = DEV_CDROM_AUTOCLOSE, + .procname = "autoclose", + .data = &cdrom_sysctl_settings.autoclose, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &cdrom_sysctl_handler, + }, + { + .ctl_name = DEV_CDROM_AUTOEJECT, + .procname = "autoeject", + .data = &cdrom_sysctl_settings.autoeject, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &cdrom_sysctl_handler, + }, + { + .ctl_name = DEV_CDROM_DEBUG, + .procname = "debug", + .data = &cdrom_sysctl_settings.debug, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &cdrom_sysctl_handler, + }, + { + .ctl_name = DEV_CDROM_LOCK, + .procname = "lock", + .data = &cdrom_sysctl_settings.lock, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &cdrom_sysctl_handler, + }, + { + .ctl_name = DEV_CDROM_CHECK_MEDIA, + .procname = "check_media", + .data = &cdrom_sysctl_settings.check, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &cdrom_sysctl_handler + }, + { .ctl_name = 0 } +}; ctl_table cdrom_cdrom_table[] = { - {DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table}, - {0} - }; + { + .ctl_name = DEV_CDROM, + .procname = "cdrom", + .maxlen = 0, + .mode = 0555, + .child = cdrom_table, + }, + { .ctl_name = 0 } +}; /* Make sure that /proc/sys/dev is there */ ctl_table cdrom_root_table[] = { #ifdef CONFIG_PROC_FS - {CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table}, + { + .ctl_name = CTL_DEV, + .procname = "dev", + .maxlen = 0, + .mode = 0555, + .child = cdrom_cdrom_table, + }, #endif /* CONFIG_PROC_FS */ - {0} - }; + { .ctl_name = 0 } +}; static struct ctl_table_header *cdrom_sysctl_header; static void cdrom_sysctl_register(void) diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Mon Feb 17 14:57:26 2003 +++ b/drivers/char/random.c Mon Feb 17 14:57:26 2003 @@ -535,14 +535,14 @@ r->extract_count = 0; memset(r->pool, 0, r->poolinfo.POOLBYTES); } - +#ifdef CONFIG_SYSCTL static void free_entropy_store(struct entropy_store *r) { if (r->pool) kfree(r->pool); kfree(r); } - +#endif /* * This function adds a byte into the entropy "pool". It does not * update the entropy estimate. The caller should call diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c --- a/drivers/char/rio/rioboot.c Mon Feb 17 14:57:27 2003 +++ b/drivers/char/rio/rioboot.c Mon Feb 17 14:57:27 2003 @@ -410,7 +410,7 @@ ** compatible with the whole Tp family. (lies, damn lies, it'll never ** work in a month of Sundays). ** - ** The nfix nyble is the 1s compliment of the nyble value you + ** The nfix nyble is the 1s complement of the nyble value you ** want to load - in this case we wanted 'F' so we nfix loaded '0'. */ diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c Mon Feb 17 14:57:27 2003 +++ b/drivers/char/rtc.c Mon Feb 17 14:57:27 2003 @@ -211,19 +211,37 @@ * sysctl-tuning infrastructure. */ static ctl_table rtc_table[] = { - { 1, "max-user-freq", &rtc_max_user_freq, sizeof(int), 0644, NULL, - &proc_dointvec, NULL, }, - { 0, } + { + .ctl_name = 1, + .procname = "max-user-freq", + .data = &rtc_max_user_freq, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = 0 } }; static ctl_table rtc_root[] = { - { 1, "rtc", NULL, 0, 0555, rtc_table, }, - { 0, } + { + .ctl_name = 1, + .procname = "rtc", + .maxlen = 0, + .mode = 0555, + .child = rtc_table, + }, + { .ctl_name = 0 } }; static ctl_table dev_root[] = { - { CTL_DEV, "dev", NULL, 0, 0555, rtc_root, }, - { 0, } + { + .ctl_name = CTL_DEV, + .procname = "dev", + .maxlen = 0, + .mode = 0555, + .child = rtc_root, + }, + { .ctl_name = 0 } }; static struct ctl_table_header *sysctl_header; diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c --- a/drivers/char/sx.c Mon Feb 17 14:57:27 2003 +++ b/drivers/char/sx.c Mon Feb 17 14:57:27 2003 @@ -2233,6 +2233,23 @@ return 0; } + /* Now we're pretty much convinced that there is an SI board here, + but to prevent trouble, we'd better double check that we don't + have an SI1 board when we're probing for an SI2 board.... */ + + write_sx_byte (board, SI2_ISA_ID_BASE,0x10); + if ( IS_SI1_BOARD(board)) { + /* This should be an SI1 board, which has this + location writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) + return 0; + } else { + /* This should be an SI2 board, which has the bottom + 3 bits non-writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) + return 0; + } + printheader (); printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Mon Feb 17 14:57:27 2003 +++ b/drivers/char/tty_io.c Mon Feb 17 14:57:27 2003 @@ -2043,7 +2043,7 @@ /* * The default put_char routine if the driver did not define one. */ -void tty_default_put_char(struct tty_struct *tty, unsigned char ch) +static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) { tty->driver.write(tty, 0, &ch, 1); } diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Mon Feb 17 14:57:28 2003 +++ b/drivers/char/vt.c Mon Feb 17 14:57:28 2003 @@ -2101,7 +2101,7 @@ if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; - /* read `x' only after setting currecons properly (otherwise + /* read `x' only after setting currcons properly (otherwise the `x' macro will read the x of the foreground console). */ myx = x; @@ -2198,8 +2198,8 @@ * * There are some functions which don't need it. * - * There are some functions which can sleep for arbitrary periods (paste_selection) - * but we don't need the lock there anyway. + * There are some functions which can sleep for arbitrary periods + * (paste_selection) but we don't need the lock there anyway. * * set_selection has locking, and definitely needs it */ diff -Nru a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c --- a/drivers/char/watchdog/wdt285.c Mon Feb 17 14:57:27 2003 +++ b/drivers/char/watchdog/wdt285.c Mon Feb 17 14:57:27 2003 @@ -37,18 +37,14 @@ */ #undef ONLY_TESTING -#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ - -#define FCLK (50*1000*1000) /* 50MHz */ - -static int soft_margin = TIMER_MARGIN; /* in seconds */ -static int timer_alive; +static unsigned int soft_margin = 60; /* in seconds */ +static unsigned int reload; +static unsigned long timer_alive; #ifdef ONLY_TESTING /* * If the timer expires.. */ - static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs) { printk(KERN_CRIT "Watchdog: Would Reboot.\n"); @@ -57,109 +53,134 @@ } #endif +/* + * Refresh the timer. + */ static void watchdog_ping(void) { - /* - * Refresh the timer. - */ - *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256); + *CSR_TIMER4_LOAD = reload; } /* * Allow only one person to hold it open */ - static int watchdog_open(struct inode *inode, struct file *file) { - if(timer_alive) + int ret; + + if (*CSR_SA110_CNTL & (1 << 13)) return -EBUSY; - /* - * Ahead watchdog factor ten, Mr Sulu - */ + + if (test_and_set_bit(1, &timer_alive)) + return -EBUSY; + + reload = soft_margin * (mem_fclk_21285 / 256); + *CSR_TIMER4_CLR = 0; watchdog_ping(); *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV256; + #ifdef ONLY_TESTING - request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL); + ret = request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL); + if (ret) { + *CSR_TIMER4_CNTL = 0; + clear_bit(1, &timer_alive); + } #else + /* + * Setting this bit is irreversible; once enabled, there is + * no way to disable the watchdog. + */ *CSR_SA110_CNTL |= 1 << 13; - MOD_INC_USE_COUNT; + + ret = 0; #endif - timer_alive = 1; - return 0; + return ret; } +/* + * Shut off the timer. + * Note: if we really have enabled the watchdog, there + * is no way to turn off. + */ static int watchdog_release(struct inode *inode, struct file *file) { #ifdef ONLY_TESTING free_irq(IRQ_TIMER4, NULL); - timer_alive = 0; -#else - /* - * It's irreversible! - */ + clear_bit(1, &timer_alive); #endif return 0; } -static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +static ssize_t +watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ + /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; /* * Refresh the timer. */ - if(len) - { + if (len) watchdog_ping(); - return 1; - } - return 0; + + return len; } -static int watchdog_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int i, new_margin; - static struct watchdog_info ident= - { - WDIOF_SETTIMEOUT, - 0, - "Footbridge Watchdog" - }; - switch(cmd) - { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); - case WDIOC_KEEPALIVE: - watchdog_ping(); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int *)arg)) - return -EFAULT; - /* Arbitrary, can't find the card's limits */ - if ((new_marg < 0) || (new_margin > 60)) - return -EINVAL; - soft_margin = new_margin; - watchdog_ping(); - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user(soft_margin, (int *)arg); +static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT, + .identity = "Footbridge Watchdog" +}; + +static int +watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int new_margin; + int ret = -ENOIOCTLCMD; + + switch(cmd) { + case WDIOC_GETSUPPORT: + ret = 0; + if (copy_to_user((void *)arg, &ident, sizeof(ident))) + ret = -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0,(int *)arg); + break; + + case WDIOC_KEEPALIVE: + watchdog_ping(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(new_margin, (int *)arg); + if (ret) + break; + + /* Arbitrary, can't find the card's limits */ + if (new_margin < 0 || new_margin > 60) { + ret = -EINVAL; + break; + } + + soft_margin = new_margin; + reload = soft_margin * (mem_fclk_21285 / 256); + watchdog_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + ret = put_user(soft_margin, (int *)arg); + break; } + return ret; } -static struct file_operations watchdog_fops= -{ +static struct file_operations watchdog_fops = { .owner = THIS_MODULE, .write = watchdog_write, .ioctl = watchdog_ioctl, @@ -167,11 +188,10 @@ .release = watchdog_release, }; -static struct miscdevice watchdog_miscdev= -{ - WATCHDOG_MINOR, - "watchdog", - &watchdog_fops +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops }; static int __init footbridge_watchdog_init(void) @@ -182,11 +202,12 @@ return -ENODEV; retval = misc_register(&watchdog_miscdev); - if(retval < 0) + if (retval < 0) return retval; printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", soft_margin); + if (machine_is_cats()) printk("Warning: Watchdog reset may not work on this machine.\n"); return 0; @@ -198,7 +219,7 @@ } MODULE_AUTHOR("Phil Blundell "); -MODULE_DESCRIPTION("21285 watchdog driver"); +MODULE_DESCRIPTION("Footbridge watchdog driver"); MODULE_LICENSE("GPL"); MODULE_PARM(soft_margin,"i"); diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c --- a/drivers/char/watchdog/wdt977.c Mon Feb 17 14:57:28 2003 +++ b/drivers/char/watchdog/wdt977.c Mon Feb 17 14:57:28 2003 @@ -58,7 +58,7 @@ /* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */ -int kick_wdog(void) +static int kick_wdog(void) { /* * Refresh the timer. @@ -216,21 +216,20 @@ static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ + /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; - if(count) - { + if (count) { if (!nowayout) { size_t i; /* In case it was set long ago */ expect_close = 0; - for (i = 0; i != len; i++) { + for (i = 0; i != count; i++) { char c; - if (get_user(c, data + i)) + if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') expect_close = 1; @@ -238,9 +237,8 @@ } kick_wdog(); - return 1; } - return 0; + return count; } /* @@ -254,14 +252,15 @@ * according to their available features. */ -static int wdt977_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ static struct watchdog_info ident = { - .identity = "Winbond 83977" + .options = WDIOF_SETTIMEOUT, + .identity = "Winbond 83977" }; -int temp; +static int wdt977_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int temp; switch(cmd) { @@ -337,9 +336,9 @@ static struct miscdevice wdt977_miscdev= { - WATCHDOG_MINOR, - "watchdog", - &wdt977_fops + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt977_fops }; static int __init nwwatchdog_init(void) @@ -360,4 +359,5 @@ module_init(nwwatchdog_init); module_exit(nwwatchdog_exit); +MODULE_DESCRIPTION("W83977AF Watchdog driver"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/cpufreq/Kconfig Mon Feb 17 14:57:28 2003 @@ -0,0 +1,11 @@ +config CPU_FREQ_PROC_INTF + tristate "/proc/cpufreq interface (deprecated)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. diff -Nru a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/cpufreq/Makefile Mon Feb 17 14:57:28 2003 @@ -0,0 +1,3 @@ +#CPUfreq governors and cross-arch helpers +obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o +obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/cpufreq/freq_table.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,203 @@ +/* + * linux/drivers/cpufreq/freq_table.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + */ + +#include +#include +#include +#include + +/********************************************************************* + * FREQUENCY TABLE HELPERS * + *********************************************************************/ + +int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table) +{ + unsigned int min_freq = ~0; + unsigned int max_freq = 0; + unsigned int i = 0; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if (freq < min_freq) + min_freq = freq; + if (freq > max_freq) + max_freq = freq; + } + + policy->min = policy->cpuinfo.min_freq = min_freq; + policy->max = policy->cpuinfo.max_freq = max_freq; + + if (policy->min == ~0) + return -EINVAL; + else + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); + + +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table) +{ + unsigned int next_larger = ~0; + unsigned int i = 0; + unsigned int count = 0; + + if (!cpu_online(policy->cpu)) + return -EINVAL; + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if ((freq >= policy->min) && (freq <= policy->max)) + count++; + else if ((next_larger > freq) && (freq > policy->max)) + next_larger = freq; + } + + if (!count) + policy->max = next_larger; + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); + + +int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int *index) +{ + struct cpufreq_frequency_table optimal = { .index = ~0, }; + unsigned int i; + + switch (policy->policy) { + case CPUFREQ_POLICY_PERFORMANCE: + optimal.frequency = 0; + break; + case CPUFREQ_POLICY_POWERSAVE: + optimal.frequency = ~0; + break; + } + + if (!cpu_online(policy->cpu)) + return -EINVAL; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if ((freq < policy->min) || (freq > policy->max)) + continue; + switch(policy->policy) { + case CPUFREQ_POLICY_PERFORMANCE: + if (optimal.frequency <= freq) { + optimal.frequency = freq; + optimal.index = i; + } + break; + case CPUFREQ_POLICY_POWERSAVE: + if (optimal.frequency >= freq) { + optimal.frequency = freq; + optimal.index = i; + } + break; + } + } + if (optimal.index > i) + return -EINVAL; + + *index = optimal.index; + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy); + + +int cpufreq_frequency_table_target(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int target_freq, + unsigned int relation, + unsigned int *index) +{ + struct cpufreq_frequency_table optimal = { .index = ~0, }; + struct cpufreq_frequency_table suboptimal = { .index = ~0, }; + unsigned int i; + + switch (relation) { + case CPUFREQ_RELATION_H: + optimal.frequency = 0; + suboptimal.frequency = ~0; + break; + case CPUFREQ_RELATION_L: + optimal.frequency = ~0; + suboptimal.frequency = 0; + break; + } + + if (!cpu_online(policy->cpu)) + return -EINVAL; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if ((freq < policy->min) || (freq > policy->max)) + continue; + switch(relation) { + case CPUFREQ_RELATION_H: + if (freq <= target_freq) { + if (freq >= optimal.frequency) { + optimal.frequency = freq; + optimal.index = i; + } + } else { + if (freq <= suboptimal.frequency) { + suboptimal.frequency = freq; + suboptimal.index = i; + } + } + break; + case CPUFREQ_RELATION_L: + if (freq >= target_freq) { + if (freq <= optimal.frequency) { + optimal.frequency = freq; + optimal.index = i; + } + } else { + if (freq >= suboptimal.frequency) { + suboptimal.frequency = freq; + suboptimal.index = i; + } + } + break; + } + } + if (optimal.index > i) { + if (suboptimal.index > i) + return -EINVAL; + *index = suboptimal.index; + } else + *index = optimal.index; + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); + + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("CPUfreq frequency table helpers"); +MODULE_LICENSE ("GPL"); diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/cpufreq/proc_intf.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,244 @@ +/* + * linux/drivers/cpufreq/proc_intf.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + */ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * cpufreq_parse_policy - parse a policy string + * @input_string: the string to parse. + * @policy: the policy written inside input_string + * + * This function parses a "policy string" - something the user echo'es into + * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy. + * If there are invalid/missing entries, they are replaced with current + * cpufreq policy. + */ +static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy) +{ + unsigned int min = 0; + unsigned int max = 0; + unsigned int cpu = 0; + char str_governor[16]; + struct cpufreq_policy current_policy; + unsigned int result = -EFAULT; + + if (!policy) + return -EINVAL; + + policy->min = 0; + policy->max = 0; + policy->policy = 0; + policy->cpu = CPUFREQ_ALL_CPUS; + + if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4) + { + policy->min = min; + policy->max = max; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.cpuinfo.max_freq) / 100; + policy->max = (max * current_policy.cpuinfo.max_freq) / 100; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + } + + if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3) + { + policy->min = min; + policy->max = max; + result = 0; + goto scan_policy; + } + + if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.cpuinfo.max_freq) / 100; + policy->max = (max * current_policy.cpuinfo.max_freq) / 100; + result = 0; + goto scan_policy; + } + } + + return -EINVAL; + +scan_policy: + result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor); + + return result; +} + +/** + * cpufreq_proc_read - read /proc/cpufreq + * + * This function prints out the current cpufreq policy. + */ +static int cpufreq_proc_read ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + char *p = page; + int len = 0; + struct cpufreq_policy policy; + unsigned int min_pctg = 0; + unsigned int max_pctg = 0; + unsigned int i = 0; + + if (off != 0) + goto end; + + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); + for (i=0;iname); + break; + default: + p += sprintf(p, "INVALID\n"); + break; + } + } +end: + len = (p - page); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + + return len; +} + + +/** + * cpufreq_proc_write - handles writing into /proc/cpufreq + * + * This function calls the parsing script and then sets the policy + * accordingly. + */ +static int cpufreq_proc_write ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + char proc_string[42] = {'\0'}; + struct cpufreq_policy policy; + unsigned int i = 0; + + + if ((count > sizeof(proc_string) - 1)) + return -EINVAL; + + if (copy_from_user(proc_string, buffer, count)) + return -EFAULT; + + proc_string[count] = '\0'; + + result = cpufreq_parse_policy(proc_string, &policy); + if (result) + return -EFAULT; + + if (policy.cpu == CPUFREQ_ALL_CPUS) + { + for (i=0; iread_proc = cpufreq_proc_read; + entry->write_proc = cpufreq_proc_write; + } + + return 0; +} + + +/** + * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory. + * + * This function removes "cpufreq" from the /proc root directory. + */ +static void __exit cpufreq_proc_exit (void) +{ + remove_proc_entry("cpufreq", &proc_root); + return; +} + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_proc_init); +module_exit(cpufreq_proc_exit); diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig --- a/drivers/eisa/Kconfig Mon Feb 17 14:57:27 2003 +++ b/drivers/eisa/Kconfig Mon Feb 17 14:57:27 2003 @@ -1,6 +1,28 @@ # -# PCI configuration +# EISA configuration # +config EISA_PCI_EISA + bool "Generic PCI/EISA bridge" + depends on PCI && EISA + default y + ---help--- + Activate this option if your system contains a PCI to EISA + bridge. If your system have both PCI and EISA slots, you + certainly need this option. + + When in doubt, say Y. + +config EISA_VIRTUAL_ROOT + bool "EISA virtual root device" + depends on EISA + default y + ---help--- + Activate this option if your system only have EISA bus + (no PCI slots). The Alpha Jensen is an example of such + a system. + + When in doubt, say Y. + config EISA_NAMES bool "EISA device name database" depends on EISA diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile --- a/drivers/eisa/Makefile Mon Feb 17 14:57:27 2003 +++ b/drivers/eisa/Makefile Mon Feb 17 14:57:27 2003 @@ -1,6 +1,11 @@ # Makefile for the Linux device tree -obj-$(CONFIG_EISA) += eisa-bus.o +obj-$(CONFIG_EISA) += eisa-bus.o +obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o + +# virtual_root.o should be the last EISA root device to initialize, +# so leave it at the end of the list. +obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o clean-files:= devlist.h diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c --- a/drivers/eisa/eisa-bus.c Mon Feb 17 14:57:27 2003 +++ b/drivers/eisa/eisa-bus.c Mon Feb 17 14:57:27 2003 @@ -15,6 +15,8 @@ #include #include +#define SLOT_ADDRESS(r,n) (r->bus_base_addr + (0x1000 * n)) + #define EISA_DEVINFO(i,s) { .id = { .sig = i }, .name = s } struct eisa_device_info { @@ -95,12 +97,6 @@ .match = eisa_bus_match, }; -/* The default EISA device parent (virtual root device). */ -static struct device eisa_bus_root = { - .name = "EISA Bridge", - .bus_id = "eisa", -}; - int eisa_driver_register (struct eisa_driver *edrv) { int r; @@ -109,7 +105,7 @@ if ((r = driver_register (&edrv->driver)) < 0) return r; - return 1; + return 0; } void eisa_driver_unregister (struct eisa_driver *edrv) @@ -125,7 +121,8 @@ static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL); -static void __init eisa_register_device (char *sig, int slot) +static void __init eisa_register_device (struct eisa_root_device *root, + char *sig, int slot) { struct eisa_device *edev; @@ -135,11 +132,11 @@ memset (edev, 0, sizeof (*edev)); memcpy (edev->id.sig, sig, 7); edev->slot = slot; - edev->base_addr = 0x1000 * slot; + edev->base_addr = SLOT_ADDRESS (root, slot); eisa_name_device (edev); - edev->dev.parent = &eisa_bus_root; + edev->dev.parent = root->dev; edev->dev.bus = &eisa_bus_type; - sprintf (edev->dev.bus_id, "00:%02X", slot); + sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot); /* Don't register resource for slot 0, since this will surely * fail... :-( */ @@ -150,7 +147,7 @@ edev->res.end = edev->res.start + 0xfff; edev->res.flags = IORESOURCE_IO; - if (request_resource (&ioport_resource, &edev->res)) { + if (request_resource (root->res, &edev->res)) { printk (KERN_WARNING \ "Cannot allocate resource for EISA slot %d\n", slot); @@ -167,16 +164,18 @@ device_create_file (&edev->dev, &dev_attr_signature); } -static int __init eisa_probe (void) +static int __init eisa_probe (struct eisa_root_device *root) { int i, c; char *str; - unsigned long slot_addr; + unsigned long sig_addr; - printk (KERN_INFO "EISA: Probing bus...\n"); - for (c = 0, i = 0; i <= EISA_MAX_SLOTS; i++) { - slot_addr = (0x1000 * i) + EISA_VENDOR_ID_OFFSET; - if ((str = decode_eisa_sig (slot_addr))) { + printk (KERN_INFO "EISA: Probing bus %d at %s\n", + root->bus_nr, root->dev->name); + + for (c = 0, i = 0; i <= root->slots; i++) { + sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET; + if ((str = decode_eisa_sig (sig_addr))) { if (!i) printk (KERN_INFO "EISA: Motherboard %s detected\n", str); @@ -187,7 +186,7 @@ c++; } - eisa_register_device (str, i); + eisa_register_device (root, str, i); } } printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s"); @@ -195,20 +194,40 @@ return 0; } + +static LIST_HEAD (eisa_root_head); + +static int eisa_bus_count; + +int eisa_root_register (struct eisa_root_device *root) +{ + struct list_head *node; + struct eisa_root_device *tmp_root; + + /* Check if this bus base address has been already + * registered. This prevents the virtual root device from + * registering after the real one has, for example... */ + + list_for_each (node, &eisa_root_head) { + tmp_root = list_entry (node, struct eisa_root_device, node); + if (tmp_root->bus_base_addr == root->bus_base_addr) + return -1; /* Space already taken, buddy... */ + } + + root->bus_nr = eisa_bus_count++; + list_add_tail (&root->node, &eisa_root_head); + return eisa_probe (root); +} + static int __init eisa_init (void) { int r; if ((r = bus_register (&eisa_bus_type))) return r; - - if ((r = device_register (&eisa_bus_root))) { - bus_unregister (&eisa_bus_type); - return r; - } printk (KERN_INFO "EISA bus registered\n"); - return eisa_probe (); + return 0; } postcore_initcall (eisa_init); diff -Nru a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/eisa/pci_eisa.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,64 @@ +/* + * Minimalist driver for a generic PCI-to-EISA bridge. + * + * (C) 2003 Marc Zyngier + * + * This code is released under the GPL version 2. + * + * Ivan Kokshaysky : + * Generalisation from i82375 to PCI_CLASS_BRIDGE_EISA. + */ + +#include +#include +#include +#include +#include +#include + +/* There is only *one* pci_eisa device per machine, right ? */ +static struct eisa_root_device pci_eisa_root; + +static int __devinit pci_eisa_init (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rc; + + if ((rc = pci_enable_device (pdev))) { + printk (KERN_ERR "pci_eisa : Could not enable device %s\n", + pdev->slot_name); + return rc; + } + + pci_eisa_root.dev = &pdev->dev; + pci_eisa_root.dev->driver_data = &pci_eisa_root; + pci_eisa_root.res = pdev->bus->resource[0]; + pci_eisa_root.bus_base_addr = pdev->bus->resource[0]->start; + pci_eisa_root.slots = EISA_MAX_SLOTS; + + if (eisa_root_register (&pci_eisa_root)) { + printk (KERN_ERR "pci_eisa : Could not register EISA root\n"); + return -1; + } + + return 0; +} + +static struct pci_device_id pci_eisa_pci_tbl[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 }, + { 0, } +}; + +static struct pci_driver pci_eisa_driver = { + .name = "pci_eisa", + .id_table = pci_eisa_pci_tbl, + .probe = pci_eisa_init, +}; + +static int __init pci_eisa_init_module (void) +{ + return pci_module_init (&pci_eisa_driver); +} + +device_initcall(pci_eisa_init_module); diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/eisa/virtual_root.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,49 @@ +/* + * Virtual EISA root driver. + * Acts as a placeholder if we don't have a proper EISA bridge. + * + * (C) 2003 Marc Zyngier + * + * This code is released under the GPL version 2. + */ + +#include +#include +#include +#include +#include + +/* The default EISA device parent (virtual root device). */ +static struct device eisa_root_dev = { + .name = "Virtual EISA Bridge", + .bus_id = "eisa", +}; + +static struct eisa_root_device eisa_bus_root = { + .dev = &eisa_root_dev, + .bus_base_addr = 0, + .res = &ioport_resource, + .slots = EISA_MAX_SLOTS, +}; + +static int virtual_eisa_root_init (void) +{ + int r; + + if ((r = device_register (&eisa_root_dev))) { + return r; + } + + eisa_root_dev.driver_data = &eisa_bus_root; + + if (eisa_root_register (&eisa_bus_root)) { + /* A real bridge may have been registered before + * us. So quietly unregister. */ + device_unregister (&eisa_root_dev); + return -1; + } + + return 0; +} + +device_initcall (virtual_eisa_root_init); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Mon Feb 17 14:57:28 2003 +++ b/drivers/ide/pci/amd74xx.c Mon Feb 17 14:57:28 2003 @@ -311,7 +311,7 @@ amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0); for (i = 24; i >= 0; i -= 8) if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { - printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n"); + printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits correctly. Enabling workaround.\n"); amd_80w |= (1 << (1 - (i >> 4))); } break; diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile --- a/drivers/ieee1394/Makefile Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/Makefile Mon Feb 17 14:57:28 2003 @@ -18,6 +18,8 @@ clean-files := oui.c +ieee1394.o: $(ieee1394-objs) + $(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs) ifeq ($(obj),) obj = . diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/amdtp.c Mon Feb 17 14:57:27 2003 @@ -598,6 +598,8 @@ struct buffer *b; b = kmalloc(sizeof *b + size, SLAB_KERNEL); + if (b == NULL) + return NULL; b->head = 0; b->tail = 0; b->length = 0; diff -Nru a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h --- a/drivers/ieee1394/amdtp.h Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/amdtp.h Mon Feb 17 14:57:27 2003 @@ -3,8 +3,8 @@ #ifndef __AMDTP_H #define __AMDTP_H -#include #include +#include "ieee1394-ioctl.h" /* The userspace interface for the Audio & Music Data Transmission * Protocol driver is really simple. First, open /dev/amdtp, use the @@ -56,13 +56,6 @@ * | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ... * */ - -/* We use '#' for our ioctl magic number because it's cool. */ - -#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_PLUG _IOW('#', 1, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_PING _IOW('#', 2, sizeof (struct amdtp_ioctl)) -#define AMDTP_IOC_ZAP _IO('#', 3) enum { AMDTP_FORMAT_RAW, diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c --- a/drivers/ieee1394/dma.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/dma.c Mon Feb 17 14:57:27 2003 @@ -25,9 +25,8 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev) { /* round up to page size */ - if(n_bytes % PAGE_SIZE) - n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE); - + n_bytes = round_up_to_page(n_bytes); + prog->n_pages = n_bytes / PAGE_SIZE; prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); @@ -47,7 +46,7 @@ if(prog->kvirt) { pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); } - + prog->kvirt = NULL; prog->dev = NULL; prog->n_pages = 0; @@ -70,11 +69,10 @@ unsigned int i, n_pages; /* round up to page size */ - if(n_bytes % PAGE_SIZE) - n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE); - + n_bytes = round_up_to_page(n_bytes); + n_pages = n_bytes / PAGE_SIZE; - + dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); if(!dma->kvirt) { printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); @@ -82,7 +80,7 @@ } dma->n_pages = n_pages; - + /* Clear the ram out, no junk to the user */ memset(dma->kvirt, 0, n_pages * PAGE_SIZE); @@ -114,7 +112,7 @@ dma->dev = dev; dma->direction = direction; - + return 0; err: @@ -148,7 +146,7 @@ { int i; unsigned long off = offset; - + for(i = 0; i < dma->n_dma_pages; i++) { if(off < sg_dma_len(&dma->sglist[i])) { *rem = off; @@ -157,14 +155,14 @@ off -= sg_dma_len(&dma->sglist[i]); } - + panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset); } dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset) { unsigned long rem; - + struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)]; return sg_dma_address(sg) + rem; } @@ -176,10 +174,10 @@ if(!len) len = 1; - + first = dma_region_find(dma, offset, &rem); last = dma_region_find(dma, offset + len - 1, &rem); - + pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); } @@ -210,13 +208,13 @@ } static struct vm_operations_struct dma_region_vm_ops = { - nopage: dma_region_pagefault, + .nopage = dma_region_pagefault, }; int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma) { unsigned long size; - + if(!dma->kvirt) return -EINVAL; @@ -233,6 +231,6 @@ vma->vm_private_data = dma; vma->vm_file = file; vma->vm_flags |= VM_RESERVED; - + return 0; } diff -Nru a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h --- a/drivers/ieee1394/dma.h Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/dma.h Mon Feb 17 14:57:28 2003 @@ -73,4 +73,12 @@ relative to the beginning of the dma_region */ dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); +/* round up a number of bytes to be a multiple of the PAGE_SIZE */ +static inline unsigned long round_up_to_page(unsigned long len) +{ + if(len % PAGE_SIZE) + len += PAGE_SIZE - (len % PAGE_SIZE); + return len; +} + #endif /* IEEE1394_DMA_H */ diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/dv1394.c Mon Feb 17 14:57:28 2003 @@ -918,6 +918,7 @@ u64 chan_mask; int retval = -EINVAL; + debug_printk( "dv1394: initialising %d\n", video->id ); if(init->api_version != DV1394_API_VERSION) goto err; @@ -1186,6 +1187,7 @@ if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { /* still active */ + debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); mb(); } else { debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); @@ -1199,7 +1201,9 @@ printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); } } - + else + debug_printk("dv1394: stop_dma: already stopped.\n"); + spin_unlock_irqrestore(&video->spinlock, flags); } @@ -1226,7 +1230,8 @@ /* disable interrupts for IT context */ reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); - clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); video->ohci_it_ctx = -1; } @@ -1240,23 +1245,14 @@ /* disable interrupts for IR context */ reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); - clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); video->ohci_ir_ctx = -1; } spin_unlock_irqrestore(&video->spinlock, flags); - /* remove tasklets */ - if(video->ohci_it_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); - video->ohci_it_ctx = -1; - } - if(video->ohci_ir_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); - video->ohci_ir_ctx = -1; - } - /* release the ISO channel */ if(video->channel != -1) { u64 chan_mask; @@ -1612,7 +1608,7 @@ switch(cmd) { - case DV1394_SUBMIT_FRAMES: { + case DV1394_IOC_SUBMIT_FRAMES: { unsigned int n_submit; if( !video_card_initialized(video) ) { @@ -1666,7 +1662,7 @@ break; } - case DV1394_WAIT_FRAMES: { + case DV1394_IOC_WAIT_FRAMES: { unsigned int n_wait; if( !video_card_initialized(video) ) { @@ -1715,7 +1711,7 @@ break; } - case DV1394_RECEIVE_FRAMES: { + case DV1394_IOC_RECEIVE_FRAMES: { unsigned int n_recv; if( !video_card_initialized(video) ) { @@ -1748,7 +1744,7 @@ break; } - case DV1394_START_RECEIVE: { + case DV1394_IOC_START_RECEIVE: { if( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if(ret) @@ -1765,7 +1761,7 @@ break; } - case DV1394_INIT: { + case DV1394_IOC_INIT: { struct dv1394_init init; if(arg == (unsigned long) NULL) { ret = do_dv1394_init_default(video); @@ -1779,12 +1775,12 @@ break; } - case DV1394_SHUTDOWN: + case DV1394_IOC_SHUTDOWN: ret = do_dv1394_shutdown(video, 0); break; - case DV1394_GET_STATUS: { + case DV1394_IOC_GET_STATUS: { struct dv1394_status status; if( !video_card_initialized(video) ) { @@ -2346,6 +2342,7 @@ dbc = (int) (p->cip_h1 >> 24); if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) { + printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" ); video->dropped_frames += video->n_clear_frames + 1; video->first_frame = 0; video->n_clear_frames = 0; @@ -2364,9 +2361,8 @@ video->n_clear_frames++; if (video->n_clear_frames > video->n_frames) { video->dropped_frames++; - video->n_clear_frames--; - if (video->n_clear_frames < 0) - video->n_clear_frames = 0; + printk(KERN_WARNING "dv1394: dropped a frame during reception\n" ); + video->n_clear_frames = video->n_frames-1; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; } if (video->first_clear_frame == -1) @@ -2375,7 +2371,6 @@ /* get the next frame */ video->active_frame = (video->active_frame + 1) % video->n_frames; f = video->frames[video->active_frame]; - irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", video->active_frame, video->n_clear_frames, video->first_clear_frame); } diff -Nru a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h --- a/drivers/ieee1394/dv1394.h Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/dv1394.h Mon Feb 17 14:57:28 2003 @@ -200,48 +200,7 @@ /* ioctl() commands */ - -enum { - /* I don't like using 0 as a valid ioctl() */ - DV1394_INVALID = 0, - - - /* get the driver ready to transmit video. - pass a struct dv1394_init* as the parameter (see below), - or NULL to get default parameters */ - DV1394_INIT, - - - /* stop transmitting video and free the ringbuffer */ - DV1394_SHUTDOWN, - - - /* submit N new frames to be transmitted, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_SUBMIT_FRAMES, - - - /* block until N buffers are clear (pass N as the parameter) - Because we re-transmit the last frame on underrun, there - will at most be n_frames - 1 clear frames at any time */ - DV1394_WAIT_FRAMES, - - /* capture new frames that have been received, where - the index of the first new frame is first_clear_buffer, - and the index of the last new frame is - (first_clear_buffer + N) % n_frames */ - DV1394_RECEIVE_FRAMES, - - - DV1394_START_RECEIVE, - - - /* pass a struct dv1394_status* as the parameter (see below) */ - DV1394_GET_STATUS, -}; - +#include "ieee1394-ioctl.h" enum pal_or_ntsc { diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c --- a/drivers/ieee1394/eth1394.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/eth1394.c Mon Feb 17 14:57:27 2003 @@ -77,7 +77,7 @@ printk(KERN_ERR fmt, ## args) static char version[] __devinitdata = - "$Rev: 641 $ Ben Collins "; + "$Rev: 770 $ Ben Collins "; /* Our ieee1394 highlevel driver */ #define ETHER1394_DRIVER_NAME "ether1394" @@ -368,6 +368,7 @@ if (register_netdev (dev)) { ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); kfree (dev); + kfree (hi); return; } diff -Nru a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c --- a/drivers/ieee1394/highlevel.c Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/highlevel.c Mon Feb 17 14:57:28 2003 @@ -164,17 +164,19 @@ return retval; } -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel) { if (channel > 63) { HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return; + return -EINVAL; } if (host->iso_listen_count[channel]++ == 0) { - host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); + return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); } + + return 0; } void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, diff -Nru a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h --- a/drivers/ieee1394/highlevel.h Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/highlevel.h Mon Feb 17 14:57:27 2003 @@ -150,8 +150,8 @@ * Enable or disable receving a certain isochronous channel through the * iso_receive op. */ -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel); +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, + unsigned int channel); void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel); diff -Nru a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c --- a/drivers/ieee1394/hosts.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/hosts.c Mon Feb 17 14:57:27 2003 @@ -38,9 +38,15 @@ return -1; } +static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg) +{ + return -1; +} + static struct hpsb_host_driver dummy_driver = { .transmit_packet = dummy_transmit_packet, - .devctl = dummy_devctl + .devctl = dummy_devctl, + .isoctl = dummy_isoctl }; /** @@ -63,9 +69,11 @@ spin_lock_irqsave(&hosts_lock, flags); list_for_each(lh, &hosts) { if (host == list_entry(lh, struct hpsb_host, host_list)) { - host->driver->devctl(host, MODIFY_USAGE, 1); - host->refcount++; - retval = 1; + if (host->driver->devctl(host, MODIFY_USAGE, 1)) { + host->driver->devctl(host, MODIFY_USAGE, 1); + host->refcount++; + retval = 1; + } break; } } diff -Nru a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h --- a/drivers/ieee1394/hosts.h Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/hosts.h Mon Feb 17 14:57:27 2003 @@ -108,19 +108,22 @@ enum isoctl_cmd { /* rawiso API - see iso.h for the meanings of these commands * INIT = allocate resources - * START = begin transmission/reception (arg: cycle to start on) + * START = begin transmission/reception * STOP = halt transmission/reception - * QUEUE/RELEASE = produce/consume packets (arg: # of packets) + * QUEUE/RELEASE = produce/consume packets * SHUTDOWN = deallocate resources */ - + XMIT_INIT, XMIT_START, XMIT_STOP, XMIT_QUEUE, XMIT_SHUTDOWN, - + RECV_INIT, + RECV_LISTEN_CHANNEL, /* multi-channel only */ + RECV_UNLISTEN_CHANNEL, /* multi-channel only */ + RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */ RECV_START, RECV_STOP, RECV_RELEASE, @@ -170,11 +173,12 @@ */ int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); - /* ISO transmission/reception functions. Return 0 on success, -1 on failure. - * If the low-level driver does not support the new ISO API, set isoctl to NULL. + /* ISO transmission/reception functions. Return 0 on success, -1 + * (or -EXXX errno code) on failure. If the low-level driver does not + * support the new ISO API, set isoctl to NULL. */ - int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, int arg); - + int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg); + /* This function is mainly to redirect local CSR reads/locks to the iso * management registers (bus manager id, bandwidth available, channels * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus diff -Nru a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/ieee1394-ioctl.h Mon Feb 17 14:57:28 2003 @@ -0,0 +1,105 @@ +/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#' + * with a range of 0x00-0x3f. */ + +#ifndef __IEEE1394_IOCTL_H +#define __IEEE1394_IOCTL_H + +#include +#include + + +/* AMDTP Gets 6 */ +#define AMDTP_IOC_CHANNEL _IOW('#', 0x00, struct amdtp_ioctl) +#define AMDTP_IOC_PLUG _IOW('#', 0x01, struct amdtp_ioctl) +#define AMDTP_IOC_PING _IOW('#', 0x02, struct amdtp_ioctl) +#define AMDTP_IOC_ZAP _IO ('#', 0x03) + + +/* DV1394 Gets 10 */ + +/* Get the driver ready to transmit video. pass a struct dv1394_init* as + * the parameter (see below), or NULL to get default parameters */ +#define DV1394_IOC_INIT _IOW('#', 0x06, struct dv1394_init) + +/* Stop transmitting video and free the ringbuffer */ +#define DV1394_IOC_SHUTDOWN _IO ('#', 0x07) + +/* Submit N new frames to be transmitted, where the index of the first new + * frame is first_clear_buffer, and the index of the last new frame is + * (first_clear_buffer + N) % n_frames */ +#define DV1394_IOC_SUBMIT_FRAMES _IO ('#', 0x08) + +/* Block until N buffers are clear (pass N as the parameter) Because we + * re-transmit the last frame on underrun, there will at most be n_frames + * - 1 clear frames at any time */ +#define DV1394_IOC_WAIT_FRAMES _IO ('#', 0x09) + +/* Capture new frames that have been received, where the index of the + * first new frame is first_clear_buffer, and the index of the last new + * frame is (first_clear_buffer + N) % n_frames */ +#define DV1394_IOC_RECEIVE_FRAMES _IO ('#', 0x0a) + +/* Tell card to start receiving DMA */ +#define DV1394_IOC_START_RECEIVE _IO ('#', 0x0b) + +/* Pass a struct dv1394_status* as the parameter */ +#define DV1394_IOC_GET_STATUS _IOR('#', 0x0c, struct dv1394_status) + + +/* Video1394 Gets 10 */ + +#define VIDEO1394_IOC_LISTEN_CHANNEL \ + _IOWR('#', 0x10, struct video1394_mmap) +#define VIDEO1394_IOC_UNLISTEN_CHANNEL \ + _IOW ('#', 0x11, int) +#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER \ + _IOW ('#', 0x12, struct video1394_wait) +#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER \ + _IOWR('#', 0x13, struct video1394_wait) +#define VIDEO1394_IOC_TALK_CHANNEL \ + _IOWR('#', 0x14, struct video1394_mmap) +#define VIDEO1394_IOC_UNTALK_CHANNEL \ + _IOW ('#', 0x15, int) +#define VIDEO1394_IOC_TALK_QUEUE_BUFFER \ + _IOW ('#', 0x16, sizeof (struct video1394_wait) + \ + sizeof (struct video1394_queue_variable)) +#define VIDEO1394_IOC_TALK_WAIT_BUFFER \ + _IOW ('#', 0x17, struct video1394_wait) +#define VIDEO1394_IOC_LISTEN_POLL_BUFFER \ + _IOWR('#', 0x18, struct video1394_wait) + + +/* Raw1394's ISO interface */ +#define RAW1394_IOC_ISO_XMIT_INIT \ + _IOW ('#', 0x1a, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_RECV_INIT \ + _IOWR('#', 0x1b, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_RECV_START \ + _IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3) +#define RAW1394_IOC_ISO_XMIT_START \ + _IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2) +#define RAW1394_IOC_ISO_XMIT_RECV_STOP \ + _IO ('#', 0x1e) +#define RAW1394_IOC_ISO_GET_STATUS \ + _IOR ('#', 0x1f, struct raw1394_iso_status) +#define RAW1394_IOC_ISO_SHUTDOWN \ + _IO ('#', 0x20) +#define RAW1394_IOC_ISO_QUEUE_ACTIVITY \ + _IO ('#', 0x21) +#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL \ + _IOW ('#', 0x22, unsigned char) +#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \ + _IOW ('#', 0x23, unsigned char) +#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \ + _IOW ('#', 0x24, u64) +#define RAW1394_IOC_ISO_RECV_PACKETS \ + _IOW ('#', 0x25, struct raw1394_iso_packets) +#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \ + _IOW ('#', 0x26, unsigned int) +#define RAW1394_IOC_ISO_XMIT_PACKETS \ + _IOW ('#', 0x27, struct raw1394_iso_packets) +#define RAW1394_IOC_ISO_XMIT_SYNC \ + _IO ('#', 0x28) + + +#endif /* __IEEE1394_IOCTL_H */ diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c --- a/drivers/ieee1394/ieee1394_core.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/ieee1394_core.c Mon Feb 17 14:57:27 2003 @@ -1000,7 +1000,7 @@ struct file_operations *file_ops) { int retval; - + if( (blocknum < 0) || (blocknum > 15) ) return -EINVAL; @@ -1016,7 +1016,7 @@ /* block already taken */ retval = -EBUSY; } - + write_unlock(&ieee1394_chardevs_lock); return retval; @@ -1027,14 +1027,14 @@ { if( (blocknum < 0) || (blocknum > 15) ) return; - + write_lock(&ieee1394_chardevs_lock); - + if(ieee1394_chardevs[blocknum].file_ops) { ieee1394_chardevs[blocknum].file_ops = NULL; ieee1394_chardevs[blocknum].module = NULL; } - + write_unlock(&ieee1394_chardevs_lock); } @@ -1055,7 +1055,7 @@ { int ret = 0; - if( (blocknum < 0) || (blocknum > 15) ) + if ((blocknum < 0) || (blocknum > 15)) return ret; read_lock(&ieee1394_chardevs_lock); @@ -1063,15 +1063,15 @@ *module = ieee1394_chardevs[blocknum].module; *file_ops = ieee1394_chardevs[blocknum].file_ops; - if(*file_ops == NULL) + if (*file_ops == NULL) goto out; - if(!try_module_get(*module)) + if (!try_module_get(*module)) goto out; /* success! */ ret = 1; - + out: read_unlock(&ieee1394_chardevs_lock); return ret; @@ -1101,11 +1101,11 @@ reference count of whatever module file->f_op->owner points to, immediately after this function returns. */ - + /* shift away lower four bits of the minor to get the index of the ieee1394_driver we want */ - + blocknum = (minor(inode->i_rdev) >> 4) & 0xF; /* look up the driver */ @@ -1126,14 +1126,14 @@ if(retval == 0) { /* If the open() succeeded, then ieee1394 will be left - with an extra module reference, so we discard it here. + * with an extra module reference, so we discard it here. + * + * The task-specific driver still has the extra reference + * given to it by ieee1394_get_chardev(). This extra + * reference prevents the module from unloading while the + * file is open, and will be dropped by the VFS when the + * file is released. */ - The task-specific driver still has the extra - reference given to it by ieee1394_get_chardev(). - This extra reference prevents the module from - unloading while the file is open, and will be - dropped by the VFS when the file is released. - */ module_put(THIS_MODULE); } else { /* point the file's f_ops back to ieee1394. The VFS will then @@ -1142,11 +1142,10 @@ file->f_op = &ieee1394_chardev_ops; - /* if the open() failed, then we need to drop the - extra reference we gave to the task-specific - driver */ + /* If the open() failed, then we need to drop the extra + * reference we gave to the task-specific driver. */ + module_put(module); - } return retval; @@ -1199,10 +1198,10 @@ kmem_cache_destroy(hpsb_packet_cache); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); - + /* it's ok to pass a NULL devfs_handle to devfs_unregister */ devfs_unregister(ieee1394_devfs_handle); - + remove_proc_entry("ieee1394", proc_bus); } @@ -1298,10 +1297,16 @@ EXPORT_SYMBOL(hpsb_iso_recv_init); EXPORT_SYMBOL(hpsb_iso_xmit_start); EXPORT_SYMBOL(hpsb_iso_recv_start); +EXPORT_SYMBOL(hpsb_iso_recv_listen_channel); +EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel); +EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); EXPORT_SYMBOL(hpsb_iso_stop); EXPORT_SYMBOL(hpsb_iso_shutdown); -EXPORT_SYMBOL(hpsb_iso_xmit_queue_packets); +EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); +EXPORT_SYMBOL(hpsb_iso_xmit_sync); EXPORT_SYMBOL(hpsb_iso_recv_release_packets); EXPORT_SYMBOL(hpsb_iso_n_ready); -EXPORT_SYMBOL(hpsb_iso_packet_data); -EXPORT_SYMBOL(hpsb_iso_packet_info); +EXPORT_SYMBOL(hpsb_iso_packet_sent); +EXPORT_SYMBOL(hpsb_iso_packet_received); +EXPORT_SYMBOL(hpsb_iso_wake); + diff -Nru a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c --- a/drivers/ieee1394/iso.c Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/iso.c Mon Feb 17 14:57:28 2003 @@ -17,7 +17,8 @@ if(!iso->flags & HPSB_ISO_DRIVER_STARTED) return; - iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? XMIT_STOP : RECV_STOP, 0); + iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? + XMIT_STOP : RECV_STOP, 0); iso->flags &= ~HPSB_ISO_DRIVER_STARTED; } @@ -25,94 +26,84 @@ { if(iso->flags & HPSB_ISO_DRIVER_INIT) { hpsb_iso_stop(iso); - iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? XMIT_SHUTDOWN : RECV_SHUTDOWN, 0); + iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? + XMIT_SHUTDOWN : RECV_SHUTDOWN, 0); iso->flags &= ~HPSB_ISO_DRIVER_INIT; } - - dma_region_free(&iso->buf); + + dma_region_free(&iso->data_buf); + kfree(iso->infos); kfree(iso); } static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type, + unsigned int data_buf_size, unsigned int buf_packets, - unsigned int max_packet_size, int channel, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso; - unsigned int packet_plus_info; int dma_direction; - int iso_header_bytes; - const int info_bytes = sizeof(struct hpsb_iso_packet_info); - + /* make sure driver supports the ISO API */ if(!host->driver->isoctl) return NULL; - if(type == HPSB_ISO_RECV) { - /* when receiving, leave 8 extra bytes in front - of the data payload for the iso header */ - iso_header_bytes = 8; - } else { - iso_header_bytes = 0; - } - /* sanitize parameters */ - + if(buf_packets < 2) buf_packets = 2; - + if(irq_interval < 1 || irq_interval > buf_packets / 2) irq_interval = buf_packets / 2; - - if(max_packet_size + info_bytes + iso_header_bytes > PAGE_SIZE) + + if(channel < -1 || channel >= 64) + return NULL; + + /* channel = -1 is OK for multi-channel recv but not for xmit */ + if(type == HPSB_ISO_XMIT && channel < 0) return NULL; - - /* size of packet payload plus the per-packet info must be a power of 2 - and at most equal to the page size */ - - for(packet_plus_info = 256; packet_plus_info < PAGE_SIZE; packet_plus_info *= 2) { - if(packet_plus_info >= (max_packet_size + info_bytes + iso_header_bytes)) { - break; - } - } /* allocate and write the struct hpsb_iso */ - + iso = kmalloc(sizeof(*iso), SLAB_KERNEL); if(!iso) return NULL; - + + /* allocate ringbuffer of packet descriptors */ + iso->infos = kmalloc(buf_packets * sizeof(struct hpsb_iso_packet_info), SLAB_KERNEL); + if(!iso->infos) + return NULL; + iso->type = type; iso->host = host; iso->hostdata = NULL; iso->callback = callback; + init_waitqueue_head(&iso->waitq); iso->channel = channel; iso->irq_interval = irq_interval; - dma_region_init(&iso->buf); + dma_region_init(&iso->data_buf); + iso->buf_size = round_up_to_page(data_buf_size); iso->buf_packets = buf_packets; - iso->buf_stride = packet_plus_info; - iso->max_packet_size = max_packet_size; - iso->packet_data_offset = iso_header_bytes; - iso->packet_info_offset = iso_header_bytes + max_packet_size; + iso->pkt_dma = 0; iso->first_packet = 0; + spin_lock_init(&iso->lock); if(iso->type == HPSB_ISO_XMIT) { - atomic_set(&iso->n_dma_packets, 0); + iso->n_ready_packets = iso->buf_packets; dma_direction = PCI_DMA_TODEVICE; } else { - atomic_set(&iso->n_dma_packets, iso->buf_packets); + iso->n_ready_packets = 0; dma_direction = PCI_DMA_FROMDEVICE; } - + atomic_set(&iso->overflows, 0); iso->flags = 0; iso->prebuffer = 0; - + /* allocate the packet buffer */ - if(dma_region_alloc(&iso->buf, iso->buf_packets * iso->buf_stride, - host->pdev, dma_direction)) + if(dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) goto err; return iso; @@ -124,26 +115,33 @@ int hpsb_iso_n_ready(struct hpsb_iso* iso) { - return iso->buf_packets - atomic_read(&iso->n_dma_packets); + unsigned long flags; + int val; + + spin_lock_irqsave(&iso->lock, flags); + val = iso->n_ready_packets; + spin_unlock_irqrestore(&iso->lock, flags); + + return val; } - + struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, + unsigned int data_buf_size, unsigned int buf_packets, - unsigned int max_packet_size, int channel, int speed, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, - buf_packets, max_packet_size, + data_buf_size, buf_packets, channel, irq_interval, callback); if(!iso) return NULL; iso->speed = speed; - + /* tell the driver to start working */ if(host->driver->isoctl(iso, XMIT_INIT, 0)) goto err; @@ -157,14 +155,14 @@ } struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, + unsigned int data_buf_size, unsigned int buf_packets, - unsigned int max_packet_size, int channel, int irq_interval, void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, - buf_packets, max_packet_size, + data_buf_size, buf_packets, channel, irq_interval, callback); if(!iso) return NULL; @@ -181,6 +179,27 @@ return NULL; } +int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) +{ + if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel); +} + +int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel) +{ + if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); +} + +int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) +{ + if(iso->type != HPSB_ISO_RECV || iso->channel != -1) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask); +} + static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) { int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle); @@ -195,11 +214,20 @@ { if(iso->type != HPSB_ISO_XMIT) return -1; - + if(iso->flags & HPSB_ISO_DRIVER_STARTED) return 0; - if(prebuffer < 1) + if(cycle < -1) + cycle = -1; + else if(cycle >= 8000) + cycle %= 8000; + + iso->xmit_cycle = cycle; + + if(prebuffer < 0) + prebuffer = iso->buf_packets; + else if(prebuffer == 0) prebuffer = 1; if(prebuffer > iso->buf_packets) @@ -207,41 +235,39 @@ iso->prebuffer = prebuffer; - if(cycle != -1) { - /* pre-fill info->cycle */ - int pkt = iso->first_packet; - int c, i; - - cycle %= 8000; - - c = cycle; - for(i = 0; i < iso->buf_packets; i++) { - struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, pkt); - - info->cycle = c; - - c = (c+1) % 8000; - pkt = (pkt+1) % iso->buf_packets; - } - } - - /* remember the starting cycle; DMA will commence from xmit_queue_packets() */ + /* remember the starting cycle; DMA will commence from xmit_queue_packets() + once enough packets have been buffered */ iso->start_cycle = cycle; return 0; } -int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle) +int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { int retval = 0; + int isoctl_args[3]; if(iso->type != HPSB_ISO_RECV) return -1; - + if(iso->flags & HPSB_ISO_DRIVER_STARTED) return 0; - retval = iso->host->driver->isoctl(iso, RECV_START, cycle); + if(cycle < -1) + cycle = -1; + else if(cycle >= 8000) + cycle %= 8000; + + isoctl_args[0] = cycle; + + if(tag_mask < 0) + /* match all tags */ + tag_mask = 0xF; + isoctl_args[1] = tag_mask; + + isoctl_args[2] = sync; + + retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]); if(retval) return retval; @@ -249,58 +275,162 @@ return retval; } -int hpsb_iso_xmit_queue_packets(struct hpsb_iso *iso, unsigned int n_packets) +/* check to make sure the user has not supplied bogus values of offset/len + that would cause the kernel to access memory outside the buffer */ + +static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, + unsigned int offset, unsigned short len, + unsigned int *out_offset, unsigned short *out_len) +{ + if(offset >= iso->buf_size) + return -EFAULT; + + /* make sure the packet does not go beyond the end of the buffer */ + if(offset + len > iso->buf_size) + return -EFAULT; + + /* check for wrap-around */ + if(offset + len < offset) + return -EFAULT; + + /* now we can trust 'offset' and 'length' */ + *out_offset = offset; + *out_len = len; + + return 0; +} + + +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy) { - int i, retval; - int pkt = iso->first_packet; + struct hpsb_iso_packet_info *info; + unsigned long flags; + int rv; if(iso->type != HPSB_ISO_XMIT) - return -1; - - /* check packet sizes for sanity */ - for(i = 0; i < n_packets; i++) { - struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, pkt); - if(info->len > iso->max_packet_size) { - printk(KERN_ERR "hpsb_iso_xmit_queue_packets: packet too long (%u, max is %u)\n", - info->len, iso->max_packet_size); - return -EINVAL; - } - - pkt = (pkt+1) % iso->buf_packets; + return -EINVAL; + + /* is there space in the buffer? */ + if(iso->n_ready_packets <= 0) { + return -EBUSY; } - retval = iso->host->driver->isoctl(iso, XMIT_QUEUE, n_packets); - if(retval) - return retval; + info = &iso->infos[iso->first_packet]; + + /* check for bogus offset/length */ + if(hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) + return -EFAULT; + + info->tag = tag; + info->sy = sy; + + spin_lock_irqsave(&iso->lock, flags); + + rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info); + if(rv) + goto out; + + /* increment cursors */ + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; + iso->n_ready_packets--; if(iso->prebuffer != 0) { - iso->prebuffer -= n_packets; + iso->prebuffer--; if(iso->prebuffer <= 0) { iso->prebuffer = 0; - return do_iso_xmit_start(iso, - iso->start_cycle); + rv = do_iso_xmit_start(iso, iso->start_cycle); } } - return 0; +out: + spin_unlock_irqrestore(&iso->lock, flags); + return rv; +} + +int hpsb_iso_xmit_sync(struct hpsb_iso *iso) +{ + if(iso->type != HPSB_ISO_XMIT) + return -EINVAL; + + return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets); +} + +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) +{ + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); + + /* predict the cycle of the next packet to be queued */ + + /* jump ahead by the number of packets that are already buffered */ + cycle += iso->buf_packets - iso->n_ready_packets; + cycle %= 8000; + + iso->xmit_cycle = cycle; + iso->n_ready_packets++; + iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; + + if(iso->n_ready_packets == iso->buf_packets || error != 0) { + /* the buffer has run empty! */ + atomic_inc(&iso->overflows); + } + + spin_unlock_irqrestore(&iso->lock, flags); +} + +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy) +{ + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); + + if(iso->n_ready_packets == iso->buf_packets) { + /* overflow! */ + atomic_inc(&iso->overflows); + } else { + struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; + info->offset = offset; + info->len = len; + info->cycle = cycle; + info->channel = channel; + info->tag = tag; + info->sy = sy; + + iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets; + iso->n_ready_packets++; + } + + spin_unlock_irqrestore(&iso->lock, flags); } int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) { + unsigned long flags; + unsigned int i; + int rv = 0; + if(iso->type != HPSB_ISO_RECV) return -1; - - return iso->host->driver->isoctl(iso, RECV_RELEASE, n_packets); -} -unsigned char* hpsb_iso_packet_data(struct hpsb_iso *iso, unsigned int pkt) -{ - return (iso->buf.kvirt + pkt * iso->buf_stride) - + iso->packet_data_offset; + spin_lock_irqsave(&iso->lock, flags); + for(i = 0; i < n_packets; i++) { + rv = iso->host->driver->isoctl(iso, RECV_RELEASE, + (unsigned long) &iso->infos[iso->first_packet]); + if(rv) + break; + + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->n_ready_packets--; + } + spin_unlock_irqrestore(&iso->lock, flags); + return rv; } -struct hpsb_iso_packet_info* hpsb_iso_packet_info(struct hpsb_iso *iso, unsigned int pkt) +void hpsb_iso_wake(struct hpsb_iso *iso) { - return (struct hpsb_iso_packet_info*) ((iso->buf.kvirt + pkt * iso->buf_stride) - + iso->packet_info_offset); + wake_up_interruptible(&iso->waitq); + + if(iso->callback) + iso->callback(iso); } diff -Nru a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h --- a/drivers/ieee1394/iso.h Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/iso.h Mon Feb 17 14:57:28 2003 @@ -17,25 +17,37 @@ /* high-level ISO interface */ -/* per-packet data embedded in the ringbuffer */ +/* This API sends and receives isochronous packets on a large, + virtually-contiguous kernel memory buffer. The buffer may be mapped + into a user-space process for zero-copy transmission and reception. + + There are no explicit boundaries between packets in the buffer. A + packet may be transmitted or received at any location. However, + low-level drivers may impose certain restrictions on alignment or + size of packets. (e.g. in OHCI no packet may cross a page boundary, + and packets should be quadlet-aligned) +*/ + +/* Packet descriptor - the API maintains a ring buffer of these packet + descriptors in kernel memory (hpsb_iso.infos[]). */ + struct hpsb_iso_packet_info { - unsigned short len; - unsigned short cycle; - unsigned char channel; /* recv only */ - unsigned char tag; - unsigned char sy; -}; + /* offset of data payload relative to the first byte of the buffer */ + __u32 offset; + + /* length of the data payload, in bytes (not including the isochronous header) */ + __u16 len; -/* - * each packet in the ringbuffer consists of three things: - * 1. the packet's data payload (no isochronous header) - * 2. a struct hpsb_iso_packet_info - * 3. some empty space before the next packet - * - * packets are separated by hpsb_iso.buf_stride bytes - * an even number of packets fit on one page - * no packet can be larger than one page - */ + /* (recv only) the cycle number (mod 8000) on which the packet was received */ + __u16 cycle; + + /* (recv only) channel on which the packet was received */ + __u8 channel; + + /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */ + __u8 tag; + __u8 sy; +}; enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 }; @@ -45,48 +57,49 @@ /* pointer to low-level driver and its private data */ struct hpsb_host *host; void *hostdata; - - /* function to be called (from interrupt context) when the iso status changes */ + + /* a function to be called (from interrupt context) after + outgoing packets have been sent, or incoming packets have + arrived */ void (*callback)(struct hpsb_iso*); + /* wait for buffer space */ + wait_queue_head_t waitq; + int speed; /* SPEED_100, 200, or 400 */ - int channel; + int channel; /* -1 if multichannel */ /* greatest # of packets between interrupts - controls the maximum latency of the buffer */ int irq_interval; - - /* the packet ringbuffer */ - struct dma_region buf; + + /* the buffer for packet data payloads */ + struct dma_region data_buf; + + /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */ + unsigned int buf_size; + + /* ringbuffer of packet descriptors in regular kernel memory */ + struct hpsb_iso_packet_info *infos; /* # of packets in the ringbuffer */ unsigned int buf_packets; - /* offset between successive packets, in bytes - - you can assume that this is a power of 2, - and less than or equal to the page size */ - int buf_stride; - - /* largest possible packet size, in bytes */ - unsigned int max_packet_size; - - /* offset relative to (buf.kvirt + N*buf_stride) at which - the data payload begins for packet N */ - int packet_data_offset; - - /* offset relative to (buf.kvirt + N*buf_stride) at which the - struct hpsb_iso_packet_info is stored for packet N */ - int packet_info_offset; + /* protects packet cursors */ + spinlock_t lock; /* the index of the next packet that will be produced or consumed by the user */ int first_packet; - /* number of packets owned by the low-level driver and - queued for transmission or reception. - this is related to the number of packets available - to the user process: n_ready = buf_packets - n_dma_packets */ - atomic_t n_dma_packets; + /* the index of the next packet that will be transmitted + or received by the 1394 hardware */ + int pkt_dma; + + /* how many packets, starting at first_packet: + (transmit) are ready to be filled with data + (receive) contain received data */ + int n_ready_packets; /* how many times the buffer has overflowed or underflowed */ atomic_t overflows; @@ -99,8 +112,12 @@ /* # of packets left to prebuffer (xmit only) */ int prebuffer; - /* starting cycle (xmit only) */ + /* starting cycle for DMA (xmit only) */ int start_cycle; + + /* cycle at which next packet will be transmitted, + -1 if not known */ + int xmit_cycle; }; /* functions available to high-level drivers (e.g. raw1394) */ @@ -108,30 +125,40 @@ /* allocate the buffer and DMA context */ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, + unsigned int data_buf_size, unsigned int buf_packets, - unsigned int max_packet_size, int channel, int speed, int irq_interval, void (*callback)(struct hpsb_iso*)); +/* note: if channel = -1, multi-channel receive is enabled */ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, + unsigned int data_buf_size, unsigned int buf_packets, - unsigned int max_packet_size, int channel, int irq_interval, void (*callback)(struct hpsb_iso*)); +/* multi-channel only */ +int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel); +int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel); +int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask); + /* start/stop DMA */ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); -int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle); +int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync); void hpsb_iso_stop(struct hpsb_iso *iso); /* deallocate buffer and DMA context */ void hpsb_iso_shutdown(struct hpsb_iso *iso); -/* N packets have been written to the buffer; queue them for transmission */ -int hpsb_iso_xmit_queue_packets(struct hpsb_iso *xmit, unsigned int n_packets); +/* queue a packet for transmission. 'offset' is relative to the beginning of the + DMA buffer, where the packet's data payload should already have been placed */ +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy); + +/* wait until all queued packets have been transmitted to the bus */ +int hpsb_iso_xmit_sync(struct hpsb_iso *iso); /* N packets have been read out of the buffer, re-use the buffer space */ int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets); @@ -139,10 +166,19 @@ /* returns # of packets ready to send or receive */ int hpsb_iso_n_ready(struct hpsb_iso *iso); -/* returns a pointer to the payload of packet 'pkt' */ -unsigned char* hpsb_iso_packet_data(struct hpsb_iso *iso, unsigned int pkt); +/* the following are callbacks available to low-level drivers */ + +/* call after a packet has been transmitted to the bus (interrupt context is OK) + 'cycle' is the _exact_ cycle the packet was sent on + 'error' should be non-zero if some sort of error occurred when sending the packet +*/ +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error); + +/* call after a packet has been received (interrupt context OK) */ +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy); -/* returns a pointer to the info struct of packet 'pkt' */ -struct hpsb_iso_packet_info* hpsb_iso_packet_info(struct hpsb_iso *iso, unsigned int pkt); +/* call to wake waiting processes after buffer space has opened up. */ +void hpsb_iso_wake(struct hpsb_iso *iso); #endif /* IEEE1394_ISO_H */ diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c --- a/drivers/ieee1394/nodemgr.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/nodemgr.c Mon Feb 17 14:57:27 2003 @@ -786,7 +786,7 @@ #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid); #endif - value = call_usermodehelper(argv[0], argv, envp); + value = call_usermodehelper(argv[0], argv, envp, 0); kfree(buf); kfree(envp); if (value != 0) @@ -1089,8 +1089,7 @@ static void nodemgr_remove_node(struct node_entry *ne) { - HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", - (ne->host->node_id == ne->nodeid) ? "Host" : "Device", + HPSB_DEBUG("Device removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid, ne->vendor_name ?: "Unknown"); diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c --- a/drivers/ieee1394/ohci1394.c Mon Feb 17 14:57:28 2003 +++ b/drivers/ieee1394/ohci1394.c Mon Feb 17 14:57:28 2003 @@ -160,7 +160,7 @@ printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 675 $ Ben Collins "; + "$Rev: 762 $ Ben Collins "; /* Module Parameters */ MODULE_PARM(phys_dma,"i"); @@ -170,6 +170,15 @@ static void dma_trm_tasklet(unsigned long data); static void dma_trm_reset(struct dma_trm_ctx *d); +static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, + enum context_type type, int ctx, int num_desc, + int buf_size, int split_buf_size, int context_base); +static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); + +static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, + enum context_type type, int ctx, int num_desc, + int context_base); + static void ohci1394_pci_remove(struct pci_dev *pdev); #ifndef __LITTLE_ENDIAN @@ -311,7 +320,7 @@ /* SelfID Ok, reset error counter. */ ohci->self_id_errors = 0; - + size = ((self_id_count & 0x00001FFC) >> 2) - 1; q++; @@ -373,12 +382,12 @@ "Running dma failed because Node ID == 63"); return -1; } - + /* Run the dma context */ reg_write(ohci, reg, 0x8000); - + if (msg) PRINT(KERN_DEBUG, ohci->id, "%s", msg); - + return 0; } @@ -415,10 +424,28 @@ d->buf_ind = 0; d->buf_offset = 0; + if(d->type == DMA_CTX_ISO) { + /* Clear contextControl */ + reg_write(ohci, d->ctrlClear, 0xffffffff); + + /* Set bufferFill, isochHeader, multichannel for IR context */ + reg_write(ohci, d->ctrlSet, 0xd0000000); + + /* Set the context match register to match on all tags */ + reg_write(ohci, d->ctxtMatch, 0xf0000000); + + /* Clear the multi channel mask high and low registers */ + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx); + } + /* Tell the controller where the first AR program is */ reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); - /* Run AR context */ + /* Run context */ reg_write(ohci, d->ctrlSet, 0x00008000); DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx); @@ -439,6 +466,11 @@ INIT_LIST_HEAD(&d->fifo_list); INIT_LIST_HEAD(&d->pending_list); + if(d->type == DMA_CTX_ISO) { + /* enable interrupts */ + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); + } + DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx); } @@ -450,7 +482,7 @@ reg_write(ohci, reg, 0xffffffff); tmp = reg_read(ohci, reg); - + DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ @@ -515,12 +547,6 @@ /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); - /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); - - /* Set the context match register to match on all tags */ - reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); - /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); @@ -529,10 +555,6 @@ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - /* Clear the multi channel mask high and low registers */ - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); - /* Initialize AR dma */ initialize_dma_rcv_ctx(&ohci->ar_req_context, 0); initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0); @@ -541,19 +563,6 @@ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); - /* Initialize IR dma */ - initialize_dma_rcv_ctx(&ohci->ir_context, 1); - - /* Initialize IT dma */ - initialize_dma_trm_ctx(&ohci->it_context); - - /* Set up isoRecvIntMask to generate interrupts for context 0 - (thanks to Michael Greger for seeing that I forgot this) */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001); - - /* Set up isoXmitIntMask to generate interrupts for context 0 */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 0x00000001); - /* * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem @@ -598,7 +607,7 @@ } /* - * Insert a packet in the AT DMA fifo and generate the DMA prg + * Insert a packet in the DMA fifo and generate the DMA prg * FIXME: rewrite the program in order to accept packets crossing * page boundaries. * check also that a single dma descriptor doesn't cross a @@ -757,8 +766,8 @@ } /* - * This function fills the AT FIFO with the (eventual) pending packets - * and runs or wakes up the AT DMA prg if necessary. + * This function fills the FIFO with the (eventual) pending packets + * and runs or wakes up the DMA prg if necessary. * * The function MUST be called with the d->lock held. */ @@ -774,7 +783,7 @@ idx = d->prg_ind; z = (p->data_size) ? 3 : 2; - /* insert the packets into the at dma fifo */ + /* insert the packets into the dma fifo */ while (d->free_prgs > 0 && !list_empty(&d->pending_list)) { struct hpsb_packet *p = driver_packet(d->pending_list.next); list_del(&p->driver_list); @@ -796,13 +805,15 @@ /* Wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } return 1; } -/* Transmission of an async packet */ +/* Transmission of an async or iso packet */ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) { struct ti_ohci *ohci = host->hostdata; @@ -819,9 +830,33 @@ /* Decide wether we have an iso, a request, or a response packet */ if (packet->type == hpsb_raw) d = &ohci->at_req_context; - else if (packet->tcode == TCODE_ISO_DATA) - d = &ohci->it_context; - else if (packet->tcode & 0x02) + else if (packet->tcode == TCODE_ISO_DATA) { + /* The legacy IT DMA context is initialized on first + * use. However, the alloc cannot be run from + * interrupt context, so we bail out if that is the + * case. I don't see anyone sending ISO packets from + * interrupt context anyway... */ + + if(ohci->it_legacy_context.ohci == NULL) { + if(in_interrupt()) { + PRINT(KERN_ERR, ohci->id, + "legacy IT context cannot be initialized during interrupt"); + return 0; + } + + if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, + DMA_CTX_ISO, 0, IT_NUM_DESC, + OHCI1394_IsoXmitContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, + "error initializing legacy IT context"); + return 0; + } + + initialize_dma_trm_ctx(&ohci->it_legacy_context); + } + + d = &ohci->it_legacy_context; + } else if (packet->tcode & 0x02) d = &ohci->at_resp_context; else d = &ohci->at_req_context; @@ -829,7 +864,7 @@ spin_lock_irqsave(&d->lock,flags); list_add_tail(&packet->driver_list, &d->pending_list); - + dma_trm_flush(ohci, d); spin_unlock_irqrestore(&d->lock,flags); @@ -898,11 +933,11 @@ case GET_CYCLE_COUNTER: retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer); break; - + case SET_CYCLE_COUNTER: reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg); break; - + case SET_BUS_ID: PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err"); break; @@ -932,12 +967,13 @@ break; case MODIFY_USAGE: - if (arg) { - MOD_INC_USE_COUNT; - } else { - MOD_DEC_USE_COUNT; - } - retval = 1; + if (arg) { + if (try_module_get(THIS_MODULE)) + retval = 1; + } else { + module_put(THIS_MODULE); + retval = 1; + } break; case ISO_LISTEN_CHANNEL: @@ -962,8 +998,26 @@ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); return -EFAULT; } - + + /* activate the legacy IR context */ + if(ohci->ir_legacy_context.ohci == NULL) { + if(alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context, + DMA_CTX_ISO, 0, IR_NUM_DESC, + IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, + OHCI1394_IsoRcvContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, + "%s: failed to allocate an IR context", + __FUNCTION__); + return -ENOMEM; + } + ohci->ir_legacy_channels = 0; + initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); + + DBGMSG(ohci->id, "ISO receive legacy context activated"); + } + ohci->ISO_channel_usage |= mask; + ohci->ir_legacy_channels |= mask; if (arg>31) reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, @@ -1000,6 +1054,7 @@ } ohci->ISO_channel_usage &= ~mask; + ohci->ir_legacy_channels &= ~mask; if (arg>31) reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, @@ -1010,6 +1065,11 @@ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); DBGMSG(ohci->id, "Listening disabled on channel %d", arg); + + if(ohci->ir_legacy_channels == 0) { + free_dma_rcv_ctx(&ohci->ir_legacy_context); + DBGMSG(ohci->id, "ISO receive legacy context deactivated"); + } break; } default: @@ -1024,61 +1084,159 @@ * rawiso ISO reception * ***********************************/ +/* + We use either buffer-fill or packet-per-buffer DMA mode. The DMA + buffer is split into "blocks" (regions described by one DMA + descriptor). Each block must be one page or less in size, and + must not cross a page boundary. + + There is one little wrinkle with buffer-fill mode: a packet that + starts in the final block may wrap around into the first block. But + the user API expects all packets to be contiguous. Our solution is + to keep the very last page of the DMA buffer in reserve - if a + packet spans the gap, we copy its tail into this page. +*/ + struct ohci_iso_recv { struct ti_ohci *ohci; - /* memory and PCI mapping for the DMA descriptors */ - struct dma_prog_region prog; - struct ohci1394_iso_tasklet task; int task_active; - /* index of next packet to arrive */ - int pkt_dma; - + enum { BUFFER_FILL_MODE, + PACKET_PER_BUFFER_MODE } dma_mode; + + /* memory and PCI mapping for the DMA descriptors */ + struct dma_prog_region prog; + struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */ + + /* how many DMA blocks fit in the buffer */ + unsigned int nblocks; + + /* stride of DMA blocks */ + unsigned int buf_stride; + + /* number of blocks to batch between interrupts */ + int block_irq_interval; + + /* block that DMA will finish next */ + int block_dma; + + /* (buffer-fill only) block that the reader will release next */ + int block_reader; + + /* (buffer-fill only) bytes of buffer the reader has released, + less than one block */ + int released_bytes; + + /* (buffer-fill only) buffer offset at which the next packet will appear */ + int dma_offset; + + /* OHCI DMA context control registers */ u32 ContextControlSet; u32 ContextControlClear; u32 CommandPtr; u32 ContextMatch; }; -static void ohci_iso_recv_task(unsigned long data); +static void ohci_iso_recv_bufferfill_task(unsigned long data); +static void ohci_iso_recv_packetperbuf_task(unsigned long data); static void ohci_iso_recv_stop(struct hpsb_iso *iso); static void ohci_iso_recv_shutdown(struct hpsb_iso *iso); +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync); static void ohci_iso_recv_program(struct hpsb_iso *iso); -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle); - static int ohci_iso_recv_init(struct hpsb_iso *iso) { + struct ti_ohci *ohci = iso->host->hostdata; struct ohci_iso_recv *recv; - unsigned int prog_size; int ctx; int ret = -ENOMEM; - + recv = kmalloc(sizeof(*recv), SLAB_KERNEL); if(!recv) return -ENOMEM; iso->hostdata = recv; - recv->ohci = iso->host->hostdata; + recv->ohci = ohci; recv->task_active = 0; - recv->pkt_dma = iso->first_packet; - dma_prog_region_init(&recv->prog); + recv->block = NULL; + + /* use buffer-fill mode, unless irq_interval is 1 + (note: multichannel requires buffer-fill) */ + + if(iso->irq_interval == 1 && iso->channel != -1) { + recv->dma_mode = PACKET_PER_BUFFER_MODE; + } else { + recv->dma_mode = BUFFER_FILL_MODE; + } + + /* set nblocks, buf_stride, block_irq_interval */ + + if(recv->dma_mode == BUFFER_FILL_MODE) { + recv->buf_stride = PAGE_SIZE; - /* size of DMA program = one INPUT_LAST per packet in the buffer */ - prog_size = sizeof(struct dma_cmd) * iso->buf_packets; + /* one block per page of data in the DMA buffer, minus the final guard page */ + recv->nblocks = iso->buf_size/PAGE_SIZE - 1; + if(recv->nblocks < 3) { + DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); + goto err; + } + + /* iso->irq_interval is in packets - translate that to blocks */ + /* (err, sort of... 1 is always the safest value) */ + recv->block_irq_interval = iso->irq_interval / recv->nblocks; + if(recv->block_irq_interval < 1) + recv->block_irq_interval = 1; + else if(recv->block_irq_interval*4 > recv->nblocks) + recv->block_irq_interval = recv->nblocks/4; + } else { + int max_packet_size; + + recv->nblocks = iso->buf_packets; + recv->block_irq_interval = 1; + + /* choose a buffer stride */ + /* must be a power of 2, and <= PAGE_SIZE */ + + max_packet_size = iso->buf_size / iso->buf_packets; + + for(recv->buf_stride = 8; recv->buf_stride < max_packet_size; + recv->buf_stride *= 2); - if(dma_prog_region_alloc(&recv->prog, prog_size, recv->ohci->dev)) + if(recv->buf_stride*iso->buf_packets > iso->buf_size || + recv->buf_stride > PAGE_SIZE) { + /* this shouldn't happen, but anyway... */ + DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride"); + goto err; + } + } + + recv->block_reader = 0; + recv->released_bytes = 0; + recv->block_dma = 0; + recv->dma_offset = 0; + + /* size of DMA program = one descriptor per block */ + if (dma_prog_region_alloc(&recv->prog, + sizeof(struct dma_cmd) * recv->nblocks, + recv->ohci->dev)) goto err; - ohci1394_init_iso_tasklet(&recv->task, OHCI_ISO_RECEIVE, - ohci_iso_recv_task, (unsigned long) iso); - + recv->block = (struct dma_cmd*) recv->prog.kvirt; + + ohci1394_init_iso_tasklet(&recv->task, + iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE : + OHCI_ISO_RECEIVE, + recv->dma_mode == BUFFER_FILL_MODE ? + ohci_iso_recv_bufferfill_task : + ohci_iso_recv_packetperbuf_task, + (unsigned long) iso); + if(ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) goto err; - + recv->task_active = 1; /* recv context registers are spaced 32 bytes apart */ @@ -1088,12 +1246,22 @@ recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx; recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx; - /* enable interrupts */ - reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << ctx); - + if(iso->channel == -1) { + /* clear multi-channel selection mask */ + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); + } + /* write the DMA program */ ohci_iso_recv_program(iso); - + + DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" + " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d", + recv->dma_mode == BUFFER_FILL_MODE ? + "buffer-fill" : "packet-per-buffer", + iso->buf_size/PAGE_SIZE, iso->buf_size, + recv->nblocks, recv->buf_stride, recv->block_irq_interval); + return 0; err: @@ -1104,7 +1272,10 @@ static void ohci_iso_recv_stop(struct hpsb_iso *iso) { struct ohci_iso_recv *recv = iso->hostdata; - + + /* disable interrupts */ + reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context); + /* halt DMA */ ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL); } @@ -1114,100 +1285,139 @@ struct ohci_iso_recv *recv = iso->hostdata; if(recv->task_active) { - /* halt DMA */ - ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL); - - /* disable interrupts */ - reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context); - + ohci_iso_recv_stop(iso); ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task); recv->task_active = 0; } - + dma_prog_region_free(&recv->prog); kfree(recv); iso->hostdata = NULL; } +/* set up a "gapped" ring buffer DMA program */ static void ohci_iso_recv_program(struct hpsb_iso *iso) { struct ohci_iso_recv *recv = iso->hostdata; - + int blk; + /* address of 'branch' field in previous DMA descriptor */ u32 *prev_branch = NULL; - /* start at pkt_dma and go around the whole buffer */ - int pkt = recv->pkt_dma; - int i; - - for(i = 0; i < iso->buf_packets; i++) { - int want_interrupt; - unsigned int data_size; - - /* pointer to the DMA descriptor */ - struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + pkt; + for (blk = 0; blk < recv->nblocks; blk++) { + /* the DMA descriptor */ + struct dma_cmd *cmd = &recv->block[blk]; /* offset of the DMA descriptor relative to the DMA prog buffer */ - unsigned long prog_offset = pkt * sizeof(struct dma_cmd); + unsigned long prog_offset = blk * sizeof(struct dma_cmd); - /* offset of this bus_cycle within the DMA buffer */ - unsigned long buf_offset = hpsb_iso_packet_data(iso, pkt) - iso->buf.kvirt; + /* offset of this packet's data within the DMA buffer */ + unsigned long buf_offset = blk * recv->buf_stride; - /* back up 8 bytes for the iso header */ - buf_offset -= 8; - data_size = iso->max_packet_size + 8; - - /* ask for an interrupt every now and then, and - always interrupt on the final descriptor */ - - if( ((i % iso->irq_interval) == 0) || - (i == (iso->buf_packets - 1)) ) { - want_interrupt = 1; + if (recv->dma_mode == BUFFER_FILL_MODE) { + cmd->control = 2 << 28; /* INPUT_MORE */ } else { - want_interrupt = 0; + cmd->control = 3 << 28; /* INPUT_LAST */ } - - /* write the DMA descriptor */ - - il->control = 3 << 28; /* INPUT_LAST */ - il->control |= 8 << 24; /* s = 1, update xferStatus and resCount */ - if(want_interrupt) - il->control |= 3 << 20; - il->control |= 0xC << 16; /* enable branch to address */ - il->control |= data_size; - il->address = dma_region_offset_to_bus(&iso->buf, buf_offset); - il->branchAddress = 0; /* filled in on next loop */ - il->status = data_size; + cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */ + + /* interrupt on last block, and at intervals */ + if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { + cmd->control |= 3 << 20; /* want interrupt */ + } + + cmd->control |= 3 << 18; /* enable branch to address */ + cmd->control |= recv->buf_stride; + + cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset); + cmd->branchAddress = 0; /* filled in on next loop */ + cmd->status = recv->buf_stride; /* link the previous descriptor to this one */ - if(prev_branch) { + if (prev_branch) { *prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset); *prev_branch |= 1; /* set Z=1 */ } - prev_branch = &il->branchAddress; - - pkt = (pkt + 1) % iso->buf_packets; + prev_branch = &cmd->branchAddress; } /* the final descriptor's branch address and Z should be left at 0 */ } -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle) +/* listen or unlisten to a specific channel (multi-channel mode only) */ +static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen) +{ + struct ohci_iso_recv *recv = iso->hostdata; + int reg, i; + + if(channel < 32) { + reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear; + i = channel; + } else { + reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear; + i = channel - 32; + } + + reg_write(recv->ohci, reg, (1 << i)); + + /* issue a dummy read to force all PCI writes to be posted immediately */ + mb(); + reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); +} + +static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) +{ + struct ohci_iso_recv *recv = iso->hostdata; + int i; + + for(i = 0; i < 64; i++) { + if(mask & (1ULL << i)) { + if(i < 32) + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i)); + else + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32))); + } else { + if(i < 32) + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i)); + else + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32))); + } + } + + /* issue a dummy read to force all PCI writes to be posted immediately */ + mb(); + reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); +} + +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { struct ohci_iso_recv *recv = iso->hostdata; u32 command, contextMatch; - + reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); wmb(); - /* use packet-per-buffer mode, and keep ISO headers */ - reg_write(recv->ohci, recv->ContextControlSet, (1 << 30)); + /* always keep ISO headers */ + command = (1 << 30); + + if(recv->dma_mode == BUFFER_FILL_MODE) + command |= (1 << 31); + + reg_write(recv->ohci, recv->ContextControlSet, command); + + /* match on specified tags */ + contextMatch = tag_mask << 28; + + if(iso->channel == -1) { + /* enable multichannel reception */ + reg_write(recv->ohci, recv->ContextControlSet, (1 << 28)); + } else { + /* listen on channel */ + contextMatch |= iso->channel; + } - /* match on all tags, listen on channel */ - contextMatch = 0xF0000000 | iso->channel; - if(cycle != -1) { u32 seconds; @@ -1229,15 +1439,29 @@ contextMatch |= cycle << 12; } + if(sync != -1) { + /* set sync flag on first DMA descriptor */ + struct dma_cmd *cmd = &recv->block[recv->block_dma]; + cmd->control |= DMA_CTL_WAIT; + + /* match sync field */ + contextMatch |= (sync&0xf)<<8; + } + reg_write(recv->ohci, recv->ContextMatch, contextMatch); - + /* address of first descriptor block */ - command = dma_prog_region_offset_to_bus(&recv->prog, recv->pkt_dma * sizeof(struct dma_cmd)); + command = dma_prog_region_offset_to_bus(&recv->prog, + recv->block_dma * sizeof(struct dma_cmd)); command |= 1; /* Z=1 */ - + reg_write(recv->ohci, recv->CommandPtr, command); + + /* enable interrupts */ + reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context); + wmb(); - + /* run */ reg_write(recv->ohci, recv->ContextControlSet, 0x8000); @@ -1248,7 +1472,8 @@ /* check RUN */ if(!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { - PRINT(KERN_ERR, recv->ohci->id, "Error starting IR DMA (ContextControl 0x%08x)\n", + PRINT(KERN_ERR, recv->ohci->id, + "Error starting IR DMA (ContextControl 0x%08x)\n", reg_read(recv->ohci, recv->ContextControlSet)); return -1; } @@ -1256,62 +1481,253 @@ return 0; } -static void ohci_iso_recv_release_one(struct hpsb_iso *iso) +static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block) { - struct ohci_iso_recv *recv = iso->hostdata; - - /* re-use the DMA descriptor for first_packet */ + /* re-use the DMA descriptor for the block */ /* by linking the previous descriptor to it */ - int next_i = iso->first_packet; - int prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1); - - struct dma_cmd *next = dma_region_i(&recv->prog, struct dma_cmd, next_i); - struct dma_cmd *prev = dma_region_i(&recv->prog, struct dma_cmd, prev_i); + int next_i = block; + int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1); + + struct dma_cmd *next = &recv->block[next_i]; + struct dma_cmd *prev = &recv->block[prev_i]; - /* 'next' becomes the new end of the DMA chain */ - next->control |= 3 << 20; /* enable interrupt */ - next->branchAddress = 0; /* disable branch */ + /* 'next' becomes the new end of the DMA chain, + so disable branch and enable interrupt */ + next->branchAddress = 0; + next->control |= 3 << 20; /* link prev to next */ - if(prev_i % iso->irq_interval) { - prev->control &= ~(3 << 20); /* no interrupt */ - } else { + prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog, + sizeof(struct dma_cmd) * next_i) + | 1; /* Z=1 */ + + /* disable interrupt on previous DMA descriptor, except at intervals */ + if((prev_i % recv->block_irq_interval) == 0) { prev->control |= 3 << 20; /* enable interrupt */ + } else { + prev->control &= ~(3<<20); /* disable interrupt */ } - prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog, - sizeof(struct dma_cmd) * next_i) | 1; wmb(); - + /* wake up DMA in case it fell asleep */ reg_write(recv->ohci, recv->ContextControlSet, (1 << 12)); +} + +static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv, + struct hpsb_iso_packet_info *info) +{ + int len; + + /* release the memory where the packet was */ + len = info->len; + + /* add the wasted space for padding to 4 bytes */ + if(len % 4) + len += 4 - (len % 4); - /* advance packet cursors */ - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; - atomic_inc(&iso->n_dma_packets); + /* add 8 bytes for the OHCI DMA data format overhead */ + len += 8; + + recv->released_bytes += len; + + /* have we released enough memory for one block? */ + while(recv->released_bytes > recv->buf_stride) { + ohci_iso_recv_release_block(recv, recv->block_reader); + recv->block_reader = (recv->block_reader + 1) % recv->nblocks; + recv->released_bytes -= recv->buf_stride; + } } -static void ohci_iso_recv_release(struct hpsb_iso *iso, int n_packets) +static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { - int i; - for(i = 0; i < n_packets; i++) - ohci_iso_recv_release_one(iso); + struct ohci_iso_recv *recv = iso->hostdata; + if(recv->dma_mode == BUFFER_FILL_MODE) { + ohci_iso_recv_bufferfill_release(recv, info); + } else { + ohci_iso_recv_release_block(recv, info - iso->infos); + } } -static void ohci_iso_recv_task(unsigned long data) +/* parse all packets from blocks that have been fully received */ +static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +{ + int wake = 0; + int runaway = 0; + + while(1) { + /* we expect the next parsable packet to begin at recv->dma_offset */ + /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */ + + unsigned int offset; + unsigned short len, cycle; + unsigned char channel, tag, sy; + + unsigned char *p = iso->data_buf.kvirt; + + unsigned int this_block = recv->dma_offset/recv->buf_stride; + + /* don't loop indefinitely */ + if(runaway++ > 100000) { + atomic_inc(&iso->overflows); + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - Runaway during buffer parsing!\n"); + break; + } + + /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */ + if(this_block == recv->block_dma) + break; + + wake = 1; + + /* parse data length, tag, channel, and sy */ + + /* note: we keep our own local copies of 'len' and 'offset' + so the user can't mess with them by poking in the mmap area */ + + len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); + + if(len > 4096) { + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - bogus 'len' value %u\n", len); + } + + channel = p[recv->dma_offset+1] & 0x3F; + tag = p[recv->dma_offset+1] >> 6; + sy = p[recv->dma_offset+0] & 0xF; + + /* advance to data payload */ + recv->dma_offset += 4; + + /* check for wrap-around */ + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + /* dma_offset now points to the first byte of the data payload */ + offset = recv->dma_offset; + + /* advance to xferStatus/timeStamp */ + recv->dma_offset += len; + + /* payload is padded to 4 bytes */ + if(len % 4) { + recv->dma_offset += 4 - (len%4); + } + + /* check for wrap-around */ + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + /* uh oh, the packet data wraps from the last + to the first DMA block - make the packet + contiguous by copying its "tail" into the + guard page */ + + int guard_off = recv->buf_stride*recv->nblocks; + int tail_len = len - (guard_off - offset); + + if(tail_len > 0 && tail_len < recv->buf_stride) { + memcpy(iso->data_buf.kvirt + guard_off, + iso->data_buf.kvirt, + tail_len); + } + + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + /* parse timestamp */ + cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8); + cycle &= 0x1FFF; + + /* advance to next packet */ + recv->dma_offset += 4; + + /* check for wrap-around */ + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; + } + + hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy); + } + + if(wake) + hpsb_iso_wake(iso); +} + +static void ohci_iso_recv_bufferfill_task(unsigned long data) { struct hpsb_iso *iso = (struct hpsb_iso*) data; struct ohci_iso_recv *recv = iso->hostdata; + int loop; + + /* loop over all blocks */ + for(loop = 0; loop < recv->nblocks; loop++) { + + /* check block_dma to see if it's done */ + + struct dma_cmd *im = &recv->block[recv->block_dma]; + + /* check the DMA descriptor for new writes to xferStatus */ + u16 xferstatus = im->status >> 16; + + /* rescount is the number of bytes *remaining to be written* in the block */ + u16 rescount = im->status & 0xFFFF; + + unsigned char event = xferstatus & 0x1F; + + if(!event) { + /* nothing has happened to this block yet */ + break; + } + + if(event != 0x11) { + atomic_inc(&iso->overflows); + PRINT(KERN_ERR, recv->ohci->id, + "IR DMA error - OHCI error code 0x%02x\n", event); + } + + if(rescount != 0) { + /* the card is still writing to this block; + we can't touch it until it's done */ + break; + } + + /* OK, the block is finished... */ + + /* sync our view of the block */ + dma_region_sync(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride); + + /* reset the DMA descriptor */ + im->status = recv->buf_stride; + + /* advance block_dma */ + recv->block_dma = (recv->block_dma + 1) % recv->nblocks; + + if((recv->block_dma+1) % recv->nblocks == recv->block_reader) { + atomic_inc(&iso->overflows); + DBGMSG(recv->ohci->id, "ISO reception overflow - " + "ran out of DMA blocks"); + } + } + + /* parse any packets that have arrived */ + ohci_iso_recv_bufferfill_parse(iso, recv); +} + +static void ohci_iso_recv_packetperbuf_task(unsigned long data) +{ + struct hpsb_iso *iso = (struct hpsb_iso*) data; + struct ohci_iso_recv *recv = iso->hostdata; int count; int wake = 0; /* loop over the entire buffer */ - for(count = 0; count < iso->buf_packets; count++) { + for(count = 0; count < recv->nblocks; count++) { u32 packet_len = 0; /* pointer to the DMA descriptor */ - struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + recv->pkt_dma; + struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma; /* check the DMA descriptor for new writes to xferStatus */ u16 xferstatus = il->status >> 16; @@ -1329,7 +1745,7 @@ /* rescount is the number of bytes *remaining* in the packet buffer, after the packet was written */ - packet_len = iso->max_packet_size - rescount; + packet_len = recv->buf_stride - rescount; } else if(event == 0x02) { PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n"); @@ -1338,42 +1754,42 @@ } /* sync our view of the buffer */ - dma_region_sync(&iso->buf, recv->pkt_dma * iso->buf_stride, iso->buf_stride); + dma_region_sync(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride); /* record the per-packet info */ { /* iso header is 8 bytes ahead of the data payload */ - unsigned char *hdr = hpsb_iso_packet_data(iso, recv->pkt_dma) - 8; - - struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, recv->pkt_dma); + unsigned char *hdr; + + unsigned int offset; + unsigned short cycle; + unsigned char channel, tag, sy; + + offset = iso->pkt_dma * recv->buf_stride; + hdr = iso->data_buf.kvirt + offset; + + /* skip iso header */ + offset += 8; + packet_len -= 8; - info->len = packet_len; - info->cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF; - info->channel = hdr[5] & 0x3F; - info->tag = hdr[5] >> 6; - info->sy = hdr[4] & 0xF; + cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF; + channel = hdr[5] & 0x3F; + tag = hdr[5] >> 6; + sy = hdr[4] & 0xF; + + hpsb_iso_packet_received(iso, offset, packet_len, cycle, channel, tag, sy); } - /* at least one packet came in, so wake up the reader */ - wake = 1; - /* reset the DMA descriptor */ - il->status = iso->max_packet_size; - - /* advance DMA packet cursor */ - recv->pkt_dma = (recv->pkt_dma + 1) % iso->buf_packets; + il->status = recv->buf_stride; - /* one more packet for the user, one less for us */ - if(atomic_dec_and_test(&iso->n_dma_packets)) { - /* if n_dma_packets reaches zero, we have an overflow */ - atomic_inc(&iso->overflows); - } + wake = 1; + recv->block_dma = iso->pkt_dma; } out: - if(wake && iso->callback) { - iso->callback(iso); - } + if(wake) + hpsb_iso_wake(iso); } @@ -1386,7 +1802,6 @@ struct dma_prog_region prog; struct ohci1394_iso_tasklet task; int task_active; - int pkt_dma; u32 ContextControlSet; u32 ContextControlClear; @@ -1415,7 +1830,7 @@ unsigned int prog_size; int ctx; int ret = -ENOMEM; - + xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL); if(!xmit) return -ENOMEM; @@ -1423,21 +1838,20 @@ iso->hostdata = xmit; xmit->ohci = iso->host->hostdata; xmit->task_active = 0; - xmit->pkt_dma = iso->first_packet; - + dma_prog_region_init(&xmit->prog); - + prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets; - + if(dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev)) goto err; ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT, ohci_iso_xmit_task, (unsigned long) iso); - + if(ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) goto err; - + xmit->task_active = 1; /* xmit context registers are spaced 16 bytes apart */ @@ -1446,11 +1860,6 @@ xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx; xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx; - reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF); - - /* enable interrupts */ - reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx); - return 0; err: @@ -1461,7 +1870,17 @@ static void ohci_iso_xmit_stop(struct hpsb_iso *iso) { struct ohci_iso_xmit *xmit = iso->hostdata; - ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL); + + /* disable interrupts */ + reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); + + /* halt DMA */ + if(ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { + /* XXX the DMA context will lock up if you try to send too much data! */ + PRINT(KERN_ERR, xmit->ohci->id, + "you probably exceeded the OHCI card's bandwidth limit - " + "reload the module and reduce xmit bandwidth"); + } } static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso) @@ -1469,16 +1888,11 @@ struct ohci_iso_xmit *xmit = iso->hostdata; if(xmit->task_active) { - /* halt DMA */ - ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL); - - /* disable interrupts */ - reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); - + ohci_iso_xmit_stop(iso); ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task); xmit->task_active = 0; } - + dma_prog_region_free(&xmit->prog); kfree(xmit); iso->hostdata = NULL; @@ -1493,9 +1907,10 @@ /* check the whole buffer if necessary, starting at pkt_dma */ for(count = 0; count < iso->buf_packets; count++) { - + int cycle; + /* DMA descriptor */ - struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, xmit->pkt_dma); + struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma); /* check for new writes to xferStatus */ u16 xferstatus = cmd->output_last.status >> 16; @@ -1503,70 +1918,68 @@ if(!event) { /* packet hasn't been sent yet; we are done for now */ - goto out; + break; } - if(event != 0x11) { - PRINT(KERN_ERR, xmit->ohci->id, "IT DMA error - OHCI error code 0x%02x\n", event); - } + if(event != 0x11) + PRINT(KERN_ERR, xmit->ohci->id, + "IT DMA error - OHCI error code 0x%02x\n", event); /* at least one packet went out, so wake up the writer */ wake = 1; - /* predict the timestamp pkt_dma will have next time around the buffer */ - { - struct hpsb_iso_packet_info* info = hpsb_iso_packet_info(iso, xmit->pkt_dma); - unsigned int cycle = cmd->output_last.status & 0x1FFF; + /* parse cycle */ + cycle = cmd->output_last.status & 0x1FFF; - cycle += iso->buf_packets; - while(cycle > 8000) - cycle -= 8000; - - info->cycle = cycle; - } + /* tell the subsystem the packet has gone out */ + hpsb_iso_packet_sent(iso, cycle, event != 0x11); /* reset the DMA descriptor for next time */ cmd->output_last.status = 0; - - /* advance packet cursor */ - xmit->pkt_dma = (xmit->pkt_dma + 1) % iso->buf_packets; - - /* one less packet for us */ - if(atomic_dec_and_test(&iso->n_dma_packets)) { - /* underflow */ - atomic_inc(&iso->overflows); - } } -out: - if(wake && iso->callback) { - iso->callback(iso); - } + if(wake) + hpsb_iso_wake(iso); } -static void ohci_iso_xmit_queue_one(struct hpsb_iso *iso) +static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { struct ohci_iso_xmit *xmit = iso->hostdata; - struct hpsb_iso_packet_info *info; + int next_i, prev_i; struct iso_xmit_cmd *next, *prev; - + + unsigned int offset; + unsigned short len; + unsigned char tag, sy; + + /* check that the packet doesn't cross a page boundary + (we could allow this if we added OUTPUT_MORE descriptor support) */ + if(cross_bound(info->offset, info->len)) { + PRINT(KERN_ERR, xmit->ohci->id, + "rawiso xmit: packet %u crosses a page boundary", + iso->first_packet); + return -EINVAL; + } + + offset = info->offset; + len = info->len; + tag = info->tag; + sy = info->sy; + /* sync up the card's view of the buffer */ - dma_region_sync(&iso->buf, iso->first_packet * iso->buf_stride, iso->buf_stride); + dma_region_sync(&iso->data_buf, offset, len); /* append first_packet to the DMA chain */ /* by linking the previous descriptor to it */ /* (next will become the new end of the DMA chain) */ - + next_i = iso->first_packet; prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1); - + next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i); prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i); - /* retrieve the packet info stashed in the buffer */ - info = hpsb_iso_packet_info(iso, iso->first_packet); - /* set up the OUTPUT_MORE_IMMEDIATE descriptor */ memset(next, 0, sizeof(struct iso_xmit_cmd)); next->output_more_immediate.control = 0x02000008; @@ -1574,29 +1987,28 @@ /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */ /* tcode = 0xA, and sy */ - next->iso_hdr[0] = 0xA0 | (info->sy & 0xF); + next->iso_hdr[0] = 0xA0 | (sy & 0xF); /* tag and channel number */ - next->iso_hdr[1] = (info->tag << 6) | (iso->channel & 0x3F); + next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F); /* transmission speed */ next->iso_hdr[2] = iso->speed & 0x7; /* payload size */ - next->iso_hdr[6] = info->len & 0xFF; - next->iso_hdr[7] = info->len >> 8; + next->iso_hdr[6] = len & 0xFF; + next->iso_hdr[7] = len >> 8; /* set up the OUTPUT_LAST */ next->output_last.control = 1 << 28; next->output_last.control |= 1 << 27; /* update timeStamp */ next->output_last.control |= 3 << 20; /* want interrupt */ next->output_last.control |= 3 << 18; /* enable branch */ - next->output_last.control |= info->len; + next->output_last.control |= len; /* payload bus address */ - next->output_last.address = dma_region_offset_to_bus(&iso->buf, - hpsb_iso_packet_data(iso, iso->first_packet) - iso->buf.kvirt); - + next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset); + /* leave branchAddress at zero for now */ /* re-write the previous DMA descriptor to chain to this one */ @@ -1604,7 +2016,7 @@ /* set prev branch address to point to next (Z=3) */ prev->output_last.branchAddress = dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3; - + /* disable interrupt, unless required by the IRQ interval */ if(prev_i % iso->irq_interval) { prev->output_last.control &= ~(3 << 20); /* no interrupt */ @@ -1622,16 +2034,7 @@ mb(); reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer); - /* increment cursors */ - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; - atomic_inc(&iso->n_dma_packets); -} - -static void ohci_iso_xmit_queue(struct hpsb_iso *iso, int n_packets) -{ - int i; - for(i = 0; i < n_packets; i++) - ohci_iso_xmit_queue_one(iso); + return 0; } static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle) @@ -1644,7 +2047,7 @@ /* address and length of first descriptor block (Z=3) */ reg_write(xmit->ohci, xmit->CommandPtr, - dma_prog_region_offset_to_bus(&xmit->prog, xmit->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); + dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); /* cycle match */ if(cycle != -1) { @@ -1662,26 +2065,29 @@ reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16)); } + /* enable interrupts */ + reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context); + /* run */ reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000); mb(); - + /* wait 100 usec to give the card time to go active */ udelay(100); - + /* check the RUN bit */ if(!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n", reg_read(xmit->ohci, xmit->ContextControlSet)); return -1; } - + return 0; } -static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, int arg) +static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, unsigned long arg) { - + switch(cmd) { case XMIT_INIT: return ohci_iso_xmit_init(iso); @@ -1691,26 +2097,36 @@ ohci_iso_xmit_stop(iso); return 0; case XMIT_QUEUE: - ohci_iso_xmit_queue(iso, arg); - return 0; + return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg); case XMIT_SHUTDOWN: ohci_iso_xmit_shutdown(iso); return 0; case RECV_INIT: return ohci_iso_recv_init(iso); - case RECV_START: - return ohci_iso_recv_start(iso, arg); + case RECV_START: { + int *args = (int*) arg; + return ohci_iso_recv_start(iso, args[0], args[1], args[2]); + } case RECV_STOP: ohci_iso_recv_stop(iso); return 0; case RECV_RELEASE: - ohci_iso_recv_release(iso, arg); + ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg); return 0; case RECV_SHUTDOWN: ohci_iso_recv_shutdown(iso); return 0; - + case RECV_LISTEN_CHANNEL: + ohci_iso_recv_change_channel(iso, arg, 1); + return 0; + case RECV_UNLISTEN_CHANNEL: + ohci_iso_recv_change_channel(iso, arg, 0); + return 0; + case RECV_SET_CHANNEL_MASK: + ohci_iso_recv_set_channel_mask(iso, *((u64*) arg)); + return 0; + default: PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet", cmd); @@ -1780,7 +2196,7 @@ if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask) tasklet_schedule(&t->tasklet); - if (t->type == OHCI_ISO_RECEIVE && rx_event & mask) + else if (rx_event & mask) tasklet_schedule(&t->tasklet); } @@ -1839,7 +2255,7 @@ for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Iso Xmit %d Context died: " + PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: " "ctrl[%08x] cmdptr[%08x]", ctx, reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)), reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx))); @@ -1847,7 +2263,7 @@ for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Iso Recv %d Context died: " + PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: " "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx, reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)), reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)), @@ -2008,8 +2424,8 @@ PRINT(KERN_ERR, ohci->id, "SelfID received outside of bus reset sequence"); - event &= ~OHCI1394_selfIDComplete; selfid_not_valid: + event &= ~OHCI1394_selfIDComplete; } /* Make sure we handle everything, just in case we accidentally @@ -2035,8 +2451,10 @@ PRINT(KERN_INFO, ohci->id, "Waking dma ctx=%d ... processing is probably too slow", d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } #define cond_le32_to_cpu(data, noswap) \ @@ -2222,7 +2640,7 @@ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); struct hpsb_packet *packet; unsigned long flags; - u32 ack; + u32 status, ack; size_t datasize; spin_lock_irqsave(&d->lock, flags); @@ -2231,25 +2649,16 @@ packet = driver_packet(d->fifo_list.next); datasize = packet->data_size; if (datasize && packet->type != hpsb_raw) - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->end.status) >> 16; else - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->begin.status) >> 16; - if (ack == 0) + if (status == 0) /* this packet hasn't been sent yet*/ break; - if (!(ack & 0x10)) { - /* XXX: This is an OHCI evt_* code. We need to handle - * this specially! For right now, we just fake an - * ackx_send_error. */ - PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x", - ack & 0xf); - ack = (ack & 0xffe0) | ACK_BUSY_A; - } - #ifdef OHCI1394_DEBUG if (datasize) DBGMSG(ohci->id, @@ -2261,7 +2670,7 @@ >>4)&0xf, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, + status&0x1f, (status>>5)&0x3, le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) >>16, d->ctx); @@ -2275,13 +2684,64 @@ >>4)&0xf, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, + status&0x1f, (status>>5)&0x3, le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]), d->ctx); #endif + if (status & 0x10) { + ack = status & 0xf; + } else { + switch (status & 0x1f) { + case EVT_NO_STATUS: /* that should never happen */ + case EVT_RESERVED_A: /* that should never happen */ + case EVT_LONG_PACKET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_MISSING_ACK: + ack = ACKX_TIMEOUT; + break; + case EVT_UNDERRUN: + ack = ACKX_SEND_ERROR; + break; + case EVT_OVERRUN: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_DESCRIPTOR_READ: + case EVT_DATA_READ: + case EVT_DATA_WRITE: + ack = ACKX_SEND_ERROR; + break; + case EVT_BUS_RESET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_TIMEOUT: + ack = ACKX_TIMEOUT; + break; + case EVT_TCODE_ERR: + ack = ACKX_SEND_ERROR; + break; + case EVT_RESERVED_B: /* that should never happen */ + case EVT_RESERVED_C: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_UNKNOWN: + case EVT_FLUSHED: + ack = ACKX_SEND_ERROR; + break; + default: + PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + BUG(); + } + } + list_del(&packet->driver_list); - hpsb_packet_sent(ohci->host, packet, ack & 0xf); + hpsb_packet_sent(ohci->host, packet, ack); if (datasize) { pci_unmap_single(ohci->dev, @@ -2307,13 +2767,18 @@ return; DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx); - - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_tasklet); - else - tasklet_kill(&d->task); + if(d->ctrlClear) { + ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->buf_cpu) { for (i=0; inum_desc; i++) @@ -2358,9 +2823,9 @@ d->buf_size = buf_size; d->split_buf_size = split_buf_size; - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + d->ctrlSet = 0; + d->ctrlClear = 0; + d->cmdPtr = 0; d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); @@ -2428,17 +2893,30 @@ spin_lock_init(&d->lock); if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_RECEIVE, + ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet, + OHCI_ISO_MULTICHANNEL_RECEIVE, dma_rcv_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->ir_tasklet) < 0) { + &ohci->ir_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); free_dma_rcv_ctx(d); return -EBUSY; } - } - else + + /* the IR context can be assigned to any DMA context + * by ohci1394_register_iso_tasklet */ + d->ctx = ohci->ir_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx; + d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx; + d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx; + d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx; + } else { + d->ctrlSet = context_base + OHCI1394_ContextControlSet; + d->ctrlClear = context_base + OHCI1394_ContextControlClear; + d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); + } return 0; } @@ -2452,12 +2930,18 @@ DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx); - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + if(d->ctrlClear) { + ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->it_tasklet); - else - tasklet_kill(&d->task); + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, + &d->ohci->it_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->prg_cpu) { for (i=0; inum_desc; i++) @@ -2486,9 +2970,9 @@ d->type = type; d->ctx = ctx; d->num_desc = num_desc; - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + d->ctrlSet = 0; + d->ctrlClear = 0; + d->cmdPtr = 0; d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), GFP_KERNEL); @@ -2524,17 +3008,26 @@ /* initialize tasklet */ if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->it_tasklet, OHCI_ISO_TRANSMIT, - dma_rcv_tasklet, (unsigned long) d); + ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT, + dma_trm_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->it_tasklet) < 0) { + &ohci->it_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IT DMA context available"); free_dma_trm_ctx(d); return -EBUSY; } - } - else + + /* IT can be assigned to any context by register_iso_tasklet */ + d->ctx = ohci->it_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx; + d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx; + d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx; + } else { + d->ctrlSet = context_base + OHCI1394_ContextControlSet; + d->ctrlClear = context_base + OHCI1394_ContextControlClear; + d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d); + } return 0; } @@ -2739,7 +3232,7 @@ struct hpsb_host *host; struct ti_ohci *ohci; /* shortcut to currently handled device */ unsigned long ohci_base; - + if (version_printed++ == 0) PRINT_G(KERN_INFO, "%s", version); @@ -2815,7 +3308,7 @@ pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, &ohci->selfid_buf_bus); OHCI_DMA_ALLOC("consistent selfid_buf"); - + if (ohci->selfid_buf_cpu == NULL) FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets"); ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; @@ -2888,19 +3381,11 @@ ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); - /* IR DMA context */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context, - DMA_CTX_ISO, 0, IR_NUM_DESC, - IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, - OHCI1394_IsoRcvContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IR context"); + /* the IR DMA context is allocated on-demand; mark it inactive */ + ohci->ir_legacy_context.ohci = NULL; - - /* IT DMA context allocation */ - if (alloc_dma_trm_ctx(ohci, &ohci->it_context, - DMA_CTX_ISO, 0, IT_NUM_DESC, - OHCI1394_IsoXmitContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IT context"); + /* same for the IT DMA context */ + ohci->it_legacy_context.ohci = NULL; if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, OHCI1394_DRIVER_NAME, ohci)) @@ -2945,11 +3430,11 @@ free_dma_trm_ctx(&ohci->at_resp_context); /* Free IR dma */ - free_dma_rcv_ctx(&ohci->ir_context); - + free_dma_rcv_ctx(&ohci->ir_legacy_context); + /* Free IT dma */ - free_dma_trm_ctx(&ohci->it_context); - + free_dma_trm_ctx(&ohci->it_legacy_context); + case OHCI_INIT_HAVE_SELFID_BUFFER: pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, ohci->selfid_buf_cpu, @@ -3025,7 +3510,7 @@ /* essentially the only purpose of this code is to allow another module to hook into ohci's interrupt handler */ -void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) +int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) { int i=0; @@ -3037,11 +3522,15 @@ i++; if (i>5000) { PRINT(KERN_ERR, ohci->id, - "Runaway loop while stopping context..."); - break; + "Runaway loop while stopping context: %s...", msg ? msg : ""); + return 1; } + + mb(); + udelay(10); } if (msg) PRINT(KERN_ERR, ohci->id, "%s: dma prg stopped", msg); + return 0; } void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type, @@ -3067,6 +3556,13 @@ else { n = ohci->nb_iso_rcv_ctx; usage = &ohci->ir_ctx_usage; + + /* only one receive context can be multichannel (OHCI sec 10.4.1) */ + if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + if(test_and_set_bit(0, &ohci->ir_multichannel_used)) { + return r; + } + } } spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); @@ -3080,7 +3576,7 @@ } spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); - + return r; } @@ -3095,8 +3591,13 @@ if (tasklet->type == OHCI_ISO_TRANSMIT) clear_bit(tasklet->context, &ohci->it_ctx_usage); - else + else { clear_bit(tasklet->context, &ohci->ir_ctx_usage); + + if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + clear_bit(0, &ohci->ir_multichannel_used); + } + } list_del(&tasklet->link); diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h --- a/drivers/ieee1394/ohci1394.h Mon Feb 17 14:57:26 2003 +++ b/drivers/ieee1394/ohci1394.h Mon Feb 17 14:57:26 2003 @@ -109,6 +109,7 @@ int ctrlClear; int ctrlSet; int cmdPtr; + int ctxtMatch; }; /* DMA transmit context */ @@ -145,7 +146,8 @@ struct tasklet_struct tasklet; struct list_head link; int context; - enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE } type; + enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE, + OHCI_ISO_MULTICHANNEL_RECEIVE } type; }; struct ti_ohci { @@ -170,7 +172,7 @@ /* dma buffer for self-id packets */ quadlet_t *selfid_buf_cpu; dma_addr_t selfid_buf_bus; - + /* buffer for csr config rom */ quadlet_t *csr_config_rom_cpu; dma_addr_t csr_config_rom_bus; @@ -187,18 +189,28 @@ struct dma_trm_ctx at_req_context; /* iso receive */ - struct dma_rcv_ctx ir_context; - struct ohci1394_iso_tasklet ir_tasklet; - spinlock_t IR_channel_lock; int nb_iso_rcv_ctx; unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ + unsigned long ir_multichannel_used; /* ditto */ + spinlock_t IR_channel_lock; + + /* iso receive (legacy API) */ + u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage; + it only accounts for channels listened to + by the legacy API, so that we can know when + it is safe to free the legacy API context */ + + struct dma_rcv_ctx ir_legacy_context; + struct ohci1394_iso_tasklet ir_legacy_tasklet; /* iso transmit */ - struct dma_trm_ctx it_context; - struct ohci1394_iso_tasklet it_tasklet; int nb_iso_xmit_ctx; unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ - + + /* iso transmit (legacy API) */ + struct dma_trm_ctx it_legacy_context; + struct ohci1394_iso_tasklet it_legacy_tasklet; + u64 ISO_channel_usage; /* IEEE-1394 part follows */ @@ -213,10 +225,10 @@ /* Tasklets for iso receive and transmit, used by video1394, * amdtp and dv1394 */ - + struct list_head iso_tasklet_list; spinlock_t iso_tasklet_list_lock; - + /* Swap the selfid buffer? */ unsigned int selfid_swap:1; /* Some Apple chipset seem to swap incoming headers for us */ @@ -385,7 +397,7 @@ /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */ #define EVT_NO_STATUS 0x0 /* No event status */ -#define EVT_RESERVED 0x1 /* Reserved, not used !!! */ +#define EVT_RESERVED_A 0x1 /* Reserved, not used !!! */ #define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */ #define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack arrived, or recv'd ack had a parity error */ @@ -404,6 +416,17 @@ 16-bit host memory write */ #define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as being a synthesized bus reset packet */ +#define EVT_TIMEOUT 0xa /* Indicates that the asynchronous transmit response + packet expired and was not transmitted, or that an + IT DMA context experienced a skip processing overflow */ +#define EVT_TCODE_ERR 0xb /* A bad tCode is associated with this packet. + The packet was flushed */ +#define EVT_RESERVED_B 0xc /* Reserved, not used !!! */ +#define EVT_RESERVED_C 0xd /* Reserved, not used !!! */ +#define EVT_UNKNOWN 0xe /* An error condition has occurred that cannot be + represented by any other event codes defined herein. */ +#define EVT_FLUSHED 0xf /* Send by the link side of output FIFO when asynchronous + packets are being flushed due to a bus reset. */ #define OHCI1394_TCODE_PHY 0xE @@ -416,8 +439,8 @@ void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci, struct ohci1394_iso_tasklet *tasklet); -void ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg); +/* returns zero if successful, one if DMA context is locked up */ +int ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg); struct ti_ohci *ohci1394_get_struct(int card_num); #endif - diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c --- a/drivers/ieee1394/pcilynx.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/pcilynx.c Mon Feb 17 14:57:27 2003 @@ -27,6 +27,7 @@ * eeprom via i2c and storing it in config ROM * Reworked code for initiating bus resets * (long, short, with or without hold-off) + * Enhancements in async and iso send code */ #include @@ -127,23 +128,20 @@ } static struct i2c_algo_bit_data bit_data = { - NULL, - bit_setsda, - bit_setscl, - bit_getsda, - bit_getscl, - 5, 5, 100, /* waits, timeout */ + .setsda = bit_setsda, + .setscl = bit_setscl, + .getsda = bit_getsda, + .getscl = bit_getscl, + .udelay = 5, + .mdelay = 5, + .timeout = 100, }; static struct i2c_adapter bit_ops = { - "PCILynx I2C adapter", - 0xAA, //FIXME: probably we should get an id in i2c-id.h - NULL, - NULL, - NULL, - NULL, - bit_reg, - bit_unreg, + .name = "PCILynx I2C adapter", + .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h + .client_register = bit_reg, + .client_unregister = bit_unreg, }; @@ -476,7 +474,14 @@ struct hpsb_packet *packet; d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async); + if (!list_empty(&d->pcl_queue)) { + PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo"); + BUG(); + } + packet = driver_packet(d->queue.next); + list_del(&packet->driver_list); + list_add_tail(&packet->driver_list, &d->pcl_queue); d->header_dma = pci_map_single(lynx->dev, packet->header, packet->header_size, PCI_DMA_TODEVICE); @@ -490,6 +495,7 @@ pcl.next = PCL_NEXT_INVALID; pcl.async_error_next = PCL_NEXT_INVALID; + pcl.pcl_status = 0; #ifdef __BIG_ENDIAN pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size; #else @@ -556,7 +562,7 @@ spin_lock_irqsave(&d->queue_lock, flags); list_add_tail(&packet->driver_list, &d->queue); - if (d->queue.next == &packet->driver_list) + if (list_empty(&d->pcl_queue)) send_next(lynx, packet->type); spin_unlock_irqrestore(&d->queue_lock, flags); @@ -748,7 +754,44 @@ list_splice(&lynx->async.queue, &packet_list); INIT_LIST_HEAD(&lynx->async.queue); - spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + if (list_empty(&lynx->async.pcl_queue)) { + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL"); + + get_pcl(lynx, lynx->async.pcl, &pcl); + + packet = driver_packet(lynx->async.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->async.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->async.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } + + spin_unlock_irqrestore(&lynx->async.queue_lock, flags); + + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "async packet was not completed"); + ack = ACKX_ABORTED; + } + hpsb_packet_sent(host, packet, ack); + } while (!list_empty(&packet_list)) { packet = driver_packet(packet_list.next); @@ -759,13 +802,14 @@ break; case MODIFY_USAGE: - if (arg) { - MOD_INC_USE_COUNT; - } else { - MOD_DEC_USE_COUNT; - } + if (arg) { + if (try_module_get(THIS_MODULE)) + retval = 1; + } else { + module_put(THIS_MODULE); + retval = 1; + } - retval = 1; break; case ISO_LISTEN_CHANNEL: @@ -1021,21 +1065,13 @@ ssize_t retval; void *membase; - if (*offset != off) /* Check for EOF before we trust wrap */ - return 0; - - /* FIXME: Signed wrap is undefined in C - wants fixing up */ - if (off + count > off) - return 0; - - if ((off + count) > PCILYNX_MAX_MEMORY + 1) { - count = PCILYNX_MAX_MEMORY + 1 - off; + if ((off + count) > PCILYNX_MAX_MEMORY+1) { + count = PCILYNX_MAX_MEMORY+1 - off; } - if (count == 0) { - return 0; + if (count == 0 || off > PCILYNX_MAX_MEMORY) { + return -ENOSPC; } - switch (md->type) { case rom: membase = md->lynx->local_rom; @@ -1145,11 +1181,11 @@ linkint = reg_read(lynx, LINK_INT_STATUS); intmask = reg_read(lynx, PCI_INT_STATUS); + if (!(intmask & PCI_INT_INT_PEND)) return; + PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask, linkint); - if (!(intmask & PCI_INT_INT_PEND)) return; - reg_write(lynx, LINK_INT_STATUS, linkint); reg_write(lynx, PCI_INT_STATUS, intmask); @@ -1248,62 +1284,96 @@ } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) { - u32 ack; - struct hpsb_packet *packet; - + PRINTD(KERN_DEBUG, lynx->id, "async sent"); spin_lock(&lynx->async.queue_lock); - ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND)); - - packet = driver_packet(lynx->async.queue.next); - list_del(&packet->driver_list); - - pci_unmap_single(lynx->dev, lynx->async.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->async.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } + if (list_empty(&lynx->async.pcl_queue)) { + spin_unlock(&lynx->async.queue_lock); + PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + get_pcl(lynx, lynx->async.pcl, &pcl); + + packet = driver_packet(lynx->async.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->async.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->async.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } - if (!list_empty(&lynx->async.queue)) { - send_next(lynx, hpsb_async); - } + if (!list_empty(&lynx->async.queue)) { + send_next(lynx, hpsb_async); + } - spin_unlock(&lynx->async.queue_lock); + spin_unlock(&lynx->async.queue_lock); - if (ack & DMA_CHAN_STAT_SPECIALACK) { - ack = (ack >> 15) & 0xf; - PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); - ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); - } else { - ack = (ack >> 15) & 0xf; + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "async packet was not completed"); + ack = ACKX_SEND_ERROR; + } + hpsb_packet_sent(host, packet, ack); } - - hpsb_packet_sent(host, packet, ack); } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) { - struct hpsb_packet *packet; - + PRINTD(KERN_DEBUG, lynx->id, "iso sent"); spin_lock(&lynx->iso_send.queue_lock); - packet = driver_packet(lynx->iso_send.queue.next); - list_del(&packet->driver_list); + if (list_empty(&lynx->iso_send.pcl_queue)) { + spin_unlock(&lynx->iso_send.queue_lock); + PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet"); + } else { + struct ti_pcl pcl; + u32 ack; + struct hpsb_packet *packet; + + get_pcl(lynx, lynx->iso_send.pcl, &pcl); + + packet = driver_packet(lynx->iso_send.pcl_queue.next); + list_del(&packet->driver_list); + + pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, + packet->header_size, PCI_DMA_TODEVICE); + if (packet->data_size) { + pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, + packet->data_size, PCI_DMA_TODEVICE); + } - pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } + if (!list_empty(&lynx->iso_send.queue)) { + send_next(lynx, hpsb_iso); + } - if (!list_empty(&lynx->iso_send.queue)) { - send_next(lynx, hpsb_iso); - } + spin_unlock(&lynx->iso_send.queue_lock); - spin_unlock(&lynx->iso_send.queue_lock); + if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { + if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { + ack = (pcl.pcl_status >> 15) & 0xf; + PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); + ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); + } else { + ack = (pcl.pcl_status >> 15) & 0xf; + } + } else { + PRINT(KERN_INFO, lynx->id, "iso send packet was not completed"); + ack = ACKX_SEND_ERROR; + } - hpsb_packet_sent(host, packet, ACK_COMPLETE); + hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR + } } if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) { @@ -1605,7 +1675,9 @@ lynx->phy_reg0 = -1; INIT_LIST_HEAD(&lynx->async.queue); + INIT_LIST_HEAD(&lynx->async.pcl_queue); INIT_LIST_HEAD(&lynx->iso_send.queue); + INIT_LIST_HEAD(&lynx->iso_send.pcl_queue); pcl.next = pcl_bus(lynx, lynx->rcv_pcl); put_pcl(lynx, lynx->rcv_pcl_start, &pcl); diff -Nru a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h --- a/drivers/ieee1394/pcilynx.h Mon Feb 17 14:57:26 2003 +++ b/drivers/ieee1394/pcilynx.h Mon Feb 17 14:57:26 2003 @@ -95,6 +95,7 @@ struct lynx_send_data { pcl_t pcl_start, pcl; struct list_head queue; + struct list_head pcl_queue; /* this queue contains at most one packet */ spinlock_t queue_lock; dma_addr_t header_dma, data_dma; int channel; @@ -514,13 +515,13 @@ static quadlet_t lynx_csr_rom[] = { /* bus info block offset (hex) */ - _(0x04040000), /* info/CRC length, CRC 400 */ + _(0x04046aaf), /* info/CRC length, CRC 400 */ _(0x31333934), /* 1394 magic number 404 */ _(0xf064a000), /* misc. settings 408 */ _(0x08002850), /* vendor ID, chip ID high 40c */ _(0x0000ffff), /* chip ID low 410 */ /* root directory */ - _(0x00090000), /* directory length, CRC 414 */ + _(0x00095778), /* directory length, CRC 414 */ _(0x03080028), /* vendor ID (Texas Instr.) 418 */ _(0x81000008), /* offset to textual ID 41c */ _(0x0c000200), /* node capabilities 420 */ @@ -530,8 +531,8 @@ _(0x81000014), /* offset to textual ID 430 */ _(0x09000000), /* node hardware version 434 */ _(0x81000018), /* offset to textual ID 438 */ - /* module vendor ID textual */ - _(0x00070000), /* CRC length, CRC 43c */ +/* module vendor ID textual */ + _(0x00070812), /* CRC length, CRC 43c */ _(0x00000000), /* 440 */ _(0x00000000), /* 444 */ _(0x54455841), /* "Texas Instruments" 448 */ @@ -540,25 +541,25 @@ _(0x4d454e54), /* 454 */ _(0x53000000), /* 458 */ /* node unique ID leaf */ - _(0x00020000), /* CRC length, CRC 45c */ + _(0x00022ead), /* CRC length, CRC 45c */ _(0x08002850), /* vendor ID, chip ID high 460 */ _(0x0000ffff), /* chip ID low 464 */ /* module dependent info */ - _(0x00050000), /* CRC length, CRC 468 */ + _(0x0005d837), /* CRC length, CRC 468 */ _(0x81000012), /* offset to module textual ID 46c */ _(0x81000017), /* textual descriptor 470 */ _(0x39010000), /* SRAM size 474 */ _(0x3a010000), /* AUXRAM size 478 */ _(0x3b000000), /* AUX device 47c */ /* module textual ID */ - _(0x00050000), /* CRC length, CRC 480 */ + _(0x000594df), /* CRC length, CRC 480 */ _(0x00000000), /* 484 */ _(0x00000000), /* 488 */ _(0x54534231), /* "TSB12LV21" 48c */ _(0x324c5632), /* 490 */ _(0x31000000), /* 494 */ /* part number */ - _(0x00060000), /* CRC length, CRC 498 */ + _(0x00068405), /* CRC length, CRC 498 */ _(0x00000000), /* 49c */ _(0x00000000), /* 4a0 */ _(0x39383036), /* "9806000-0001" 4a4 */ @@ -566,14 +567,14 @@ _(0x30303031), /* 4ac */ _(0x20000001), /* 4b0 */ /* module hardware version textual */ - _(0x00050000), /* CRC length, CRC 4b4 */ + _(0x00056501), /* CRC length, CRC 4b4 */ _(0x00000000), /* 4b8 */ _(0x00000000), /* 4bc */ _(0x5453424b), /* "TSBKPCITST" 4c0 */ _(0x50434954), /* 4c4 */ _(0x53540000), /* 4c8 */ /* node hardware version textual */ - _(0x00050000), /* CRC length, CRC 4d0 */ + _(0x0005d805), /* CRC length, CRC 4d0 */ _(0x00000000), /* 4d4 */ _(0x00000000), /* 4d8 */ _(0x54534232), /* "TSB21LV03" 4dc */ diff -Nru a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/raw1394-private.h Mon Feb 17 14:57:28 2003 @@ -0,0 +1,78 @@ +#ifndef IEEE1394_RAW1394_PRIVATE_H +#define IEEE1394_RAW1394_PRIVATE_H + +/* header for definitions that are private to the raw1394 driver + and not visible to user-space */ + +#define RAW1394_DEVICE_MAJOR 171 +#define RAW1394_DEVICE_NAME "raw1394" + +struct iso_block_store { + atomic_t refcount; + size_t data_size; + quadlet_t data[0]; +}; + +enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, + RAW1394_ISO_RECV = 1, + RAW1394_ISO_XMIT = 2 }; + +struct file_info { + struct list_head list; + + enum { opened, initialized, connected } state; + unsigned int protocol_version; + + struct hpsb_host *host; + + struct list_head req_pending; + struct list_head req_complete; + struct semaphore complete_sem; + spinlock_t reqlists_lock; + wait_queue_head_t poll_wait_complete; + + struct list_head addr_list; + + u8 *fcp_buffer; + + /* old ISO API */ + u64 listen_channels; + quadlet_t *iso_buffer; + size_t iso_buffer_length; + + u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ + + /* new rawiso API */ + enum raw1394_iso_state iso_state; + struct hpsb_iso *iso_handle; +}; + +struct arm_addr { + struct list_head addr_list; /* file_info list */ + u64 start, end; + u64 arm_tag; + u8 access_rights; + u8 notification_options; + u8 client_transactions; + u64 recvb; + u16 rec_length; + u8 *addr_space_buffer; /* accessed by read/write/lock */ +}; + +struct pending_request { + struct list_head list; + struct file_info *file_info; + struct hpsb_packet *packet; + struct iso_block_store *ibs; + quadlet_t *data; + int free_data; + struct raw1394_request req; +}; + +struct host_info { + struct list_head list; + struct hpsb_host *host; + struct list_head file_info_list; +}; + +#endif /* IEEE1394_RAW1394_PRIVATE_H */ diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Mon Feb 17 14:57:26 2003 +++ b/drivers/ieee1394/raw1394.c Mon Feb 17 14:57:26 2003 @@ -50,7 +50,7 @@ #include "iso.h" #include "ieee1394_transactions.h" #include "raw1394.h" - +#include "raw1394-private.h" #if BITS_PER_LONG == 64 #define int2ptr(x) ((void *)x) @@ -558,7 +558,7 @@ lh = lh->next; } hi = list_entry(lh, struct host_info, list); - hpsb_ref_host(hi->host); + hpsb_ref_host(hi->host); // XXX Need to handle failure case list_add_tail(&fi->list, &hi->file_info_list); fi->host = hi->host; fi->state = connected; @@ -603,10 +603,13 @@ if (fi->listen_channels & (1ULL << channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { - fi->listen_channels |= 1ULL << channel; - hpsb_listen_channel(hl_handle, fi->host, channel); - fi->iso_buffer = int2ptr(req->req.recvb); - fi->iso_buffer_length = req->req.length; + if(hpsb_listen_channel(hl_handle, fi->host, channel)) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->listen_channels |= 1ULL << channel; + fi->iso_buffer = int2ptr(req->req.recvb); + fi->iso_buffer_length = req->req.length; + } } } else { /* deallocate channel (one's complement neg) req.misc */ @@ -2004,7 +2007,7 @@ { struct list_head *lh; struct pending_request *req; - + list_for_each(lh, &fi->req_complete) { req = list_entry(lh, struct pending_request, list); if(req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { @@ -2015,59 +2018,63 @@ return 0; } +/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */ +static void queue_rawiso_event(struct file_info *fi) +{ + unsigned long flags; + + spin_lock_irqsave(&fi->reqlists_lock, flags); + + /* only one ISO activity event may be in the queue */ + if(!__rawiso_event_in_queue(fi)) { + struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); + + if(req) { + req->file_info = fi; + req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; + req->req.generation = get_hpsb_generation(fi->host); + __queue_complete_req(req); + } else { + /* on allocation failure, signal an overflow */ + if(fi->iso_handle) { + atomic_inc(&fi->iso_handle->overflows); + } + } + } + spin_unlock_irqrestore(&fi->reqlists_lock, flags); +} + static void rawiso_activity_cb(struct hpsb_iso *iso) { - unsigned long host_flags; + unsigned long flags; struct list_head *lh; struct host_info *hi; - spin_lock_irqsave(&host_info_lock, host_flags); + spin_lock_irqsave(&host_info_lock, flags); hi = find_host_info(iso->host); - + if (hi != NULL) { list_for_each(lh, &hi->file_info_list) { - unsigned long reqlist_flags; struct file_info *fi = list_entry(lh, struct file_info, list); - - spin_lock_irqsave(&fi->reqlists_lock, reqlist_flags); - - /* only one ISO activity event may be in the queue */ - if(!__rawiso_event_in_queue(fi)) { - struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); - - if(req) { - req->file_info = fi; - req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; - req->req.generation = get_hpsb_generation(iso->host); - __queue_complete_req(req); - } else { - /* on allocation failure, signal an overflow */ - if(fi->iso_handle) { - atomic_inc(&fi->iso_handle->overflows); - } - } - } - spin_unlock_irqrestore(&fi->reqlists_lock, reqlist_flags); + if(fi->iso_handle == iso) + queue_rawiso_event(fi); } } - - spin_unlock_irqrestore(&host_info_lock, host_flags); + + spin_unlock_irqrestore(&host_info_lock, flags); } /* helper function - gather all the kernel iso status bits for returning to user-space */ static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat) { + stat->config.data_buf_size = iso->buf_size; stat->config.buf_packets = iso->buf_packets; - stat->config.max_packet_size = iso->max_packet_size; stat->config.channel = iso->channel; stat->config.speed = iso->speed; stat->config.irq_interval = iso->irq_interval; - stat->buf_stride = iso->buf_stride; - stat->packet_data_offset = iso->packet_data_offset; - stat->packet_info_offset = iso->packet_info_offset; - stat->first_packet = iso->first_packet; stat->n_packets = hpsb_iso_n_ready(iso); stat->overflows = atomic_read(&iso->overflows); + stat->xmit_cycle = iso->xmit_cycle; } static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr) @@ -2076,10 +2083,10 @@ if(copy_from_user(&stat, uaddr, sizeof(stat))) return -EFAULT; - + fi->iso_handle = hpsb_iso_xmit_init(fi->host, + stat.config.data_buf_size, stat.config.buf_packets, - stat.config.max_packet_size, stat.config.channel, stat.config.speed, stat.config.irq_interval, @@ -2088,14 +2095,14 @@ return -ENOMEM; fi->iso_state = RAW1394_ISO_XMIT; - + raw1394_iso_fill_status(fi->iso_handle, &stat); if(copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; /* queue an event to get things started */ rawiso_activity_cb(fi->iso_handle); - + return 0; } @@ -2105,10 +2112,10 @@ if(copy_from_user(&stat, uaddr, sizeof(stat))) return -EFAULT; - + fi->iso_handle = hpsb_iso_recv_init(fi->host, + stat.config.data_buf_size, stat.config.buf_packets, - stat.config.max_packet_size, stat.config.channel, stat.config.irq_interval, rawiso_activity_cb); @@ -2116,7 +2123,7 @@ return -ENOMEM; fi->iso_state = RAW1394_ISO_RECV; - + raw1394_iso_fill_status(fi->iso_handle, &stat); if(copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; @@ -2134,7 +2141,72 @@ /* reset overflow counter */ atomic_set(&iso->overflows, 0); - + + return 0; +} + +/* copy N packet_infos out of the ringbuffer into user-supplied array */ +static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_packets upackets; + unsigned int packet = fi->iso_handle->first_packet; + int i; + + if(copy_from_user(&upackets, uaddr, sizeof(upackets))) + return -EFAULT; + + if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + return -EINVAL; + + /* ensure user-supplied buffer is accessible and big enough */ + if(verify_area(VERIFY_WRITE, upackets.infos, + upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + /* copy the packet_infos out */ + for(i = 0; i < upackets.n_packets; i++) { + if(__copy_to_user(&upackets.infos[i], + &fi->iso_handle->infos[packet], + sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + packet = (packet + 1) % fi->iso_handle->buf_packets; + } + + return 0; +} + +/* copy N packet_infos from user to ringbuffer, and queue them for transmission */ +static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr) +{ + struct raw1394_iso_packets upackets; + int i, rv; + + if(copy_from_user(&upackets, uaddr, sizeof(upackets))) + return -EFAULT; + + if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + return -EINVAL; + + /* ensure user-supplied buffer is accessible and big enough */ + if(verify_area(VERIFY_READ, upackets.infos, + upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + /* copy the infos structs in and queue the packets */ + for(i = 0; i < upackets.n_packets; i++) { + struct raw1394_iso_packet_info info; + + if(__copy_from_user(&info, &upackets.infos[i], + sizeof(struct raw1394_iso_packet_info))) + return -EFAULT; + + rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, + info.len, info.tag, info.sy); + if(rv) + return rv; + } + return 0; } @@ -2142,7 +2214,7 @@ { if(fi->iso_handle) hpsb_iso_shutdown(fi->iso_handle); - + fi->iso_handle = NULL; fi->iso_state = RAW1394_ISO_INACTIVE; } @@ -2155,20 +2227,20 @@ if(fi->iso_state == RAW1394_ISO_INACTIVE) return -EINVAL; - return dma_region_mmap(&fi->iso_handle->buf, file, vma); + return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); } /* ioctl is only used for rawiso operations */ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct file_info *fi = file->private_data; - + switch(fi->iso_state) { case RAW1394_ISO_INACTIVE: switch(cmd) { - case RAW1394_ISO_XMIT_INIT: + case RAW1394_IOC_ISO_XMIT_INIT: return raw1394_iso_xmit_init(fi, (void*) arg); - case RAW1394_ISO_RECV_INIT: + case RAW1394_IOC_ISO_RECV_INIT: return raw1394_iso_recv_init(fi, (void*) arg); default: break; @@ -2176,51 +2248,71 @@ break; case RAW1394_ISO_RECV: switch(cmd) { - case RAW1394_ISO_RECV_START: - return hpsb_iso_recv_start(fi->iso_handle, arg); - case RAW1394_ISO_STOP: + case RAW1394_IOC_ISO_RECV_START: { + /* copy args from user-space */ + int args[3]; + if(copy_from_user(&args[0], (void*) arg, sizeof(args))) + return -EFAULT; + return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); + } + case RAW1394_IOC_ISO_XMIT_RECV_STOP: hpsb_iso_stop(fi->iso_handle); return 0; - - case RAW1394_ISO_GET_STATUS: + case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: + return hpsb_iso_recv_listen_channel(fi->iso_handle, arg); + case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: + return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg); + case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: { + /* copy the u64 from user-space */ + u64 mask; + if(copy_from_user(&mask, (void*) arg, sizeof(mask))) + return -EFAULT; + return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask); + } + case RAW1394_IOC_ISO_GET_STATUS: return raw1394_iso_get_status(fi, (void*) arg); - - case RAW1394_ISO_PRODUCE_CONSUME: + case RAW1394_IOC_ISO_RECV_PACKETS: + return raw1394_iso_recv_packets(fi, (void*) arg); + case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: return hpsb_iso_recv_release_packets(fi->iso_handle, arg); - - case RAW1394_ISO_SHUTDOWN: + case RAW1394_IOC_ISO_SHUTDOWN: raw1394_iso_shutdown(fi); return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; } break; case RAW1394_ISO_XMIT: switch(cmd) { - case RAW1394_ISO_XMIT_START: { + case RAW1394_IOC_ISO_XMIT_START: { /* copy two ints from user-space */ int args[2]; if(copy_from_user(&args[0], (void*) arg, sizeof(args))) return -EFAULT; return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); } - case RAW1394_ISO_STOP: + case RAW1394_IOC_ISO_XMIT_SYNC: + return hpsb_iso_xmit_sync(fi->iso_handle); + case RAW1394_IOC_ISO_XMIT_RECV_STOP: hpsb_iso_stop(fi->iso_handle); return 0; - - case RAW1394_ISO_GET_STATUS: + case RAW1394_IOC_ISO_GET_STATUS: return raw1394_iso_get_status(fi, (void*) arg); - - case RAW1394_ISO_PRODUCE_CONSUME: - return hpsb_iso_xmit_queue_packets(fi->iso_handle, arg); - - case RAW1394_ISO_SHUTDOWN: + case RAW1394_IOC_ISO_XMIT_PACKETS: + return raw1394_iso_send_packets(fi, (void*) arg); + case RAW1394_IOC_ISO_SHUTDOWN: raw1394_iso_shutdown(fi); return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; } break; default: break; } - + return -EINVAL; } @@ -2236,7 +2328,7 @@ mask |= POLLIN | POLLRDNORM; } spin_unlock_irq(&fi->reqlists_lock); - + return mask; } @@ -2286,7 +2378,7 @@ if(fi->iso_state != RAW1394_ISO_INACTIVE) raw1394_iso_shutdown(fi); - + for (i = 0; i < 64; i++) { if (fi->listen_channels & (1ULL << i)) { hpsb_unlisten_channel(hl_handle, fi->host, i); diff -Nru a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h --- a/drivers/ieee1394/raw1394.h Mon Feb 17 14:57:26 2003 +++ b/drivers/ieee1394/raw1394.h Mon Feb 17 14:57:26 2003 @@ -1,8 +1,7 @@ #ifndef IEEE1394_RAW1394_H #define IEEE1394_RAW1394_H -#define RAW1394_DEVICE_MAJOR 171 -#define RAW1394_DEVICE_NAME "raw1394" +/* header for the raw1394 API that is exported to user-space */ #define RAW1394_KERNELAPI_VERSION 4 @@ -94,21 +93,21 @@ }; typedef struct arm_request { - nodeid_t destination_nodeid; - nodeid_t source_nodeid; - nodeaddr_t destination_offset; - u8 tlabel; - u8 tcode; - u_int8_t extended_transaction_code; - u_int32_t generation; - arm_length_t buffer_length; - byte_t *buffer; + __u16 destination_nodeid; + __u16 source_nodeid; + __u64 destination_offset; + __u8 tlabel; + __u8 tcode; + __u8 extended_transaction_code; + __u32 generation; + __u16 buffer_length; + __u8 *buffer; } *arm_request_t; typedef struct arm_response { - int response_code; - arm_length_t buffer_length; - byte_t *buffer; + __s32 response_code; + __u16 buffer_length; + __u8 *buffer; } *arm_response_t; typedef struct arm_request_response { @@ -117,133 +116,59 @@ } *arm_request_response_t; /* rawiso API */ - -/* ioctls */ -#define RAW1394_ISO_XMIT_INIT 1 /* arg: raw1394_iso_status* */ -#define RAW1394_ISO_RECV_INIT 2 /* arg: raw1394_iso_status* */ -#define RAW1394_ISO_RECV_START 3 /* arg: int, starting cycle */ -#define RAW1394_ISO_XMIT_START 8 /* arg: int[2], { starting cycle, prebuffer } */ -#define RAW1394_ISO_STOP 4 -#define RAW1394_ISO_GET_STATUS 5 /* arg: raw1394_iso_status* */ -#define RAW1394_ISO_PRODUCE_CONSUME 6 /* arg: int, # of packets */ -#define RAW1394_ISO_SHUTDOWN 7 +#include "ieee1394-ioctl.h" /* per-packet metadata embedded in the ringbuffer */ /* must be identical to hpsb_iso_packet_info in iso.h! */ struct raw1394_iso_packet_info { - unsigned short len; - unsigned short cycle; - unsigned char channel; /* recv only */ - unsigned char tag; - unsigned char sy; + __u32 offset; + __u16 len; + __u16 cycle; /* recv only */ + __u8 channel; /* recv only */ + __u8 tag; + __u8 sy; +}; + +/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */ +struct raw1394_iso_packets { + __u32 n_packets; + struct raw1394_iso_packet_info *infos; }; struct raw1394_iso_config { - unsigned int buf_packets; - unsigned int max_packet_size; - int channel; - int speed; /* xmit only */ - int irq_interval; + /* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */ + __u32 data_buf_size; + + /* # of packets to buffer */ + __u32 buf_packets; + + /* iso channel (set to -1 for multi-channel recv) */ + __s32 channel; + + /* xmit only - iso transmission speed */ + __u8 speed; + + /* max. latency of buffer, in packets (-1 if you don't care) */ + __s32 irq_interval; }; /* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */ struct raw1394_iso_status { /* current settings */ struct raw1394_iso_config config; - - /* byte offset between successive packets in the buffer */ - int buf_stride; - - /* byte offset of data payload within each packet */ - int packet_data_offset; - - /* byte offset of struct iso_packet_info within each packet */ - int packet_info_offset; - - /* index of next packet to fill with data (ISO transmission) - or next packet containing data recieved (ISO reception) */ - unsigned int first_packet; /* number of packets waiting to be filled with data (ISO transmission) or containing data received (ISO reception) */ - unsigned int n_packets; + __u32 n_packets; /* approximate number of packets dropped due to overflow or underflow of the packet buffer (a value of zero guarantees that no packets have been dropped) */ - unsigned int overflows; -}; - -#ifdef __KERNEL__ + __u32 overflows; -struct iso_block_store { - atomic_t refcount; - size_t data_size; - quadlet_t data[0]; + /* cycle number at which next packet will be transmitted; + -1 if not known */ + __s16 xmit_cycle; }; - -enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, - RAW1394_ISO_RECV = 1, - RAW1394_ISO_XMIT = 2 }; - -struct file_info { - struct list_head list; - - enum { opened, initialized, connected } state; - unsigned int protocol_version; - - struct hpsb_host *host; - - struct list_head req_pending; - struct list_head req_complete; - struct semaphore complete_sem; - spinlock_t reqlists_lock; - wait_queue_head_t poll_wait_complete; - - struct list_head addr_list; - - u8 *fcp_buffer; - - /* old ISO API */ - u64 listen_channels; - quadlet_t *iso_buffer; - size_t iso_buffer_length; - - u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ - - /* new rawiso API */ - enum raw1394_iso_state iso_state; - struct hpsb_iso *iso_handle; -}; - -struct arm_addr { - struct list_head addr_list; /* file_info list */ - u64 start, end; - u64 arm_tag; - u8 access_rights; - u8 notification_options; - u8 client_transactions; - u64 recvb; - u16 rec_length; - u8 *addr_space_buffer; /* accessed by read/write/lock */ -}; - -struct pending_request { - struct list_head list; - struct file_info *file_info; - struct hpsb_packet *packet; - struct iso_block_store *ibs; - quadlet_t *data; - int free_data; - struct raw1394_request req; -}; - -struct host_info { - struct list_head list; - struct hpsb_host *host; - struct list_head file_info_list; -}; - -#endif /* __KERNEL__ */ #endif /* IEEE1394_RAW1394_H */ diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/sbp2.c Mon Feb 17 14:57:27 2003 @@ -296,6 +296,10 @@ * returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one. * 04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG) * 06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG) + * 02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command). + * Also save/restore irq flags in sbp2scsi_complete_command - Sancho Dauskardt + * 02/06/03 - Removed spinlock debugging; use kernel stuff instead (sda) + * */ @@ -346,7 +350,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 697 $ James Goodwin "; + "$Rev: 779 $ James Goodwin "; /* * Module load parameter definitions @@ -488,19 +492,6 @@ #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -/* - * Spinlock debugging stuff. - */ -#define SBP2_USE_REAL_SPINLOCKS - -#ifdef SBP2_USE_REAL_SPINLOCKS -#define sbp2_spin_lock(lock, flags) spin_lock_irqsave(lock, flags) -#define sbp2_spin_unlock(lock, flags) spin_unlock_irqrestore(lock, flags); -static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED; -#else -#define sbp2_spin_lock(lock, flags) do {save_flags(flags); cli();} while (0) -#define sbp2_spin_unlock(lock, flags) do {restore_flags(flags);} while (0) -#endif /* * Globals @@ -512,6 +503,8 @@ static LIST_HEAD(sbp2_host_info_list); +static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED; + static struct hpsb_highlevel *sbp2_hl_handle = NULL; static struct hpsb_highlevel_ops sbp2_hl_ops = { @@ -686,12 +679,12 @@ orbs = sbp2_serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); for (i = 0; i < orbs; i++) { command = (struct sbp2_command_info *) kmalloc(sizeof(struct sbp2_command_info), GFP_KERNEL); if (!command) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return(-ENOMEM); } memset(command, '\0', sizeof(struct sbp2_command_info)); @@ -708,7 +701,7 @@ INIT_LIST_HEAD(&command->list); list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return 0; } @@ -722,7 +715,7 @@ struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) { command = list_entry(lh, struct sbp2_command_info, list); @@ -740,7 +733,7 @@ kfree(command); } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return; } @@ -755,17 +748,17 @@ struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { command = list_entry(lh, struct sbp2_command_info, list); if (command->command_orb_dma == orb) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb); @@ -782,17 +775,17 @@ struct sbp2_command_info *command; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { command = list_entry(lh, struct sbp2_command_info, list); if (command->Current_SCpnt == SCpnt) { - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } } } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return(NULL); } @@ -809,7 +802,7 @@ struct sbp2_command_info *command = NULL; unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { lh = scsi_id->sbp2_command_orb_completed.next; list_del(lh); @@ -820,7 +813,7 @@ } else { SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!"); } - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); } @@ -865,11 +858,11 @@ { unsigned long flags; - sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); list_del(&command->list); sbp2util_free_command_dma(command); list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); - sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); } @@ -992,9 +985,9 @@ /* Complete any pending commands with busy (so they get * retried) and remove them from our queue */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); } /* @@ -1024,9 +1017,9 @@ hi->host = host; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; - sbp2_spin_lock(&sbp2_host_info_lock, flags); + spin_lock_irqsave(&sbp2_host_info_lock, flags); list_add_tail(&hi->list, &sbp2_host_info_list); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + spin_unlock_irqrestore(&sbp2_host_info_lock, flags); /* Register our host with the SCSI stack. */ hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *)); @@ -1085,7 +1078,7 @@ SBP2_DEBUG("sbp2_remove_host"); - sbp2_spin_lock(&sbp2_host_info_lock, flags); + spin_lock_irqsave(&sbp2_host_info_lock, flags); hi = sbp2_find_host_info(host); if (hi != NULL) { @@ -1095,7 +1088,7 @@ else SBP2_ERR("attempt to remove unknown host %p", host); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + spin_unlock_irqrestore(&sbp2_host_info_lock, flags); } /* @@ -2521,16 +2514,16 @@ return(RCODE_ADDRESS_ERROR); } - sbp2_spin_lock(&sbp2_host_info_lock, flags); + spin_lock_irqsave(&sbp2_host_info_lock, flags); hi = sbp2_find_host_info(host); - sbp2_spin_unlock(&sbp2_host_info_lock, flags); + spin_unlock_irqrestore(&sbp2_host_info_lock, flags); if (!hi) { SBP2_ERR("host info is NULL - this is bad!"); return(RCODE_ADDRESS_ERROR); } - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); /* * Find our scsi_id structure by looking at the status fifo address written to by @@ -2541,7 +2534,7 @@ if (!scsi_id) { SBP2_ERR("scsi_id is NULL - device is gone?"); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(RCODE_ADDRESS_ERROR); } @@ -2605,13 +2598,6 @@ } SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); - - /* - * Complete the SCSI command - */ - SBP2_DEBUG("Completing SCSI command"); - sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done); - SBP2_ORB_DEBUG("command orb completed"); } /* @@ -2635,7 +2621,23 @@ } } - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); + + + if (SCpnt) { + + /* + * Complete the SCSI command. + * + * Only do it after we've released the sbp2_command_lock, + * as it might otherwise deadlock with the + * io_request_lock (in sbp2scsi_queuecommand). + */ + SBP2_DEBUG("Completing SCSI command"); + sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done); + SBP2_ORB_DEBUG("command orb completed"); + } + return(RCODE_COMPLETE); } @@ -2715,12 +2717,12 @@ /* * Try and send our SCSI command */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); if (sbp2_send_command(hi, scsi_id, SCpnt, done)) { SBP2_ERR("Error sending SCSI command"); sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done); } - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(0); } @@ -2761,10 +2763,14 @@ /* * This function is called in order to complete a regular SBP-2 command. + * + * This can be called in interrupt context. */ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { + unsigned long flags; + SBP2_DEBUG("sbp2scsi_complete_command"); /* @@ -2864,13 +2870,13 @@ * Tell scsi stack that we're done with this command */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); + spin_lock_irqsave(&io_request_lock,flags); done (SCpnt); - spin_unlock_irq(&io_request_lock); + spin_unlock_irqrestore(&io_request_lock,flags); #else - spin_lock_irq(hi->scsi_host->host_lock); + spin_lock_irqsave(hi->scsi_host->host_lock,flags); done (SCpnt); - spin_unlock_irq(hi->scsi_host->host_lock); + spin_unlock_irqrestore(hi->scsi_host->host_lock,flags); #endif return; @@ -2896,7 +2902,7 @@ * Right now, just return any matching command structures * to the free pool. */ - sbp2_spin_lock(&hi->sbp2_command_lock, flags); + spin_lock_irqsave(&hi->sbp2_command_lock, flags); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); if (command) { SBP2_DEBUG("Found command to abort"); @@ -2921,7 +2927,7 @@ */ sbp2_agent_reset(hi, scsi_id, 0); sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); - sbp2_spin_unlock(&hi->sbp2_command_lock, flags); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); } return(SUCCESS); diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/video1394.c Mon Feb 17 14:57:27 2003 @@ -50,6 +50,7 @@ #include "ieee1394_core.h" #include "highlevel.h" #include "video1394.h" +#include "dma.h" #include "ohci1394.h" @@ -94,9 +95,14 @@ unsigned int packet_size; unsigned int left_size; unsigned int nb_cmd; - unsigned char *buf; + + struct dma_region dma; + + struct dma_prog_region *prg_reg; + struct dma_cmd **ir_prg; struct it_dma_prg **it_prg; + unsigned int *buffer_status; struct timeval *buffer_time; /* time when the buffer was received */ unsigned int *last_used_cmd; /* For ISO Transmit with @@ -159,74 +165,6 @@ static devfs_handle_t devfs_handle; static struct hpsb_highlevel *hl_handle = NULL; -/* Code taken from bttv.c */ - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = virt_to_bus((void *)kva); - return ret; -} - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - -static void * rvmalloc(unsigned long size) -{ - void * mem; - unsigned long adr; - - size=PAGE_ALIGN(size); - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, - no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - mem_map_reserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - unsigned long adr; - - if (mem) - { - adr=(unsigned long) mem; - while ((long) size > 0) - { - mem_map_unreserve(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} -/* End of code taken from bttv.c */ static int free_dma_iso_ctx(struct dma_iso_ctx *d) { @@ -238,20 +176,19 @@ if (d->iso_tasklet.link.next != NULL) ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet); - if (d->buf) - rvfree((void *)d->buf, d->num_desc * d->buf_size); + dma_region_free(&d->dma); - if (d->ir_prg) { - for (i=0;inum_desc;i++) - if (d->ir_prg[i]) kfree(d->ir_prg[i]); - kfree(d->ir_prg); + if (d->prg_reg) { + for (i = 0; i < d->num_desc; i++) + dma_prog_region_free(&d->prg_reg[i]); + kfree(d->prg_reg); } - if (d->it_prg) { - for (i=0;inum_desc;i++) - if (d->it_prg[i]) kfree(d->it_prg[i]); + if (d->ir_prg) + kfree(d->ir_prg); + + if (d->it_prg) kfree(d->it_prg); - } if (d->buffer_status) kfree(d->buffer_status); @@ -291,18 +228,17 @@ d->frame_size = buf_size; d->buf_size = PAGE_ALIGN(buf_size); d->last_buffer = -1; - d->buf = NULL; - d->ir_prg = NULL; init_waitqueue_head(&d->waitq); - d->buf = rvmalloc(d->num_desc * d->buf_size); + /* Init the regions for easy cleanup */ + dma_region_init(&d->dma); - if (d->buf == NULL) { + if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev, + PCI_DMA_BIDIRECTIONAL)) { PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer"); free_dma_iso_ctx(d); return NULL; } - memset(d->buf, 0, d->num_desc * d->buf_size); if (type == OHCI_ISO_RECEIVE) ohci1394_init_iso_tasklet(&d->iso_tasklet, type, @@ -321,6 +257,17 @@ } d->ctx = d->iso_tasklet.context; + d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region), + GFP_KERNEL); + if (d->prg_reg == NULL) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs"); + free_dma_iso_ctx(d); + return NULL; + } + /* Makes for easier cleanup */ + for (i = 0; i < d->num_desc; i++) + dma_prog_region_init(&d->prg_reg[i]); + if (type == OHCI_ISO_RECEIVE) { d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx; d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx; @@ -331,31 +278,27 @@ GFP_KERNEL); if (d->ir_prg == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma ir prg"); + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *)); - + d->nb_cmd = d->buf_size / PAGE_SIZE + 1; d->left_size = (d->frame_size % PAGE_SIZE) ? d->frame_size % PAGE_SIZE : PAGE_SIZE; - for (i=0;inum_desc;i++) { - d->ir_prg[i] = kmalloc(d->nb_cmd * - sizeof(struct dma_cmd), - GFP_KERNEL); - if (d->ir_prg[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma ir prg"); + for (i = 0;i < d->num_desc; i++) { + if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * + sizeof(struct dma_cmd), ohci->dev)) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } + d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt; } - } - else { /* OHCI_ISO_TRANSMIT */ + } else { /* OHCI_ISO_TRANSMIT */ d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx; d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx; d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx; @@ -386,20 +329,17 @@ if (d->frame_size % d->packet_size) { d->nb_cmd++; d->left_size = d->frame_size % d->packet_size; - } - else + } else d->left_size = d->packet_size; - for (i=0;inum_desc;i++) { - d->it_prg[i] = kmalloc(d->nb_cmd * - sizeof(struct it_dma_prg), - GFP_KERNEL); - if (d->it_prg[i] == NULL) { - PRINT(KERN_ERR, ohci->id, - "Failed to allocate dma it prg"); + for (i = 0; i < d->num_desc; i++) { + if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * + sizeof(struct it_dma_prg), ohci->dev)) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg"); free_dma_iso_ctx(d); return NULL; } + d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt; } } @@ -452,7 +392,7 @@ int i; d->ir_prg[n][0].status = cpu_to_le32(4); d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4); - for (i=2;inb_cmd-1;i++) + for (i = 2; i < d->nb_cmd - 1; i++) d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE); d->ir_prg[n][i].status = cpu_to_le32(d->left_size); } @@ -460,7 +400,8 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags) { struct dma_cmd *ir_prg = d->ir_prg[n]; - unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + struct dma_prog_region *ir_reg = &d->prg_reg[n]; + unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size; int i; /* the first descriptor will read only 4 bytes */ @@ -471,31 +412,37 @@ if (flags & VIDEO1394_SYNC_FRAMES) ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT); - ir_prg[0].address = cpu_to_le32(kvirt_to_bus(buf)); - ir_prg[0].branchAddress = cpu_to_le32((virt_to_bus(&(ir_prg[1].control)) - & 0xfffffff0) | 0x1); + ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf - + (unsigned long)d->dma.kvirt)); + ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + 1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); /* the second descriptor will read PAGE_SIZE-4 bytes */ ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH | (PAGE_SIZE-4)); - ir_prg[1].address = cpu_to_le32(kvirt_to_bus(buf+4)); - ir_prg[1].branchAddress = cpu_to_le32((virt_to_bus(&(ir_prg[2].control)) - & 0xfffffff0) | 0x1); + ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) - + (unsigned long)d->dma.kvirt)); + ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + 2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); for (i=2;inb_cmd-1;i++) { ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH | PAGE_SIZE); - ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE)); - - ir_prg[i].branchAddress = - cpu_to_le32((virt_to_bus(&(ir_prg[i+1].control)) - & 0xfffffff0) | 0x1); + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, + (buf+(i-1)*PAGE_SIZE) - + (unsigned long)d->dma.kvirt)); + + ir_prg[i].branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, + (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); } /* the last descriptor will generate an interrupt */ ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size); - ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE)); + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, + (buf+(i-1)*PAGE_SIZE) - + (unsigned long)d->dma.kvirt)); } static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags) @@ -574,7 +521,7 @@ static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d, int n) { - unsigned char* buf = d->buf + n * d->buf_size; + unsigned char* buf = d->dma.kvirt + n * d->buf_size; u32 cycleTimer; u32 timeStamp; @@ -603,7 +550,7 @@ if (n == -1) { return; } - buf = d->buf + n * d->buf_size; + buf = d->dma.kvirt + n * d->buf_size; timeStamp += (d->last_used_cmd[n] << 12) & 0xffff; @@ -650,7 +597,8 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag) { struct it_dma_prg *it_prg = d->it_prg[n]; - unsigned long buf = (unsigned long)d->buf+n*d->buf_size; + struct dma_prog_region *it_reg = &d->prg_reg[n]; + unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size; int i; d->last_used_cmd[n] = d->nb_cmd - 1; for (i=0;inb_cmd;i++) { @@ -674,18 +622,18 @@ it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH); it_prg[i].end.address = - cpu_to_le32(kvirt_to_bus(buf+i*d->packet_size)); + cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) - + (unsigned long)d->dma.kvirt)); if (inb_cmd-1) { it_prg[i].end.control |= cpu_to_le32(d->packet_size); it_prg[i].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); it_prg[i].end.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); - } - else { + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); + } else { /* the last prg generates an interrupt */ it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | DMA_CTL_IRQ | d->left_size); @@ -694,15 +642,6 @@ it_prg[i].end.branchAddress = 0; } it_prg[i].end.status = 0; - -#if 0 - printk("%d:%d: %08x-%08x ctrl %08x brch %08x d0 %08x d1 %08x\n",n,i, - virt_to_bus(&(it_prg[i].begin.control)), - virt_to_bus(&(it_prg[i].end.control)), - it_prg[i].end.control, - it_prg[i].end.branchAddress, - it_prg[i].data[0], it_prg[i].data[1]); -#endif } } @@ -711,6 +650,7 @@ struct ti_ohci *ohci) { struct it_dma_prg *it_prg = d->it_prg[n]; + struct dma_prog_region *it_reg = &d->prg_reg[n]; int i; #if 0 @@ -732,12 +672,12 @@ if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) { it_prg[i].end.control |= cpu_to_le32(size); - it_prg[i].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); - it_prg[i].end.branchAddress = - cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) - & 0xfffffff0) | 0x3); + it_prg[i].begin.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); + it_prg[i].end.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * + sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); } else { /* the last prg generates an interrupt */ it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | @@ -769,37 +709,6 @@ reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<ctx); } -static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d, - struct vm_area_struct *vma) -{ - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long page, pos; - - if (size > d->num_desc * d->buf_size) { - PRINT(KERN_ERR, ohci->id, - "iso context %d buf size is different from mmap size", - d->ctx); - return -EINVAL; - } - if (!d->buf) { - PRINT(KERN_ERR, ohci->id, - "iso context %d is not allocated", d->ctx); - return -EINVAL; - } - - pos = (unsigned long) d->buf; - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range_1394(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - return 0; -} - static int video1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -810,8 +719,8 @@ switch(cmd) { - case VIDEO1394_LISTEN_CHANNEL: - case VIDEO1394_TALK_CHANNEL: + case VIDEO1394_IOC_LISTEN_CHANNEL: + case VIDEO1394_IOC_TALK_CHANNEL: { struct video1394_mmap v; u64 mask; @@ -870,7 +779,7 @@ return -EFAULT; } - if (cmd == VIDEO1394_LISTEN_CHANNEL) { + if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) { d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE, v.nb_buffers, v.buf_size, v.channel, 0); @@ -920,8 +829,8 @@ return 0; } - case VIDEO1394_UNLISTEN_CHANNEL: - case VIDEO1394_UNTALK_CHANNEL: + case VIDEO1394_IOC_UNLISTEN_CHANNEL: + case VIDEO1394_IOC_UNTALK_CHANNEL: { int channel; u64 mask; @@ -945,7 +854,7 @@ /* Mark this channel as unused */ ohci->ISO_channel_usage &= ~mask; - if (cmd == VIDEO1394_UNLISTEN_CHANNEL) + if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL) d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel); else d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); @@ -957,7 +866,7 @@ return 0; } - case VIDEO1394_LISTEN_QUEUE_BUFFER: + case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; @@ -984,10 +893,10 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - if (d->last_buffer>=0) - d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = - cpu_to_le32((virt_to_bus(&(d->ir_prg[v.buffer][0].control)) - & 0xfffffff0) | 0x1); + if (d->last_buffer>=0) + d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) + & 0xfffffff0) | 0x1); d->last_buffer = v.buffer; @@ -1000,9 +909,9 @@ DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->ir_prg[v.buffer][0]))|0x1); - + reg_write(ohci, d->cmdPtr, + dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1); + /* Run IR context */ reg_write(ohci, d->ctrlSet, 0x8000); } @@ -1017,8 +926,8 @@ return 0; } - case VIDEO1394_LISTEN_WAIT_BUFFER: - case VIDEO1394_LISTEN_POLL_BUFFER: + case VIDEO1394_IOC_LISTEN_WAIT_BUFFER: + case VIDEO1394_IOC_LISTEN_POLL_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; @@ -1045,7 +954,7 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; break; case VIDEO1394_BUFFER_QUEUED: - if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) { + if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) { /* for polling, return error code EINTR */ spin_unlock_irqrestore(&d->lock, flags); return -EINTR; @@ -1099,7 +1008,7 @@ return 0; } - case VIDEO1394_TALK_QUEUE_BUFFER: + case VIDEO1394_IOC_TALK_QUEUE_BUFFER: { struct video1394_wait v; struct video1394_queue_variable qv; @@ -1142,18 +1051,16 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - if (d->last_buffer>=0) { + if (d->last_buffer >= 0) { d->it_prg[d->last_buffer] - [ d->last_used_cmd[d->last_buffer] - ].end.branchAddress = - cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) - & 0xfffffff0) | 0x3); + [ d->last_used_cmd[d->last_buffer] ].end.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], + 0) & 0xfffffff0) | 0x3); d->it_prg[d->last_buffer] - [d->last_used_cmd[d->last_buffer] - ].begin.branchAddress = - cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) - & 0xfffffff0) | 0x3); + [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress = + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], + 0) & 0xfffffff0) | 0x3); d->next_buffer[d->last_buffer] = v.buffer; } d->last_buffer = v.buffer; @@ -1170,9 +1077,9 @@ put_timestamp(ohci, d, d->last_buffer); /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - virt_to_bus(&(d->it_prg[v.buffer][0]))|0x3); - + reg_write(ohci, d->cmdPtr, + dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3); + /* Run IT context */ reg_write(ohci, d->ctrlSet, 0x8000); } @@ -1189,7 +1096,7 @@ return 0; } - case VIDEO1394_TALK_WAIT_BUFFER: + case VIDEO1394_IOC_TALK_WAIT_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; @@ -1254,7 +1161,7 @@ if (ctx->current_ctx == NULL) { PRINT(KERN_ERR, ctx->video->ohci->id, "Current iso context not set"); } else - res = do_iso_mmap(ctx->video->ohci, ctx->current_ctx, vma); + res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); unlock_kernel(); return res; diff -Nru a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h --- a/drivers/ieee1394/video1394.h Mon Feb 17 14:57:27 2003 +++ b/drivers/ieee1394/video1394.h Mon Feb 17 14:57:27 2003 @@ -21,6 +21,8 @@ #ifndef _VIDEO_1394_H #define _VIDEO_1394_H +#include "ieee1394-ioctl.h" + #define VIDEO1394_DRIVER_NAME "video1394" #define VIDEO1394_MAX_SIZE 0x4000000 @@ -29,18 +31,6 @@ VIDEO1394_BUFFER_FREE = 0, VIDEO1394_BUFFER_QUEUED, VIDEO1394_BUFFER_READY -}; - -enum { - VIDEO1394_LISTEN_CHANNEL = 0, - VIDEO1394_UNLISTEN_CHANNEL, - VIDEO1394_LISTEN_QUEUE_BUFFER, - VIDEO1394_LISTEN_WAIT_BUFFER, // wait until buffer is ready - VIDEO1394_TALK_CHANNEL, - VIDEO1394_UNTALK_CHANNEL, - VIDEO1394_TALK_QUEUE_BUFFER, - VIDEO1394_TALK_WAIT_BUFFER, - VIDEO1394_LISTEN_POLL_BUFFER // return immediately with -EINTR if not ready }; #define VIDEO1394_SYNC_FRAMES 0x00000001 diff -Nru a/drivers/input/input.c b/drivers/input/input.c --- a/drivers/input/input.c Mon Feb 17 14:57:27 2003 +++ b/drivers/input/input.c Mon Feb 17 14:57:27 2003 @@ -383,7 +383,7 @@ argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]); #endif - value = call_usermodehelper(argv [0], argv, envp); + value = call_usermodehelper(argv [0], argv, envp, 0); kfree(buf); kfree(envp); diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c --- a/drivers/input/serio/sa1111ps2.c Mon Feb 17 14:57:27 2003 +++ b/drivers/input/serio/sa1111ps2.c Mon Feb 17 14:57:27 2003 @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -339,6 +340,7 @@ .drv = { .name = "sa1111-ps2", .bus = &sa1111_bus_type, + .devclass = &input_devclass, .probe = ps2_probe, .remove = ps2_remove, .suspend = ps2_suspend, diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Mon Feb 17 14:57:27 2003 +++ b/drivers/isdn/hardware/eicon/divasmain.c Mon Feb 17 14:57:27 2003 @@ -263,7 +263,7 @@ pdpc->card_failed = 0; argv[2] = &adapter[0]; - ret = call_usermodehelper(argv[0], argv, envp); + ret = call_usermodehelper(argv[0], argv, envp, 0); if (ret) { printk(KERN_ERR diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c --- a/drivers/isdn/hisax/amd7930_fn.c Mon Feb 17 14:57:27 2003 +++ b/drivers/isdn/hisax/amd7930_fn.c Mon Feb 17 14:57:27 2003 @@ -176,7 +176,7 @@ cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state; - /* abort transmit if nessesary */ + /* abort transmit if necessary */ if ((message & 0xf0) && (cs->tx_skb)) { wByteAMD(cs, 0x21, 0xC2); wByteAMD(cs, 0x21, 0x02); diff -Nru a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c --- a/drivers/mtd/chips/jedec.c Mon Feb 17 14:57:27 2003 +++ b/drivers/mtd/chips/jedec.c Mon Feb 17 14:57:27 2003 @@ -754,7 +754,7 @@ size_t *retlen, const u_char *buf) { /* Does IO to the currently selected chip. It takes the bank addressing - base (which is divisable by the chip size) adds the necesary lower bits + base (which is divisible by the chip size) adds the necessary lower bits of addrshift (interleve index) and then adds the control register index. */ #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c --- a/drivers/mtd/maps/sa1100-flash.c Mon Feb 17 14:57:27 2003 +++ b/drivers/mtd/maps/sa1100-flash.c Mon Feb 17 14:57:27 2003 @@ -773,14 +773,15 @@ #ifdef CONFIG_SA1100_TRIZEPS static struct mtd_partition trizeps_partitions[] = { { - .name = "Bootloader & the kernel", - .size = 0x00200000, + .name = "Bootloader", + .size = 0x00100000, .offset = 0, }, { - .name = "Data", - .size = 0x00400000, + .name = "Kernel", + .size = 0x00100000, .offset = MTDPART_OFS_APPEND, }, { + .name = "root", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_APPEND, } @@ -937,7 +938,7 @@ #ifdef CONFIG_SA1100_TRIZEPS if (machine_is_trizeps()) { *parts = trizeps_partitions; - nb_parts = ARRAY_SIZE(trizeps_parititons); + nb_parts = ARRAY_SIZE(trizeps_partitions); } #endif #ifdef CONFIG_SA1100_YOPY diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c Mon Feb 17 14:57:26 2003 +++ b/drivers/net/3c59x.c Mon Feb 17 14:57:26 2003 @@ -1007,6 +1007,7 @@ /* returns count found (>= 0), or negative on error */ static int __init vortex_eisa_init (void) { + int eisa_found = 0; int orig_cards_found = vortex_cards_found; /* Now check all slots of the EISA bus. */ @@ -1014,8 +1015,14 @@ return 0; #ifdef CONFIG_EISA - if (eisa_driver_register (&vortex_eisa_driver) < 0) { - eisa_driver_unregister (&vortex_eisa_driver); + if (eisa_driver_register (&vortex_eisa_driver) >= 0) { + /* Because of the way EISA bus is probed, we cannot assume + * any device have been found when we exit from + * eisa_driver_register (the bus root driver may not be + * initialized yet). So we blindly assume something was + * found, and let the sysfs magic happend... */ + + eisa_found = 1; } #endif @@ -1025,7 +1032,7 @@ compaq_device_id, vortex_cards_found++); } - return vortex_cards_found - orig_cards_found; + return vortex_cards_found - orig_cards_found + eisa_found; } /* returns count (>= 0), or negative on error */ diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c Mon Feb 17 14:57:26 2003 +++ b/drivers/net/8139too.c Mon Feb 17 14:57:26 2003 @@ -1589,7 +1589,7 @@ unsigned long timeout; daemonize("%s", dev->name); - allow_signal(SIGKILL); + allow_signal(SIGTERM); while (1) { timeout = next_tick; diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Mon Feb 17 14:57:28 2003 +++ b/drivers/net/Kconfig Mon Feb 17 14:57:28 2003 @@ -1,3 +1,4 @@ + # # Network device configuration # @@ -213,7 +214,7 @@ the questions about Ethernet network cards. If unsure, say N. config MII - tristate "generic Media Independent Interface device support" + tristate "Generic Media Independent Interface device support" depends on NET_ETHERNET help Most ethernet controllers have MII transceiver either as an external diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c --- a/drivers/net/aironet4500_proc.c Mon Feb 17 14:57:26 2003 +++ b/drivers/net/aironet4500_proc.c Mon Feb 17 14:57:26 2003 @@ -356,41 +356,160 @@ ctl_table awc_exdev_table[] = { - {0, NULL, NULL,0, 0400, NULL}, - {0} + { + .ctl_name = 0, + .maxlen = 0, + .mode = 0400, + }, + { .ctl_name = 0 } }; ctl_table awc_exroot_table[] = { - {254, "aironet4500", NULL, 0, 0555, NULL}, - {0} + { + .ctl_name = 254, + .procname = "aironet4500", + .maxlen = 0, + .mode = 0555, + }, + { .ctl_name = 0 } }; ctl_table awc_driver_proc_table[] = { - {1, "debug" , &awc_debug, sizeof(awc_debug), 0600,NULL, proc_dointvec}, - {2, "bap_sleep" , &bap_sleep, sizeof(bap_sleep), 0600,NULL, proc_dointvec}, - {3, "bap_sleep_after_setup" , &bap_sleep_after_setup, sizeof(bap_sleep_after_setup), 0600,NULL, proc_dointvec}, - {4, "sleep_before_command" , &sleep_before_command, sizeof(sleep_before_command), 0600,NULL, proc_dointvec}, - {5, "bap_sleep_before_write" , &bap_sleep_before_write, sizeof(bap_sleep_before_write), 0600,NULL, proc_dointvec}, - {6, "sleep_in_command" , &sleep_in_command , sizeof(sleep_in_command), 0600,NULL, proc_dointvec}, - {7, "both_bap_lock" , &both_bap_lock , sizeof(both_bap_lock), 0600,NULL, proc_dointvec}, - {8, "bap_setup_spinlock" , &bap_setup_spinlock , sizeof(bap_setup_spinlock), 0600,NULL, proc_dointvec}, - {0} + { + .ctl_name = 1, + .procname = "debug", + .data = &awc_debug, + .maxlen = sizeof(awc_debug), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 2, + .procname = "bap_sleep", + .data = &bap_sleep, + .maxlen = sizeof(bap_sleep), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 3, + .procname = "bap_sleep_after_setup", + .data = &bap_sleep_after_setup, + .maxlen = sizeof(bap_sleep_after_setup), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 4, + .procname = "sleep_before_command", + .data = &sleep_before_command, + .maxlen = sizeof(sleep_before_command), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 5, + .procname = "bap_sleep_before_write", + .data = &bap_sleep_before_write, + .maxlen = sizeof(bap_sleep_before_write), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 6, + .procname = "sleep_in_command", + .data = &sleep_in_command, + .maxlen = sizeof(sleep_in_command), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 7, + .procname = "both_bap_lock", + .data = &both_bap_lock, + .maxlen = sizeof(both_bap_lock), + .mode = 0600, + .proc_handler = proc_dointvec + }, + { + .ctl_name = 8, + .procname = "bap_setup_spinlock", + .data = &bap_setup_spinlock, + .maxlen = sizeof(bap_setup_spinlock), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { .ctl_name = 0 } }; ctl_table awc_driver_level_ctable[] = { - {1, "force_rts_on_shorter" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {2, "force_tx_rate" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {3, "ip_tos_reliability_rts" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {4, "ip_tos_troughput_no_retries", NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {5, "debug" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {6, "simple_bridge" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {7, "p802_11_send" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {8, "full_stats" , NULL, sizeof(int), 0600,NULL, proc_dointvec}, - {0} + { + .ctl_name = 1, + .procname = "force_rts_on_shorter", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 2, + .procname = "force_tx_rate", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 3, + .procname = "ip_tos_reliability_rts", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 4, + .procname = "ip_tos_troughput_no_retries", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 5, + .procname = "debug", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 6, + .procname = "simple_bridge", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 7, + .procname = "p802_11_send", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = 8, + .procname = "full_stats", + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec, + }, + { .ctl_name = 0 } }; ctl_table awc_root_table[] = { - {254, "aironet4500", NULL, 0, 0555, awc_driver_proc_table}, - {0} + { + .ctl_name = 254, + .procname = "aironet4500", + .maxlen = 0, + .mode = 0555, + .child = awc_driver_proc_table, + }, + { .ctl_name = 0 } }; struct ctl_table_header * awc_driver_sysctl_header; diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c --- a/drivers/net/arcnet/com20020-pci.c Mon Feb 17 14:57:27 2003 +++ b/drivers/net/arcnet/com20020-pci.c Mon Feb 17 14:57:27 2003 @@ -1,5 +1,6 @@ /* - * Linux ARCnet driver - COM20020 PCI support (Contemporary Controls PCI20) + * Linux ARCnet driver - COM20020 PCI support + * Contemporary Controls PCI20 and SOHARD SH-ARC PCI * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. @@ -86,7 +87,21 @@ memset(lp, 0, sizeof(struct arcnet_local)); pci_set_drvdata(pdev, dev); - ioaddr = pci_resource_start(pdev, 2); + // SOHARD needs PCI base addr 4 + if (pdev->vendor==0x10B5) { + BUGMSG(D_NORMAL, "SOHARD\n"); + ioaddr = pci_resource_start(pdev, 4); + } + else { + BUGMSG(D_NORMAL, "Contemporary Controls\n"); + ioaddr = pci_resource_start(pdev, 2); + } + + // Dummy access after Reset + // ARCNET controller needs this access to detect bustype + outb(0x00,ioaddr+1); + inb(ioaddr+1); + dev->base_addr = ioaddr; dev->irq = pdev->irq; dev->dev_addr[0] = node; @@ -152,6 +167,7 @@ { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, + { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, {0,} }; diff -Nru a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c --- a/drivers/net/arcnet/com20020.c Mon Feb 17 14:57:27 2003 +++ b/drivers/net/arcnet/com20020.c Mon Feb 17 14:57:27 2003 @@ -98,6 +98,10 @@ lp->setup = lp->clockm ? 0 : (lp->clockp << 1); lp->setup2 = (lp->clockm << 4) | 8; + /* CHECK: should we do this for SOHARD cards ? */ + /* Enable P1Mode for backplane mode */ + lp->setup = lp->setup | P1MODE; + SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -202,7 +206,7 @@ return -ENODEV; } /* reserve the I/O region */ - if (request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { + if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { free_irq(dev->irq, dev); return -EBUSY; } @@ -300,8 +304,9 @@ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int ioaddr = dev->base_addr; - if (open) + if (open) { MOD_INC_USE_COUNT; + } else { /* disable transmitter */ lp->config &= ~TXENcfg; diff -Nru a/drivers/net/arlan-proc.c b/drivers/net/arlan-proc.c --- a/drivers/net/arlan-proc.c Mon Feb 17 14:57:27 2003 +++ b/drivers/net/arlan-proc.c Mon Feb 17 14:57:27 2003 @@ -816,14 +816,18 @@ /* Place files in /proc/sys/dev/arlan */ #define CTBLN(num,card,nam) \ - {num , #nam, &(arlan_conf[card].nam), \ - sizeof(int), 0600, NULL, &proc_dointvec} + { .ctl_name = num,\ + .procname = #nam,\ + .data = &(arlan_conf[card].nam),\ + .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec} #ifdef ARLAN_DEBUGGING -#define ARLAN_PROC_DEBUG_ENTRIES {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \ - sizeof(int), 0600, NULL, &proc_dointvec},\ - {49, "debug", &arlan_debug, \ - sizeof(int), 0600, NULL, &proc_dointvec}, +#define ARLAN_PROC_DEBUG_ENTRIES \ + { .ctl_name = 48, .procname = "entry_exit_debug",\ + .data = &arlan_entry_and_exit_debug,\ + .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec},\ + { .ctl_name = 49, .procname = "debug", .data = &arlan_debug,\ + .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec}, #else #define ARLAN_PROC_DEBUG_ENTRIES #endif @@ -858,8 +862,9 @@ CTBLN(27,cardNo, txTimeoutMs),\ CTBLN(28,cardNo, waitCardTimeout),\ CTBLN(29,cardNo, channelSet), \ - {30, "name", arlan_conf[cardNo].siteName, \ - 16, 0600, NULL, &proc_dostring},\ + {.ctl_name = 30, .procname = "name",\ + .data = arlan_conf[cardNo].siteName,\ + .maxlen = 16, .mode = 0600, .proc_handler = &proc_dostring},\ CTBLN(31,cardNo,waitTime),\ CTBLN(32,cardNo,lParameter),\ CTBLN(33,cardNo,_15),\ @@ -897,22 +902,64 @@ ARLAN_SYSCTL_TABLE_TOTAL(0) #ifdef ARLAN_PROC_SHM_DUMP - {150, "arlan0-txRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, - {151, "arlan0-rxRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, - {152, "arlan0-18", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, - {153, "arlan0-ring", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, - {154, "arlan0-shm-cpy", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, -#endif - {155, "config0", &conf_reset_result, \ - 100, 0400, NULL, &arlan_configure}, \ - {156, "reset0", &conf_reset_result, \ - 100, 0400, NULL, &arlan_sysctl_reset}, \ - {0} + { + .ctl_name = 150, + .procname = "arlan0-txRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_infotxRing, + }, + { + .ctl_name = 151, + .procname = "arlan0-rxRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_inforxRing, + }, + { + .ctl_name = 152, + .procname = "arlan0-18", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info18, + }, + { + .ctl_name = 153, + .procname = "arlan0-ring", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info161719, + }, + { + .ctl_name = 154, + .procname = "arlan0-shm-cpy", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info, + }, +#endif + { + .ctl_name = 155, + .procname = "config0", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_configure + }, + { + .ctl_name = 156, + .procname = "reset0", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_sysctl_reset, + }, + { .ctl_name = 0 } }; static ctl_table arlan_conf_table1[] = @@ -921,22 +968,64 @@ ARLAN_SYSCTL_TABLE_TOTAL(1) #ifdef ARLAN_PROC_SHM_DUMP - {150, "arlan1-txRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, - {151, "arlan1-rxRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, - {152, "arlan1-18", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, - {153, "arlan1-ring", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, - {154, "arlan1-shm-cpy", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, -#endif - {155, "config1", &conf_reset_result, - 100, 0400, NULL, &arlan_configure}, - {156, "reset1", &conf_reset_result, - 100, 0400, NULL, &arlan_sysctl_reset}, - {0} + { + .ctl_name = 150, + .procname = "arlan1-txRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_infotxRing, + }, + { + .ctl_name = 151, + .procname = "arlan1-rxRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_inforxRing, + }, + { + .ctl_name = 152, + .procname = "arlan1-18", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info18, + }, + { + .ctl_name = 153, + .procname = "arlan1-ring", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info161719, + }, + { + .ctl_name = 154, + .procname = "arlan1-shm-cpy", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info, + }, +#endif + { + .ctl_name = 155, + .procname = "config1", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_configure, + }, + { + .ctl_name = 156, + .procname = "reset1", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_sysctl_reset, + }, + { .ctl_name = 0 } }; static ctl_table arlan_conf_table2[] = @@ -945,22 +1034,64 @@ ARLAN_SYSCTL_TABLE_TOTAL(2) #ifdef ARLAN_PROC_SHM_DUMP - {150, "arlan2-txRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, - {151, "arlan2-rxRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, - {152, "arlan2-18", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, - {153, "arlan2-ring", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, - {154, "arlan2-shm-cpy", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, -#endif - {155, "config2", &conf_reset_result, - 100, 0400, NULL, &arlan_configure}, - {156, "reset2", &conf_reset_result, - 100, 0400, NULL, &arlan_sysctl_reset}, - {0} + { + .ctl_name = 150, + .procname = "arlan2-txRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_infotxRing, + }, + { + .ctl_name = 151, + .procname = "arlan2-rxRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_inforxRing, + }, + { + .ctl_name = 152, + .procname = "arlan2-18", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info18, + }, + { + .ctl_name = 153, + .procname = "arlan2-ring", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info161719, + }, + { + .ctl_name = 154, + .procname = "arlan2-shm-cpy", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info, + }, +#endif + { + .ctl_name = 155, + .procname = "config2", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_configure, + }, + { + .ctl_name = 156, + .procname = "reset2", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_sysctl_reset, + }, + { .ctl_name = 0 } }; static ctl_table arlan_conf_table3[] = @@ -969,47 +1100,113 @@ ARLAN_SYSCTL_TABLE_TOTAL(3) #ifdef ARLAN_PROC_SHM_DUMP - {150, "arlan3-txRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, - {151, "arlan3-rxRing", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, - {152, "arlan3-18", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, - {153, "arlan3-ring", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, - {154, "arlan3-shm-cpy", &arlan_drive_info, - ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, -#endif - {155, "config3", &conf_reset_result, - 100, 0400, NULL, &arlan_configure}, - {156, "reset3", &conf_reset_result, - 100, 0400, NULL, &arlan_sysctl_reset}, - {0} + { + .ctl_name = 150, + .procname = "arlan3-txRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_infotxRing, + }, + { + .ctl_name = 151, + .procname = "arlan3-rxRing", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_inforxRing, + }, + { + .ctl_name = 152, + .procname = "arlan3-18", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info18, + }, + { + .ctl_name = 153, + .procname = "arlan3-ring", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info161719, + }, + { + .ctl_name = 154, + .procname = "arlan3-shm-cpy", + .data = &arlan_drive_info, + .maxlen = ARLAN_STR_SIZE, + .mode = 0400, + .proc_handler = &arlan_sysctl_info, + }, +#endif + { + .ctl_name = 155, + .procname = "config3", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_configure, + }, + { + .ctl_name = 156, + .procname = "reset3", + .data = &conf_reset_result, + .maxlen = 100, + .mode = 0400, + .proc_handler = &arlan_sysctl_reset, + }, + { .ctl_name = 0 } }; static ctl_table arlan_table[] = { - {0, "arlan0", NULL, 0, 0600, arlan_conf_table0}, - {0, "arlan1", NULL, 0, 0600, arlan_conf_table1}, - {0, "arlan2", NULL, 0, 0600, arlan_conf_table2}, - {0, "arlan3", NULL, 0, 0600, arlan_conf_table3}, - {0} + { + .ctl_name = 0, + .procname = "arlan0", + .maxlen = 0, + .mode = 0600, + .child = arlan_conf_table0, + }, + { + .ctl_name = 0, + .procname = "arlan1", + .maxlen = 0, + .mode = 0600, + .child = arlan_conf_table1, + }, + { + .ctl_name = 0, + .procname = "arlan2", + .maxlen = 0, + .mode = 0600, + .child = arlan_conf_table2, + }, + { + .ctl_name = 0, + .procname = "arlan3", + .maxlen = 0, + .mode = 0600, + .child = arlan_conf_table3, + }, + { .ctl_name = 0 } }; #else static ctl_table arlan_table[MAX_ARLANS + 1] = { - {0} + { .ctl_name = 0 } }; #endif #else static ctl_table arlan_table[MAX_ARLANS + 1] = { - {0} + { .ctl_name = 0 } }; #endif @@ -1018,8 +1215,14 @@ static ctl_table arlan_root_table[] = { - {254, "arlan", NULL, 0, 0555, arlan_table}, - {0} + { + .ctl_name = 254, + .procname = "arlan", + .maxlen = 0, + .mode = 0555, + .child = arlan_table, + }, + { .ctl_name = 0 } }; /* Make sure that /proc/sys/dev is there */ diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c --- a/drivers/net/hamradio/baycom_epp.c Mon Feb 17 14:57:28 2003 +++ b/drivers/net/hamradio/baycom_epp.c Mon Feb 17 14:57:28 2003 @@ -369,15 +369,14 @@ static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; -static int errno; - -static int exec_eppfpga(void *b) +/* eppconfig: called during ifconfig up to configure the modem */ +static int eppconfig(struct baycom_state *bc) { - struct baycom_state *bc = (struct baycom_state *)b; char modearg[256]; char portarg[16]; - char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg, NULL}; - int i; + char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg, + NULL }; + int ret; /* set up arguments */ sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat", @@ -388,39 +387,7 @@ sprintf(portarg, "%ld", bc->pdev->port->base); printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg); - i = exec_usermodehelper(eppconfig_path, argv, envp); - if (i < 0) { - printk(KERN_ERR "%s: failed to exec %s -s -p %s -m %s, errno = %d\n", - bc_drvname, eppconfig_path, portarg, modearg, i); - return i; - } - return 0; -} - - -/* eppconfig: called during ifconfig up to configure the modem */ - -static int eppconfig(struct baycom_state *bc) -{ - int i, pid, r; - mm_segment_t fs; - - pid = kernel_thread(exec_eppfpga, bc, CLONE_FS); - if (pid < 0) { - printk(KERN_ERR "%s: fork failed, errno %d\n", bc_drvname, -pid); - return pid; - } - fs = get_fs(); - set_fs(KERNEL_DS); /* Allow i to be in kernel space. */ - r = waitpid(pid, &i, __WCLONE); - set_fs(fs); - if (r != pid) { - printk(KERN_ERR "%s: waitpid(%d) failed, returning %d\n", - bc_drvname, pid, r); - return -1; - } - printk(KERN_DEBUG "%s: eppfpga returned %d\n", bc_drvname, i); - return i; + return call_usermodehelper(eppconfig_path, argv, envp, 1); } /* ---------------------------------------------------------------------- */ diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c --- a/drivers/net/rrunner.c Mon Feb 17 14:57:27 2003 +++ b/drivers/net/rrunner.c Mon Feb 17 14:57:27 2003 @@ -255,6 +255,7 @@ iounmap(rr->regs); kfree(dev); pci_release_regions(pdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } } @@ -1128,14 +1129,12 @@ spin_unlock(&rrpriv->lock); } - static void rr_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct rr_private *rrpriv = (struct rr_private *)dev->priv; struct rr_regs *regs = rrpriv->regs; unsigned long flags; - int i; if (readl(®s->HostCtrl) & NIC_HALTED){ printk("%s: Restarting nic\n", dev->name); @@ -1143,23 +1142,8 @@ memset(rrpriv->info, 0, sizeof(struct rr_info)); wmb(); - for (i = 0; i < TX_RING_ENTRIES; i++) { - if (rrpriv->tx_skbuff[i]) { - rrpriv->tx_ring[i].size = 0; - set_rraddr(&rrpriv->tx_ring[i].addr, 0); - dev_kfree_skb(rrpriv->tx_skbuff[i]); - rrpriv->tx_skbuff[i] = NULL; - } - } - - for (i = 0; i < RX_RING_ENTRIES; i++) { - if (rrpriv->rx_skbuff[i]) { - rrpriv->rx_ring[i].size = 0; - set_rraddr(&rrpriv->rx_ring[i].addr, 0); - dev_kfree_skb(rrpriv->rx_skbuff[i]); - rrpriv->rx_skbuff[i] = NULL; - } - } + rr_raz_tx(rrpriv, dev); + rr_raz_rx(rrpriv, dev); if (rr_init1(dev)) { spin_lock_irqsave(&rrpriv->lock, flags); @@ -1246,11 +1230,13 @@ spin_unlock_irqrestore(&rrpriv->lock, flags); if (rrpriv->info) { - kfree(rrpriv->info); + pci_free_consistent(pdev, sizeof(struct rr_info), rrpriv->info, + rrpriv->info_dma); rrpriv->info = NULL; } if (rrpriv->rx_ctrl) { - kfree(rrpriv->rx_ctrl); + pci_free_consistent(pdev, sizeof(struct ring_ctrl), + rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma); rrpriv->rx_ctrl = NULL; } @@ -1413,23 +1399,8 @@ rrpriv->info->evt_ctrl.pi = 0; rrpriv->rx_ctrl[4].entries = 0; - for (i = 0; i < TX_RING_ENTRIES; i++) { - if (rrpriv->tx_skbuff[i]) { - rrpriv->tx_ring[i].size = 0; - set_rraddr(&rrpriv->tx_ring[i].addr, 0); - dev_kfree_skb(rrpriv->tx_skbuff[i]); - rrpriv->tx_skbuff[i] = NULL; - } - } - - for (i = 0; i < RX_RING_ENTRIES; i++) { - if (rrpriv->rx_skbuff[i]) { - rrpriv->rx_ring[i].size = 0; - set_rraddr(&rrpriv->rx_ring[i].addr, 0); - dev_kfree_skb(rrpriv->rx_skbuff[i]); - rrpriv->rx_skbuff[i] = NULL; - } - } + rr_raz_tx(rrpriv, dev); + rr_raz_rx(rrpriv, dev); pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl), rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma); diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Mon Feb 17 14:57:27 2003 +++ b/drivers/net/shaper.c Mon Feb 17 14:57:27 2003 @@ -681,7 +681,7 @@ #ifdef MODULE MODULE_PARM(shapers, "i"); -MODULE_PARM_DESC(shapers, "Traffic shaper: maximum nuber of shapers"); +MODULE_PARM_DESC(shapers, "Traffic shaper: maximum number of shapers"); #else /* MODULE */ diff -Nru a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c --- a/drivers/net/tokenring/proteon.c Mon Feb 17 14:57:28 2003 +++ b/drivers/net/tokenring/proteon.c Mon Feb 17 14:57:28 2003 @@ -322,7 +322,7 @@ * Calling this on a board that does not support it can be a very * dangerous thing. The Madge board, for instance, will lock your * machine hard when this is called. Luckily, its supported in a - * seperate driver. --ASF + * separate driver. --ASF */ static void proteon_read_eeprom(struct net_device *dev) { diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c --- a/drivers/net/via-rhine.c Mon Feb 17 14:57:28 2003 +++ b/drivers/net/via-rhine.c Mon Feb 17 14:57:28 2003 @@ -101,11 +101,18 @@ LK1.1.15 (jgarzik): - Use new MII lib helper generic_mii_ioctl + LK1.1.16 (Roger Luethi) + - Etherleak fix + - Handle Tx buffer underrun + - Fix bugs in full duplex handling + - New reset code uses "force reset" cmd on Rhine-II + - Various clean ups + */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.1.15" -#define DRV_RELDATE "November-22-2002" +#define DRV_VERSION "1.1.16" +#define DRV_RELDATE "February-15-2003" /* A few user-configurable values. @@ -395,7 +402,7 @@ MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, - RxMissed=0x7C, RxCRCErrs=0x7E, + RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC, }; @@ -416,29 +423,15 @@ /* Bits in the interrupt status/mask registers. */ enum intr_status_bits { IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020, - IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0010, + IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210, IntrPCIErr=0x0040, - IntrStatsMax=0x0080, IntrRxEarly=0x0100, IntrMIIChange=0x0200, + IntrStatsMax=0x0080, IntrRxEarly=0x0100, IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, IntrTxAborted=0x2000, IntrLinkChange=0x4000, IntrRxWakeUp=0x8000, IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260, }; -/* MII interface, status flags. - Not to be confused with the MIIStatus register ... */ -enum mii_status_bits { - MIICap100T4 = 0x8000, - MIICap10100HdFd = 0x7800, - MIIPreambleSupr = 0x0040, - MIIAutoNegCompleted = 0x0020, - MIIRemoteFault = 0x0010, - MIICapAutoNeg = 0x0008, - MIILink = 0x0004, - MIIJabber = 0x0002, - MIIExtended = 0x0001 -}; - /* The Rx and Tx buffer descriptors. */ struct rx_desc { s32 rx_status; @@ -533,30 +526,29 @@ static struct net_device_stats *via_rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int via_rhine_close(struct net_device *dev); -static inline void clear_tally_counters(long ioaddr); -static inline void via_restart_tx(struct net_device *dev); static void wait_for_reset(struct net_device *dev, int chip_id, char *name) { long ioaddr = dev->base_addr; - int i; - /* VT86C100A may need long delay after reset (dlink) */ - if (chip_id == VT86C100A) + udelay(5); + + if (readw(ioaddr + ChipCmd) & CmdReset) { + printk(KERN_INFO "%s: Reset did not complete in 5 us. " + "Trying harder.\n", name); + + /* Rhine-II needs to be forced sometimes */ + if (chip_id == VT6102) + writeb(0x40, ioaddr + MiscCmd); + + /* VT86C100A may need long delay after reset (dlink) */ + /* Seen on Rhine-II as well (rl) */ udelay(100); + } - i = 0; - do { - udelay(5); - i++; - if(i > 2000) { - printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", name); - break; - } - } while(readw(ioaddr + ChipCmd) & CmdReset); if (debug > 1) - printk(KERN_INFO "%s: reset finished after %d microseconds.\n", - name, 5*i); + printk(KERN_INFO "%s: Reset %s.\n", name, + (readw(ioaddr + ChipCmd) & CmdReset) ? "failed" : "succeeded"); } #ifdef USE_MEM @@ -742,21 +734,6 @@ if (dev->mem_start) option = dev->mem_start; - /* The lower four bits are the media type. */ - if (option > 0) { - if (option & 0x200) - np->mii_if.full_duplex = 1; - np->default_port = option & 15; - } - if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) - np->mii_if.full_duplex = 1; - - if (np->mii_if.full_duplex) { - printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation" - " disabled.\n", dev->name); - np->mii_if.force_media = 1; - } - /* The chip-specific entries in the device structure. */ dev->open = via_rhine_open; dev->hard_start_xmit = via_rhine_start_tx; @@ -768,11 +745,27 @@ dev->watchdog_timeo = TX_TIMEOUT; if (np->drv_flags & ReqTxAlign) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; - + + /* dev->name not defined before register_netdev()! */ i = register_netdev(dev); if (i) goto err_out_unmap; + /* The lower four bits are the media type. */ + if (option > 0) { + if (option & 0x220) + np->mii_if.full_duplex = 1; + np->default_port = option & 15; + } + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + np->mii_if.full_duplex = 1; + + if (np->mii_if.full_duplex) { + printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation" + " disabled.\n", dev->name); + np->mii_if.force_media = 1; + } + printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, via_rhine_chip_info[chip_id].name, (pci_flags & PCI_USES_IO) ? ioaddr : memaddr); @@ -797,7 +790,7 @@ mdio_read(dev, phy, 5)); /* set IFF_RUNNING */ - if (mii_status & MIILink) + if (mii_status & BMSR_LSTATUS) netif_carrier_on(dev); else netif_carrier_off(dev); @@ -1008,6 +1001,7 @@ writeb(0x20, ioaddr + TxConfig); np->tx_thresh = 0x20; np->rx_thresh = 0x60; /* Written in via_rhine_set_rx_mode(). */ + np->mii_if.full_duplex = 0; if (dev->if_port == 0) dev->if_port = np->default_port; @@ -1021,7 +1015,7 @@ writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | IntrRxDropped | IntrRxNoBuf | IntrTxAborted | IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange | IntrMIIChange, + IntrPCIErr | IntrStatsMax | IntrLinkChange, ioaddr + IntrEnable); np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll; @@ -1175,8 +1169,8 @@ /* make IFF_RUNNING follow the MII status bit "Link established" */ mii_status = mdio_read(dev, np->phys[0], MII_BMSR); - if ( (mii_status & MIILink) != (np->mii_status & MIILink) ) { - if (mii_status & MIILink) + if ( (mii_status & BMSR_LSTATUS) != (np->mii_status & BMSR_LSTATUS) ) { + if (mii_status & BMSR_LSTATUS) netif_carrier_on(dev); else netif_carrier_off(dev); @@ -1326,7 +1320,7 @@ via_rhine_tx(dev); /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & (IntrPCIErr | IntrLinkChange | IntrMIIChange | + if (intr_status & (IntrPCIErr | IntrLinkChange | IntrStatsMax | IntrTxError | IntrTxAborted | IntrTxUnderrun)) via_rhine_error(dev, intr_status); @@ -1414,8 +1408,8 @@ int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; if (debug > 4) { - printk(KERN_DEBUG " In via_rhine_rx(), entry %d status %8.8x.\n", - entry, le32_to_cpu(np->rx_head_desc->rx_status)); + printk(KERN_DEBUG "%s: via_rhine_rx(), entry %d status %8.8x.\n", + dev->name, entry, le32_to_cpu(np->rx_head_desc->rx_status)); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ @@ -1521,7 +1515,18 @@ writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd); } -static inline void via_restart_tx(struct net_device *dev) { +/* Clears the "tally counters" for CRC errors and missed frames(?). + It has been reported that some chips need a write of 0 to clear + these, for others the counters are set to 1 when written to and + instead cleared when read. So we clear them both ways ... */ +static inline void clear_tally_counters(const long ioaddr) +{ + writel(0, ioaddr + RxMissed); + readw(ioaddr + RxCRCErrs); + readw(ioaddr + RxMissed); +} + +static inline void via_rhine_restart_tx(struct net_device *dev) { struct netdev_private *np = dev->priv; int entry = np->dirty_tx % TX_RING_SIZE; @@ -1539,7 +1544,7 @@ spin_lock (&np->lock); - if (intr_status & (IntrMIIChange | IntrLinkChange)) { + if (intr_status & (IntrLinkChange)) { if (readb(ioaddr + MIIStatus) & 0x02) { /* Link failed, restart autonegotiation. */ if (np->drv_flags & HasDavicomPhy) @@ -1557,11 +1562,11 @@ np->stats.rx_missed_errors += readw(ioaddr + RxMissed); clear_tally_counters(ioaddr); } - if (intr_status & IntrTxError) { + if (intr_status & IntrTxAborted) { if (debug > 1) printk(KERN_INFO "%s: Abort %4.4x, frame dropped.\n", dev->name, intr_status); - via_restart_tx(dev); + via_rhine_restart_tx(dev); } if (intr_status & IntrTxUnderrun) { if (np->tx_thresh < 0xE0) @@ -1570,9 +1575,9 @@ printk(KERN_INFO "%s: Transmitter underrun, Tx " "threshold now %2.2x.\n", dev->name, np->tx_thresh); - via_restart_tx(dev); + via_rhine_restart_tx(dev); } - if (intr_status & ~( IntrLinkChange | IntrStatsMax | + if (intr_status & ~( IntrLinkChange | IntrStatsMax | IntrTxUnderrun | IntrTxError | IntrTxAborted | IntrNormalSummary)) { if (debug > 1) printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", @@ -1597,17 +1602,6 @@ spin_unlock_irqrestore(&np->lock, flags); return &np->stats; -} - -/* Clears the "tally counters" for CRC errors and missed frames(?). - It has been reported that some chips need a write of 0 to clear - these, for others the counters are set to 1 when written to and - instead cleared when read. So we clear them both ways ... */ -static inline void clear_tally_counters(const long ioaddr) -{ - writel(0, ioaddr + RxMissed); - readw(ioaddr + RxCRCErrs); - readw(ioaddr + RxMissed); } static void via_rhine_set_rx_mode(struct net_device *dev) diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c --- a/drivers/parisc/eisa.c Mon Feb 17 14:57:26 2003 +++ b/drivers/parisc/eisa.c Mon Feb 17 14:57:26 2003 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,7 @@ static struct eisa_ba { struct pci_hba_data hba; unsigned long eeprom_addr; + struct eisa_root_device root; } eisa_dev; /* Port ops */ @@ -376,6 +378,18 @@ eisa_eeprom_init(eisa_dev.eeprom_addr); eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space); init_eisa_pic(); + + /* FIXME : Get the number of slots from the enumerator, not a + * hadcoded value. Also don't enumerate the bus twice. */ + eisa_dev.root.dev = &dev->dev; + dev->dev.driver_data = &eisa_dev.root; + eisa_dev.root.bus_base_addr = 0; + eisa_dev.root.res = &eisa_dev.hba.io_space; + eisa_dev.root.slots = EISA_MAX_SLOTS; + if (eisa_root_register (&eisa_dev.root)) { + printk(KERN_ERR "EISA: Failed to register EISA root\n"); + return -1; + } return 0; } diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Mon Feb 17 14:57:27 2003 +++ b/drivers/pci/pci.c Mon Feb 17 14:57:27 2003 @@ -592,7 +592,7 @@ * function. Originally copied from drivers/net/acenic.c. * Copyright 1998-2001 by Jes Sorensen, . * - * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ static int pci_generic_prep_mwi(struct pci_dev *dev) @@ -634,7 +634,7 @@ * and then calls @pcibios_set_mwi to do the needed arch specific * operations or a generic mwi-prep function. * - * RETURNS: An appriopriate -ERRNO error value on eror, or zero for success. + * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ int pci_set_mwi(struct pci_dev *dev) diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Mon Feb 17 14:57:26 2003 +++ b/drivers/pci/quirks.c Mon Feb 17 14:57:26 2003 @@ -535,6 +535,15 @@ } } +/* This was originally an Alpha specific thing, but it really fits here. + * The i82375 PCI/EISA bridge appears as non-classified. Fix that. + */ + +static void __init quirk_eisa_bridge(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_EISA << 8; +} + /* * The main table of quirks. */ @@ -604,6 +613,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge }, { 0 } }; diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Mon Feb 17 14:57:27 2003 +++ b/drivers/pcmcia/cs.c Mon Feb 17 14:57:27 2003 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -308,119 +309,123 @@ static void unreset_socket(socket_info_t *); static void parse_events(void *info, u_int events); -socket_info_t *pcmcia_register_socket (int slot, - struct pccard_operations * ss_entry, - int use_bus_pm) -{ - socket_info_t *s; - int i; +#define to_class_data(dev) dev->class_data - DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", ss_entry); - - s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL); - if (!s) - return NULL; - memset(s, 0, sizeof(socket_info_t)); - - s->ss_entry = ss_entry; - s->sock = slot; - - /* base address = 0, map = 0 */ - s->cis_mem.flags = 0; - s->cis_mem.speed = cis_speed; - s->use_bus_pm = use_bus_pm; - s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; - spin_lock_init(&s->lock); - - for (i = 0; i < sockets; i++) - if (socket_table[i] == NULL) break; - socket_table[i] = s; - if (i == sockets) sockets++; +/** + * pcmcia_register_socket - add a new pcmcia socket device + */ +int pcmcia_register_socket(struct device *dev) +{ + struct pcmcia_socket_class_data *cls_d = to_class_data(dev); + socket_info_t *s_info; + unsigned int i, j; + + if (!cls_d) + return -EINVAL; + + DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops); + + s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL); + if (!s_info) + return -ENOMEM; + memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t)); + + /* socket initialization */ + for (i = 0; i < cls_d->nsock; i++) { + socket_info_t *s = &s_info[i]; + + cls_d->s_info[i] = s; + s->ss_entry = cls_d->ops; + s->sock = i; + + /* base address = 0, map = 0 */ + s->cis_mem.flags = 0; + s->cis_mem.speed = cis_speed; + s->use_bus_pm = cls_d->use_bus_pm; + s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; + spin_lock_init(&s->lock); + + /* TBD: remove usage of socket_table, use class_for_each_dev instead */ + for (j = 0; j < sockets; j++) + if (socket_table[j] == NULL) break; + socket_table[j] = s; + if (j == sockets) sockets++; - init_socket(s); - ss_entry->inquire_socket(slot, &s->cap); + init_socket(s); + s->ss_entry->inquire_socket(i, &s->cap); #ifdef CONFIG_PROC_FS - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", i); - s->proc = proc_mkdir(name, proc_pccard); - if (s->proc) - ss_entry->proc_setup(slot, s->proc); + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", j); + s->proc = proc_mkdir(name, proc_pccard); + if (s->proc) + s->ss_entry->proc_setup(i, s->proc); #ifdef PCMCIA_DEBUG - if (s->proc) - create_proc_read_entry("clients", 0, s->proc, - proc_read_clients, s); + if (s->proc) + create_proc_read_entry("clients", 0, s->proc, + proc_read_clients, s); #endif - } + } #endif - return s; + } + return 0; } /* pcmcia_register_socket */ -int register_ss_entry(int nsock, struct pccard_operations * ss_entry) -{ - int ns; - - DEBUG(0, "cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry); - - for (ns = 0; ns < nsock; ns++) { - pcmcia_register_socket (ns, ss_entry, 0); - } - - return 0; -} /* register_ss_entry */ - -/*====================================================================*/ -void pcmcia_unregister_socket(socket_info_t *s) +/** + * pcmcia_unregister_socket - remove a pcmcia socket device + */ +void pcmcia_unregister_socket(struct device *dev) { - int j, socket = -1; - client_t *client; + struct pcmcia_socket_class_data *cls_d = to_class_data(dev); + unsigned int i; + int j, socket = -1; + client_t *client; + socket_info_t *s; - for (j = 0; j < MAX_SOCK; j++) - if (socket_table [j] == s) { - socket = j; - break; - } - if (socket < 0) - return; + if (!cls_d) + return; + + s = (socket_info_t *) cls_d->s_info; + for (i = 0; i < cls_d->nsock; i++) { + for (j = 0; j < MAX_SOCK; j++) + if (socket_table [j] == s) { + socket = j; + break; + } + if (socket < 0) + continue; + #ifdef CONFIG_PROC_FS - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", socket); + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", socket); #ifdef PCMCIA_DEBUG - remove_proc_entry("clients", s->proc); + remove_proc_entry("clients", s->proc); #endif - remove_proc_entry(name, proc_pccard); - } + remove_proc_entry(name, proc_pccard); + } #endif + + shutdown_socket(s); + release_cis_mem(s); + while (s->clients) { + client = s->clients; + s->clients = s->clients->next; + kfree(client); + } + s->ss_entry = NULL; + socket_table[socket] = NULL; + for (j = socket; j < sockets-1; j++) + socket_table[j] = socket_table[j+1]; + sockets--; - shutdown_socket(s); - release_cis_mem(s); - while (s->clients) { - client = s->clients; - s->clients = s->clients->next; - kfree(client); - } - s->ss_entry = NULL; - kfree(s); - - socket_table[socket] = NULL; - for (j = socket; j < sockets-1; j++) - socket_table[j] = socket_table[j+1]; - sockets--; + s++; + } + kfree(cls_d->s_info); } /* pcmcia_unregister_socket */ -void unregister_ss_entry(struct pccard_operations * ss_entry) -{ - int i; - - for (i = sockets-1; i >= 0; i-- ) { - socket_info_t *socket = socket_table[i]; - if (socket->ss_entry == ss_entry) - pcmcia_unregister_socket (socket); - } -} /* unregister_ss_entry */ /*====================================================================== @@ -2402,8 +2407,6 @@ EXPORT_SYMBOL(pcmcia_write_memory); EXPORT_SYMBOL(dead_socket); -EXPORT_SYMBOL(register_ss_entry); -EXPORT_SYMBOL(unregister_ss_entry); EXPORT_SYMBOL(CardServices); EXPORT_SYMBOL(MTDHelperEntry); #ifdef CONFIG_PROC_FS @@ -2415,16 +2418,26 @@ EXPORT_SYMBOL(pcmcia_suspend_socket); EXPORT_SYMBOL(pcmcia_resume_socket); +struct device_class pcmcia_socket_class = { + .name = "pcmcia_socket", + .add_device = &pcmcia_register_socket, + .remove_device = &pcmcia_unregister_socket, +}; +EXPORT_SYMBOL(pcmcia_socket_class); + + static int __init init_pcmcia_cs(void) { printk(KERN_INFO "%s\n", release); printk(KERN_INFO " %s\n", options); DEBUG(0, "%s\n", version); + devclass_register(&pcmcia_socket_class); if (do_apm) pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event); #ifdef CONFIG_PROC_FS proc_pccard = proc_mkdir("pccard", proc_bus); #endif + return 0; } @@ -2439,9 +2452,10 @@ if (do_apm) pm_unregister_all(handle_pm_event); release_resource_db(); + devclass_unregister(&pcmcia_socket_class); } -module_init(init_pcmcia_cs); +subsys_initcall(init_pcmcia_cs); module_exit(exit_pcmcia_cs); /*====================================================================*/ diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Mon Feb 17 14:57:27 2003 +++ b/drivers/pcmcia/hd64465_ss.c Mon Feb 17 14:57:27 2003 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -960,6 +961,10 @@ hs_reset_socket(sp, 1); + printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n", + i, sp->mem_base, sp->irq, + sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr); + return 0; } @@ -990,6 +995,24 @@ vfree(sp->io_vma->addr); } +static struct pcmcia_socket_class_data hd64465_data = { + .nsock = HS_MAX_SOCKETS, + .ops = &hs_operations, +}; + +static struct device_driver hd64465_driver = { + .name = "hd64465-pcmcia", + .bus = &platform_bus_type, + .devclass = &pcmcia_socket_class, +}; + +static struct platform_device hd64465_device = { + .name = "hd64465-pcmcia", + .id = 0, + .dev = { + .name = "hd64465-pcmcia", + }, +}; static int __init init_hs(void) { @@ -1007,6 +1030,7 @@ } /* hd64465_io_debug = 1; */ + register_driver(&hd64465_driver); /* Wake both sockets out of STANDBY mode */ /* TODO: wait 15ms */ @@ -1036,34 +1060,24 @@ HD64465_IRQ_PCMCIA0, HD64465_PCC0_BASE, HD64465_REG_PCC0ISR); - if (i < 0) - return i; + if (i < 0) { + unregister_driver(&hd64465_driver); + return i; + } i = hs_init_socket(&hs_sockets[1], HD64465_IRQ_PCMCIA1, HD64465_PCC1_BASE, HD64465_REG_PCC1ISR); - if (i < 0) - return i; - -/* hd64465_io_debug = 0; */ - - - if (register_ss_entry(HS_MAX_SOCKETS, &hs_operations) != 0) { - for (i=0 ; imem_base, sp->irq, - sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr); - } +/* hd64465_io_debug = 0; */ + platform_device_register(&hd64465_device); + hd64465_device.dev.class_data = &hd64465_data; - return 0; + return 0; } static void __exit exit_hs(void) @@ -1078,9 +1092,10 @@ */ for (i=0 ; i #include #include +#include #include #include @@ -46,6 +47,9 @@ .id_table = i82092aa_pci_ids, .probe = i82092aa_pci_probe, .remove = __devexit_p(i82092aa_pci_remove), + .driver = { + .devclass = &pcmcia_socket_class, + }, }; @@ -93,6 +97,7 @@ { unsigned char configbyte; int i, ret; + struct pcmcia_socket_class_data *cls_d; enter("i82092aa_pci_probe"); @@ -150,11 +155,17 @@ printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq); goto err_out_free_res; } - - if ((ret = register_ss_entry(socket_count, &i82092aa_operations) != 0)) { - printk(KERN_ERR "i82092aa: register_ss_entry() failed\n"); + + + cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL); + if (!cls_d) { + printk(KERN_ERR "i82092aa: kmalloc failed\n"); goto err_out_free_irq; } + memset(cls_d, 0, sizeof(*cls_d)); + cls_d->nsock = socket_count; + cls_d->ops = &i82092aa_operations; + dev->dev.class_data = cls_d; leave("i82092aa_pci_probe"); return 0; @@ -173,6 +184,8 @@ enter("i82092aa_pci_remove"); free_irq(dev->irq, i82092aa_interrupt); + if (dev->dev.class_data) + kfree(dev->dev.class_data); leave("i82092aa_pci_remove"); } @@ -903,7 +916,6 @@ { enter("i82092aa_module_exit"); pci_unregister_driver(&i82092aa_pci_drv); - unregister_ss_entry(&i82092aa_operations); if (sockets[0].io_base>0) release_region(sockets[0].io_base, 2); leave("i82092aa_module_exit"); diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Mon Feb 17 14:57:28 2003 +++ b/drivers/pcmcia/i82365.c Mon Feb 17 14:57:28 2003 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1583,6 +1584,24 @@ /*====================================================================*/ +static struct pcmcia_socket_class_data i82365_data = { + .ops = &pcic_operations, +}; + +static struct device_driver i82365_driver = { + .name = "i82365", + .bus = &platform_bus_type, + .devclass = &pcmcia_socket_class, +}; + +static struct platform_device i82365_device = { + .name = "i82365", + .id = 0, + .dev = { + .name = "i82365", + }, +}; + static int __init init_i82365(void) { servinfo_t serv; @@ -1595,6 +1614,7 @@ DEBUG(0, "%s\n", version); printk(KERN_INFO "Intel PCIC probe: "); sockets = 0; + driver_register(&i82365_driver); #ifdef CONFIG_ISA isa_probe(); @@ -1602,6 +1622,7 @@ if (sockets == 0) { printk("not found.\n"); + driver_unregister(&i82365_driver); return -ENODEV; } @@ -1611,9 +1632,11 @@ request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); #endif - if (register_ss_entry(sockets, &pcic_operations) != 0) - printk(KERN_NOTICE "i82365: register_ss_entry() failed\n"); + platform_device_register(&i82365_device); + i82365_data.nsock = sockets; + i82365_device.dev.class_data = &i82365_data; + /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { poll_timer.function = pcic_interrupt_wrapper; @@ -1633,7 +1656,7 @@ #ifdef CONFIG_PROC_FS for (i = 0; i < sockets; i++) pcic_proc_remove(i); #endif - unregister_ss_entry(&pcic_operations); + platform_device_unregister(&i82365_device); if (poll_interval != 0) del_timer_sync(&poll_timer); #ifdef CONFIG_ISA @@ -1649,6 +1672,7 @@ if (i82365_pnpdev) pnp_disable_dev(i82365_pnpdev); #endif + driver_unregister(&i82365_driver); } /* exit_i82365 */ module_init(init_i82365); diff -Nru a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c --- a/drivers/pcmcia/pci_socket.c Mon Feb 17 14:57:28 2003 +++ b/drivers/pcmcia/pci_socket.c Mon Feb 17 14:57:28 2003 @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -30,9 +31,6 @@ #include "pci_socket.h" -extern struct socket_info_t *pcmcia_register_socket (int slot, - struct pccard_operations *vtable, int use_bus_pm); -extern void pcmcia_unregister_socket (struct socket_info_t *socket); extern void pcmcia_suspend_socket (struct socket_info_t *socket); extern void pcmcia_resume_socket (struct socket_info_t *socket); @@ -189,11 +187,21 @@ return err; } -void cardbus_register(pci_socket_t *socket) +int cardbus_register(struct pci_dev *p_dev) { - int nr = socket - pci_socket_array; + pci_socket_t *socket = pci_get_drvdata(p_dev); + struct pcmcia_socket_class_data *cls_d; - socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1); + if (!socket) + return -EINVAL; + + cls_d = &socket->cls_d; + cls_d->nsock = 1; /* yenta is 1, no other low-level driver uses + this yet */ + cls_d->ops = &pci_socket_operations; + cls_d->use_bus_pm = 1; + p_dev->dev.class_data = cls_d; + return 0; } static int __devinit @@ -213,7 +221,7 @@ { pci_socket_t *socket = pci_get_drvdata(dev); - pcmcia_unregister_socket (socket->pcmcia_socket); + /* note: we are already unregistered from the cs core */ if (socket->op && socket->op->close) socket->op->close(socket); pci_set_drvdata(dev, NULL); @@ -253,11 +261,14 @@ .remove = __devexit_p(cardbus_remove), .suspend = cardbus_suspend, .resume = cardbus_resume, + .driver = { + .devclass = &pcmcia_socket_class, + }, }; static int __init pci_socket_init(void) { - return pci_module_init (&pci_cardbus_driver); + return pci_register_driver (&pci_cardbus_driver); } static void __exit pci_socket_exit (void) diff -Nru a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h --- a/drivers/pcmcia/pci_socket.h Mon Feb 17 14:57:27 2003 +++ b/drivers/pcmcia/pci_socket.h Mon Feb 17 14:57:27 2003 @@ -24,6 +24,7 @@ struct work_struct tq_task; struct timer_list poll_timer; + struct pcmcia_socket_class_data cls_d; /* A few words of private data for the low-level driver.. */ unsigned int private[8]; } pci_socket_t; diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Mon Feb 17 14:57:27 2003 +++ b/drivers/pcmcia/tcic.c Mon Feb 17 14:57:27 2003 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -375,6 +376,24 @@ /*====================================================================*/ +static struct pcmcia_socket_class_data tcic_data = { + .ops = &tcic_operations, +}; + +static struct device_driver tcic_driver = { + .name = "tcic-pcmcia", + .bus = &platform_bus_type, + .devclass = &pcmcia_socket_class, +}; + +static struct platform_device tcic_device = { + .name = "tcic-pcmcia", + .id = 0, + .dev = { + .name = "tcic-pcmcia", + }, +}; + static int __init init_tcic(void) { int i, sock; @@ -388,12 +407,15 @@ "does not match!\n"); return -1; } + + driver_register(&tcic_driver); printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: "); sock = 0; if (!request_region(tcic_base, 16, "tcic-2")) { printk("could not allocate ports,\n "); + driver_unregister(&tcic_driver); return -ENODEV; } else { @@ -416,6 +438,7 @@ if (sock == 0) { printk("not found.\n"); release_region(tcic_base, 16); + driver_unregister(&tcic_driver); return -ENODEV; } @@ -429,6 +452,8 @@ sockets++; } + platform_device_register(&tcic_device); + switch (socket_table[0].id) { case TCIC_ID_DB86082: printk("DB86082"); break; @@ -499,13 +524,8 @@ /* jump start interrupt handler, if needed */ tcic_interrupt(0, NULL, NULL); - if (register_ss_entry(sockets, &tcic_operations) != 0) { - printk(KERN_NOTICE "tcic: register_ss_entry() failed\n"); - release_region(tcic_base, 16); - if (cs_irq != 0) - free_irq(cs_irq, tcic_interrupt); - return -ENODEV; - } + tcic_data.nsock = sockets; + tcic_device.dev.class_data = &tcic_data; return 0; @@ -515,13 +535,14 @@ static void __exit exit_tcic(void) { - unregister_ss_entry(&tcic_operations); del_timer_sync(&poll_timer); if (cs_irq != 0) { tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00); free_irq(cs_irq, tcic_interrupt); } release_region(tcic_base, 16); + platform_device_unregister(&tcic_device); + driver_unregister(&tcic_driver); } /* exit_tcic */ /*====================================================================*/ diff -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c --- a/drivers/pcmcia/yenta.c Mon Feb 17 14:57:27 2003 +++ b/drivers/pcmcia/yenta.c Mon Feb 17 14:57:27 2003 @@ -577,39 +577,6 @@ printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq); } -extern void cardbus_register(pci_socket_t *socket); - -/* - * 'Bottom half' for the yenta_open routine. Allocate the interrupt line - * and register the socket with the upper layers. - */ -static void yenta_open_bh(void * data) -{ - pci_socket_t * socket = (pci_socket_t *) data; - - /* It's OK to overwrite this now */ - INIT_WORK(&socket->tq_task, yenta_bh, socket); - - if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { - /* No IRQ or request_irq failed. Poll */ - socket->cb_irq = 0; /* But zero is a valid IRQ number. */ - init_timer(&socket->poll_timer); - socket->poll_timer.function = yenta_interrupt_wrapper; - socket->poll_timer.data = (unsigned long)socket; - socket->poll_timer.expires = jiffies + HZ; - add_timer(&socket->poll_timer); - } - - /* Figure out what the dang thing can do for the PCMCIA layer... */ - yenta_get_socket_capabilities(socket, isa_interrupts); - printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); - - /* Register it with the pcmcia layer.. */ - cardbus_register(socket); - - MOD_DEC_USE_COUNT; -} - static void yenta_clear_maps(pci_socket_t *socket) { int i; @@ -881,6 +848,9 @@ #define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct)) + +extern int cardbus_register(struct pci_dev *p_dev); + /* * Initialize a cardbus controller. Make sure we have a usable * interrupt, and that we can map the cardbus area. Fill in the @@ -932,16 +902,26 @@ } } - /* Get the PCMCIA kernel thread to complete the - initialisation later. We can't do this here, - because, er, because Linus says so :) - */ - INIT_WORK(&socket->tq_task, yenta_open_bh, socket); + /* We must finish initialization here */ - MOD_INC_USE_COUNT; - schedule_work(&socket->tq_task); + INIT_WORK(&socket->tq_task, yenta_bh, socket); - return 0; + if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { + /* No IRQ or request_irq failed. Poll */ + socket->cb_irq = 0; /* But zero is a valid IRQ number. */ + init_timer(&socket->poll_timer); + socket->poll_timer.function = yenta_interrupt_wrapper; + socket->poll_timer.data = (unsigned long)socket; + socket->poll_timer.expires = jiffies + HZ; + add_timer(&socket->poll_timer); + } + + /* Figure out what the dang thing can do for the PCMCIA layer... */ + yenta_get_socket_capabilities(socket, isa_interrupts); + printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); + + /* Register it with the pcmcia layer.. */ + return cardbus_register(dev); } /* diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c --- a/drivers/pnp/pnpbios/core.c Mon Feb 17 14:57:26 2003 +++ b/drivers/pnp/pnpbios/core.c Mon Feb 17 14:57:26 2003 @@ -602,7 +602,7 @@ info->location_id, info->serial, info->capabilities); envp[i] = 0; - value = call_usermodehelper (argv [0], argv, envp); + value = call_usermodehelper (argv [0], argv, envp, 0); kfree (buf); kfree (envp); return 0; diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c --- a/drivers/s390/block/dasd_eckd.c Mon Feb 17 14:57:26 2003 +++ b/drivers/s390/block/dasd_eckd.c Mon Feb 17 14:57:26 2003 @@ -1195,7 +1195,7 @@ rc = dasd_sleep_on_immediatly(cqr); if (rc == -EIO) { - /* Request got an eror or has been timed out. */ + /* Request got an error or has been timed out. */ dasd_eckd_release(bdev, no, args); } dasd_kfree_request(cqr, cqr->device); @@ -1238,7 +1238,7 @@ rc = dasd_sleep_on_immediatly(cqr); if (rc == -EIO) { - /* Request got an eror or has been timed out. */ + /* Request got an error or has been timed out. */ dasd_eckd_release(bdev, no, args); } dasd_kfree_request(cqr, cqr->device); diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Mon Feb 17 14:57:27 2003 +++ b/drivers/scsi/NCR53C9x.c Mon Feb 17 14:57:27 2003 @@ -356,7 +356,7 @@ Scsi_Cmnd *ptr, *prev; for(ptr = *SC, prev = NULL; - ptr && ((ptr->target != target) || (ptr->lun != lun)); + ptr && ((ptr->device->id != target) || (ptr->device->lun != lun)); prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) ; if(ptr) { @@ -946,7 +946,7 @@ static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp) { - struct esp_pointers *ep = &esp->data_pointers[sp->target]; + struct esp_pointers *ep = &esp->data_pointers[sp->device->id]; sp->SCp.ptr = ep->saved_ptr; sp->SCp.buffer = ep->saved_buffer; @@ -956,7 +956,7 @@ static void esp_save_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp) { - struct esp_pointers *ep = &esp->data_pointers[sp->target]; + struct esp_pointers *ep = &esp->data_pointers[sp->device->id]; ep->saved_ptr = sp->SCp.ptr; ep->saved_buffer = sp->SCp.buffer; @@ -1037,8 +1037,8 @@ SDptr = SCptr->device; esp_dev = SDptr->hostdata; - lun = SCptr->lun; - target = SCptr->target; + lun = SCptr->device->lun; + target = SCptr->device->id; esp->snip = 0; esp->msgout_len = 0; @@ -1249,7 +1249,7 @@ SCpnt->scsi_done = done; SCpnt->SCp.phase = not_issued; - esp = (struct NCR_ESP *) SCpnt->host->hostdata; + esp = (struct NCR_ESP *) SCpnt->device->host->hostdata; if(esp->dma_led_on) esp->dma_led_on(esp); @@ -1285,7 +1285,7 @@ int esp_command(Scsi_Cmnd *SCpnt) { #ifdef DEBUG_ESP - struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->host->hostdata; + struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->device->host->hostdata; #endif ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id)); @@ -1297,7 +1297,7 @@ { ESPLOG(("[tgt<%02x> lun<%02x> " "pphase<%s> cphase<%s>]", - SCptr->target, SCptr->lun, + SCptr->device->id, SCptr->device->lun, phase_string(SCptr->SCp.sent_command), phase_string(SCptr->SCp.phase))); } @@ -1358,7 +1358,7 @@ /* Abort a command. The host_lock is acquired by caller. */ int esp_abort(Scsi_Cmnd *SCptr) { - struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata; + struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata; struct ESP_regs *eregs = esp->eregs; int don; @@ -1486,7 +1486,7 @@ */ int esp_reset(Scsi_Cmnd *SCptr) { - struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata; + struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata; (void) esp_do_resetbus(esp, esp->eregs); @@ -1716,13 +1716,13 @@ if(esp->prev_soff != esp_dev->sync_max_offset || esp->prev_stp != esp_dev->sync_min_period || (esp->erev > esp100a && - esp->prev_cfg3 != esp->config3[sp->target])) { + esp->prev_cfg3 != esp->config3[sp->device->id])) { esp->prev_soff = esp_dev->sync_max_offset; esp_write(eregs->esp_soff, esp->prev_soff); esp->prev_stp = esp_dev->sync_min_period; esp_write(eregs->esp_stp, esp->prev_stp); if(esp->erev > esp100a) { - esp->prev_cfg3 = esp->config3[sp->target]; + esp->prev_cfg3 = esp->config3[sp->device->id]; esp_write(eregs->esp_cfg3, esp->prev_cfg3); } } @@ -2117,7 +2117,7 @@ esp->esp_id, SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual)); ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, - SCptr->target)); + SCptr->device->id)); SCptr->device->borken = 1; esp_dev->sync = 0; bytes_sent = 0; @@ -2225,7 +2225,7 @@ if(SCptr->SCp.Status != GOOD && SCptr->SCp.Status != CONDITION_GOOD && - ((1<target) & esp->targets_present) && + ((1<device->id) & esp->targets_present) && esp_dev->sync && esp_dev->sync_max_offset) { /* SCSI standard says that the synchronous capabilities * should be renegotiated at this point. Most likely @@ -2283,21 +2283,21 @@ sp = esp->issue_SC; ESPLOG(("esp%d: issue_SC[", esp->esp_id)); while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun)); sp = (Scsi_Cmnd *) sp->host_scribble; } ESPLOG(("]\n")); sp = esp->current_SC; ESPLOG(("esp%d: current_SC[", esp->esp_id)); while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun)); sp = (Scsi_Cmnd *) sp->host_scribble; } ESPLOG(("]\n")); sp = esp->disconnected_SC; ESPLOG(("esp%d: disconnected_SC[", esp->esp_id)); while(sp) { - ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); + ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun)); sp = (Scsi_Cmnd *) sp->host_scribble; } ESPLOG(("]\n")); @@ -2617,7 +2617,7 @@ */ if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) { /* target speaks... */ - esp->targets_present |= (1<target); + esp->targets_present |= (1<device->id); /* What if the target ignores the sdtr? */ if(esp->snip) @@ -2646,7 +2646,7 @@ * XXX for synchronous transfers. */ ESPLOG(("esp%d: STEP_ASEL for tgt %d\n", - esp->esp_id, SCptr->target)); + esp->esp_id, SCptr->device->id)); case ESP_STEP_SID: /* Arbitration won, target selected, went @@ -2763,14 +2763,14 @@ if(esp->disconnected_SC) esp_cmd(esp, eregs, ESP_CMD_ESEL); - if(((1<target) & esp->targets_present) && + if(((1<device->id) & esp->targets_present) && esp->seqreg && esp->cur_msgout[0] == EXTENDED_MESSAGE && (SCptr->SCp.phase == in_slct_msg || SCptr->SCp.phase == in_slct_stop)) { /* shit */ esp->snip = 0; ESPLOG(("esp%d: Failed synchronous negotiation for target %d " - "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun)); + "lun %d\n", esp->esp_id, SCptr->device->id, SCptr->device->lun)); esp_dev->sync_max_offset = 0; esp_dev->sync_min_period = 0; esp_dev->sync = 1; /* so we don't negotiate again */ @@ -2796,9 +2796,9 @@ * or whenever when we are scanning the bus for targets. * But first make sure that is really what is happening. */ - if(((1<target) & esp->targets_present)) { + if(((1<device->id) & esp->targets_present)) { ESPLOG(("esp%d: Warning, live target %d not responding to " - "selection.\n", esp->esp_id, SCptr->target)); + "selection.\n", esp->esp_id, SCptr->device->id)); /* This _CAN_ happen. The SCSI standard states that * the target is to _not_ respond to selection if @@ -2892,7 +2892,7 @@ case NOP: ESPLOG(("esp%d: target %d sends a nop\n", esp->esp_id, - esp->current_SC->target)); + esp->current_SC->device->id)); return 0; case RESTORE_POINTERS: @@ -2985,7 +2985,7 @@ * sibling call optimization. -DaveM */ ESPLOG((KERN_INFO "esp%d: target %d ", - esp->esp_id, esp->current_SC->target)); + esp->esp_id, esp->current_SC->device->id)); ESPLOG(("[period %dns offset %d %d.%02dMHz ", (int) msg3 * 4, (int) msg4, integer, fraction)); @@ -2993,7 +2993,7 @@ (((msg3 * 4) < 200) ? "-II" : ""))); } else { ESPLOG((KERN_INFO "esp%d: target %d asynchronous\n", - esp->esp_id, esp->current_SC->target)); + esp->esp_id, esp->current_SC->device->id)); } } @@ -3070,10 +3070,10 @@ else bit = ESP_CONFIG3_FSCSI; if(period < 50) - esp->config3[SCptr->target] |= bit; + esp->config3[SCptr->device->id] |= bit; else - esp->config3[SCptr->target] &= ~bit; - esp->prev_cfg3 = esp->config3[SCptr->target]; + esp->config3[SCptr->device->id] &= ~bit; + esp->prev_cfg3 = esp->config3[SCptr->device->id]; esp_write(eregs->esp_cfg3, esp->prev_cfg3); } esp->prev_soff = esp_dev->sync_min_period; @@ -3103,8 +3103,8 @@ bit = ESP_CONFIG3_FAST; else bit = ESP_CONFIG3_FSCSI; - esp->config3[SCptr->target] &= ~bit; - esp->prev_cfg3 = esp->config3[SCptr->target]; + esp->config3[SCptr->device->id] &= ~bit; + esp->prev_cfg3 = esp->config3[SCptr->device->id]; esp_write(eregs->esp_cfg3, esp->prev_cfg3); } } @@ -3493,7 +3493,7 @@ * a nexus is alive on the bus. */ ESPLOG(("esp%d: Forcing async and disabling disconnect for " - "target %d\n", esp->esp_id, SCptr->target)); + "target %d\n", esp->esp_id, SCptr->device->id)); SCptr->device->borken = 1; /* foo on you */ } diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Mon Feb 17 14:57:27 2003 +++ b/drivers/scsi/aha1542.c Mon Feb 17 14:57:27 2003 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -597,8 +598,8 @@ unchar ahacmd = CMD_START_SCSI; unchar direction; unchar *cmd = (unchar *) SCpnt->cmnd; - unchar target = SCpnt->target; - unchar lun = SCpnt->lun; + unchar target = SCpnt->device->id; + unchar lun = SCpnt->device->lun; unsigned long flags; void *buff = SCpnt->request_buffer; int bufflen = SCpnt->request_bufflen; @@ -608,8 +609,8 @@ DEB(int i); - mb = HOSTDATA(SCpnt->host)->mb; - ccb = HOSTDATA(SCpnt->host)->ccb; + mb = HOSTDATA(SCpnt->device->host)->mb; + ccb = HOSTDATA(SCpnt->device->host)->ccb; DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16; @@ -653,25 +654,25 @@ is how the host adapter will scan for them */ spin_lock_irqsave(&aha1542_lock, flags); - mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1; + mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1; if (mbo >= AHA1542_MAILBOXES) mbo = 0; do { - if (mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL) + if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL) break; mbo++; if (mbo >= AHA1542_MAILBOXES) mbo = 0; - } while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used); + } while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used); - if (mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo]) + if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo]) panic("Unable to find empty mailbox for aha1542.\n"); - HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from + HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from screwing with this cdb. */ - HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo; + HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo; spin_unlock_irqrestore(&aha1542_lock, flags); #ifdef DEBUG @@ -762,7 +763,7 @@ aha1542_stat()); SCpnt->scsi_done = done; mb[mbo].status = 1; - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ + aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); /* start scsi command */ DEB(aha1542_stat()); } else printk("aha1542_queuecommand: done can't be NULL\n"); @@ -1356,7 +1357,7 @@ */ printk(KERN_ERR "aha1542.c: Unable to abort command for target %d\n", - SCpnt->target); + SCpnt->device->id); return FAILED; } @@ -1368,36 +1369,36 @@ { unsigned long flags; struct mailbox *mb; - unchar target = SCpnt->target; - unchar lun = SCpnt->lun; + unchar target = SCpnt->device->id; + unchar lun = SCpnt->device->lun; int mbo; struct ccb *ccb; unchar ahacmd = CMD_START_SCSI; - ccb = HOSTDATA(SCpnt->host)->ccb; - mb = HOSTDATA(SCpnt->host)->mb; + ccb = HOSTDATA(SCpnt->device->host)->ccb; + mb = HOSTDATA(SCpnt->device->host)->mb; spin_lock_irqsave(&aha1542_lock, flags); - mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1; + mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1; if (mbo >= AHA1542_MAILBOXES) mbo = 0; do { - if (mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL) + if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL) break; mbo++; if (mbo >= AHA1542_MAILBOXES) mbo = 0; - } while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used); + } while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used); - if (mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo]) + if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo]) panic("Unable to find empty mailbox for aha1542.\n"); - HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt; /* This will effectively + HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from screwing with this cdb. */ - HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo; + HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo; spin_unlock_irqrestore(&aha1542_lock, flags); any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo])); /* This gets trashed for some reason */ @@ -1415,9 +1416,9 @@ * Now tell the 1542 to flush all pending commands for this * target */ - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); + aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); - printk(KERN_WARNING "aha1542.c: Trying device reset for target %d\n", SCpnt->target); + printk(KERN_WARNING "aha1542.c: Trying device reset for target %d\n", SCpnt->device->id); return SUCCESS; @@ -1467,7 +1468,7 @@ * we do this? Try this first, and we can add that later * if it turns out to be useful. */ - outb(SCRST, CONTROL(SCpnt->host->io_port)); + outb(SCRST, CONTROL(SCpnt->device->host->io_port)); /* * Wait for the thing to settle down a bit. Unfortunately @@ -1476,11 +1477,11 @@ * check for timeout, and if we are doing something like this * we are pretty desperate anyways. */ - spin_unlock_irq(SCpnt->host->host_lock); + spin_unlock_irq(SCpnt->device->host->host_lock); scsi_sleep(4 * HZ); - spin_lock_irq(SCpnt->host->host_lock); + spin_lock_irq(SCpnt->device->host->host_lock); - WAIT(STATUS(SCpnt->host->io_port), + WAIT(STATUS(SCpnt->device->host->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); /* @@ -1489,12 +1490,12 @@ * out. We do not try and restart any commands or anything - * the strategy handler takes care of that crap. */ - printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no); + printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no); for (i = 0; i < AHA1542_MAILBOXES; i++) { - if (HOSTDATA(SCpnt->host)->SCint[i] != NULL) { + if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) { Scsi_Cmnd *SCtmp; - SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; + SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i]; if (SCtmp->device->soft_reset) { @@ -1510,8 +1511,8 @@ kfree(SCtmp->host_scribble); SCtmp->host_scribble = NULL; } - HOSTDATA(SCpnt->host)->SCint[i] = NULL; - HOSTDATA(SCpnt->host)->mb[i].status = 0; + HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; + HOSTDATA(SCpnt->device->host)->mb[i].status = 0; } } @@ -1531,7 +1532,7 @@ * we do this? Try this first, and we can add that later * if it turns out to be useful. */ - outb(HRST | SCRST, CONTROL(SCpnt->host->io_port)); + outb(HRST | SCRST, CONTROL(SCpnt->device->host->io_port)); /* * Wait for the thing to settle down a bit. Unfortunately @@ -1540,18 +1541,18 @@ * check for timeout, and if we are doing something like this * we are pretty desperate anyways. */ - spin_unlock_irq(SCpnt->host->host_lock); + spin_unlock_irq(SCpnt->device->host->host_lock); scsi_sleep(4 * HZ); - spin_lock_irq(SCpnt->host->host_lock); + spin_lock_irq(SCpnt->device->host->host_lock); - WAIT(STATUS(SCpnt->host->io_port), + WAIT(STATUS(SCpnt->device->host->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); /* * We need to do this too before the 1542 can interact with * us again. */ - setup_mailboxes(SCpnt->host->io_port, SCpnt->host); + setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host); /* * Now try to pick up the pieces. For all pending commands, @@ -1559,12 +1560,12 @@ * out. We do not try and restart any commands or anything - * the strategy handler takes care of that crap. */ - printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no); + printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no); for (i = 0; i < AHA1542_MAILBOXES; i++) { - if (HOSTDATA(SCpnt->host)->SCint[i] != NULL) { + if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) { Scsi_Cmnd *SCtmp; - SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; + SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i]; if (SCtmp->device->soft_reset) { /* @@ -1579,8 +1580,8 @@ kfree(SCtmp->host_scribble); SCtmp->host_scribble = NULL; } - HOSTDATA(SCpnt->host)->SCint[i] = NULL; - HOSTDATA(SCpnt->host)->mb[i].status = 0; + HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; + HOSTDATA(SCpnt->device->host)->mb[i].status = 0; } } diff -Nru a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg --- a/drivers/scsi/aic7xxx/aic79xx.reg Mon Feb 17 14:57:28 2003 +++ b/drivers/scsi/aic7xxx/aic79xx.reg Mon Feb 17 14:57:28 2003 @@ -3725,7 +3725,7 @@ /* * The minimum number of commands still outstanding required - * to continue coalessing (2's compliment of value). + * to continue coalessing (2's complement of value). */ INT_COALESSING_MINCMDS { size 1 diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c Mon Feb 17 14:57:27 2003 +++ b/drivers/scsi/mca_53c9x.c Mon Feb 17 14:57:27 2003 @@ -40,6 +40,7 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c --- a/drivers/usb/image/scanner.c Mon Feb 17 14:57:27 2003 +++ b/drivers/usb/image/scanner.c Mon Feb 17 14:57:27 2003 @@ -54,7 +54,7 @@ * allocation/registration for linux-2.3.22+. * - Adopted David Brownell's technique for * assigning bulk endpoints. - * - Removed unnessesary #include's + * - Removed unnecessary #include's * - Scanner model now reported via syslog INFO after being detected * *and* configured. * - Added user specified vendor:product USB ID's which can be passed diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig --- a/drivers/video/Kconfig Mon Feb 17 14:57:26 2003 +++ b/drivers/video/Kconfig Mon Feb 17 14:57:26 2003 @@ -235,7 +235,7 @@ config FB_OF bool "Open Firmware frame buffer device support" - depends on FB && PPC && ALL_PPC + depends on FB && (PPC64 || (PPC && ALL_PPC)) help Say Y if you want support with Open Firmware for your graphics board. diff -Nru a/fs/befs/ChangeLog b/fs/befs/ChangeLog --- a/fs/befs/ChangeLog Mon Feb 17 14:57:26 2003 +++ b/fs/befs/ChangeLog Mon Feb 17 14:57:26 2003 @@ -102,7 +102,7 @@ The option is, simply enough, 'debug'. (super.c, debug.c) [WD] -* Removed notion of btree handle from btree.c. It was unessisary, as the +* Removed notion of btree handle from btree.c. It was unnecessary, as the linux VFS doesn't allow us to keep any state between calls. Updated dir.c, namei.c befs_fs.h to account for it. [WD] @@ -312,9 +312,9 @@ ========== * Fixed a misunderstanding of the inode fields. This fixed the problmem with wrong file sizes from du and others. - The i_blocks field of the inode struct is not the nuber of blocks for the + The i_blocks field of the inode struct is not the number of blocks for the inode, it is the number of blocks for the file. Also, i_blksize is not - nessisarily the size of the inode, although in practice it works out. + necessarily the size of the inode, although in practice it works out. Changed to blocksize of filesystem. (fs/befs/inode.c) diff -Nru a/fs/befs/btree.c b/fs/befs/btree.c --- a/fs/befs/btree.c Mon Feb 17 14:57:26 2003 +++ b/fs/befs/btree.c Mon Feb 17 14:57:26 2003 @@ -56,9 +56,9 @@ /* Note: * * The book states 2 confusing things about befs b+trees. First, - * it states that the overflow feild of node headers is used by internal nodes - * to point to another node that "effectivly continues this one". Here is what - * I belive that means. Each key in internal nodes points to another node that + * it states that the overflow field of node headers is used by internal nodes + * to point to another node that "effectively continues this one". Here is what + * I believe that means. Each key in internal nodes points to another node that * contains key values less than itself. Inspection reveals that the last key * in the internal node is not the last key in the index. Keys that are * greater than the last key in the internal node go into the overflow node. @@ -124,7 +124,7 @@ * @sup: Buffer in which to place the btree superblock * * Calls befs_read_datastream to read in the btree superblock and - * makes sure it is in cpu byteorder, byteswapping if nessisary. + * makes sure it is in cpu byteorder, byteswapping if necessary. * * On success, returns BEFS_OK and *@sup contains the btree superblock, * in cpu byte order. @@ -179,8 +179,8 @@ * @node_off: Starting offset (in bytes) of the node in @ds * * Calls befs_read_datastream to read in the indicated btree node and - * makes sure its header feilds are in cpu byteorder, byteswapping if - * nessisary. + * makes sure its header fields are in cpu byteorder, byteswapping if + * necessary. * Note: node->bh must be NULL when this function called first * time. Don't forget brelse(node->bh) after last call. * diff -Nru a/fs/befs/datastream.c b/fs/befs/datastream.c --- a/fs/befs/datastream.c Mon Feb 17 14:57:28 2003 +++ b/fs/befs/datastream.c Mon Feb 17 14:57:28 2003 @@ -229,7 +229,7 @@ Algorithm: Linear search. Checks each element of array[] to see if it - contains the blockno-th filesystem block. This is nessisary + contains the blockno-th filesystem block. This is necessary because the block runs map variable amounts of data. Simply keeps a count of the number of blocks searched so far (sum), incrementing this by the length of each block run as we come diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c --- a/fs/binfmt_aout.c Mon Feb 17 14:57:27 2003 +++ b/fs/binfmt_aout.c Mon Feb 17 14:57:27 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff -Nru a/fs/buffer.c b/fs/buffer.c --- a/fs/buffer.c Mon Feb 17 14:57:27 2003 +++ b/fs/buffer.c Mon Feb 17 14:57:27 2003 @@ -2484,6 +2484,12 @@ /* Is the page fully outside i_size? (truncate in progress) */ offset = inode->i_size & (PAGE_CACHE_SIZE-1); if (page->index >= end_index+1 || !offset) { + /* + * The page may have dirty, unmapped buffers. For example, + * they may have been added in ext3_writepage(). Make them + * freeable here, so the page does not leak. + */ + block_invalidatepage(page, 0); unlock_page(page); return -EIO; } diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/CHANGES Mon Feb 17 14:57:28 2003 @@ -1,3 +1,42 @@ +Version 0.65 +------------ +Finish fixes to commit write for caching/readahead consistency. fsx +now works to Samba servers. Fix oops caused when readahead +was interrupted by a signal. + +Version 0.64 +------------ +Fix data corruption (in partial page after truncate) that caused fsx to +fail to Windows servers. Cleaned up some extraneous error logging in +common error paths. Add generic sendfile support. + +Version 0.63 +------------ +Fix memory leak in AllocMidQEntry. +Finish reconnection logic, so connection with server can be dropped +(or server rebooted) and the cifs client will reconnect. + +Version 0.62 +------------ +Fix temporary socket leak when bad userid or password specified +(or other SMBSessSetup failure). Increase maximum buffer size to slightly +over 16K to allow negotiation of up to Samba and Windows server default read +sizes. Add support for readpages + +Version 0.61 +------------ +Fix oops when username not passed in on mount. Extensive fixes and improvements +to error logging (strip redundant newlines, change debug macros to ensure newline +passed in and to be more consistent). Fix writepage wrong file handle problem, +a readonly file handle could be incorrectly used to attempt to write out +file updates through the page cache to multiply open files. This could cause +the iozone benchmark to fail on the fwrite test. Fix bug mounting two different +shares to the same Windows server when using different usernames +(doing this to Samba servers worked but Windows was rejecting it) - now it is +possible to use different userids when connecting to the same server from a +Linux client. Fix oops when treeDisconnect called during unmount on +previously freed socket. + Version 0.60 ------------ Fix oops in readpages caused by not setting address space operations in inode in diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO --- a/fs/cifs/TODO Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/TODO Mon Feb 17 14:57:28 2003 @@ -1,4 +1,4 @@ -version 0.5.3 October 8th, 2002 +version 0.6.5 February 15, 2003 A Partial List of Known Problems and Missing Features ===================================================== @@ -7,7 +7,8 @@ for visible, important contributions to this module. Here is a partial list of the known problems and missing features: -a) Support for SecurityDescriptors for chmod/chgrp/chown +a) Support for SecurityDescriptors for chmod/chgrp/chown so +these can be supported for Windows servers b) Better pam/winbind integration @@ -16,9 +17,9 @@ d) Kerberos/SPNEGO session setup support - (started) -e)NTLMv2 authentication and MD5-HMAC signing of SMB PDUs - (mostly implemented) +e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented) -f) oplock support (ie safe CIFS distributed file caching) is not complete. +f) oplock support (ie safe CIFS distributed file caching) is not quite complete. In addition Directory entry caching relies on a 1 second timer, rather than using FindNotify or equivalent. - (started) @@ -28,27 +29,34 @@ h) quota support i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr +which will allow us to expose dos attributes as well as real +ACLs j) finish off the mount helper, mount.cifs - (started) -KNOWN BUGS (updated October 8nd, 2002) +k) finish writepages support (multi-page write behind for improved +performance) and syncpage + +l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the +extra copy in/out of the socket buffers in some cases. + +m) finish support for IPv6 + +KNOWN BUGS (updated February 15, 2003) ==================================== -1) symbolic links (Windows reparse points) are recognized but +1) existing symbolic links (Windows reparse points) are recognized but can not be created remotely. They are implemented for Samba and those that support the CIFS Unix extensions but Samba has a bug currently handling symlink text beginning with slash 2) delete of file with read-only attribute set will fail (may be ok) -3) autoreconnection logic is only partially complete. -4) there may be a problem with truncating a memmapped file to smaller than 4k with -the size being reported as exactly 4k. Misc testing to do ================= 1) check out max path names and max path name components against various server types. -2) Run POSIX bencharks against cifs +2) Run dbench -3) Run dbench +3) Finish FSX testing on SMP now that we workaround the Samba bug -4) Finish FSX testing on SMP now that we workaround the Samba bug +4) Additional performance testing and optimization diff -Nru a/fs/cifs/asn1.c b/fs/cifs/asn1.c --- a/fs/cifs/asn1.c Mon Feb 17 14:57:26 2003 +++ b/fs/cifs/asn1.c Mon Feb 17 14:57:26 2003 @@ -458,16 +458,18 @@ unsigned int cls, con, tag, oidlen, rc; int use_ntlmssp = FALSE; + *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */ + /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ asn1_open(&ctx, security_blob, length); if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("\nError decoding negTokenInit header ")); + cFYI(1, ("Error decoding negTokenInit header ")); return 0; } else if ((cls != ASN1_APL) || (con != ASN1_CON) || (tag != ASN1_EOC)) { - cFYI(1, ("\ncls = %d con = %d tag = %d", cls, con, tag)); + cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); return 0; } else { /* remember to free obj->oid */ @@ -486,51 +488,49 @@ } if (!rc) { - cFYI(1, ("\nError decoding negTokenInit header")); + cFYI(1, ("Error decoding negTokenInit header")); return 0; } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("\nError decoding negTokenInit ")); + cFYI(1, ("Error decoding negTokenInit ")); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON) || (tag != ASN1_EOC)) { - cFYI(1, - ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0", + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0", cls, con, tag, end, *end)); return 0; } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("\nError decoding negTokenInit ")); + cFYI(1, ("Error decoding negTokenInit ")); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, - ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1", + cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1", cls, con, tag, end, *end)); return 0; } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("\nError decoding 2nd part of negTokenInit ")); + cFYI(1, ("Error decoding 2nd part of negTokenInit ")); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON) || (tag != ASN1_EOC)) { cFYI(1, - ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0", + ("cls = %d con = %d tag = %d end = %p (%d) exit 0", cls, con, tag, end, *end)); return 0; } if (asn1_header_decode (&ctx, &sequence_end, &cls, &con, &tag) == 0) { - cFYI(1, ("\nError decoding 2nd part of negTokenInit ")); + cFYI(1, ("Error decoding 2nd part of negTokenInit ")); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { cFYI(1, - ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1", + ("cls = %d con = %d tag = %d end = %p (%d) exit 1", cls, con, tag, end, *end)); return 0; } @@ -539,13 +539,13 @@ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); if (!rc) { cFYI(1, - ("\nError 1 decoding negTokenInit header exit 2")); + ("Error 1 decoding negTokenInit header exit 2")); return 0; } if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { asn1_oid_decode(&ctx, end, &oid, &oidlen); cFYI(1, - ("\nOID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx", + ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx", oidlen, *oid, *(oid + 1), *(oid + 2), *(oid + 3))); rc = compare_oid(oid, oidlen, NTLMSSP_OID, @@ -554,54 +554,53 @@ if (rc) use_ntlmssp = TRUE; } else { - cFYI(1, - ("\nThis should be an oid what is going on? ")); + cFYI(1,("This should be an oid what is going on? ")); } } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, - ("\nError decoding last part of negTokenInit exit 3")); + ("Error decoding last part of negTokenInit exit 3")); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ cFYI(1, - ("\nExit 4 cls = %d con = %d tag = %d end = %p (%d)", + ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", cls, con, tag, end, *end)); return 0; } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, - ("\nError decoding last part of negTokenInit exit 5")); + ("Error decoding last part of negTokenInit exit 5")); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { cFYI(1, - ("\nExit 6 cls = %d con = %d tag = %d end = %p (%d)", + ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", cls, con, tag, end, *end)); } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, - ("\nError decoding last part of negTokenInit exit 7")); + ("Error decoding last part of negTokenInit exit 7")); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { cFYI(1, - ("\nExit 8 cls = %d con = %d tag = %d end = %p (%d)", + ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", cls, con, tag, end, *end)); return 0; } if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, - ("\nError decoding last part of negTokenInit exit 9")); + ("Error decoding last part of negTokenInit exit 9")); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) || (tag != ASN1_GENSTR)) { cFYI(1, - ("\nExit 10 cls = %d con = %d tag = %d end = %p (%d)", + ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)", cls, con, tag, end, *end)); return 0; } - cFYI(1, ("\nNeed to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ + cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ } /* if (use_kerberos) diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c --- a/fs/cifs/cifs_debug.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifs_debug.c Mon Feb 17 14:57:27 2003 @@ -39,7 +39,8 @@ char *charptr = data; char buf[10], line[80]; - printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length, data); + printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", + label, length, data); for (i = 0; i < length; i += 16) { line[0] = 0; for (j = 0; (j < 4) && (i + j * 4 < length); j++) { @@ -52,7 +53,7 @@ buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.'; strcat(line, buf); } - printk("%s\n", line); + printk(KERN_DEBUG "%s\n", line); } } @@ -68,7 +69,6 @@ int length = 0; char *buf_start = buf; - printk("\n\nEntering cifs_debug_data_read: buf=0x%p, beginBuffer=0x%p, offset=%ld, count=%d, eof=%d, data=0x%p\n", buf, *beginBuffer, offset, count, *eof, data); /* BB remove */ length = sprintf(buf, "Display Internal CIFS Data Structures for Debugging\n" @@ -85,17 +85,17 @@ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); length = sprintf(buf, - "\n%d) Name: %s Domain: %s HowManyMounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x", + "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x", i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), ses->serverOS, ses->serverNOS, ses->capabilities); buf += length; if(ses->server) - buf += sprintf(buf, "\tLocal Users To Same Server: %d ",atomic_read(&ses->server->socketUseCount)); + buf += sprintf(buf, "\tLocal Users To Same Server: %d ", + atomic_read(&ses->server->socketUseCount)); } read_unlock(&GlobalSMBSeslock); sprintf(buf, "\n"); buf++; - printk("\nTotal Buffer so far: %s\n", buf_start); length = sprintf(buf, "\nShares: \n"); buf += length; @@ -107,7 +107,7 @@ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); length = sprintf(buf, - "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentLengthMax: %d", + "\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d", i, tcon->treeName, atomic_read(&tcon->useCount), tcon->nativeFileSystem, diff -Nru a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h --- a/fs/cifs/cifs_debug.h Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifs_debug.h Mon Feb 17 14:57:27 2003 @@ -33,29 +33,35 @@ */ #ifdef CIFS_DEBUG + /* information message: e.g., configuration, major event */ extern int cifsFYI; -#define cFYI(button,prspec)\ -{ if (button && cifsFYI) printk prspec; } +#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) + +#define cFYI(button,prspec) if (button) cifsfyi prspec + +#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg) /* debug event message: */ -#define cEVENT(button,prspec)\ -{ if (button) printk prspec; } +extern int cifsERROR; + +#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg) /* error event message: e.g., i/o error */ -extern int cifsERROR; -#define cERROR(button, prspec)\ -{ if (button && cifsERROR) { printk prspec; if (button > 1) BUG(); } } +#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg) + +#define cERROR(button, prspec) if (button) cifserror prspec /* * debug OFF * --------- */ -#else /* _CIFS_DEBUG */ +#else /* _CIFS_DEBUG */ #define cERROR(button,prspec) -#define cEVENT(button,prspec) +#define cEVENT(format,arg...) #define cFYI(button, prspec) -#endif /* _CIFS_DEBUG */ +#define cifserror(format,arg...) +#endif /* _CIFS_DEBUG */ /* * statistics diff -Nru a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c --- a/fs/cifs/cifs_unicode.c Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/cifs_unicode.c Mon Feb 17 14:57:28 2003 @@ -69,7 +69,6 @@ } } to[outlen] = 0; - cEVENT(0, ("cifs_strfromUCS returning %d - '%s'\n", outlen, to)); return outlen; } @@ -86,15 +85,13 @@ int charlen; int i; - cEVENT(0, ("cifs_strtoUCS - '%s'\n", from)); - for (i = 0; len && *from; i++, from += charlen, len -= charlen) { /* works for 2.4.0 kernel or later */ charlen = codepage->char2uni(from, len, &to[i]); if (charlen < 1) { cERROR(1, - ("cifs_strtoUCS: char2uni returned %d.\n", + ("cifs_strtoUCS: char2uni returned %d", charlen)); to[i] = cpu_to_le16(0x003f); /* a question mark */ charlen = 1; @@ -102,8 +99,6 @@ to[i] = cpu_to_le16(to[i]); } - - cEVENT(0, (" returning %d\n", i)); to[i] = 0; return i; diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c --- a/fs/cifs/cifsfs.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifsfs.c Mon Feb 17 14:57:27 2003 @@ -71,12 +71,13 @@ if(cifs_sb == NULL) return -ENOMEM; cifs_sb->local_nls = load_nls_default(); /* needed for ASCII cp to Unicode converts */ + rc = cifs_mount(sb, cifs_sb, data, devname); if (rc) { if (!silent) cERROR(1, - ("cifs_mount failed w/return code = %d\n", rc)); + ("cifs_mount failed w/return code = %d", rc)); goto out_mount_failed; } @@ -97,13 +98,10 @@ return 0; out_no_root: - cEVENT(1, ("cifs_read_super: get root inode failed\n")); + cERROR(1, ("cifs_read_super: get root inode failed")); if (inode) iput(inode); - if (rc) { - cERROR(1, ("cifs_mount failed with no root inode")); - } out_mount_failed: if(cifs_sb) kfree(cifs_sb); @@ -116,15 +114,15 @@ int rc = 0; struct cifs_sb_info *cifs_sb; - cFYI(1, ("In cifs_put_super\n")); + cFYI(1, ("In cifs_put_super")); cifs_sb = CIFS_SB(sb); if(cifs_sb == NULL) { - cFYI(1,("\nEmpty cifs superblock info passed to unmount")); + cFYI(1,("Empty cifs superblock info passed to unmount")); return; } rc = cifs_umount(sb, cifs_sb); if (rc) { - cERROR(1, ("cifs_umount failed with return code %d\n", rc)); + cERROR(1, ("cifs_umount failed with return code %d", rc)); } unload_nls(cifs_sb->local_nls); kfree(cifs_sb); @@ -180,7 +178,8 @@ cifs_inode->cifsAttrs = 0x20; /* default */ atomic_set(&cifs_inode->inUse, 0); cifs_inode->time = 0; - cifs_inode->clientCanCache = 0; + if(oplockEnabled) + cifs_inode->clientCanCacheAll = 1; INIT_LIST_HEAD(&cifs_inode->openFileList); return &cifs_inode->vfs_inode; } @@ -236,7 +235,7 @@ int rc; struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); - cFYI(1, ("\nDevname: %s flags: %d ", dev_name, flags)); + cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); if (IS_ERR(sb)) return sb; @@ -277,8 +276,15 @@ struct inode_operations cifs_file_inode_ops = { /* revalidate:cifs_revalidate, */ .setattr = cifs_setattr, - .getattr = cifs_getattr, + .getattr = cifs_getattr, /* do we need this anymore? */ .rename = cifs_rename, +#ifdef CIFS_XATTR + .setxattr = cifs_setxattr, + .getxattr = cifs_getxattr, + .listxattr = cifs_listxattr, + .removexattr = cifs_removexattr, + .permission = cifs_permission, +#endif }; struct inode_operations cifs_symlink_inode_ops = { @@ -287,16 +293,24 @@ /* BB add the following two eventually */ /* revalidate: cifs_revalidate, setattr: cifs_notify_change, *//* BB do we need notify change */ +#ifdef CIFS_XATTR + .setxattr = cifs_setxattr, + .getxattr = cifs_getxattr, + .listxattr = cifs_listxattr, + .removexattr = cifs_removexattr, +#endif }; struct file_operations cifs_file_ops = { .read = generic_file_read, - .write = generic_file_write, + .write = generic_file_write, .open = cifs_open, .release = cifs_close, .lock = cifs_lock, .fsync = cifs_fsync, + .flush = cifs_flush, .mmap = cifs_file_mmap, + .sendfile = generic_file_sendfile, }; struct file_operations cifs_dir_ops = { @@ -333,7 +347,7 @@ cifs_destroy_inodecache(void) { if (kmem_cache_destroy(cifs_inode_cachep)) - printk(KERN_INFO "cifs_inode_cache: error freeing\n"); + printk(KERN_WARNING "cifs_inode_cache: error freeing\n"); } int @@ -353,7 +367,7 @@ cifs_destroy_request_bufs(void) { if (kmem_cache_destroy(cifs_req_cachep)) - printk(KERN_INFO + printk(KERN_WARNING "cifs_destroy_request_cache: error not all structures were freed\n"); } @@ -373,7 +387,7 @@ cifs_destroy_mids(void) { if (kmem_cache_destroy(cifs_mid_cachep)) - printk(KERN_INFO + printk(KERN_WARNING "cifs_destroy_mids: error not all structures were freed\n"); } @@ -426,7 +440,7 @@ static void __exit exit_cifs(void) { - cFYI(0, ("\nIn unregister ie exit_cifs")); + cFYI(0, ("In unregister ie exit_cifs")); #if CONFIG_PROC_FS cifs_proc_clean(); #endif diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifsfs.h Mon Feb 17 14:57:27 2003 @@ -74,6 +74,7 @@ size_t write_size, loff_t * poffset); extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_fsync(struct file *, struct dentry *, int); +extern int cifs_flush(struct file *); extern int cifs_file_mmap(struct file * , struct vm_area_struct *); extern struct file_operations cifs_dir_ops; extern int cifs_dir_open(struct inode *inode, struct file *file); diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h --- a/fs/cifs/cifsglob.h Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifsglob.h Mon Feb 17 14:57:27 2003 @@ -27,7 +27,7 @@ #define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1 #define MAX_SERVER_SIZE 15 #define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */ -#define MAX_USERNAME_SIZE 32 /* 22 is to allow for 15 char names + null +#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null termination then *2 for unicode versions */ #define MAX_PASSWORD_SIZE 16 @@ -109,6 +109,21 @@ struct semaphore tcpSem; struct task_struct *tsk; char server_GUID[16]; + char secMode; + enum securityEnum secType; + unsigned int maxReq; /* Clients should submit no more */ + /* than maxReq distinct unanswered SMBs to the server when using */ + /* multiplexed reads or writes */ + unsigned int maxBuf; /* maxBuf specifies the maximum */ + /* message size the server can send or receive for non-raw SMBs */ + unsigned int maxRw; /* maxRw specifies the maximum */ + /* message size the server can send or receive for */ + /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ + char sessid[4]; /* unique token id for this session */ + /* (returned on Negotiate */ + int capabilities; /* allow selective disabling of caps by smb sess */ + __u16 timeZone; + char cryptKey[CIFS_CRYPTO_KEY_SIZE]; }; /* @@ -117,12 +132,11 @@ * has changed. We also hang a list of sessions owned by this user off here. */ struct cifsUidInfo { - struct cifsUidInfo *next1; /* BB replace with list and atomicize */ - struct cifsSesInfo *ses; /* list of sessions *//* BB replace with list and atomicize */ - struct srSesInfo *sesSR; /* Save/Restore session list */ + struct list_head userList; + struct list_head sessionList; /* SMB sessions for this user */ uid_t linux_uid; char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */ - /* BB eventually need ptr into PAM or WinBind info */ + /* BB may need ptr or callback for PAM or WinBind info */ }; /* @@ -135,28 +149,16 @@ struct TCP_Server_Info *server; /* pointer to server info */ atomic_t inUse; /* # of CURRENT users of this ses */ enum statusEnum status; - int dialectIndex; /* the negotiated dialect index */ - char secMode; - enum securityEnum secType; - unsigned int maxReq; /* Clients should submit no more */ - /* than maxReq distinct unanswered SMBs to the server when using */ - /* multiplexed reads or writes */ - unsigned int maxBuf; /* maxBuf specifies the maximum */ - /* message size the server can send or receive for non-raw SMBs */ - unsigned int maxRw; /* maxRw specifies the maximum */ - /* message size the server can send or receive for */ - /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ - char sessid[4]; /* unique token id for this session */ - /* (returned on Negotiate */ __u16 ipc_tid; /* special tid for connection to IPC share */ - int capabilities; - __u16 timeZone; char *serverOS; /* name of operating system underlying the server */ char *serverNOS; /* name of network operating system that the server is running */ char *serverDomain; /* security realm of server */ int Suid; /* needed for user level security */ + int capabilities; char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ - char userName[MAX_USERNAME_SIZE + 1]; /* BB remove and replace with list of cifsUidInfo structures */ + char userName[MAX_USERNAME_SIZE + 1]; + char domainName[MAX_USERNAME_SIZE + 1]; + char password_with_pad[CIFS_ENCPWD_SIZE]; }; /* @@ -172,6 +174,7 @@ char *nativeFileSystem; __u16 tid; /* The 2 byte transaction id */ __u16 Flags; /* optional support bits */ + enum statusEnum tidStatus; atomic_t useCount; /* how many mounts (explicit or implicit refer to this share */ FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* note file system name may be truncated - but very unlikely */ @@ -214,11 +217,11 @@ struct list_head lockList; /* BB add in lists for dirty pages - i.e. write caching info for oplock */ struct list_head openFileList; - __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system etc. */ - atomic_t inUse; /* num concurrent users (local openers cifs) of file */ + __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ + atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ unsigned long time; /* jiffies of last update/check of inode */ - int clientCanCache:1; /* oplocked. We need to extend cases beyond this i.e. what - if file read-only or if file locked? or if file on r/o vol? */ + int clientCanCacheRead:1; /* read oplock */ + int clientCanCacheAll:1; /* read and writebehind oplock */ struct inode vfs_inode; }; diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/cifspdu.h Mon Feb 17 14:57:28 2003 @@ -79,7 +79,7 @@ /* * Starting value for maximum SMB size negotiation */ -#define CIFS_MAX_MSGSIZE (4*1024) +#define CIFS_MAX_MSGSIZE (4*4096) /* * Size of encrypted user password in bytes diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h --- a/fs/cifs/cifsproto.h Mon Feb 17 14:57:26 2003 +++ b/fs/cifs/cifsproto.h Mon Feb 17 14:57:26 2003 @@ -36,8 +36,8 @@ unsigned int /* length */ , struct sockaddr *); extern unsigned int _GetXid(void); extern void _FreeXid(unsigned int); -#define GetXid() (int)_GetXid(); cFYI(1,("\nCIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); -#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("\nCIFS VFS: leaving %s (xid = %d) rc = %d\n",__FUNCTION__,curr_xid,rc));} +#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); +#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));} extern char *build_path_from_dentry(struct dentry *); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); extern void renew_parental_timestamps(struct dentry *direntry); @@ -72,28 +72,21 @@ const unsigned char *search_path, struct super_block *sb); -extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses, - char cryptokey[CIFS_CRYPTO_KEY_SIZE]); +extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, + struct nls_table * nls_info); +extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses); extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *user, char *domain, char *session_key, char *ntlm_session_key, const struct nls_table *); extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *user, char *domain, - char *SecurityBlob, - int SecurityBlobLength, + char *SecurityBlob,int SecurityBlobLength, const struct nls_table *); extern int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, - struct cifsSesInfo *ses, - char *domain, - char *ntlm_session_key, - int *ntlmv2_flag, + struct cifsSesInfo *ses, int *ntlmv2_flag, const struct nls_table *); extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid, - struct cifsSesInfo *ses, char *user, - char *domain, char *ntlm_session_key, - char *lanman_session_key, - int ntlmv2_flag, + struct cifsSesInfo *ses, char *ntlm_session_key, + char *lanman_session_key,int ntlmv2_flag, const struct nls_table *); extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, @@ -202,7 +195,7 @@ extern int CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon, const int netfid, unsigned int count, - const __u64 lseek, unsigned int *nbytes, char *buf); + const __u64 lseek, unsigned int *nbytes, char **buf); extern int CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 lseek, unsigned int *nbytes, diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/cifssmb.c Mon Feb 17 14:57:27 2003 @@ -49,6 +49,11 @@ { int rc = 0; + if(tcon) + if(tcon->ses) + if(tcon->ses->status == CifsNeedReconnect) + setup_session(0, tcon->ses, load_nls_default()); + *request_buf = buf_get(); if (request_buf == 0) { return -ENOMEM; @@ -65,13 +70,20 @@ } int -CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses, - char cryptokey[CIFS_CRYPTO_KEY_SIZE]) +CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) { NEGOTIATE_REQ *pSMB; NEGOTIATE_RSP *pSMBr; int rc = 0; int bytes_returned; + struct TCP_Server_Info * server; + + if(ses->server) + server = ses->server; + else { + rc = -EIO; + return rc; + } rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ , (void **) &pSMB, (void **) &pSMBr); @@ -81,9 +93,9 @@ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; if (extended_security) pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; - if (sign_CIFS_PDUs) { - pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - } + if (sign_CIFS_PDUs) { + pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + } pSMB->ByteCount = strlen(protocols[0].name) + 1; strncpy(pSMB->DialectsArray, protocols[0].name, 30); @@ -95,22 +107,22 @@ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc == 0) { - ses->dialectIndex = le16_to_cpu(pSMBr->DialectIndex); - ses->secMode = pSMBr->SecurityMode; + server->secMode = pSMBr->SecurityMode; + server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ /* one byte - no need to convert this or EncryptionKeyLen from le,*/ - ses->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); + server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); /* probably no need to store and check maxvcs */ - ses->maxBuf = + server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE); - ses->maxRw = le32_to_cpu(pSMBr->MaxRawSize); - cFYI(1, ("\nMax buf = %d ", ses->maxBuf)); - GETU32(ses->sessid) = le32_to_cpu(pSMBr->SessionKey); - ses->capabilities = le32_to_cpu(pSMBr->Capabilities); - ses->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); + server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); + cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); + GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); + server->capabilities = le32_to_cpu(pSMBr->Capabilities); + server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); /* BB with UTC do we ever need to be using srvr timezone? */ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { - memcpy(cryptokey, pSMBr->u.EncryptionKey, + memcpy(server->cryptKey, pSMBr->u.EncryptionKey, CIFS_CRYPTO_KEY_SIZE); } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && (pSMBr->EncryptionKeyLength == 0)) { @@ -124,22 +136,22 @@ if (pSMBr->ByteCount < 16) rc = -EIO; else if (pSMBr->ByteCount == 16) { - ses->secType = RawNTLMSSP; - if (ses->server->socketUseCount.counter > 1) { + server->secType = RawNTLMSSP; + if (server->socketUseCount.counter > 1) { if (memcmp - (ses->server->server_GUID, - pSMBr->u.extended_response. - GUID, 16) != 0) { + (server->server_GUID, + pSMBr->u.extended_response. + GUID, 16) != 0) { cFYI(1, - ("UID of server does not match that of previous connection to same ip address")); - memcpy(ses->server-> - server_GUID, - pSMBr->u. - extended_response. - GUID, 16); + ("UID of server does not match that of previous connection to same ip address")); + memcpy(server-> + server_GUID, + pSMBr->u. + extended_response. + GUID, 16); } } else - memcpy(ses->server->server_GUID, + memcpy(server->server_GUID, pSMBr->u.extended_response. GUID, 16); } else { @@ -147,16 +159,16 @@ extended_response. SecurityBlob, pSMBr->ByteCount - - 16, &ses->secType); + 16, &server->secType); } } else - ses->capabilities &= ~CAP_EXTENDED_SECURITY; - if(sign_CIFS_PDUs == FALSE) { - if(ses->secMode & SECMODE_SIGN_REQUIRED) - cERROR(1,("\nServer required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled")); - ses->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); - } + server->capabilities &= ~CAP_EXTENDED_SECURITY; + if(sign_CIFS_PDUs == FALSE) { + if(server->secMode & SECMODE_SIGN_REQUIRED) + cERROR(1,("Server required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled")); + server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); + } } if (pSMB) buf_release(pSMB); @@ -171,7 +183,7 @@ int rc = 0; int length; - cFYI(1, ("\nIn tree disconnect")); + cFYI(1, ("In tree disconnect")); /* * If last user of the connection and * connection alive - disconnect it @@ -192,6 +204,10 @@ /* BB remove (from server) list of shares - but with smp safety BB */ /* BB is ses active - do we need to check here - but how? BB */ + if((tcon->ses == 0) || (tcon->ses->server == 0)) { + up(&tcon->tconSem); + return -EIO; + } rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **) &smb_buffer, (void **) &smb_buffer_response); @@ -218,7 +234,7 @@ int rc = 0; int length; - cFYI(1, ("\nIn SMBLogoff for session disconnect")); + cFYI(1, ("In SMBLogoff for session disconnect")); if (ses) down(&ses->sesSem); /* need to add more places where this sem is checked */ @@ -230,7 +246,7 @@ up(&ses->sesSem); return -EBUSY; } - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */ , (void **) &pSMB, (void **) &smb_buffer_response); @@ -278,7 +294,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); name_len++; /* trailing null */ strncpy(pSMB->fileName, fileName, name_len); @@ -292,7 +307,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in RMFile = %d\n", rc)); + cFYI(1, ("Error in RMFile = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -309,7 +324,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn CIFSSMBRmDir")); + cFYI(1, ("In CIFSSMBRmDir")); rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -323,7 +338,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(dirName, 530); name_len++; /* trailing null */ strncpy(pSMB->DirName, dirName, name_len); @@ -336,7 +350,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in RMDir = %d\n", rc)); + cFYI(1, ("Error in RMDir = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -353,7 +367,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn CIFSSMBMkDir")); + cFYI(1, ("In CIFSSMBMkDir")); rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -367,7 +381,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(name, 530); name_len++; /* trailing null */ strncpy(pSMB->DirName, name, name_len); @@ -380,7 +393,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in RMDir = %d\n", rc)); + cFYI(1, ("Error in Mkdir = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -418,15 +431,17 @@ name_len *= 2; pSMB->NameLength = cpu_to_le16(name_len); } else { /* BB improve the check for buffer overruns BB */ - pSMB->ByteCount = 0; /* no pad */ name_len = strnlen(fileName, 530); name_len++; /* trailing null */ pSMB->NameLength = cpu_to_le16(name_len); strncpy(pSMB->fileName, fileName, name_len); } - if (*pOplock) + if (*pOplock & REQ_OPLOCK) pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); + else if (*pOplock & REQ_BATCHOPLOCK) { + pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); + } pSMB->DesiredAccess = cpu_to_le32(access_flags); pSMB->AllocationSize = 0; pSMB->FileAttributes = ATTR_NORMAL; /* XP does not handle ATTR_POSIX_SEMANTICS */ @@ -449,7 +464,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in Open = %d\n", rc)); + cFYI(1, ("Error in Open = %d", rc)); } else { *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ *netfid = pSMBr->Fid; /* cifs fid stays in le */ @@ -463,17 +478,22 @@ return rc; } +/* If no buffer passed in, then caller wants to do the copy + as in the case of readpages so the SMB buffer must be + freed by the caller */ + int CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon, const int netfid, const unsigned int count, - const __u64 lseek, unsigned int *nbytes, char *buf) + const __u64 lseek, unsigned int *nbytes, char **buf) { int rc = -EACCES; READ_REQ *pSMB = NULL; READ_RSP *pSMBr = NULL; - char *pReadData; + char *pReadData = NULL; int bytes_returned; + *nbytes = 0; rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -485,7 +505,7 @@ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); pSMB->Remaining = 0; pSMB->MaxCount = cpu_to_le16(min(count, - (tcon->ses->maxBuf - + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00)); pSMB->MaxCountHigh = 0; pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ @@ -493,14 +513,14 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in read = %d\n", rc)); - *nbytes = 0; + cERROR(1, ("Send error in read = %d", rc)); } else { pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength); *nbytes = pSMBr->DataLength; /*check that DataLength would not go beyond end of SMB */ if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) || (pSMBr->DataLength > count)) { + cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count)); rc = -EIO; *nbytes = 0; } else { @@ -508,16 +528,19 @@ (char *) (&pSMBr->hdr.Protocol) + le16_to_cpu(pSMBr->DataOffset); /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) { - cERROR(1,("\nFaulting on read rc = %d",rc)); + cERROR(1,("Faulting on read rc = %d",rc)); rc = -EFAULT; }*/ /* can not use copy_to_user when using page cache*/ - memcpy(buf,pReadData,pSMBr->DataLength); + if(*buf) + memcpy(*buf,pReadData,pSMBr->DataLength); } } - - if (pSMB) - buf_release(pSMB); - + if (pSMB) { + if(*buf) + buf_release(pSMB); + else + *buf = (char *)pSMB; + } return rc; } @@ -542,9 +565,9 @@ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); pSMB->OffsetHigh = cpu_to_le32(offset >> 32); pSMB->Remaining = 0; - if (count > ((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00)) + if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00)) pSMB->DataLengthLow = - (tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00; + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00; else pSMB->DataLengthLow = count; pSMB->DataLengthHigh = 0; @@ -561,7 +584,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, long_op); if (rc) { - cERROR(1, ("\nSend error in write = %d\n", rc)); + cERROR(1, ("Send error in write = %d", rc)); *nbytes = 0; } else *nbytes = le16_to_cpu(pSMBr->Count); @@ -583,7 +606,7 @@ LOCK_RSP *pSMBr = NULL; int bytes_returned; - cFYI(1, ("\nIn CIFSSMBLock")); + cFYI(1, ("In CIFSSMBLock")); rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -607,7 +630,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in Lock = %d\n", rc)); + cERROR(1, ("Send error in Lock = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -622,7 +645,7 @@ CLOSE_REQ *pSMB = NULL; CLOSE_RSP *pSMBr = NULL; int bytes_returned; - cFYI(1, ("\nIn CIFSSMBClose")); + cFYI(1, ("In CIFSSMBClose")); rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -635,7 +658,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in Close = %d\n", rc)); + cERROR(1, ("Send error in Close = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -654,7 +677,7 @@ int bytes_returned; int name_len, name_len2; - cFYI(1, ("\nIn CIFSSMBRename")); + cFYI(1, ("In CIFSSMBRename")); rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -682,7 +705,6 @@ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len); @@ -702,7 +724,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in RMDir = %d\n", rc)); + cFYI(1, ("Send error in RMDir = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -723,7 +745,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn Symlink Unix style")); + cFYI(1, ("In Symlink Unix style")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -788,7 +810,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, - ("\nSend error in SetPathInfo (create symlink) = %d\n", + ("Send error in SetPathInfo (create symlink) = %d", rc)); } @@ -810,7 +832,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn Create Hard link Unix style")); + cFYI(1, ("In Create Hard link Unix style")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -873,7 +895,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in SetPathInfo (hard link) = %d\n", rc)); + cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); } if (pSMB) @@ -892,7 +914,7 @@ int bytes_returned; int name_len, name_len2; - cFYI(1, ("\nIn CIFSCreateHardLink")); + cFYI(1, ("In CIFSCreateHardLink")); rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -923,7 +945,6 @@ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len); @@ -942,7 +963,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in hard link (NT rename) = %d\n", rc)); + cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); } if (pSMB) buf_release(pSMB); @@ -963,7 +984,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn QPathSymLinkInfo (Unix) for path %s", searchName)); + cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -977,7 +998,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -1011,7 +1031,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in QuerySymLinkInfo = %d\n", rc)); + cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); @@ -1066,7 +1086,7 @@ struct smb_com_transaction_ioctl_req * pSMB; struct smb_com_transaction_ioctl_rsp * pSMBr; - cFYI(1, ("\nIn Windows reparse style QueryLink info for path %s", searchName)); + cFYI(1, ("In Windows reparse style QueryLink info for path %s", searchName)); rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1093,7 +1113,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in QueryReparseLinkInfo = %d\n", rc)); + cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount); @@ -1121,11 +1141,11 @@ } } else { rc = -EIO; - cFYI(1,("\nInvalid return data count on get reparse info ioctl")); + cFYI(1,("Invalid return data count on get reparse info ioctl")); } symlinkinfo[buflen] = 0; /* just in case so the caller does not go off the end of the buffer */ - cFYI(1,("\nreadlink result - %s ",symlinkinfo)); + cFYI(1,("readlink result - %s ",symlinkinfo)); } } if (pSMB) @@ -1146,7 +1166,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn QPathInfo path %s", searchName)); + cFYI(1, ("In QPathInfo path %s", searchName)); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1160,7 +1180,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -1194,7 +1213,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in QPathInfo = %d\n", rc)); + cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ @@ -1223,7 +1242,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn QPathInfo (Unix) the path %s", searchName)); + cFYI(1, ("In QPathInfo (Unix) the path %s", searchName)); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1237,7 +1256,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -1271,7 +1289,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in QPathInfo = %d\n", rc)); + cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ @@ -1300,7 +1318,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn FindUnique")); + cFYI(1, ("In FindUnique")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1314,7 +1332,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -1353,7 +1370,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in FindFileDirInfo = %d\n", rc)); + cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); } else { /* decode response */ /* BB fill in */ @@ -1378,7 +1395,7 @@ int bytes_returned; int name_len; - cFYI(1, ("\nIn FindFirst")); + cFYI(1, ("In FindFirst")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1392,7 +1409,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -1401,7 +1417,7 @@ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(10); - pSMB->MaxDataCount = cpu_to_le16((tcon->ses->maxBuf - + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; @@ -1441,7 +1457,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ - cFYI(1, ("\nError in FindFirst = %d\n", rc)); + cFYI(1, ("Error in FindFirst = %d", rc)); } else { /* decode response */ /* BB add safety checks for these memcpys */ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) @@ -1480,7 +1496,7 @@ int rc = 0; int bytes_returned; - cFYI(1, ("\nIn FindNext")); + cFYI(1, ("In FindNext")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1490,7 +1506,7 @@ pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(8); pSMB->MaxDataCount = - cpu_to_le16((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -1533,7 +1549,7 @@ if (rc == -EBADF) rc = 0; /* search probably was closed at end of search above */ else - cFYI(1, ("\nFindNext returned = %d\n", rc)); + cFYI(1, ("FindNext returned = %d", rc)); } else { /* decode response */ /* BB add safety checks for these memcpys */ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) @@ -1574,7 +1590,7 @@ *number_of_UNC_in_array = 0; *targetUNCs = NULL; - cFYI(1, ("\nIn GetDFSRefer the path %s", searchName)); + cFYI(1, ("In GetDFSRefer the path %s", searchName)); if (ses == NULL) return -ENODEV; @@ -1591,7 +1607,7 @@ if (ses->capabilities & CAP_DFS) { pSMB->hdr.Flags2 |= SMBFLG2_DFS; } - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; if (ses->capabilities & CAP_UNICODE) { @@ -1604,7 +1620,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->RequestFileName, searchName, name_len); @@ -1636,7 +1651,7 @@ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSend error in GetDFSRefer = %d\n", rc)); + cFYI(1, ("Send error in GetDFSRefer = %d", rc)); } else { /* decode response */ /* BB Add logic to parse referrals here */ } @@ -1656,7 +1671,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn QFSInfo")); + cFYI(1, ("In QFSInfo")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1689,11 +1704,11 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in QFSInfo = %d\n", rc)); + cERROR(1, ("Send error in QFSInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); cFYI(1, - ("\nDecoding qfsinfo response. BCC: %d Offset %d\n", + ("Decoding qfsinfo response. BCC: %d Offset %d", pSMBr->ByteCount, pSMBr->DataOffset)); if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ @@ -1711,7 +1726,7 @@ FSData->f_bfree = FSData->f_bavail = le64_to_cpu(response_data->FreeAllocationUnits); cFYI(1, - ("\nBlocks: %ld Free: %ld Block size %ld\n", + ("Blocks: %ld Free: %ld Block size %ld", FSData->f_blocks, FSData->f_bfree, FSData->f_bsize)); } @@ -1732,7 +1747,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn QFSAttributeInfo")); + cFYI(1, ("In QFSAttributeInfo")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1764,7 +1779,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in QFSAttributeInfo = %d\n", rc)); + cERROR(1, ("Send error in QFSAttributeInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */ @@ -1794,7 +1809,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn QFSDeviceInfo")); + cFYI(1, ("In QFSDeviceInfo")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1828,7 +1843,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in QFSDeviceInfo = %d\n", rc)); + cERROR(1, ("Send error in QFSDeviceInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) @@ -1859,7 +1874,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn QFSUnixInfo")); + cFYI(1, ("In QFSUnixInfo")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -1891,7 +1906,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("\nSend error in QFSUnixInfo = %d\n", rc)); + cERROR(1, ("Send error in QFSUnixInfo = %d", rc)); } else { /* decode response */ pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset); if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { @@ -1927,7 +1942,7 @@ int rc = 0; int bytes_returned = 0; - cFYI(1, ("\nIn SetEOF")); + cFYI(1, ("In SetEOF")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1942,7 +1957,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); @@ -1995,7 +2009,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSetPathInfo (file size) returned %d\n", rc)); + cFYI(1, ("SetPathInfo (file size) returned %d", rc)); } if (pSMB) @@ -2015,7 +2029,7 @@ int bytes_returned = 0; __u32 tmp; - cFYI(1, ("\nSetFileSize (via SetFileInfo)")); + cFYI(1, ("SetFileSize (via SetFileInfo)")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2080,7 +2094,7 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, - ("\nSend error in SetFileInfo (SetFileSize) = %d\n", + ("Send error in SetFileInfo (SetFileSize) = %d", rc)); } @@ -2100,7 +2114,7 @@ int bytes_returned = 0; char *data_offset; - cFYI(1, ("\nIn SetTimes")); + cFYI(1, ("In SetTimes")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2115,7 +2129,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); @@ -2156,7 +2169,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSetPathInfo (times) returned %d\n", rc)); + cFYI(1, ("SetPathInfo (times) returned %d", rc)); } if (pSMB) @@ -2176,7 +2189,7 @@ int bytes_returned = 0; FILE_UNIX_BASIC_INFO *data_offset; - cFYI(1, ("\nIn SetUID/GID/Mode")); + cFYI(1, ("In SetUID/GID/Mode")); rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2191,7 +2204,6 @@ name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); @@ -2232,7 +2244,7 @@ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("\nSetPathInfo (perms) returned %d\n", rc)); + cFYI(1, ("SetPathInfo (perms) returned %d", rc)); } if (pSMB) diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/connect.c Mon Feb 17 14:57:28 2003 @@ -60,22 +60,61 @@ int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket); + + /* + * cifs tcp session reconnection + * + * mark tcp session as reconnecting so temporarily locked + * mark all smb sessions as reconnecting for tcp session (TBD BB) + * reconnect tcp session + * wake up waiters on reconnection? - (not needed currently) + */ + int cifs_reconnect(struct TCP_Server_Info *server) { int rc = 0; + struct list_head *tmp; + struct cifsSesInfo *ses; - cFYI(1, ("\nReconnecting tcp session ")); + server->tcpStatus = CifsNeedReconnect; + server->maxBuf = 0; - /* lock tcp session */ - /* mark all smb sessions as reconnecting which use this tcp session */ - /* reconnect tcp session */ - /* wake up waiters on reconnection */ - cFYI(1, - ("\nState: 0x%x Flags: 0x%lx", server->ssocket->state, - server->ssocket->flags)); + cFYI(1, ("Reconnecting tcp session ")); + + read_lock(&GlobalSMBSeslock); + list_for_each(tmp, &GlobalSMBSessionList) { + ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); + if (ses->server) { + if (ses->server == server) { + ses->status = CifsNeedReconnect; + } + } + /* else tcp and smb sessions need reconnection */ + } + read_unlock(&GlobalSMBSeslock); + + if(server->ssocket) { + cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state, + server->ssocket->flags)); + server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);; + cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state, + server->ssocket->flags)); + sock_release(server->ssocket); + server->ssocket = NULL; + } + + while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) + { + rc = ipv4_connect(&server->sockAddr, &server->ssocket); + if(rc) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(3 * HZ); + } else { + server->tcpStatus = CifsGood; + } + } - ipv4_connect(&server->sockAddr, &server->ssocket); return rc; } @@ -99,7 +138,7 @@ allow_signal(SIGKILL); server->tsk = current; /* save process info to wake at shutdown */ - cFYI(1, ("\nDemultiplex PID: %d", current->pid)); + cFYI(1, ("Demultiplex PID: %d", current->pid)); temp_fs = get_fs(); /* we must turn off socket api parm checking */ set_fs(get_ds()); @@ -112,7 +151,7 @@ if (smb_buffer == NULL) { cERROR(1, - ("\n Error - can not get mem for SMB response buffer ")); + ("Can not get mem for SMB response buffer ")); return -ENOMEM; } iov.iov_base = smb_buffer; @@ -130,25 +169,26 @@ MSG_PEEK /* flags see socket.h */ ); if (length < 0) { if (length == -ECONNRESET) { - cERROR(1, ("\nConnection reset by peer ")); - /* BB fix call below */ - /* cifs_reconnect(server); */ + cERROR(1, ("Connection reset by peer ")); + cifs_reconnect(server); + csocket = server->ssocket; + continue; } else { /* find define for the -512 returned at unmount time */ cFYI(1, - ("\nReceived error on sock_recvmsg( peek) with length = %d\n", + ("Received error on sock_recvmsg( peek) with length = %d", length)); } break; } if (length == 0) { cFYI(1, - ("\nZero length peek received - dead session?? ")); - /* schedule_timeout(HZ/4); - continue; */ - break; + ("Zero length peek received - dead session?")); + cifs_reconnect(server); + csocket = server->ssocket; + continue; } pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); - cFYI(1, ("\nPeek length rcvd: %d with smb length: %d", length, pdu_length)); /* BB */ + cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length)); /* BB */ temp = (char *) smb_buffer; if (length > 3) { @@ -157,18 +197,18 @@ iov.iov_len = 4; length = sock_recvmsg(csocket, &smb_msg, 4, 0); cFYI(0, - ("\nReceived 4 byte keep alive packet ")); + ("Received 4 byte keep alive packet ")); } else if ((temp[0] == (char) 0x83) && (length == 5)) { /* we get this from Windows 98 instead of error on SMB negprot response */ cERROR(1, - ("\nNegative RFC 1002 Session response. Error = 0x%x", + ("Negative RFC 1002 Session response. Error = 0x%x", temp[4])); break; } else if (temp[0] != (char) 0) { cERROR(1, - ("\nUnknown RFC 1001 frame received not 0x00 nor 0x85")); + ("Unknown RFC 1001 frame received not 0x00 nor 0x85")); cifs_dump_mem(" Received Data is: ", temp, length); break; } else { @@ -182,7 +222,7 @@ (smb_buffer, smb_buffer->Mid))) { cERROR(1, (KERN_ERR - "\nInvalid size or format for SMB found with length %d and pdu_lenght %d\n", + "Invalid size or format for SMB found with length %d and pdu_lenght %d", length, pdu_length)); /* BB fix by finding next smb signature - and reading off data until next smb ? BB */ @@ -200,11 +240,11 @@ iov.iov_len = pdu_length-total_read; */ length = sock_recvmsg(csocket, &smb_msg, pdu_length - total_read, 0); - /* cERROR(1,("\nFor iovlen %d Length received: %d with total read %d", + /* cERROR(1,("For iovlen %d Length received: %d with total read %d", iov.iov_len, length,total_read)); */ if (length == 0) { cERROR(1, - ("\nZero length receive when expecting %d ", + ("Zero length receive when expecting %d ", pdu_length - total_read)); /* BB add reconnect here */ break; @@ -215,11 +255,11 @@ dump_smb(smb_buffer, length); if (checkSMB (smb_buffer, smb_buffer->Mid, total_read)) { - cERROR(1, ("\n Bad SMB Received ")); + cERROR(1, ("Bad SMB Received ")); continue; } - task_to_wake = NULL; + task_to_wake = NULL; read_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct @@ -228,7 +268,7 @@ if (mid_entry->mid == smb_buffer->Mid) { cFYI(1, - (" Mid 0x%x matched - waking up\n ",mid_entry->mid)); + (" Mid 0x%x matched - waking up ",mid_entry->mid)); task_to_wake = mid_entry->tsk; mid_entry->resp_buf = smb_buffer; @@ -241,17 +281,17 @@ smb_buffer = NULL; /* will be freed by users thread after he is done */ wake_up_process(task_to_wake); } else if (is_valid_oplock_break(smb_buffer) == FALSE) { - cERROR(1, ("\n No task to wake, unknown frame rcvd!\n")); - } + cERROR(1, ("No task to wake, unknown frame rcvd!")); + } } } else { cFYI(0, - ("\nFrame less than four bytes received %d bytes long.", + ("Frame less than four bytes received %d bytes long.", length)); if (length > 0) { length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */ cFYI(1, - (" with junk 0x%x in it\n", + (" with junk 0x%x in it ", *(__u32 *) smb_buffer)); } } @@ -280,13 +320,12 @@ kfree(server); } else /* BB need to more gracefully handle the rare negative session response case because response will be still outstanding */ - cERROR(1, ("\nThere are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!\n ")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */ + cERROR(1, ("There are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */ /* BB Need to fix bug in error path above - perhaps wait until smb requests time out and then free the tcp per server struct BB */ read_unlock(&GlobalSMBSeslock); - - cFYI(1, ("\nAbout to exit from demultiplex thread\n")); + cFYI(1, ("About to exit from demultiplex thread")); return 0; } @@ -315,14 +354,14 @@ *value++ = '\0'; if (strnicmp(data, "user", 4) == 0) { if (!value || !*value) { - printk(KERN_ERR - "CIFS: invalid or missing username"); + printk(KERN_WARNING + "CIFS: invalid or missing username\n"); return 1; /* needs_arg; */ } if (strnlen(value, 200) < 200) { vol->username = value; } else { - printk(KERN_ERR "CIFS: username too long"); + printk(KERN_WARNING "CIFS: username too long\n"); return 1; } } else if (strnicmp(data, "pass", 4) == 0) { @@ -331,15 +370,15 @@ } else if (strnlen(value, 17) < 17) { vol->password = value; } else { - printk(KERN_ERR "CIFS: password too long"); + printk(KERN_WARNING "CIFS: password too long\n"); return 1; } } else if ((strnicmp(data, "unc", 3) == 0) || (strnicmp(data, "target", 6) == 0) || (strnicmp(data, "path", 4) == 0)) { if (!value || !*value) { - printk(KERN_ERR - "CIFS: invalid path to network resource"); + printk(KERN_WARNING + "CIFS: invalid path to network resource\n"); return 1; /* needs_arg; */ } if (strnlen(value, 300) < 300) { @@ -348,26 +387,26 @@ vol->UNC[0] = '\\'; vol->UNC[1] = '\\'; } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { - printk(KERN_ERR - "CIFS: UNC Path does not begin with // or \\\\"); + printk(KERN_WARNING + "CIFS: UNC Path does not begin with // or \\\\ \n"); return 1; } vol->UNCip = &vol->UNC[2]; } else { - printk(KERN_ERR "CIFS: UNC name too long"); + printk(KERN_WARNING "CIFS: UNC name too long\n"); return 1; } } else if ((strnicmp(data, "domain", 3) == 0) || (strnicmp(data, "workgroup", 5) == 0)) { if (!value || !*value) { - printk(KERN_ERR "CIFS: invalid domain name"); + printk(KERN_WARNING "CIFS: invalid domain name\n"); return 1; /* needs_arg; */ } if (strnlen(value, 65) < 65) { vol->domainname = value; - cFYI(1, ("\nDomain name set")); + cFYI(1, ("Domain name set")); } else { - printk(KERN_ERR "CIFS: domain name too long"); + printk(KERN_WARNING "CIFS: domain name too long\n"); return 1; } } else if (strnicmp(data, "uid", 3) == 0) { @@ -395,9 +434,7 @@ } else if (strnicmp(data, "rw", 2) == 0) { vol->rw = TRUE; } else - printk(KERN_ERR - "CIFS: Unrecognized mount option %s = %s", - data, value); + printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data); } if (vol->UNC == NULL) { if (strnlen(devname, 300) < 300) { @@ -406,13 +443,12 @@ vol->UNC[0] = '\\'; vol->UNC[1] = '\\'; } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { - printk(KERN_ERR - "CIFS: UNC Path does not begin with // or \\\\"); + printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n"); return 1; } vol->UNCip = &vol->UNC[2]; } else { - printk(KERN_ERR "CIFS: UNC name too long"); + printk(KERN_WARNING "CIFS: UNC name too long\n"); return 1; } } @@ -458,7 +494,7 @@ read_lock(&GlobalSMBSeslock); list_for_each(tmp, &GlobalTreeConnectionList) { - cFYI(1, ("\nNext tcon - ")); + cFYI(1, ("Next tcon - ")); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); if (tcon->ses) { if (tcon->ses->server) { @@ -472,13 +508,13 @@ /* found a match on the TCP session */ /* BB check if reconnection needed */ cFYI(1, - ("\nMatched ip, old UNC: %s == new: %s ?", + ("Matched ip, old UNC: %s == new: %s ?", tcon->treeName, uncName)); if (strncmp (tcon->treeName, uncName, MAX_TREE_SIZE) == 0) { cFYI(1, - ("\nMatched UNC, old user: %s == new: %s ?", + ("Matched UNC, old user: %s == new: %s ?", tcon->treeName, uncName)); if (strncmp (tcon->ses->userName, @@ -522,45 +558,118 @@ SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6); rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); cFYI(1, - ("\nCIFS Tcon rc = %d ipc_tid = %d\n", rc, - pSesInfo->ipc_tid)); + ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid)); kfree(temp_unc); } if (rc == 0) rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &referrals, &num_referrals, nls_codepage); - return -ENODEV; /* BB remove and add return rc; */ + return -ENODEV; /* BB remove and add return code processing */ } +int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info) +{ + int rc = 0; + char session_key[CIFS_SESSION_KEY_SIZE]; + char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; + int ntlmv2_flag = FALSE; + + if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ + rc = CIFSSMBNegotiate(xid, pSesInfo); + pSesInfo->capabilities = pSesInfo->server->capabilities; + if (!rc) { + cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", + pSesInfo->server->secMode, + pSesInfo->server->capabilities, + pSesInfo->server->timeZone)); + if (extended_security + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) + && (pSesInfo->server->secType == NTLMSSP)) { + cFYI(1, ("New style sesssetup ")); + rc = CIFSSpnegoSessSetup(xid, pSesInfo, + NULL /* security blob */, + 0 /* blob length */, + nls_info); + } else if (extended_security + && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) + && (pSesInfo->server->secType == RawNTLMSSP)) { + cFYI(1, ("NTLMSSP sesssetup ")); + rc = CIFSNTLMSSPNegotiateSessSetup(xid, + pSesInfo, + &ntlmv2_flag, + nls_info); + if (!rc) { + if(ntlmv2_flag) { + cFYI(1,("Able to use the more secure NTLM version 2 password hash")); + /* SMBNTv2encrypt( ...); */ /* BB fix this up - + and note that Samba client equivalent looks wrong */ + } else + SMBNTencrypt(pSesInfo->password_with_pad, + pSesInfo->server->cryptKey,ntlm_session_key); + + /* for better security the weaker lanman hash not sent + in AuthSessSetup so why bother calculating it */ + /* toUpper(nls_info, + password_with_pad); + SMBencrypt(password_with_pad, + pSesInfo->server->cryptKey, session_key); */ + + rc = CIFSNTLMSSPAuthSessSetup(xid, + pSesInfo, + ntlm_session_key, + session_key, + ntlmv2_flag, + nls_info); + } + } else { /* old style NTLM 0.12 session setup */ + SMBNTencrypt(pSesInfo->password_with_pad, + pSesInfo->server->cryptKey, + ntlm_session_key); + rc = CIFSSessSetup(xid, pSesInfo, + session_key, + ntlm_session_key, + nls_info); + } + if (rc) { + cERROR(1,("Send error in SessSetup = %d",rc)); + } else { + cFYI(1,("CIFS Session Established successfully")); + pSesInfo->status = CifsGood; + } + } + return rc; +} + int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket) { int rc = 0; - rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket); - if (rc < 0) { - cERROR(1, ("Error creating socket. Aborting operation\n")); - return rc; + if(*csocket == NULL) { + rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket); + if (rc < 0) { + cERROR(1, ("Error %d creating socket",rc)); + *csocket = NULL; + return rc; + } else { + cFYI(1,("Socket created")); + } } psin_server->sin_family = AF_INET; psin_server->sin_port = htons(CIFS_PORT); rc = (*csocket)->ops->connect(*csocket, - (struct sockaddr *) psin_server, - sizeof (struct sockaddr_in), 0 - /* Is there a way to fix a polling timeout - - and find out what more of the flags really mean? */ - ); + (struct sockaddr *) psin_server, + sizeof (struct sockaddr_in),0); if (rc < 0) { psin_server->sin_port = htons(RFC1001_PORT); rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) - psin_server, - sizeof (struct sockaddr_in), 0); + psin_server, sizeof (struct sockaddr_in),0); if (rc < 0) { - cFYI(1, ("Error connecting to socket. %d\n", rc)); + cFYI(1, ("Error connecting to socket. %d", rc)); sock_release(*csocket); *csocket = NULL; return rc; @@ -578,7 +687,7 @@ rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP /* IPPROTO_IPV6 ? */ , csocket); if (rc < 0) { - cERROR(1, ("Error creating socket. Aborting operation\n")); + cERROR(1, ("Error creating socket. Aborting operation")); return rc; } @@ -597,7 +706,7 @@ sizeof (struct sockaddr_in6), 0); if (rc < 0) { cFYI(1, - ("Error connecting to socket (via ipv6). %d\n", + ("Error connecting to socket (via ipv6). %d", rc)); sock_release(*csocket); *csocket = NULL; @@ -614,8 +723,7 @@ { int rc = 0; int xid; - int ntlmv2_flag = FALSE; - struct socket *csocket; + struct socket *csocket = NULL; struct sockaddr_in sin_server; /* struct sockaddr_in6 sin_server6; */ struct smb_vol volume_info; @@ -623,35 +731,33 @@ struct cifsSesInfo *existingCifsSes = NULL; struct cifsTconInfo *tcon = NULL; struct TCP_Server_Info *srvTcp = NULL; - char cryptKey[CIFS_CRYPTO_KEY_SIZE]; - char session_key[CIFS_SESSION_KEY_SIZE]; - char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; - char password_with_pad[CIFS_ENCPWD_SIZE]; xid = GetXid(); - cFYI(0, ("\nEntering cifs_mount. Xid: %d with: %s\n", xid, mount_data)); + cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); if(parse_mount_options(mount_data, devname, &volume_info)) { FreeXid(xid); return -EINVAL; } - if (volume_info.username) { - cFYI(1, ("\nUsername: %s ", volume_info.username)); + cFYI(1, ("Username: %s ", volume_info.username)); } else { - cERROR(1, ("\nNo username specified ")); - /* Could add ways to allow getting user name from alternate locations */ + cifserror("No username specified "); + /* In userspace mount helper we can get user name from alternate + locations such as env variables and files on disk */ + FreeXid(xid); + return -EINVAL; } if (volume_info.UNC) { sin_server.sin_addr.s_addr = inet_addr(volume_info.UNCip); - cFYI(1, ("\nUNC: %s ", volume_info.UNC)); + cFYI(1, ("UNC: %s ", volume_info.UNC)); } else { /* BB we could connect to the DFS root? but which server do we ask? */ cERROR(1, - ("\nCIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); + ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); FreeXid(xid); return -EINVAL; } @@ -660,12 +766,14 @@ find_tcp_session(sin_server.sin_addr.s_addr, volume_info.username, &srvTcp); if (srvTcp) { - cFYI(1, ("\nExisting tcp session with server found ")); + cFYI(1, ("Existing tcp session with server found ")); } else { /* create socket */ rc = ipv4_connect(&sin_server, &csocket); if (rc < 0) { cERROR(1, - ("Error connecting to IPv4 socket. Aborting operation\n")); + ("Error connecting to IPv4 socket. Aborting operation")); + if(csocket != NULL) + sock_release(csocket); FreeXid(xid); return rc; } @@ -683,6 +791,7 @@ srvTcp->ssocket = csocket; init_waitqueue_head(&srvTcp->response_q); INIT_LIST_HEAD(&srvTcp->pending_mid_q); + srvTcp->tcpStatus = CifsGood; kernel_thread((void *) (void *) cifs_demultiplex_thread, srvTcp, CLONE_FS | CLONE_FILES | CLONE_VM); @@ -691,113 +800,32 @@ if (existingCifsSes) { pSesInfo = existingCifsSes; - cFYI(1, ("\nExisting smb sess found ")); + cFYI(1, ("Existing smb sess found ")); } else if (!rc) { - cFYI(1, ("\nExisting smb sess not found ")); + cFYI(1, ("Existing smb sess not found ")); pSesInfo = sesInfoAlloc(); if (pSesInfo == NULL) rc = -ENOMEM; else { pSesInfo->server = srvTcp; - pSesInfo->status = CifsGood; sprintf(pSesInfo->serverName, "%u.%u.%u.%u", NIPQUAD(sin_server.sin_addr.s_addr)); } - /* send negotiate protocol smb */ - if (!rc) - rc = CIFSSMBNegotiate(xid, pSesInfo, cryptKey); - cFYI(0, ("\nNegotiate rc = %d ", rc)); - if (!rc) { - cFYI(1, ("\nSecurity Mode: %x", pSesInfo->secMode)); - cFYI(1, - (" Server Capabilities: %x", - pSesInfo->capabilities)); - cFYI(1, - (" Time Zone: 0x%x %d\n", pSesInfo->timeZone, - pSesInfo->timeZone)); - - memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); + if (!rc){ if (volume_info.password) - strcpy(password_with_pad, volume_info.password); - - if (extended_security - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) - && (pSesInfo->secType == NTLMSSP)) { - cFYI(1, ("\nNew style sesssetup ")); - rc = CIFSSpnegoSessSetup(xid, pSesInfo, - volume_info. - username, - volume_info. - domainname, NULL - /* security blob */ - , 0 /* blob length */ - , cifs_sb->local_nls); - } else if (extended_security - && (pSesInfo-> - capabilities & CAP_EXTENDED_SECURITY) - && (pSesInfo->secType == RawNTLMSSP)) { - cFYI(1, ("\nNTLMSSP sesssetup ")); - rc = CIFSNTLMSSPNegotiateSessSetup(xid, - pSesInfo, - cryptKey, - volume_info.domainname, - &ntlmv2_flag, - cifs_sb->local_nls); - if (!rc) { - if(ntlmv2_flag) { - cFYI(1,("\nAble to use the more secure NTLM version 2 password hash")); - /* SMBNTv2encrypt( ...); */ /* BB fix this up - - and note that Samba client equivalent looks wrong */ - } else - SMBNTencrypt(password_with_pad,cryptKey,ntlm_session_key); - - /* for better security the weaker lanman hash not sent - in AuthSessSetup so why bother calculating it */ - - /* toUpper(cifs_sb->local_nls, - password_with_pad); - SMBencrypt(password_with_pad, - cryptKey, session_key); */ - - rc = CIFSNTLMSSPAuthSessSetup(xid, - pSesInfo, - volume_info. - username, - volume_info.domainname, - ntlm_session_key, - session_key, - ntlmv2_flag, - cifs_sb->local_nls); - } - } else { /* old style NTLM 0.12 session setup */ - SMBNTencrypt(password_with_pad, cryptKey, - ntlm_session_key); - /* Removed following few lines to not send old style password - hash ever - for better security */ - /* toUpper(cifs_sb->local_nls, password_with_pad); - SMBencrypt(password_with_pad, cryptKey,session_key); */ - - rc = CIFSSessSetup(xid, pSesInfo, - volume_info.username, - volume_info. - domainname, - session_key, - ntlm_session_key, - cifs_sb->local_nls); - } - if (rc) { - cERROR(1, - ("\nSend error in SessSetup = %d\n", - rc)); - } else { - cFYI(1, - ("CIFS Session Established successfully ")); + strncpy(pSesInfo->password_with_pad, + volume_info.password,CIFS_ENCPWD_SIZE); + if (volume_info.username) strncpy(pSesInfo->userName, - volume_info.username, - MAX_USERNAME_SIZE); + volume_info.username,MAX_USERNAME_SIZE); + if (volume_info.domainname) + strncpy(pSesInfo->domainName, + volume_info.domainname,MAX_USERNAME_SIZE); + + rc = setup_session(xid,pSesInfo, cifs_sb->local_nls); + if(!rc) atomic_inc(&srvTcp->socketUseCount); - } } } @@ -807,7 +835,7 @@ find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, volume_info.username); if (tcon) { - cFYI(1, ("\nFound match on UNC path ")); + cFYI(1, ("Found match on UNC path ")); } else { tcon = tconInfoAlloc(); if (tcon == NULL) @@ -830,7 +858,7 @@ rc = CIFSTCon(xid, pSesInfo, volume_info.UNC, tcon, cifs_sb->local_nls); - cFYI(1, ("\nCIFS Tcon rc = %d\n", rc)); + cFYI(1, ("CIFS Tcon rc = %d", rc)); } if (!rc) atomic_inc(&pSesInfo->inUse); @@ -838,7 +866,7 @@ } } if (pSesInfo->capabilities & CAP_LARGE_FILES) { - cFYI(0, ("\nLarge files supported ")); + cFYI(0, ("Large files supported ")); sb->s_maxbytes = (u64) 1 << 63; } else sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ @@ -846,19 +874,21 @@ /* on error free sesinfo and tcon struct if needed */ if (rc) { /* If find_unc succeeded then rc == 0 so we can not end */ - if (tcon) /* up here accidently freeing someone elses tcon struct */ + if (tcon) /* up here accidently freeing someone elses tcon struct */ tconInfoFree(tcon); if (existingCifsSes == 0) { if (pSesInfo) { if (pSesInfo->server) { - cFYI(0, - ("\nAbout to check if we need to do SMBLogoff ")); if (pSesInfo->Suid) CIFSSMBLogoff(xid, pSesInfo); - wake_up_process(pSesInfo->server->tsk); + if(pSesInfo->server->tsk) + send_sig(SIGINT,pSesInfo->server->tsk,1); + else + cFYI(1,("Can not wake captive thread on cleanup of failed mount")); + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 4); /* give captive thread time to exit */ } else - cFYI(1, ("\nNo session or bad tcon")); + cFYI(1, ("No session or bad tcon")); sesInfoFree(pSesInfo); /* pSesInfo = NULL; */ } @@ -876,13 +906,12 @@ } FreeXid(xid); - return rc; } int -CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user, - char *domain, char session_key[CIFS_SESSION_KEY_SIZE], +CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, + char session_key[CIFS_SESSION_KEY_SIZE], char session_key2[CIFS_SESSION_KEY_SIZE], const struct nls_table *nls_codepage) { @@ -891,12 +920,14 @@ SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; + char *user = ses->userName; + char *domain = ses->domainName; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; - cFYI(1, ("\nIn sesssetup ")); + cFYI(1, ("In sesssetup ")); smb_buffer = buf_get(); if (smb_buffer == 0) { @@ -910,10 +941,10 @@ 0 /* no tCon exists yet */ , 13 /* wct */ ); pSMB->req_no_secext.AndXCommand = 0xFF; - pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->maxBuf); - pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->maxReq); + pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; pSMB->req_no_secext.Capabilities = @@ -1136,21 +1167,22 @@ int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *user, char *domain, char *SecurityBlob, - int SecurityBlobLength, - const struct nls_table *nls_codepage) + char *SecurityBlob,int SecurityBlobLength, + const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer_response; SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; + char *user = ses->userName; + char *domain = ses->domainName; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; - cFYI(1, ("\nIn v2 sesssetup ")); + cFYI(1, ("In v2 sesssetup ")); smb_buffer = buf_get(); if (smb_buffer == 0) { @@ -1164,10 +1196,10 @@ 0 /* no tCon exists yet */ , 12 /* wct */ ); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq); + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; pSMB->req.Capabilities = @@ -1276,7 +1308,7 @@ bcc_ptr += pSMBr->resp.SecurityBlobLength; cFYI(1, - ("\nSecurity Blob Length %d ", + ("Security Blob Length %d ", pSMBr->resp.SecurityBlobLength)); } @@ -1394,9 +1426,7 @@ int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, - struct cifsSesInfo *ses, - char *challenge_from_server, - char *domain, int * pNTLMv2_flag, + struct cifsSesInfo *ses, int * pNTLMv2_flag, const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; @@ -1404,6 +1434,7 @@ SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; + char *domain = ses->domainName; int rc = 0; int remaining_words = 0; int bytes_returned = 0; @@ -1412,7 +1443,7 @@ PNEGOTIATE_MESSAGE SecurityBlob; PCHALLENGE_MESSAGE SecurityBlob2; - cFYI(1, ("\nIn NTLMSSP sesssetup (negotiate) ")); + cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); *pNTLMv2_flag = FALSE; smb_buffer = buf_get(); if (smb_buffer == 0) { @@ -1429,10 +1460,10 @@ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq); + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; pSMB->req.Capabilities = @@ -1555,7 +1586,7 @@ SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; if (SecurityBlob2->MessageType != NtLmChallenge) { cFYI(1, - ("\nUnexpected NTLMSSP message type received %d", + ("Unexpected NTLMSSP message type received %d", SecurityBlob2->MessageType)); } else if (ses) { ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ @@ -1568,13 +1599,13 @@ bcc_ptr += pSMBr->resp.SecurityBlobLength; cFYI(1, - ("\nSecurity Blob Length %d ", + ("Security Blob Length %d ", pSMBr->resp.SecurityBlobLength)); } - cFYI(1, ("\nNTLMSSP Challenge rcvd ")); + cFYI(1, ("NTLMSSP Challenge rcvd ")); - memcpy(challenge_from_server, + memcpy(ses->server->cryptKey, SecurityBlob2->Challenge, CIFS_CRYPTO_KEY_SIZE); if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2) @@ -1722,16 +1753,16 @@ int CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *user, char *domain, - char *ntlm_session_key, - char *lanman_session_key, int ntlmv2_flag, - const struct nls_table *nls_codepage) + char *ntlm_session_key, char *lanman_session_key, int ntlmv2_flag, + const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer_response; SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; + char *user = ses->userName; + char *domain = ses->domainName; int rc = 0; int remaining_words = 0; int bytes_returned = 0; @@ -1739,7 +1770,7 @@ int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); PAUTHENTICATE_MESSAGE SecurityBlob; - cFYI(1, ("\nIn NTLMSSPSessSetup (Authenticate)")); + cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); smb_buffer = buf_get(); if (smb_buffer == 0) { @@ -1755,12 +1786,12 @@ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq); + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); pSMB->req.hdr.Uid = ses->Suid; - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; pSMB->req.Capabilities = @@ -1949,7 +1980,7 @@ if (pSMBr->resp.Action & GUEST_LOGIN) cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ /* if(SecurityBlob2->MessageType != NtLm??){ - cFYI("\nUnexpected message type on auth response is %d ")); + cFYI("Unexpected message type on auth response is %d ")); } */ if (ses) { cFYI(1, @@ -1966,12 +1997,12 @@ bcc_ptr += pSMBr->resp.SecurityBlobLength; cFYI(1, - ("\nSecurity Blob Length %d ", + ("Security Blob Length %d ", pSMBr->resp.SecurityBlobLength)); } cFYI(1, - ("\nNTLMSSP response to Authenticate ")); + ("NTLMSSP response to Authenticate ")); if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) { if ((long) (bcc_ptr) % 2) { @@ -2133,7 +2164,7 @@ bcc_ptr = &(pSMB->Password[0]); bcc_ptr++; /* skip password */ - if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; if (ses->capabilities & CAP_STATUS32) { @@ -2163,7 +2194,7 @@ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ - /* above now done in SendReceive */ + /* above now done in SendReceive */ if ((rc == 0) && (tcon != NULL)) { tcon->tid = smb_buffer_response->Tid; bcc_ptr = pByteArea(smb_buffer_response); @@ -2200,7 +2231,7 @@ /* else do not bother copying these informational fields */ } tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); - cFYI(1, ("\nTcon flags: 0x%x ", tcon->Flags)); + cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); } else if ((rc == 0) && tcon == NULL) { /* all we need to save for IPC$ connection */ ses->ipc_tid = smb_buffer_response->Tid; @@ -2229,27 +2260,28 @@ } tconInfoFree(cifs_sb->tcon); if ((ses) && (ses->server)) { - cFYI(1, ("\nAbout to do SMBLogoff ")); + cFYI(1, ("About to do SMBLogoff ")); rc = CIFSSMBLogoff(xid, ses); if (rc == -EBUSY) { - /* BB this looks wrong - why is this here? */ FreeXid(xid); return 0; } + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 4); /* give captive thread time to exit */ if((ses->server) && (ses->server->ssocket)) { - cFYI(1,("\nWaking up socket by sending it signal ")); + cFYI(1,("Waking up socket by sending it signal ")); send_sig(SIGINT,ses->server->tsk,1); } } else - cFYI(1, ("\nNo session or bad tcon")); + cFYI(1, ("No session or bad tcon")); } /* BB future check active count of tcon and then free if needed BB */ cifs_sb->tcon = NULL; if (ses) { + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 2); /* if ((ses->server) && (ses->server->ssocket)) { - cFYI(1,("\nReleasing socket ")); + cFYI(1,("Releasing socket ")); sock_release(ses->server->ssocket); kfree(ses->server); } */ diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c --- a/fs/cifs/dir.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/dir.c Mon Feb 17 14:57:27 2003 @@ -54,7 +54,6 @@ temp = temp->d_parent; } namelen += 1; /* allow for trailing null */ - cFYI(1, ("Final namelength (in build_path): %d ", namelen)); /* BB remove */ full_path = kmalloc(namelen, GFP_KERNEL); namelen--; full_path[namelen] = 0; /* trailing null */ @@ -66,13 +65,13 @@ full_path[namelen] = '\\'; strncpy(full_path + namelen + 1, temp->d_name.name, temp->d_name.len); - cFYI(1, (" name: %s ", full_path + namelen)); /* BB remove */ + cFYI(0, (" name: %s ", full_path + namelen)); } temp = temp->d_parent; } if (namelen != 0) cERROR(1, - ("\nWe did not end path lookup where we expected namelen is %d", + ("We did not end path lookup where we expected namelen is %d", namelen)); return full_path; @@ -111,7 +110,7 @@ } if (namelen != 0) cERROR(1, - ("\nWe did not end path lookup where we expected namelen is %d", + ("We did not end path lookup where we expected namelen is %d", namelen)); return full_path; @@ -124,7 +123,7 @@ { int rc = -ENOENT; int xid; - int oplock = FALSE; /* no need to oplock when we are not going to read from the file */ + int oplock = REQ_OPLOCK; __u16 fileHandle; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; @@ -144,7 +143,7 @@ /* 0x20197 was used previously */ , CREATE_NOT_DIR, &fileHandle, &oplock, cifs_sb->local_nls); if (rc) { - cFYI(1, ("\ncifs_create returned 0x%x ", rc)); + cFYI(1, ("cifs_create returned 0x%x ", rc)); } else { if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newinode, full_path, @@ -154,14 +153,17 @@ inode->i_sb); if (rc != 0) { - cFYI(1, - ("\nCreate worked but get_inode_info failed with rc = %d ", + cFYI(1,("Create worked but get_inode_info failed with rc = %d", rc)); /* close handle */ } else { direntry->d_op = &cifs_dentry_ops; d_instantiate(direntry, newinode); } + /* BB check oplock state before deciding to call following */ +/* if(*oplock) + save off handle in inode and dontdoclose */ + CIFSSMBClose(xid, pTcon, fileHandle); /* BB In the future chain close with the NTCreateX to narrow window */ @@ -204,7 +206,7 @@ cFYI(1, (" NULL inode in lookup")); } cFYI(1, - (" Full path: %s inode = 0x%p\n", full_path, direntry->d_inode)); + (" Full path: %s inode = 0x%p", full_path, direntry->d_inode)); if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newInode, full_path, parent_dir_inode->i_sb); @@ -224,7 +226,7 @@ d_add(direntry, NULL); } else { cERROR(1, - ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup\n", + ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup", rc, rc)); /* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ } @@ -251,7 +253,7 @@ full_path = build_wildcard_path_from_dentry(file->f_dentry); - cFYI(1, (" inode = 0x%p and full path is %s\n", inode, full_path)); + cFYI(1, (" inode = 0x%p and full path is %s", inode, full_path)); if (full_path) kfree(full_path); @@ -273,7 +275,7 @@ } } else { cFYI(1, - ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p\n", + ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p", direntry->d_name.name, direntry)); } @@ -286,7 +288,7 @@ { int rc = 0; - cFYI(1, ("In cifs d_delete, name = %s\n", direntry->d_name.name)); + cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name)); return rc; } */ diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c Mon Feb 17 14:57:26 2003 +++ b/fs/cifs/file.c Mon Feb 17 14:57:26 2003 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include "cifsfs.h" @@ -85,9 +86,11 @@ if (file->f_flags & O_CREAT) disposition = FILE_OVERWRITE; + /* BB first check if file has batch oplock (or oplock ?) */ + /* BB finish adding in oplock support BB */ if (oplockEnabled) - oplock = TRUE; + oplock = REQ_OPLOCK; else oplock = FALSE; @@ -95,8 +98,8 @@ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls); if (rc) { - cFYI(1, ("\ncifs_open returned 0x%x ", rc)); - cFYI(1, (" oplock: %d ", oplock)); + cFYI(1, ("cifs_open returned 0x%x ", rc)); + cFYI(1, ("oplock: %d ", oplock)); } else { file->private_data = kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); @@ -142,9 +145,7 @@ struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; struct cifsFileInfo *pSMBFile = - (struct cifsFileInfo *) file->private_data; - - cFYI(1, ("\n inode = 0x%p with ", inode)); + (struct cifsFileInfo *) file->private_data; xid = GetXid(); @@ -172,12 +173,12 @@ struct cifsFileInfo *pSMBFileStruct = (struct cifsFileInfo *) file->private_data; - cFYI(1, ("\nClosedir inode = 0x%p with ", inode)); + cFYI(1, ("Closedir inode = 0x%p with ", inode)); xid = GetXid(); if (pSMBFileStruct) { - cFYI(1, ("\nFreeing private data in close dir")); + cFYI(1, ("Freeing private data in close dir")); kfree(file->private_data); file->private_data = NULL; } @@ -202,42 +203,42 @@ xid = GetXid(); cFYI(1, - ("\nLock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld", + ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld", cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, pfLock->fl_end)); if (pfLock->fl_flags & FL_POSIX) - cFYI(1, ("\nPosix ")); + cFYI(1, ("Posix ")); if (pfLock->fl_flags & FL_FLOCK) - cFYI(1, ("\nFlock ")); + cFYI(1, ("Flock ")); if (pfLock->fl_flags & FL_SLEEP) - cFYI(1, ("\nBlocking lock ")); + cFYI(1, ("Blocking lock ")); if (pfLock->fl_flags & FL_ACCESS) - cFYI(1, ("\nProcess suspended by mandatory locking ")); + cFYI(1, ("Process suspended by mandatory locking ")); if (pfLock->fl_flags & FL_LEASE) - cFYI(1, ("\nLease on file ")); + cFYI(1, ("Lease on file ")); if (pfLock->fl_flags & 0xFFD0) - cFYI(1, ("\n Unknown lock flags ")); + cFYI(1, ("Unknown lock flags ")); if (pfLock->fl_type == F_WRLCK) { - cFYI(1, ("\nF_WRLCK ")); + cFYI(1, ("F_WRLCK ")); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { - cFYI(1, ("\nF_UNLCK ")); + cFYI(1, ("F_UNLCK ")); numUnlock = 1; } else if (pfLock->fl_type == F_RDLCK) { - cFYI(1, ("\nF_RDLCK ")); + cFYI(1, ("F_RDLCK ")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { - cFYI(1, ("\nF_EXLCK ")); + cFYI(1, ("F_EXLCK ")); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { - cFYI(1, ("\nF_SHLCK ")); + cFYI(1, ("F_SHLCK ")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else - cFYI(1, ("\nUnknown type of lock ")); + cFYI(1, ("Unknown type of lock ")); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; @@ -265,7 +266,7 @@ pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, - ("\nError unlocking previously locked range %d during test of lock ", + ("Error unlocking previously locked range %d during test of lock ", rc)); rc = 0; @@ -304,7 +305,7 @@ pTcon = cifs_sb->tcon; /*cFYI(1, - (" write %d bytes to offset %lld of %s \n", write_size, + (" write %d bytes to offset %lld of %s", write_size, *poffset, file->f_dentry->d_name.name)); */ if (file->private_data == NULL) { @@ -360,6 +361,7 @@ struct inode *inode = page->mapping->host; struct cifsInodeInfo *cifsInode; struct cifsFileInfo *open_file = NULL; + struct list_head *tmp; int xid; xid = GetXid(); @@ -381,32 +383,39 @@ return -EFAULT; } - if((to > PAGE_CACHE_SIZE) || (from > to)) + offset += (loff_t)from; + write_data += from; + + if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) { + FreeXid(xid); return -EIO; + } - offset += (loff_t)from; - write_data += from; + /* check to make sure that we are not extending the file */ + if(mapping->host->i_size - offset < (loff_t)to) + to = (unsigned)(mapping->host->i_size - offset); + cifsInode = CIFS_I(mapping->host); - if(!list_empty(&(cifsInode->openFileList))) { - open_file = list_entry(cifsInode->openFileList.next, - struct cifsFileInfo, flist); + list_for_each(tmp, &cifsInode->openFileList) { + open_file = list_entry(tmp,struct cifsFileInfo, flist); /* We could check if file is open for writing first */ - if(open_file->pfile) + if((open_file->pfile) && + ((open_file->pfile->f_flags & O_RDWR) || + (open_file->pfile->f_flags & O_WRONLY))) { bytes_written = cifs_write(open_file->pfile, write_data, to-from, &offset); /* Does mm or vfs already set times? */ - inode->i_atime = inode->i_mtime = CURRENT_TIME; - if ((bytes_written > 0) && (offset)) { - rc = 0; - if (offset > inode->i_size) - inode->i_size = offset; - } else if(bytes_written < 0) { - rc = bytes_written; + inode->i_atime = inode->i_mtime = CURRENT_TIME; + if ((bytes_written > 0) && (offset)) { + rc = 0; + } else if(bytes_written < 0) { + rc = bytes_written; + } } - mark_inode_dirty_sync(inode); - } else { - cFYI(1,("\nNo open files to get file handle from")); + } + if(open_file == NULL) { + cFYI(1,("No writeable filehandles for inode")); rc = -EIO; } @@ -415,15 +424,29 @@ } static int +cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) +{ + int rc = -EFAULT; + int xid; + + xid = GetXid(); +/* call 16K write then Setpageuptodate */ + FreeXid(xid); + return rc; +} + +static int cifs_writepage(struct page* page, struct writeback_control *wbc) { int rc = -EFAULT; int xid; xid = GetXid(); +/* BB add check for wbc flags */ page_cache_get(page); + rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE); - /* insert call to SetPageToUpdate like function here? */ + SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ unlock_page(page); page_cache_release(page); FreeXid(xid); @@ -434,32 +457,47 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) { - int xid,rc; + int xid; + int rc = 0; + struct inode *inode = page->mapping->host; + loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + struct cifsFileInfo *open_file; + struct cifs_sb_info *cifs_sb; + xid = GetXid(); - if(offset > to) - return -EIO; - rc = cifs_partialpagewrite(page,offset,to); + if (position > inode->i_size){ + inode->i_size = position; + if (file->private_data == NULL) { + rc = -EBADF; + } else { + cifs_sb = CIFS_SB(inode->i_sb); + open_file = (struct cifsFileInfo *)file->private_data; + rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, position, + open_file->netfid,open_file->pid,FALSE); + cFYI(1,(" SetEOF (commit write) rc = %d",rc)); + } + } + set_page_dirty(page); FreeXid(xid); return rc; } -static int -cifs_prepare_write(struct file *file, struct page *page, unsigned offset, - unsigned to) -{ - return 0; /* eventually add code to flush any incompatible requests */ -} - int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) { int xid; int rc = 0; + struct inode * inode = file->f_dentry->d_inode; + xid = GetXid(); - /* BB fill in code to flush write behind buffers - when we start supporting oplock */ - cFYI(1, (" name: %s datasync: 0x%x ", dentry->d_name.name, datasync)); + + cFYI(1, ("Sync file - name: %s datasync: 0x%x ", + dentry->d_name.name, datasync)); + + rc = filemap_fdatawrite(inode->i_mapping); + FreeXid(xid); return rc; } @@ -473,6 +511,7 @@ unsigned int rpages = 0; int rc = 0; + cFYI(1,("sync page %p",page)); mapping = page->mapping; if (!mapping) return 0; @@ -483,13 +522,39 @@ /* fill in rpages then result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */ - cFYI(1, ("\nrpages is %d for sync page of Index %ld ", rpages, index)); + cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); if (rc < 0) return rc; return 0; } +/* + * As file closes, flush all cached write data for this inode checking + * for write behind errors. + * + */ +int cifs_flush(struct file *file) +{ + struct inode * inode = file->f_dentry->d_inode; + int rc = 0; + + /* Rather than do the steps manually: */ + /* lock the inode for writing */ + /* loop through pages looking for write behind data (dirty pages) */ + /* coalesce into contiguous 16K (or smaller) chunks to write to server */ + /* send to server (prefer in parallel) */ + /* deal with writebehind errors */ + /* unlock inode for writing */ + /* filemapfdatawrite appears easier for the time being */ + + rc = filemap_fdatawrite(inode->i_mapping); + cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc)); + + return rc; +} + + ssize_t cifs_read(struct file * file, char *read_data, size_t read_size, loff_t * poffset) @@ -500,6 +565,7 @@ struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; int xid; + char * current_offset; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -510,12 +576,13 @@ return -EBADF; } - for (total_read = 0; read_size > total_read; total_read += bytes_read) { + for (total_read = 0,current_offset=read_data; read_size > total_read; + total_read += bytes_read,current_offset+=bytes_read) { rc = CIFSSMBRead(xid, pTcon, ((struct cifsFileInfo *) file-> private_data)->netfid, read_size - total_read, *poffset, - &bytes_read, read_data + total_read); + &bytes_read, ¤t_offset); if (rc || (bytes_read == 0)) { if (total_read) { break; @@ -531,8 +598,7 @@ return total_read; } -int -cifs_file_mmap(struct file * file, struct vm_area_struct * vma) +int cifs_file_mmap(struct file * file, struct vm_area_struct * vma) { struct dentry * dentry = file->f_dentry; int rc, xid; @@ -540,7 +606,7 @@ xid = GetXid(); rc = cifs_revalidate(dentry); if (rc) { - cFYI(1,("Validation prior to mmap failed, error=%d\n", rc)); + cFYI(1,("Validation prior to mmap failed, error=%d", rc)); FreeXid(xid); return rc; } @@ -549,34 +615,157 @@ return rc; } +static void cifs_copy_cache_pages(struct address_space *mapping, + struct list_head *pages, int bytes_read, + char *data,struct pagevec * plru_pvec) +{ + struct page *page; + char * target; + + while (bytes_read > 0) { + if(list_empty(pages)) + break; + page = list_entry(pages->prev, struct page, list); + + list_del(&page->list); + if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) { + page_cache_release(page); + cFYI(1,("Add page cache failed")); + continue; + } + + page_cache_get(page); + target = kmap(page); + + if(PAGE_CACHE_SIZE > bytes_read) { + memcpy(target,data,bytes_read); + bytes_read = 0; + } else { + memcpy(target,data,PAGE_CACHE_SIZE); + bytes_read -= PAGE_CACHE_SIZE; + } + + if (!pagevec_add(plru_pvec, page)) + __pagevec_lru_add(plru_pvec); + flush_dcache_page(page); + SetPageUptodate(page); + kunmap(page); + unlock_page(page); + page_cache_release(page); + data += PAGE_CACHE_SIZE; + } + return; +} + + +static int +cifs_readpages(struct file *file, struct address_space *mapping, + struct list_head *page_list, unsigned num_pages) +{ + int rc = -EACCES; + int xid,i; + loff_t offset; + struct page * page; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + int bytes_read = 0; + unsigned int read_size; + char * smb_read_data = 0; + struct smb_com_read_rsp * pSMBr; + struct pagevec lru_pvec; + + xid = GetXid(); + if (file->private_data == NULL) { + FreeXid(xid); + return -EBADF; + } + + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + pTcon = cifs_sb->tcon; + + pagevec_init(&lru_pvec, 0); + + for(i = 0;iprev, struct page, list); + offset = (loff_t)page->index << PAGE_CACHE_SHIFT; + /* for reads over a certain size could initiate async read ahead */ + + cFYI(0,("Read %d pages into cache at offset %ld ", + num_pages-i, (unsigned long) offset)); + + read_size = (num_pages - i) * PAGE_CACHE_SIZE; + rc = CIFSSMBRead(xid, pTcon, + ((struct cifsFileInfo *) file-> + private_data)->netfid, + read_size, offset, + &bytes_read, &smb_read_data); + + if ((rc < 0) || (smb_read_data == NULL)) { + cFYI(1,("Read error in readpages: %d",rc)); + /* clean up remaing pages off list */ + while (!list_empty(page_list) && (i < num_pages)) { + page = list_entry(page_list->prev, struct page, list); + list_del(&page->list); + } + break; + } else if (bytes_read > 0){ + pSMBr = (struct smb_com_read_rsp *)smb_read_data; + cifs_copy_cache_pages(mapping, page_list, bytes_read, + smb_read_data + 4 /* RFC1000 hdr */ + + le16_to_cpu(pSMBr->DataOffset), &lru_pvec); + i += bytes_read >> PAGE_CACHE_SHIFT; + if((bytes_read & PAGE_CACHE_MASK) != bytes_read) { + cFYI(1,("Partial page %d of %d read to cache",i++,num_pages)); + break; + } + } else { + cFYI(1,("No bytes read")); + break; + } + if(smb_read_data) { + buf_release(smb_read_data); + smb_read_data = 0; + } + bytes_read = 0; + } + + pagevec_lru_add(&lru_pvec); + + FreeXid(xid); + return rc; +} + static int cifs_readpage(struct file *file, struct page *page) { loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; char * read_data; int rc = -EACCES; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; int xid; xid = GetXid(); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); - pTcon = cifs_sb->tcon; if (file->private_data == NULL) { FreeXid(xid); return -EBADF; } + + cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); + page_cache_get(page); read_data = kmap(page); - /* for reads over a certain size we could initiate async read ahead */ + /* for reads over a certain size could initiate async read ahead */ rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset); if (rc < 0) goto io_error; else { - cFYI(1,("\nBytes read %d ",rc)); + cFYI(1,("Bytes read %d ",rc)); } file->f_dentry->d_inode->i_atime = CURRENT_TIME; @@ -610,38 +799,41 @@ cifsInfo->time = jiffies; atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode info */ - /* Linux can not store file creation time unfortunately so we ignore it */ + /* Linux can not store file creation time unfortunately so ignore it */ tmp_inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); tmp_inode->i_mtime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); tmp_inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); - /* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */ - tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); /* 2767 perms - indicate mandatory locking */ + /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ + /* 2767 perms - indicate mandatory locking */ + tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); cFYI(0, - ("\nCIFS FFIRST: Attributes came in as 0x%x", + ("CIFS FFIRST: Attributes came in as 0x%x", pfindData->ExtFileAttributes)); if (pfindData->ExtFileAttributes & ATTR_REPARSE) { *pobject_type = DT_LNK; - tmp_inode->i_mode |= S_IFLNK; /* BB can this and S_IFREG or S_IFDIR be set at same time as in Windows? */ + /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */ + tmp_inode->i_mode |= S_IFLNK; } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) { *pobject_type = DT_DIR; - tmp_inode->i_mode = S_IRWXUGO; /* override default perms since we do not lock dirs */ + /* override default perms since we do not lock dirs */ + tmp_inode->i_mode = S_IRWXUGO; tmp_inode->i_mode |= S_IFDIR; } else { *pobject_type = DT_REG; tmp_inode->i_mode |= S_IFREG; }/* could add code here - to validate if device or weird share type? */ - /* can not fill in nlink here as in qpathinfo version and in Unx search */ + /* can not fill in nlink here as in qpathinfo version and Unx search */ tmp_inode->i_size = pfindData->EndOfFile; tmp_inode->i_blocks = do_div(pfindData->AllocationSize, tmp_inode->i_blksize); if (pfindData->AllocationSize < pfindData->EndOfFile) - cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file ")); + cFYI(1, ("Possible sparse file: allocation size less than end of file ")); cFYI(1, - ("\nCIFS FFIRST: Size %ld and blocks %ld and blocksize %ld", + ("File Size %ld and blocks %ld and blocksize %ld", (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks, tmp_inode->i_blksize)); if (S_ISREG(tmp_inode->i_mode)) { @@ -657,7 +849,7 @@ cFYI(1, (" Symbolic Link inode ")); tmp_inode->i_op = &cifs_symlink_inode_ops; } else { - cFYI(1, ("\nInit special inode ")); + cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, kdev_t_to_nr(tmp_inode->i_rdev)); } @@ -726,7 +918,7 @@ tmp_inode->i_op = &cifs_symlink_inode_ops; /* tmp_inode->i_fop = *//* do not need to set to anything */ } else { - cFYI(1, ("\nInit special inode ")); + cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, kdev_t_to_nr(tmp_inode->i_rdev)); } @@ -740,22 +932,21 @@ struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; - cFYI(1, ("\nFor %s ", qstring->name)); + cFYI(1, ("For %s ", qstring->name)); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; qstring->hash = full_name_hash(qstring->name, qstring->len); tmp_dentry = d_lookup(file->f_dentry, qstring); if (tmp_dentry) { - cFYI(1, (" existing dentry with inode 0x%p ", tmp_dentry->d_inode)); /* BB remove */ + cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode)); *ptmp_inode = tmp_dentry->d_inode; /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */ } else { tmp_dentry = d_alloc(file->f_dentry, qstring); *ptmp_inode = new_inode(file->f_dentry->d_sb); - cFYI(1, ("\nAlloc new inode %p ", *ptmp_inode)); tmp_dentry->d_op = &cifs_dentry_ops; - cFYI(1, (" instantiate dentry 0x%p with inode 0x%p ", + cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ", tmp_dentry, *ptmp_inode)); d_instantiate(tmp_dentry, *ptmp_inode); d_rehash(tmp_dentry); @@ -763,8 +954,8 @@ tmp_dentry->d_time = jiffies; (*ptmp_inode)->i_blksize = - (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; - cFYI(1, ("\ni_blksize = %ld", (*ptmp_inode)->i_blksize)); + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; + cFYI(1, ("i_blksize = %ld", (*ptmp_inode)->i_blksize)); *pnew_dentry = tmp_dentry; } @@ -836,14 +1027,14 @@ full_path = build_wildcard_path_from_dentry(file->f_dentry); - cFYI(1, ("\nFull path: %s start at: %lld ", full_path, file->f_pos)); + cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); switch ((int) file->f_pos) { case 0: if (filldir (direntry, ".", 1, file->f_pos, file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("\nFilldir for current dir failed ")); + cERROR(1, ("Filldir for current dir failed ")); break; } file->f_pos++; @@ -852,7 +1043,7 @@ if (filldir (direntry, "..", 2, file->f_pos, file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("\nFilldir for parent dir failed ")); + cERROR(1, ("Filldir for parent dir failed ")); break; } file->f_pos++; @@ -957,13 +1148,13 @@ if (file->private_data == NULL) { rc = -EBADF; cFYI(1, - ("\nReaddir on closed srch, pos = %lld", + ("Readdir on closed srch, pos = %lld", file->f_pos)); } else { cifsFile = (struct cifsFileInfo *) file->private_data; if (cifsFile->endOfSearch) { rc = 0; - cFYI(1, ("\nEnd of search ")); + cFYI(1, ("End of search ")); break; } searchHandle = cifsFile->netfid; @@ -1077,17 +1268,28 @@ struct address_space_operations cifs_addr_ops = { .readpage = cifs_readpage, + .readpages = cifs_readpages, .writepage = cifs_writepage, - .prepare_write = cifs_prepare_write, + .prepare_write = simple_prepare_write, .commit_write = cifs_commit_write, -/* .sync_page = cifs_sync_page, */ + .sync_page = cifs_sync_page, }; -/* change over to struct below when sync page tested and complete */ -struct address_space_operations cifs_addr_ops2 = { +struct address_space_operations cifs_addr_ops_writethrough = { .readpage = cifs_readpage, + .readpages = cifs_readpages, .writepage = cifs_writepage, - .prepare_write = cifs_prepare_write, + .prepare_write = simple_prepare_write, .commit_write = cifs_commit_write, .sync_page = cifs_sync_page, }; + +struct address_space_operations cifs_addr_ops_nocache = { + .readpage = cifs_readpage, + .readpages = cifs_readpages, + .writepage = cifs_writepage, + .prepare_write = simple_prepare_write, + .commit_write = cifs_commit_write, + .sync_page = cifs_sync_page, +}; + diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c Mon Feb 17 14:57:26 2003 +++ b/fs/cifs/inode.c Mon Feb 17 14:57:26 2003 @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include #include "cifsfs.h" @@ -44,7 +45,7 @@ xid = GetXid(); pTcon = cifs_sb->tcon; - cFYI(1, ("\nGetting info on %s ", search_path)); + cFYI(1, (" Getting info on %s ", search_path)); /* we could have done a find first instead but this returns more info */ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, cifs_sb->local_nls); @@ -85,7 +86,7 @@ /* get new inode */ if (*pinode == NULL) { *pinode = new_inode(sb); - cFYI(1, ("\nAlloc new inode %p ", *pinode)); + cFYI(1, (" Alloc new inode %p ", *pinode)); } inode = *pinode; /* new_inode = iget(parent_dir_inode->i_sb, findData.IndexNumber); */ @@ -93,7 +94,7 @@ cifsInfo = CIFS_I(inode); - cFYI(1, ("\nOld time %ld ", cifsInfo->time)); + cFYI(1, (" Old time %ld ", cifsInfo->time)); cifsInfo->time = jiffies; cFYI(1, (" New time %ld ", cifsInfo->time)); atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */ @@ -129,12 +130,12 @@ findData.EndOfFile = le64_to_cpu(findData.EndOfFile); inode->i_size = findData.EndOfFile; inode->i_blksize = - (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; inode->i_blocks = do_div(findData.NumOfBytes, inode->i_blksize); if (findData.NumOfBytes < findData.EndOfFile) - cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file ")); + cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file ")); cFYI(1, - ("\nCIFS FFIRST: Size %ld and blocks %ld ", + ("Size %ld and blocks %ld ", (unsigned long) inode->i_size, inode->i_blocks)); if (S_ISREG(inode->i_mode)) { cFYI(1, (" File inode ")); @@ -150,7 +151,7 @@ inode->i_op = &cifs_symlink_inode_ops; /* tmp_inode->i_fop = *//* do not need to set to anything */ } else { - cFYI(1, ("\nInit special inode ")); + cFYI(1, (" Init special inode ")); init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev)); } @@ -174,7 +175,7 @@ xid = GetXid(); pTcon = cifs_sb->tcon; - cFYI(1, ("\nGetting info on %s ", search_path)); + cFYI(1, (" Getting info on %s ", search_path)); /* we could have done a find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, &findData, cifs_sb->local_nls); @@ -214,20 +215,20 @@ /* get new inode */ if (*pinode == NULL) { *pinode = new_inode(sb); - cFYI(1, ("\nAlloc new inode %p ", *pinode)); + cFYI(1, (" Alloc new inode %p ", *pinode)); } inode = *pinode; cifsInfo = CIFS_I(inode); findData.Attributes = le32_to_cpu(findData.Attributes); cifsInfo->cifsAttrs = findData.Attributes; - cFYI(1, ("\nOld time %ld ", cifsInfo->time)); + cFYI(1, (" Old time %ld ", cifsInfo->time)); cifsInfo->time = jiffies; cFYI(1, (" New time %ld ", cifsInfo->time)); atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */ inode->i_blksize = - (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00; /* Linux can not store file creation time unfortunately so we ignore it */ inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); @@ -239,7 +240,7 @@ /* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */ inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); /* 2767 perms indicate mandatory locking - will override for dirs later */ cFYI(0, - ("\nAttributes came in as 0x%x\n", findData.Attributes)); + (" Attributes came in as 0x%x ", findData.Attributes)); if (findData.Attributes & ATTR_REPARSE) { /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */ inode->i_mode |= S_IFLNK; @@ -256,7 +257,7 @@ inode->i_blocks = do_div(findData.AllocationSize, inode->i_blksize); cFYI(1, - ("\n Size %ld and blocks %ld ", + (" Size %ld and blocks %ld ", (unsigned long) inode->i_size, inode->i_blocks)); inode->i_nlink = le32_to_cpu(findData.NumberOfLinks); @@ -307,7 +308,7 @@ char *full_path = NULL; struct cifsInodeInfo *cifsInode; - cFYI(1, ("\n cifs_unlink, inode = 0x%p with ", inode)); + cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); xid = GetXid(); @@ -356,7 +357,7 @@ char *full_path = NULL; struct inode *newinode = NULL; - cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p\n", mode, inode)); + cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); xid = GetXid(); @@ -367,7 +368,7 @@ /* BB add setting the equivalent of mode via CreateX w/ACLs */ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); if (rc) { - cFYI(1, ("\ncifs_mkdir returned 0x%x ", rc)); + cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); } else { inode->i_nlink++; if (pTcon->ses->capabilities & CAP_UNIX) @@ -407,7 +408,7 @@ char *full_path = NULL; struct cifsInodeInfo *cifsInode; - cFYI(1, ("\nn cifs_rmdir, inode = 0x%p with ", inode)); + cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); xid = GetXid(); @@ -493,7 +494,7 @@ full_path = build_path_from_dentry(direntry); cFYI(1, - (" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld \n", + (" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld ", full_path, direntry->d_inode, direntry->d_inode->i_count.counter, direntry, direntry->d_time, jiffies)); @@ -562,7 +563,7 @@ full_path = build_path_from_dentry(dirent); rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE, cifs_sb->local_nls); - cFYI(1,("\nSetEOF (truncate) rc = %d",rc)); + cFYI(1,(" SetEOF (truncate) rc = %d",rc)); if(rc == -ETXTBSY) { cifsInode = CIFS_I(inode); if(!list_empty(&(cifsInode->openFileList))) { @@ -572,7 +573,7 @@ rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size, open_file->netfid,open_file->pid,FALSE); } else { - cFYI(1,("\nNo open files to get file handle from")); + cFYI(1,(" No open files to get file handle from")); } } if (!rc) @@ -604,7 +605,7 @@ xid = GetXid(); cFYI(1, - ("\nIn cifs_setattr, name = %s attrs->iavalid 0x%x\n", + (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", direntry->d_name.name, attrs->ia_valid)); cifs_sb = CIFS_SB(direntry->d_inode->i_sb); pTcon = cifs_sb->tcon; @@ -614,12 +615,12 @@ /* BB check if we need to refresh inode from server now ? BB */ - cFYI(1, ("\nChanging attributes 0x%x", attrs->ia_valid)); + cFYI(1, (" Changing attributes 0x%x", attrs->ia_valid)); if (attrs->ia_valid & ATTR_SIZE) { rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE, cifs_sb->local_nls); - cFYI(1,("\nSetEOF (setattrs) rc = %d",rc)); + cFYI(1,(" SetEOF (setattrs) rc = %d",rc)); if(rc == -ETXTBSY) { if(!list_empty(&(cifsInode->openFileList))) { @@ -629,29 +630,30 @@ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, open_file->netfid,open_file->pid,FALSE); } else { - cFYI(1,("\nNo open files to get file handle from")); + cFYI(1,(" No open files to get file handle from")); } } - /* Set Allocation Size of file - might not even need to call the - following but might as well and it does not hurt if it fails */ - CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls); - if (rc == 0) - vmtruncate(direntry->d_inode, attrs->ia_size); - /* BB add special case to handle sharing violation (due to Samba bug) - by calling SetFileInfo to set the sizes */ + /* For Allocation Size - do not need to call the following + it did not hurt if it fails but why bother */ + /* CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/ + if (rc == 0) { + rc = vmtruncate(direntry->d_inode, attrs->ia_size); + nobh_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size); +/* cFYI(1,("truncate_page to 0x%lx \n",direntry->d_inode->i_size)); */ + } } if (attrs->ia_valid & ATTR_UID) { - cFYI(1, ("\nCIFS - UID changed to %d", attrs->ia_uid)); + cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid)); uid = attrs->ia_uid; /* entry->uid = cpu_to_le16(attr->ia_uid); */ } if (attrs->ia_valid & ATTR_GID) { - cFYI(1, ("\nCIFS - GID changed to %d", attrs->ia_gid)); + cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid)); gid = attrs->ia_gid; /* entry->gid = cpu_to_le16(attr->ia_gid); */ } if (attrs->ia_valid & ATTR_MODE) { - cFYI(1, ("\nCIFS - Mode changed to 0x%x", attrs->ia_mode)); + cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode)); mode = attrs->ia_mode; /* entry->mode = cpu_to_le16(attr->ia_mode); */ } @@ -680,7 +682,7 @@ if (attrs->ia_valid & ATTR_CTIME) { set_time = TRUE; - cFYI(1, ("\nCIFS - CTIME changed ")); /* BB probably do not need */ + cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */ time_buf.ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); } else @@ -695,7 +697,7 @@ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, cifs_sb->local_nls); } - cifsInode->time = 0; /* force revalidate to get attributes when needed */ +/* cifsInode->time = 0; */ /* force revalidate to get attributes when needed */ if (full_path) kfree(full_path); @@ -707,7 +709,7 @@ cifs_delete_inode(struct inode *inode) { /* Note: called without the big kernel filelock - remember spinlocks! */ - cFYI(1, ("In cifs_delete_inode, inode = 0x%p\n", inode)); + cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode)); /* may have to add back in when safe distributed caching of directories via e.g. FindNotify added */ } diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c --- a/fs/cifs/link.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/link.c Mon Feb 17 14:57:27 2003 @@ -88,7 +88,7 @@ xid = GetXid(); full_path = build_path_from_dentry(direntry); - cFYI(1, ("\nFull path: %s inode = 0x%p\n", full_path, inode)); + cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; @@ -136,8 +136,8 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - cFYI(1, ("\nFull path: %s ", full_path)); - cFYI(1, (" symname is %s\n", symname)); + cFYI(1, ("Full path: %s ", full_path)); + cFYI(1, ("symname is %s", symname)); /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) @@ -156,7 +156,7 @@ if (rc != 0) { cFYI(1, - ("\nCreate symlink worked but get_inode_info failed with rc = %d ", + ("Create symlink worked but get_inode_info failed with rc = %d ", rc)); } else { direntry->d_op = &cifs_dentry_ops; @@ -188,7 +188,7 @@ pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); cFYI(1, - ("\nFull path: %s inode = 0x%p pBuffer = 0x%p buflen = %d\n", + ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", full_path, inode, pBuffer, buflen)); /* BB add read reparse point symlink code and Unix extensions symlink code here BB */ diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c --- a/fs/cifs/misc.c Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/misc.c Mon Feb 17 14:57:28 2003 @@ -81,7 +81,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("\nNull buffer passed to sesInfoFree")); + cFYI(1, ("Null buffer passed to sesInfoFree")); return; } @@ -122,7 +122,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("\nNull buffer passed to tconInfoFree")); + cFYI(1, ("Null buffer passed to tconInfoFree")); return; } write_lock(&GlobalSMBSeslock); @@ -169,7 +169,7 @@ { if (buf_to_free == NULL) { - cFYI(1, ("\nNull buffer passed to buf_release")); + cFYI(1, ("Null buffer passed to buf_release")); return; } kmem_cache_free(cifs_req_cachep, buf_to_free); @@ -225,8 +225,10 @@ } if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) buffer->Flags2 |= SMBFLG2_DFS; - if(treeCon->ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + if(treeCon->ses->server) + if(treeCon->ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; } /* endian conversion of flags is now done just before sending */ @@ -248,17 +250,17 @@ if(smb->Command == SMB_COM_LOCKING_ANDX) return 0; else - cERROR(1, ("\n Rcvd Request not response ")); + cERROR(1, ("Rcvd Request not response ")); } } else { /* bad signature or mid */ if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff)) cERROR(1, - ("\nBad protocol string signature header %x ", + ("Bad protocol string signature header %x ", *(unsigned int *) smb->Protocol)); if (mid != smb->Mid) - cERROR(1, ("\n Mids do not match \n")); + cERROR(1, ("Mids do not match")); } - cERROR(1, ("\nCIFS: bad smb detected. The Mid=%d\n", smb->Mid)); + cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid)); return 1; } @@ -266,13 +268,13 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) { cFYI(0, - ("\nEntering checkSMB with Length: %x, smb_buf_length: %x ", + ("Entering checkSMB with Length: %x, smb_buf_length: %x ", length, ntohl(smb->smb_buf_length))); if ((length < 2 + sizeof (struct smb_hdr)) || (4 + ntohl(smb->smb_buf_length) > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)) { if (length < 2 + sizeof (struct smb_hdr)) { - cERROR(1, ("\n Length less than 2 + sizeof smb_hdr ")); + cERROR(1, ("Length less than 2 + sizeof smb_hdr ")); if ((length >= sizeof (struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) return 0; /* some error cases do not return wct and bcc */ @@ -281,9 +283,9 @@ if (4 + ntohl(smb->smb_buf_length) > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) cERROR(1, - ("\n smb_buf_length greater than CIFS_MAX_MSGSIZE ... ")); + ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... ")); cERROR(1, - ("CIFS: bad smb detected. Illegal length. The mid=%d\n", + ("bad smb detected. Illegal length. The mid=%d", smb->Mid)); return 1; } @@ -295,51 +297,62 @@ || (4 + ntohl(smb->smb_buf_length) != length)) { return 0; } else { - cERROR(1, ("\nCIFS: smbCalcSize %x ", smbCalcSize(smb))); + cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); cERROR(1, - ("CIFS: bad smb size detected. The Mid=%d\n", smb->Mid)); + ("bad smb size detected. The Mid=%d", smb->Mid)); return 1; } } int is_valid_oplock_break(struct smb_hdr *buf) { - struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; - struct list_head *tmp; - struct cifsTconInfo *tcon; - - /* could add check for smb response flag 0x80 */ - cFYI(1,("\nChecking for oplock break")); - if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) - return FALSE; - if(pSMB->hdr.Flags & SMBFLG_RESPONSE) - return FALSE; /* server sends us "request" here */ - if(pSMB->hdr.WordCount != 8) - return FALSE; - - cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel)); - if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) - return FALSE; - - /* look up tcon based on tid & uid */ - read_lock(&GlobalSMBSeslock); - list_for_each(tmp, &GlobalTreeConnectionList) { - tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); - if (tcon->tid == buf->Tid) - if(tcon->ses->Suid == buf->Uid) { - /* BB Add following logic: - 2) look up inode from tcon->openFileList->file->f_dentry->d_inode - 3) flush dirty pages and cached byte range locks and mark inode - 4) depending on break type change to r/o caching or no caching - 5) send oplock break response to server */ - read_unlock(&GlobalSMBSeslock); - cFYI(1,("\nFound matching connection, process oplock break")); - return TRUE; - } - } - read_unlock(&GlobalSMBSeslock); - cFYI(1,("\nProcessing oplock break for non-existent connection")); - return TRUE; + struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; + struct list_head *tmp; + struct list_head *tmp1; + struct cifsTconInfo *tcon; + struct cifsFileInfo *netfile; + + /* could add check for smb response flag 0x80 */ + cFYI(1,("Checking for oplock break")); + if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) + return FALSE; + if(pSMB->hdr.Flags & SMBFLG_RESPONSE) + return FALSE; /* server sends us "request" here */ + if(pSMB->hdr.WordCount != 8) + return FALSE; + + cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel)); + if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) + return FALSE; + + /* look up tcon based on tid & uid */ + read_lock(&GlobalSMBSeslock); + list_for_each(tmp, &GlobalTreeConnectionList) { + tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); + if (tcon->tid == buf->Tid) { + list_for_each(tmp1,&tcon->openFileList){ + netfile = list_entry(tmp1,struct cifsFileInfo,tlist); + if(pSMB->Fid == netfile->netfid) { + /* BB Add following logic: + 2) look up inode from tcon->openFileList->file->f_dentry->d_inode + 3) flush dirty pages and cached byte range locks and mark inode + 4) depending on break type change to r/o caching or no caching + cifsinode->clientCanCacheAll = 0 + 5) inode->i_data.a_ops = &cifs_addr_ops_writethrough; + 6) send oplock break response to server */ + read_unlock(&GlobalSMBSeslock); + cFYI(1,("Matching file id, processing oplock break")); + return TRUE; + } + } + read_unlock(&GlobalSMBSeslock); + cFYI(1,("No matching file for oplock break on connection")); + return TRUE; + } + } + read_unlock(&GlobalSMBSeslock); + cFYI(1,("Can not process oplock break for non-existent connection")); + return TRUE; } void @@ -355,7 +368,7 @@ buffer = (unsigned char *) smb_buf; for (i = 0, j = 0; i < smb_buf_length; i++, j++) { if (i % 8 == 0) { /* we have reached the beginning of line */ - printk("\n| "); + printk(KERN_DEBUG "| "); j = 0; } printk("%0#4x ", buffer[i]); @@ -367,7 +380,7 @@ if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ debug_line[16] = 0; - printk(" | %s", debug_line); + printk(" | %s\n", debug_line); } } for (; j < 8; j++) { @@ -375,6 +388,6 @@ debug_line[2 * j] = ' '; debug_line[1 + (2 * j)] = ' '; } - printk(" | %s\n", debug_line); + printk( " | %s\n", debug_line); return; } diff -Nru a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c --- a/fs/cifs/netmisc.c Mon Feb 17 14:57:28 2003 +++ b/fs/cifs/netmisc.c Mon Feb 17 14:57:28 2003 @@ -753,12 +753,11 @@ { int idx = 0; - printk("\nStatus code returned: 0x%08x ", status_code); - while (nt_errs[idx].nt_errstr != NULL) { if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == (status_code & 0xFFFFFF)) { - printk(nt_errs[idx].nt_errstr); + printk(KERN_NOTICE "Status code returned 0x%08x %s\n", + status_code,nt_errs[idx].nt_errstr); } idx++; } @@ -815,11 +814,8 @@ } /* old style errors */ - cFYI(1, (" !!Mapping smb error code %d ", smberrcode)); - /* DOS class smb error codes - map DOS */ - - /* BB special case reconnect tid and reconnect uid here? */ + /* DOS class smb error codes - map DOS */ if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */ for (i = 0; i < @@ -849,10 +845,7 @@ } /* else ERRHRD class errors or junk - return EIO */ - /* BB get smb->error_class and code lookup in table if ERR_STATUS is not - set in this frame else translate newer NT Status code - in both cases - change to equivalent posix error BB */ - cFYI(1, (" to POSIX err %d !!", rc)); + cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc)); /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */ diff -Nru a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c --- a/fs/cifs/smbencrypt.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/smbencrypt.c Mon Feb 17 14:57:27 2003 @@ -305,7 +305,7 @@ if (new_pw_len > 512) { cERROR(1, - ("CIFS make_oem_passwd_hash: new password is too long.\n")); + ("CIFS make_oem_passwd_hash: new password is too long.")); return FALSE; } diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c Mon Feb 17 14:57:27 2003 +++ b/fs/cifs/transport.c Mon Feb 17 14:57:27 2003 @@ -40,10 +40,9 @@ /* BB add spinlock to protect midq for each session BB */ if (ses == NULL) { - cERROR(1, ("\nNull session passed in to AllocMidQEntry ")); + cERROR(1, ("Null session passed in to AllocMidQEntry ")); return NULL; } - temp = kmalloc(sizeof (struct mid_q_entry), GFP_KERNEL); temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep, SLAB_KERNEL); if (temp == NULL) @@ -53,21 +52,19 @@ temp->mid = smb_buffer->Mid; /* always LE */ temp->pid = current->pid; temp->command = smb_buffer->Command; - cFYI(1, ("\nFor smb_command %d", temp->command)); + cFYI(1, ("For smb_command %d", temp->command)); do_gettimeofday(&temp->when_sent); temp->ses = ses; temp->tsk = current; } - if (ses->status == CifsGood) { + if (ses->server->tcpStatus == CifsGood) { write_lock(&GlobalMid_Lock); list_add_tail(&temp->qhead, &ses->server->pending_mid_q); atomic_inc(&midCount); temp->midState = MID_REQUEST_ALLOCATED; write_unlock(&GlobalMid_Lock); - } else { /* BB add reconnect code here BB */ - - cERROR(1, - ("\nNeed to reconnect after session died to server\n")); + } else { /* could add more reconnect code here BB */ + cERROR(1,("Need to reconnect after session died to server")); if (temp) kmem_cache_free(cifs_mid_cachep, temp); return NULL; @@ -121,7 +118,7 @@ sign_smb(smb_buffer); */ /* BB enable when signing tested more */ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); - cFYI(1, ("\nSending smb of length %d ", smb_buf_length)); + cFYI(1, ("Sending smb of length %d ", smb_buf_length)); dump_smb(smb_buffer, smb_buf_length + 4); temp_fs = get_fs(); /* we must turn off socket api parm checking */ @@ -132,7 +129,7 @@ if (rc < 0) { cERROR(1, - ("\nError %d sending data on socket to server.\n", rc)); + ("Error %d sending data on socket to server.", rc)); } else rc = 0; @@ -154,7 +151,7 @@ return -EIO; /* reconnect should be done, if possible, in AllocMidQEntry */ if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { cERROR(1, - ("\nIllegal length, greater than maximum frame, %d ", + ("Illegal length, greater than maximum frame, %d ", in_buf->smb_buf_length)); DeleteMidQEntry(midQ); return -EIO; @@ -163,27 +160,21 @@ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, (struct sockaddr *) &(ses->server->sockAddr)); - if (long_op > 1) /* writes past end of file can take a looooooong time */ + if (long_op > 1) /* writes past end of file can take looooong time */ timeout = 300 * HZ; else if (long_op == 1) timeout = 60 * HZ; else timeout = 15 * HZ; - /* wait for 15 seconds or until woken up due to response arriving or due to - last connection to this server being unmounted */ - - /* timeout = interruptible_sleep_on_timeout(&ses->server->response_q,timeout); */ - /* Replace above line with wait_event to get rid of sleep_on per lk guidelines */ + /* wait for 15 seconds or until woken up due to response arriving or + due to last connection to this server being unmounted */ timeout = wait_event_interruptible_timeout(ses->server->response_q, midQ-> midState & MID_RESPONSE_RECEIVED, timeout); - cFYI(1, - (" with timeout %ld and Out_buf: %p midQ->resp_buf: %p ", timeout, - out_buf, midQ->resp_buf)); if (signal_pending(current)) { - cERROR(1, (KERN_ERR "\nCIFS: caught signal")); + cERROR(1, ("CIFS: caught signal")); DeleteMidQEntry(midQ); return -EINTR; } else { @@ -198,11 +189,11 @@ if (timeout == 0) { cFYI(1, - ("\nTimeout on receive. Assume response SMB is invalid.\n")); + ("Timeout on receive. Assume response SMB is invalid.")); rc = -ETIMEDOUT; } else if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { cERROR(1, - ("\nFrame too large received. Length: %d Xid: %d\n", + ("Frame too large received. Length: %d Xid: %d", receive_len, xid)); rc = -EIO; } else { /* rcvd frame is ok */ @@ -215,7 +206,6 @@ /* convert the length back to a form that we can use */ dump_smb(out_buf, 92); - out_buf->smb_buf_length = be32_to_cpu(out_buf->smb_buf_length); if (out_buf->smb_buf_length > 12) diff -Nru a/fs/dcache.c b/fs/dcache.c --- a/fs/dcache.c Mon Feb 17 14:57:26 2003 +++ b/fs/dcache.c Mon Feb 17 14:57:26 2003 @@ -49,12 +49,30 @@ static unsigned int d_hash_shift; static struct list_head *dentry_hashtable; static LIST_HEAD(dentry_unused); +static int max_dentries; +static void * hashtable_end; + +static inline int is_bucket(void * addr) +{ + return ((addr < (void *)dentry_hashtable) + || (addr > hashtable_end) ? 0 : 1); +} /* Statistics gathering. */ struct dentry_stat_t dentry_stat = { .age_limit = 45, }; +static void d_callback(void *arg) +{ + struct dentry * dentry = (struct dentry *)arg; + + if (dname_external(dentry)) { + kfree(dentry->d_qstr); + } + kmem_cache_free(dentry_cache, dentry); +} + /* * no dcache_lock, please. The caller must decrement dentry_stat.nr_dentry * inside dcache_lock. @@ -63,9 +81,7 @@ { if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); - if (dname_external(dentry)) - kfree(dentry->d_name.name); - kmem_cache_free(dentry_cache, dentry); + call_rcu(&dentry->d_rcu, d_callback, dentry); } /* @@ -126,9 +142,13 @@ if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock)) return; - /* dput on a free dentry? */ - if (!list_empty(&dentry->d_lru)) - BUG(); + spin_lock(&dentry->d_lock); + if (atomic_read(&dentry->d_count)) { + spin_unlock(&dentry->d_lock); + spin_unlock(&dcache_lock); + return; + } + /* * AV: ->d_delete() is _NOT_ allowed to block now. */ @@ -139,8 +159,12 @@ /* Unreachable? Get rid of it */ if (d_unhashed(dentry)) goto kill_it; - list_add(&dentry->d_lru, &dentry_unused); - dentry_stat.nr_unused++; + if (list_empty(&dentry->d_lru)) { + dentry->d_vfs_flags &= ~DCACHE_REFERENCED; + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; + } + spin_unlock(&dentry->d_lock); dentry->d_vfs_flags |= DCACHE_REFERENCED; spin_unlock(&dcache_lock); return; @@ -150,7 +174,16 @@ kill_it: { struct dentry *parent; - list_del(&dentry->d_child); + + /* If dentry was on d_lru list + * delete it from there + */ + if (!list_empty(&dentry->d_lru)) { + list_del(&dentry->d_lru); + dentry_stat.nr_unused--; + } + list_del(&dentry->d_child); + spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ /* drops the lock, at that point nobody can reach this dentry */ dentry_iput(dentry); @@ -222,6 +255,7 @@ static inline struct dentry * __dget_locked(struct dentry *dentry) { atomic_inc(&dentry->d_count); + dentry->d_vfs_flags |= DCACHE_REFERENCED; if (atomic_read(&dentry->d_count) == 1) { dentry_stat.nr_unused--; list_del_init(&dentry->d_lru); @@ -289,8 +323,8 @@ struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); if (!atomic_read(&dentry->d_count)) { __dget_locked(dentry); + __d_drop(dentry); spin_unlock(&dcache_lock); - d_drop(dentry); dput(dentry); goto restart; } @@ -310,6 +344,7 @@ __d_drop(dentry); list_del(&dentry->d_child); + spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ dentry_iput(dentry); parent = dentry->d_parent; @@ -343,18 +378,24 @@ if (tmp == &dentry_unused) break; list_del_init(tmp); + dentry_stat.nr_unused--; dentry = list_entry(tmp, struct dentry, d_lru); + spin_lock(&dentry->d_lock); /* If the dentry was recently referenced, don't free it. */ if (dentry->d_vfs_flags & DCACHE_REFERENCED) { dentry->d_vfs_flags &= ~DCACHE_REFERENCED; - list_add(&dentry->d_lru, &dentry_unused); + + /* don't add non zero d_count dentries + * back to d_lru list + */ + if (!atomic_read(&dentry->d_count)) { + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; + } + spin_unlock(&dentry->d_lock); continue; } - dentry_stat.nr_unused--; - - /* Unused dentry with a count? */ - BUG_ON(atomic_read(&dentry->d_count)); prune_one_dentry(dentry); } spin_unlock(&dcache_lock); @@ -414,10 +455,13 @@ dentry = list_entry(tmp, struct dentry, d_lru); if (dentry->d_sb != sb) continue; - if (atomic_read(&dentry->d_count)) - continue; dentry_stat.nr_unused--; list_del_init(tmp); + spin_lock(&dentry->d_lock); + if (atomic_read(&dentry->d_count)) { + spin_unlock(&dentry->d_lock); + continue; + } prune_one_dentry(dentry); goto repeat; } @@ -497,8 +541,12 @@ struct list_head *tmp = next; struct dentry *dentry = list_entry(tmp, struct dentry, d_child); next = tmp->next; + list_del_init(&dentry->d_lru); + + /* don't add non zero d_count dentries + * back to d_lru list + */ if (!atomic_read(&dentry->d_count)) { - list_del(&dentry->d_lru); list_add(&dentry->d_lru, dentry_unused.prev); found++; } @@ -551,6 +599,9 @@ * * Prune the dentries that are anonymous * + * parsing d_hash list does not read_barrier_depends() as it + * done under dcache_lock. + * */ void shrink_dcache_anon(struct list_head *head) { @@ -561,8 +612,12 @@ spin_lock(&dcache_lock); list_for_each(lp, head) { struct dentry *this = list_entry(lp, struct dentry, d_hash); + list_del(&this->d_lru); + + /* don't add non zero d_count dentries + * back to d_lru list + */ if (!atomic_read(&this->d_count)) { - list_del(&this->d_lru); list_add_tail(&this->d_lru, &dentry_unused); found++; } @@ -630,28 +685,39 @@ { char * str; struct dentry *dentry; + struct qstr * qstr; dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); if (!dentry) return NULL; if (name->len > DNAME_INLINE_LEN-1) { - str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); - if (!str) { + qstr = kmalloc(sizeof(*qstr) + NAME_ALLOC_LEN(name->len), + GFP_KERNEL); + if (!qstr) { kmem_cache_free(dentry_cache, dentry); return NULL; } - } else - str = dentry->d_iname; + qstr->name = qstr->name_str; + qstr->len = name->len; + qstr->hash = name->hash; + dentry->d_qstr = qstr; + str = qstr->name_str; + } else { + dentry->d_qstr = &dentry->d_name; + str = dentry->d_iname; + } memcpy(str, name->name, name->len); str[name->len] = 0; atomic_set(&dentry->d_count, 1); - dentry->d_vfs_flags = 0; + dentry->d_vfs_flags = DCACHE_UNHASHED; + dentry->d_lock = SPIN_LOCK_UNLOCKED; dentry->d_flags = 0; dentry->d_inode = NULL; dentry->d_parent = NULL; + dentry->d_move_count = 0; dentry->d_sb = NULL; dentry->d_name.name = str; dentry->d_name.len = name->len; @@ -660,6 +726,7 @@ dentry->d_fsdata = NULL; dentry->d_mounted = 0; dentry->d_cookie = NULL; + dentry->d_bucket = NULL; INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); @@ -785,12 +852,16 @@ res = tmp; tmp = NULL; if (res) { + spin_lock(&res->d_lock); res->d_sb = inode->i_sb; res->d_parent = res; res->d_inode = inode; + res->d_bucket = d_hash(res, res->d_name.hash); res->d_flags |= DCACHE_DISCONNECTED; + res->d_vfs_flags &= ~DCACHE_UNHASHED; list_add(&res->d_alias, &inode->i_dentry); list_add(&res->d_hash, &inode->i_sb->s_anon); + spin_unlock(&res->d_lock); } inode = NULL; /* don't drop reference */ } @@ -855,50 +926,92 @@ * the dentry is found its reference count is incremented and the dentry * is returned. The caller must use d_put to free the entry when it has * finished using it. %NULL is returned on failure. + * + * d_lookup is now, dcache_lock free. The hash list is protected using RCU. + * Memory barriers are used while updating and doing lockless traversal. + * To avoid races with d_move while rename is happening, d_move_count is + * used. + * + * Overflows in memcmp(), while d_move, are avoided by keeping the length + * and name pointer in one structure pointed by d_qstr. + * + * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while + * lookup is going on. + * + * d_lru list is not updated, which can leave non-zero d_count dentries + * around in d_lru list. */ - -struct dentry * d_lookup(struct dentry * parent, struct qstr * name) -{ - struct dentry * dentry; - spin_lock(&dcache_lock); - dentry = __d_lookup(parent,name); - if (dentry) - __dget_locked(dentry); - spin_unlock(&dcache_lock); - return dentry; -} -struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) +struct dentry * d_lookup(struct dentry * parent, struct qstr * name) { - unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; struct list_head *head = d_hash(parent,hash); + struct dentry *found = NULL; struct list_head *tmp; + int lookup_count = 0; - tmp = head->next; - for (;;) { - struct dentry * dentry = list_entry(tmp, struct dentry, d_hash); - if (tmp == head) + rcu_read_lock(); + + /* lookup is terminated when flow reaches any bucket head */ + for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) { + struct dentry *dentry; + unsigned long move_count; + struct qstr * qstr; + + smp_read_barrier_depends(); + dentry = list_entry(tmp, struct dentry, d_hash); + + /* if lookup ends up in a different bucket + * due to concurrent rename, fail it + */ + if (unlikely(dentry->d_bucket != head)) break; - tmp = tmp->next; + + /* to avoid race if dentry keep coming back to original + * bucket due to double moves + */ + if (unlikely(++lookup_count > max_dentries)) + break; + + /* + * We must take a snapshot of d_move_count followed by + * read memory barrier before any search key comparison + */ + move_count = dentry->d_move_count; + smp_rmb(); + if (dentry->d_name.hash != hash) continue; if (dentry->d_parent != parent) continue; + + qstr = dentry->d_qstr; + smp_read_barrier_depends(); if (parent->d_op && parent->d_op->d_compare) { - if (parent->d_op->d_compare(parent, &dentry->d_name, name)) + if (parent->d_op->d_compare(parent, qstr, name)) continue; } else { - if (dentry->d_name.len != len) + if (qstr->len != len) continue; - if (memcmp(dentry->d_name.name, str, len)) + if (memcmp(qstr->name, str, len)) continue; } - return dentry; - } - return NULL; + spin_lock(&dentry->d_lock); + /* + * If dentry is moved, fail the lookup + */ + if (unlikely(move_count != dentry->d_move_count)) + break; + if (!d_unhashed(dentry)) + found = dget(dentry); + spin_unlock(&dentry->d_lock); + break; + } + rcu_read_unlock(); + + return found; } /** @@ -936,8 +1049,11 @@ spin_lock(&dcache_lock); lhp = base = d_hash(dparent, dentry->d_name.hash); while ((lhp = lhp->next) != base) { + /* read_barrier_depends() not required for d_hash list + * as it is parsed under dcache_lock + */ if (dentry == list_entry(lhp, struct dentry, d_hash)) { - __dget_locked(dentry); + dget(dentry); spin_unlock(&dcache_lock); return 1; } @@ -974,17 +1090,18 @@ * Are we the only user? */ spin_lock(&dcache_lock); + spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) == 1) { + spin_unlock(&dentry->d_lock); dentry_iput(dentry); return; } - spin_unlock(&dcache_lock); - /* - * If not, just drop the dentry and let dput - * pick up the tab.. - */ - d_drop(dentry); + if (!d_unhashed(dentry)) + __d_drop(dentry); + + spin_unlock(&dentry->d_lock); + spin_unlock(&dcache_lock); } /** @@ -997,9 +1114,11 @@ void d_rehash(struct dentry * entry) { struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!d_unhashed(entry)) BUG(); spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); + if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG(); + entry->d_vfs_flags &= ~DCACHE_UNHASHED; + entry->d_bucket = list; + list_add_rcu(&entry->d_hash, list); spin_unlock(&dcache_lock); } @@ -1021,16 +1140,25 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target) { const unsigned char *old_name, *new_name; + struct qstr *old_qstr, *new_qstr; memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); + old_qstr = target->d_qstr; old_name = target->d_name.name; + new_qstr = dentry->d_qstr; new_name = dentry->d_name.name; - if (old_name == target->d_iname) + if (old_name == target->d_iname) { old_name = dentry->d_iname; - if (new_name == dentry->d_iname) + old_qstr = &dentry->d_name; + } + if (new_name == dentry->d_iname) { new_name = target->d_iname; + new_qstr = &target->d_name; + } target->d_name.name = new_name; dentry->d_name.name = old_name; + target->d_qstr = new_qstr; + dentry->d_qstr = old_qstr; } /* @@ -1057,15 +1185,21 @@ * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. */ - + void d_move(struct dentry * dentry, struct dentry * target) { if (!dentry->d_inode) printk(KERN_WARNING "VFS: moving negative dcache entry\n"); spin_lock(&dcache_lock); - /* Move the dentry to the target hash queue */ - list_move(&dentry->d_hash, &target->d_hash); + spin_lock(&dentry->d_lock); + + /* Move the dentry to the target hash queue, if on different bucket */ + if (dentry->d_bucket != target->d_bucket) { + dentry->d_bucket = target->d_bucket; + list_del_rcu(&dentry->d_hash); + list_add_rcu(&dentry->d_hash, &target->d_hash); + } /* Unhash the target: dput() will then get rid of it */ __d_drop(target); @@ -1075,6 +1209,7 @@ /* Switch the names.. */ switch_names(dentry, target); + smp_wmb(); do_switch(dentry->d_name.len, target->d_name.len); do_switch(dentry->d_name.hash, target->d_name.hash); /* ... and switch the parents */ @@ -1092,6 +1227,8 @@ write_unlock(&dparent_lock); list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); + dentry->d_move_count++; + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } @@ -1384,6 +1521,9 @@ if (!dentry_cache) panic("Cannot create dentry cache"); + /* approximate maximum number of dentries in one hash bucket */ + max_dentries = (mempages * (PAGE_SIZE / sizeof(struct dentry))); + set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); #if PAGE_SHIFT < 13 @@ -1414,6 +1554,8 @@ if (!dentry_hashtable) panic("Failed to allocate dcache hash table\n"); + + hashtable_end = dentry_hashtable + nr_hash; d = dentry_hashtable; i = nr_hash; diff -Nru a/fs/direct-io.c b/fs/direct-io.c --- a/fs/direct-io.c Mon Feb 17 14:57:27 2003 +++ b/fs/direct-io.c Mon Feb 17 14:57:27 2003 @@ -57,7 +57,7 @@ struct inode *inode; int rw; unsigned blkbits; /* doesn't change */ - unsigned blkfactor; /* When we're using an aligment which + unsigned blkfactor; /* When we're using an alignment which is finer than the filesystem's soft blocksize, this specifies how much finer. blkfactor=2 means 1/4-block @@ -754,7 +754,15 @@ do_holes: /* Handle holes */ if (!buffer_mapped(map_bh)) { - char *kaddr = kmap_atomic(page, KM_USER0); + char *kaddr; + + if (dio->block_in_file >= + dio->inode->i_size>>blkbits) { + /* We hit eof */ + page_cache_release(page); + goto out; + } + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + (block_in_page << blkbits), 0, 1 << blkbits); flush_dcache_page(page); @@ -927,20 +935,24 @@ ret = dio->result; /* Bytes written */ finished_one_bio(dio); /* This can free the dio */ blk_run_queues(); - goto out; + } else { + finished_one_bio(dio); + ret2 = dio_await_completion(dio); + if (ret == 0) + ret = ret2; + if (ret == 0) + ret = dio->page_errors; + if (ret == 0 && dio->result) { + ret = dio->result; + /* + * Adjust the return value if the read crossed a + * non-block-aligned EOF. + */ + if (rw == READ && (offset + ret > inode->i_size)) + ret = inode->i_size - offset; + } + kfree(dio); } - - finished_one_bio(dio); - ret2 = dio_await_completion(dio); - if (ret == 0) - ret = ret2; - if (ret == 0) - ret = dio->page_errors; - - if (dio->result) - ret = dio->result; - kfree(dio); -out: return ret; } diff -Nru a/fs/ext2/Makefile b/fs/ext2/Makefile --- a/fs/ext2/Makefile Mon Feb 17 14:57:28 2003 +++ b/fs/ext2/Makefile Mon Feb 17 14:57:28 2003 @@ -8,7 +8,7 @@ ioctl.o namei.o super.o symlink.o ifeq ($(CONFIG_EXT2_FS_XATTR),y) -ext2-objs += xattr.o xattr_user.o +ext2-objs += xattr.o xattr_user.o xattr_trusted.o endif ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y) diff -Nru a/fs/ext2/acl.c b/fs/ext2/acl.c --- a/fs/ext2/acl.c Mon Feb 17 14:57:28 2003 +++ b/fs/ext2/acl.c Mon Feb 17 14:57:28 2003 @@ -419,28 +419,28 @@ */ static size_t ext2_xattr_list_acl_access(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { - const size_t len = sizeof(XATTR_NAME_ACL_ACCESS)-1; + const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; if (list) - memcpy(list, XATTR_NAME_ACL_ACCESS, len); - return len; + memcpy(list, XATTR_NAME_ACL_ACCESS, size); + return size; } static size_t ext2_xattr_list_acl_default(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { - const size_t len = sizeof(XATTR_NAME_ACL_DEFAULT)-1; + const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; if (list) - memcpy(list, XATTR_NAME_ACL_DEFAULT, len); - return len; + memcpy(list, XATTR_NAME_ACL_DEFAULT, size); + return size; } static int @@ -465,7 +465,7 @@ static int ext2_xattr_get_acl_access(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { if (strcmp(name, "") != 0) return -EINVAL; @@ -474,7 +474,7 @@ static int ext2_xattr_get_acl_default(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { if (strcmp(name, "") != 0) return -EINVAL; @@ -482,7 +482,8 @@ } static int -ext2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) +ext2_xattr_set_acl(struct inode *inode, int type, const void *value, + size_t size) { struct posix_acl *acl; int error; diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c --- a/fs/ext2/xattr.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext2/xattr.c Mon Feb 17 14:57:27 2003 @@ -199,7 +199,7 @@ */ ssize_t ext2_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { struct ext2_xattr_handler *handler; struct inode *inode = dentry->d_inode; @@ -207,7 +207,7 @@ handler = ext2_xattr_resolve_name(&name); if (!handler) return -EOPNOTSUPP; - return handler->get(inode, name, buffer, size); + return handler->get(inode, name, buffer, size, flags); } /* @@ -217,9 +217,9 @@ * BKL held [before 2.5.x] */ ssize_t -ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size, int flags) { - return ext2_xattr_list(dentry->d_inode, buffer, size); + return ext2_xattr_list(dentry->d_inode, buffer, size, flags); } /* @@ -250,7 +250,7 @@ * BKL held [before 2.5.x] */ int -ext2_removexattr(struct dentry *dentry, const char *name) +ext2_removexattr(struct dentry *dentry, const char *name, int flags) { struct ext2_xattr_handler *handler; struct inode *inode = dentry->d_inode; @@ -258,7 +258,7 @@ handler = ext2_xattr_resolve_name(&name); if (!handler) return -EOPNOTSUPP; - return handler->set(inode, name, NULL, 0, XATTR_REPLACE); + return handler->set(inode, name, NULL, 0, flags | XATTR_REPLACE); } /* @@ -371,7 +371,8 @@ * used / required on success. */ int -ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size, + int flags) { struct buffer_head *bh = NULL; struct ext2_xattr_entry *entry; @@ -409,10 +410,9 @@ goto bad_block; handler = ext2_xattr_handler(entry->e_name_index); - if (handler) { + if (handler) size += handler->list(NULL, inode, entry->e_name, - entry->e_name_len) + 1; - } + entry->e_name_len, flags); } if (ext2_xattr_cache_insert(bh)) @@ -433,11 +433,9 @@ struct ext2_xattr_handler *handler; handler = ext2_xattr_handler(entry->e_name_index); - if (handler) { + if (handler) buf += handler->list(buf, inode, entry->e_name, - entry->e_name_len); - *buf++ = '\0'; - } + entry->e_name_len, flags); } error = size; @@ -1095,27 +1093,35 @@ { int err; - err = ext2_xattr_register(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler); + err = ext2_xattr_register(EXT2_XATTR_INDEX_USER, + &ext2_xattr_user_handler); if (err) return err; + err = ext2_xattr_register(EXT2_XATTR_INDEX_TRUSTED, + &ext2_xattr_trusted_handler); + if (err) + goto out; #ifdef CONFIG_EXT2_FS_POSIX_ACL err = init_ext2_acl(); if (err) - goto out; + goto out1; #endif ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry_index), 1, 6); if (!ext2_xattr_cache) { err = -ENOMEM; - goto out1; + goto out2; } return 0; -out1: +out2: #ifdef CONFIG_EXT2_FS_POSIX_ACL exit_ext2_acl(); -out: +out1: #endif + ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED, + &ext2_xattr_trusted_handler); +out: ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler); return err; @@ -1128,5 +1134,8 @@ #ifdef CONFIG_EXT2_FS_POSIX_ACL exit_ext2_acl(); #endif - ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler); + ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED, + &ext2_xattr_trusted_handler); + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, + &ext2_xattr_user_handler); } diff -Nru a/fs/ext2/xattr.h b/fs/ext2/xattr.h --- a/fs/ext2/xattr.h Mon Feb 17 14:57:26 2003 +++ b/fs/ext2/xattr.h Mon Feb 17 14:57:26 2003 @@ -21,6 +21,7 @@ #define EXT2_XATTR_INDEX_USER 1 #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 +#define EXT2_XATTR_INDEX_TRUSTED 4 struct ext2_xattr_header { __u32 h_magic; /* magic number for identification */ @@ -57,9 +58,9 @@ struct ext2_xattr_handler { char *prefix; size_t (*list)(char *list, struct inode *inode, const char *name, - int name_len); + int name_len, int flags); int (*get)(struct inode *inode, const char *name, void *buffer, - size_t size); + size_t size, int flags); int (*set)(struct inode *inode, const char *name, const void *buffer, size_t size, int flags); }; @@ -68,12 +69,12 @@ extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); -extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); -extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); -extern int ext2_removexattr(struct dentry *, const char *); +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t, int); +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t, int); +extern int ext2_removexattr(struct dentry *, const char *, int); extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t); -extern int ext2_xattr_list(struct inode *, char *, size_t); +extern int ext2_xattr_list(struct inode *, char *, size_t, int flags); extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern void ext2_xattr_delete_inode(struct inode *); @@ -132,4 +133,5 @@ # endif /* CONFIG_EXT2_FS_XATTR */ extern struct ext2_xattr_handler ext2_xattr_user_handler; +extern struct ext2_xattr_handler ext2_xattr_trusted_handler; diff -Nru a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ext2/xattr_trusted.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,63 @@ +/* + * linux/fs/ext2/xattr_trusted.c + * Handler for trusted extended attributes. + * + * Copyright (C) 2003 by Andreas Gruenbacher, + */ + +#include +#include +#include +#include +#include +#include "xattr.h" + +#define XATTR_TRUSTED_PREFIX "trusted." + +static size_t +ext2_xattr_trusted_list(char *list, struct inode *inode, + const char *name, int name_len, int flags) +{ + const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1; + + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return 0; + + if (list) { + memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); + memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; + } + return prefix_len + name_len + 1; +} + +static int +ext2_xattr_trusted_get(struct inode *inode, const char *name, + void *buffer, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return -EPERM; + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name, + buffer, size); +} + +static int +ext2_xattr_trusted_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return -EPERM; + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name, + value, size, flags); +} + +struct ext2_xattr_handler ext2_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .list = ext2_xattr_trusted_list, + .get = ext2_xattr_trusted_get, + .set = ext2_xattr_trusted_set, +}; diff -Nru a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c --- a/fs/ext2/xattr_user.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext2/xattr_user.c Mon Feb 17 14:57:27 2003 @@ -19,38 +19,41 @@ static size_t ext2_xattr_user_list(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; - if (!test_opt(inode->i_sb, XATTR_USER)) + if (!(flags & XATTR_KERNEL_CONTEXT) && + !test_opt(inode->i_sb, XATTR_USER)) return 0; if (list) { memcpy(list, XATTR_USER_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; } - return prefix_len + name_len; + return prefix_len + name_len + 1; } static int ext2_xattr_user_get(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { - int error; - if (strcmp(name, "") == 0) return -EINVAL; - if (!test_opt(inode->i_sb, XATTR_USER)) - return -EOPNOTSUPP; + if (!(flags & XATTR_KERNEL_CONTEXT)) { + int error; + + if (!test_opt(inode->i_sb, XATTR_USER)) + return -EOPNOTSUPP; #ifdef CONFIG_EXT2_FS_POSIX_ACL - error = ext2_permission_locked(inode, MAY_READ); + error = ext2_permission_locked(inode, MAY_READ); #else - error = permission(inode, MAY_READ); + error = permission(inode, MAY_READ); #endif - if (error) - return error; - + if (error) + return error; + } return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size); } @@ -59,23 +62,24 @@ ext2_xattr_user_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - int error; - if (strcmp(name, "") == 0) return -EINVAL; - if (!test_opt(inode->i_sb, XATTR_USER)) - return -EOPNOTSUPP; if ( !S_ISREG(inode->i_mode) && (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) return -EPERM; + if (!(flags & XATTR_KERNEL_CONTEXT)) { + int error; + + if (!test_opt(inode->i_sb, XATTR_USER)) + return -EOPNOTSUPP; #ifdef CONFIG_EXT2_FS_POSIX_ACL - error = ext2_permission_locked(inode, MAY_WRITE); + error = ext2_permission_locked(inode, MAY_WRITE); #else - error = permission(inode, MAY_WRITE); + error = permission(inode, MAY_WRITE); #endif - if (error) - return error; - + if (error) + return error; + } return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, value, size, flags); } diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile --- a/fs/ext3/Makefile Mon Feb 17 14:57:26 2003 +++ b/fs/ext3/Makefile Mon Feb 17 14:57:26 2003 @@ -8,7 +8,7 @@ ioctl.o namei.o super.o symlink.o hash.o ifeq ($(CONFIG_EXT3_FS_XATTR),y) -ext3-objs += xattr.o xattr_user.o +ext3-objs += xattr.o xattr_user.o xattr_trusted.o endif ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y) diff -Nru a/fs/ext3/acl.c b/fs/ext3/acl.c --- a/fs/ext3/acl.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext3/acl.c Mon Feb 17 14:57:27 2003 @@ -431,28 +431,28 @@ */ static size_t ext3_xattr_list_acl_access(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { - const size_t len = sizeof(XATTR_NAME_ACL_ACCESS)-1; + const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; if (list) - memcpy(list, XATTR_NAME_ACL_ACCESS, len); - return len; + memcpy(list, XATTR_NAME_ACL_ACCESS, size); + return size; } static size_t ext3_xattr_list_acl_default(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { - const size_t len = sizeof(XATTR_NAME_ACL_DEFAULT)-1; + const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; if (list) - memcpy(list, XATTR_NAME_ACL_DEFAULT, len); - return len; + memcpy(list, XATTR_NAME_ACL_DEFAULT, size); + return size; } static int @@ -477,7 +477,7 @@ static int ext3_xattr_get_acl_access(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { if (strcmp(name, "") != 0) return -EINVAL; @@ -486,7 +486,7 @@ static int ext3_xattr_get_acl_default(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { if (strcmp(name, "") != 0) return -EINVAL; @@ -494,7 +494,8 @@ } static int -ext3_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) +ext3_xattr_set_acl(struct inode *inode, int type, const void *value, + size_t size) { handle_t *handle; struct posix_acl *acl; diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c --- a/fs/ext3/balloc.c Mon Feb 17 14:57:26 2003 +++ b/fs/ext3/balloc.c Mon Feb 17 14:57:26 2003 @@ -503,7 +503,8 @@ got_block: - ext3_debug("using block group %d(%d)\n", i, gdp->bg_free_blocks_count); + ext3_debug("using block group %d(%d)\n", + group_no, gdp->bg_free_blocks_count); /* Make sure we use undo access for the bitmap, because it is critical that we do the frozen_data COW on bitmap buffers in @@ -658,7 +659,7 @@ bitmap_count += x; } brelse(bitmap_bh); - printk("ext3_count_free_blocks: stored = %lu, computed = %lu, %lu\n", + printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n", le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); unlock_super(sb); return bitmap_count; diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c --- a/fs/ext3/ialloc.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext3/ialloc.c Mon Feb 17 14:57:27 2003 @@ -704,7 +704,7 @@ bitmap_count += x; } brelse(bitmap_bh); - printk("ext3_count_free_inodes: stored = %lu, computed = %lu, %lu\n", + printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n", le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count); unlock_super(sb); return desc_count; diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c --- a/fs/ext3/inode.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext3/inode.c Mon Feb 17 14:57:27 2003 @@ -263,12 +263,12 @@ static int ext3_alloc_block (handle_t *handle, struct inode * inode, unsigned long goal, int *err) { -#ifdef EXT3FS_DEBUG - static unsigned long alloc_hits = 0, alloc_attempts = 0; -#endif unsigned long result; #ifdef EXT3_PREALLOCATE +#ifdef EXT3FS_DEBUG + static unsigned long alloc_hits = 0, alloc_attempts = 0; +#endif struct ext3_inode_info *ei = EXT3_I(inode); /* Writer: ->i_prealloc* */ if (ei->i_prealloc_count && @@ -1357,14 +1357,21 @@ handle = ext3_journal_current_handle(); lock_kernel(); - /* And attach them to the current transaction */ + /* + * And attach them to the current transaction. But only if + * block_write_full_page() succeeded. Otherwise they are unmapped, + * and generally junk. + */ if (order_data) { - err = walk_page_buffers(handle, page_bufs, - 0, PAGE_CACHE_SIZE, NULL, ext3_journal_dirty_data); + if (ret == 0) { + err = walk_page_buffers(handle, page_bufs, + 0, PAGE_CACHE_SIZE, NULL, + ext3_journal_dirty_data); + if (!ret) + ret = err; + } walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL, bput_one); - if (!ret) - ret = err; } err = ext3_journal_stop(handle, inode); diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c --- a/fs/ext3/xattr.c Mon Feb 17 14:57:27 2003 +++ b/fs/ext3/xattr.c Mon Feb 17 14:57:27 2003 @@ -195,7 +195,7 @@ */ ssize_t ext3_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { struct ext3_xattr_handler *handler; struct inode *inode = dentry->d_inode; @@ -203,7 +203,7 @@ handler = ext3_xattr_resolve_name(&name); if (!handler) return -EOPNOTSUPP; - return handler->get(inode, name, buffer, size); + return handler->get(inode, name, buffer, size, flags); } /* @@ -212,9 +212,9 @@ * dentry->d_inode->i_sem down */ ssize_t -ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size, int flags) { - return ext3_xattr_list(dentry->d_inode, buffer, size); + return ext3_xattr_list(dentry->d_inode, buffer, size, flags); } /* @@ -243,7 +243,7 @@ * dentry->d_inode->i_sem down */ int -ext3_removexattr(struct dentry *dentry, const char *name) +ext3_removexattr(struct dentry *dentry, const char *name, int flags) { struct ext3_xattr_handler *handler; struct inode *inode = dentry->d_inode; @@ -251,7 +251,7 @@ handler = ext3_xattr_resolve_name(&name); if (!handler) return -EOPNOTSUPP; - return handler->set(inode, name, NULL, 0, XATTR_REPLACE); + return handler->set(inode, name, NULL, 0, flags | XATTR_REPLACE); } /* @@ -364,7 +364,8 @@ * used / required on success. */ int -ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size, + int flags) { struct buffer_head *bh = NULL; struct ext3_xattr_entry *entry; @@ -402,10 +403,9 @@ goto bad_block; handler = ext3_xattr_handler(entry->e_name_index); - if (handler) { + if (handler) size += handler->list(NULL, inode, entry->e_name, - entry->e_name_len) + 1; - } + entry->e_name_len, flags); } if (ext3_xattr_cache_insert(bh)) @@ -426,11 +426,9 @@ struct ext3_xattr_handler *handler; handler = ext3_xattr_handler(entry->e_name_index); - if (handler) { + if (handler) buf += handler->list(buf, inode, entry->e_name, - entry->e_name_len); - *buf++ = '\0'; - } + entry->e_name_len, flags); } error = size; @@ -848,7 +846,7 @@ const void *value, size_t value_len, int flags) { handle_t *handle; - int error; + int error, error2; lock_kernel(); handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS); @@ -857,10 +855,10 @@ else error = ext3_xattr_set_handle(handle, inode, name_index, name, value, value_len, flags); - ext3_journal_stop(handle, inode); + error2 = ext3_journal_stop(handle, inode); unlock_kernel(); - return error; + return error ? error : error2; } /* @@ -1135,27 +1133,35 @@ { int err; - err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler); + err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, + &ext3_xattr_user_handler); if (err) return err; + err = ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED, + &ext3_xattr_trusted_handler); + if (err) + goto out; #ifdef CONFIG_EXT3_FS_POSIX_ACL err = init_ext3_acl(); if (err) - goto out; + goto out1; #endif ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry_index), 1, 6); if (!ext3_xattr_cache) { err = -ENOMEM; - goto out1; + goto out2; } return 0; -out1: +out2: #ifdef CONFIG_EXT3_FS_POSIX_ACL exit_ext3_acl(); -out: +out1: #endif + ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED, + &ext3_xattr_trusted_handler); +out: ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler); return err; @@ -1170,5 +1176,8 @@ #ifdef CONFIG_EXT3_FS_POSIX_ACL exit_ext3_acl(); #endif - ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler); + ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED, + &ext3_xattr_trusted_handler); + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, + &ext3_xattr_user_handler); } diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h --- a/fs/ext3/xattr.h Mon Feb 17 14:57:28 2003 +++ b/fs/ext3/xattr.h Mon Feb 17 14:57:28 2003 @@ -20,6 +20,7 @@ #define EXT3_XATTR_INDEX_USER 1 #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 +#define EXT3_XATTR_INDEX_TRUSTED 4 struct ext3_xattr_header { __u32 h_magic; /* magic number for identification */ @@ -56,9 +57,9 @@ struct ext3_xattr_handler { char *prefix; size_t (*list)(char *list, struct inode *inode, const char *name, - int name_len); + int name_len, int flags); int (*get)(struct inode *inode, const char *name, void *buffer, - size_t size); + size_t size, int flags); int (*set)(struct inode *inode, const char *name, const void *buffer, size_t size, int flags); }; @@ -67,12 +68,12 @@ extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *); extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int); -extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t); -extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); -extern int ext3_removexattr(struct dentry *, const char *); +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t, int); +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t, int); +extern int ext3_removexattr(struct dentry *, const char *, int); extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -extern int ext3_xattr_list(struct inode *, char *, size_t); +extern int ext3_xattr_list(struct inode *, char *, size_t, int flags); extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); @@ -139,3 +140,4 @@ # endif /* CONFIG_EXT3_FS_XATTR */ extern struct ext3_xattr_handler ext3_xattr_user_handler; +extern struct ext3_xattr_handler ext3_xattr_trusted_handler; diff -Nru a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ext3/xattr_trusted.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,64 @@ +/* + * linux/fs/ext3/xattr_trusted.c + * Handler for trusted extended attributes. + * + * Copyright (C) 2003 by Andreas Gruenbacher, + */ + +#include +#include +#include +#include +#include +#include +#include "xattr.h" + +#define XATTR_TRUSTED_PREFIX "trusted." + +static size_t +ext3_xattr_trusted_list(char *list, struct inode *inode, + const char *name, int name_len, int flags) +{ + const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1; + + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return 0; + + if (list) { + memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); + memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; + } + return prefix_len + name_len + 1; +} + +static int +ext3_xattr_trusted_get(struct inode *inode, const char *name, + void *buffer, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return -EPERM; + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name, + buffer, size); +} + +static int +ext3_xattr_trusted_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN))) + return -EPERM; + return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name, + value, size, flags); +} + +struct ext3_xattr_handler ext3_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .list = ext3_xattr_trusted_list, + .get = ext3_xattr_trusted_get, + .set = ext3_xattr_trusted_set, +}; diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c --- a/fs/ext3/xattr_user.c Mon Feb 17 14:57:26 2003 +++ b/fs/ext3/xattr_user.c Mon Feb 17 14:57:26 2003 @@ -21,38 +21,41 @@ static size_t ext3_xattr_user_list(char *list, struct inode *inode, - const char *name, int name_len) + const char *name, int name_len, int flags) { const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; - if (!test_opt(inode->i_sb, XATTR_USER)) + if (!(flags & XATTR_KERNEL_CONTEXT) && + !test_opt(inode->i_sb, XATTR_USER)) return 0; if (list) { memcpy(list, XATTR_USER_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; } - return prefix_len + name_len; + return prefix_len + name_len + 1; } static int ext3_xattr_user_get(struct inode *inode, const char *name, - void *buffer, size_t size) + void *buffer, size_t size, int flags) { - int error; - if (strcmp(name, "") == 0) return -EINVAL; - if (!test_opt(inode->i_sb, XATTR_USER)) - return -EOPNOTSUPP; + if (!(flags & XATTR_KERNEL_CONTEXT)) { + int error; + + if (!test_opt(inode->i_sb, XATTR_USER)) + return -EOPNOTSUPP; #ifdef CONFIG_EXT3_FS_POSIX_ACL - error = ext3_permission_locked(inode, MAY_READ); + error = ext3_permission_locked(inode, MAY_READ); #else - error = permission(inode, MAY_READ); + error = permission(inode, MAY_READ); #endif - if (error) - return error; - + if (error) + return error; + } return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size); } @@ -61,26 +64,26 @@ ext3_xattr_user_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - int error; - if (strcmp(name, "") == 0) return -EINVAL; - if (!test_opt(inode->i_sb, XATTR_USER)) - return -EOPNOTSUPP; if ( !S_ISREG(inode->i_mode) && (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) return -EPERM; + if (!(flags & XATTR_KERNEL_CONTEXT)) { + int error; + + if (!test_opt(inode->i_sb, XATTR_USER)) + return -EOPNOTSUPP; #ifdef CONFIG_EXT3_FS_POSIX_ACL - error = ext3_permission_locked(inode, MAY_WRITE); + error = ext3_permission_locked(inode, MAY_WRITE); #else - error = permission(inode, MAY_WRITE); + error = permission(inode, MAY_WRITE); #endif - if (error) - return error; - + if (error) + return error; + } return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name, value, size, flags); - } struct ext3_xattr_handler ext3_xattr_user_handler = { diff -Nru a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h --- a/fs/jfs/jfs_debug.h Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/jfs_debug.h Mon Feb 17 14:57:27 2003 @@ -89,8 +89,7 @@ /* error event message: e.g., i/o error */ #define jfs_err(fmt, arg...) do { \ if (jfsloglevel >= JFS_LOGLEVEL_ERR) \ - printk(KERN_ERR "%s:%d " fmt "\n", \ - __FILE__, __LINE__, ## arg); \ + printk(KERN_ERR fmt "\n", ## arg); \ } while (0) /* diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c --- a/fs/jfs/jfs_logmgr.c Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/jfs_logmgr.c Mon Feb 17 14:57:27 2003 @@ -97,7 +97,7 @@ #define LOGGC_LOCK_INIT(log) spin_lock_init(&(log)->gclock) #define LOGGC_LOCK(log) spin_lock_irq(&(log)->gclock) #define LOGGC_UNLOCK(log) spin_unlock_irq(&(log)->gclock) -#define LOGGC_WAKEUP(tblk) wake_up(&(tblk)->gcwait) +#define LOGGC_WAKEUP(tblk) wake_up_all(&(tblk)->gcwait) /* * log sync serialization (per log) @@ -511,7 +511,6 @@ tblk->bp = log->bp; tblk->pn = log->page; tblk->eor = log->eor; - init_waitqueue_head(&tblk->gcwait); /* enqueue transaction to commit queue */ tblk->cqnext = NULL; @@ -831,6 +830,12 @@ tblk->flag &= ~tblkGC_QUEUE; tblk->cqnext = 0; + if (tblk == log->flush_tblk) { + /* we can stop flushing the log now */ + clear_bit(log_FLUSH, &log->flag); + log->flush_tblk = NULL; + } + jfs_info("lmPostGC: tblk = 0x%p, flag = 0x%x", tblk, tblk->flag); @@ -843,10 +848,10 @@ /* state transition: COMMIT -> COMMITTED */ tblk->flag |= tblkGC_COMMITTED; - if (tblk->flag & tblkGC_READY) { + if (tblk->flag & tblkGC_READY) log->gcrtc--; - LOGGC_WAKEUP(tblk); - } + + LOGGC_WAKEUP(tblk); } /* was page full before pageout ? @@ -892,6 +897,7 @@ else { log->cflag &= ~logGC_PAGEOUT; clear_bit(log_FLUSH, &log->flag); + WARN_ON(log->flush_tblk); } //LOGGC_UNLOCK(log); @@ -1307,7 +1313,8 @@ INIT_LIST_HEAD(&log->synclist); - log->cqueue.head = log->cqueue.tail = 0; + log->cqueue.head = log->cqueue.tail = NULL; + log->flush_tblk = NULL; log->count = 0; @@ -1395,38 +1402,78 @@ * * FUNCTION: initiate write of any outstanding transactions to the journal * and optionally wait until they are all written to disk + * + * wait == 0 flush until latest txn is committed, don't wait + * wait == 1 flush until latest txn is committed, wait + * wait > 1 flush until all txn's are complete, wait */ void jfs_flush_journal(struct jfs_log *log, int wait) { int i; + struct tblock *target; jfs_info("jfs_flush_journal: log:0x%p wait=%d", log, wait); - /* - * This ensures that we will keep writing to the journal as long - * as there are unwritten commit records - */ - set_bit(log_FLUSH, &log->flag); - - /* - * Initiate I/O on outstanding transactions - */ LOGGC_LOCK(log); - if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) { - log->cflag |= logGC_PAGEOUT; - lmGCwrite(log, 0); + + target = log->cqueue.head; + + if (target) { + /* + * This ensures that we will keep writing to the journal as long + * as there are unwritten commit records + */ + + if (test_bit(log_FLUSH, &log->flag)) { + /* + * We're already flushing. + * if flush_tblk is NULL, we are flushing everything, + * so leave it that way. Otherwise, update it to the + * latest transaction + */ + if (log->flush_tblk) + log->flush_tblk = target; + } else { + /* Only flush until latest transaction is committed */ + log->flush_tblk = target; + set_bit(log_FLUSH, &log->flag); + + /* + * Initiate I/O on outstanding transactions + */ + if (!(log->cflag & logGC_PAGEOUT)) { + log->cflag |= logGC_PAGEOUT; + lmGCwrite(log, 0); + } + } + } + if ((wait > 1) || test_bit(log_SYNCBARRIER, &log->flag)) { + /* Flush until all activity complete */ + set_bit(log_FLUSH, &log->flag); + log->flush_tblk = NULL; + } + + if (wait && target && !(target->flag & tblkGC_COMMITTED)) { + DECLARE_WAITQUEUE(__wait, current); + + add_wait_queue(&target->gcwait, &__wait); + set_current_state(TASK_UNINTERRUPTIBLE); + LOGGC_UNLOCK(log); + schedule(); + current->state = TASK_RUNNING; + LOGGC_LOCK(log); + remove_wait_queue(&target->gcwait, &__wait); } LOGGC_UNLOCK(log); - if (!wait) + if (wait < 2) return; + /* + * If there was recent activity, we may need to wait + * for the lazycommit thread to catch up + */ if (log->cqueue.head || !list_empty(&log->synclist)) { - /* - * If there was very recent activity, we may need to wait - * for the lazycommit thread to catch up - */ - for (i = 0; i < 800; i++) { /* Too much? */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ / 4); @@ -1437,7 +1484,6 @@ } assert(log->cqueue.head == NULL); assert(list_empty(&log->synclist)); - clear_bit(log_FLUSH, &log->flag); } @@ -1467,7 +1513,7 @@ jfs_info("lmLogShutdown: log:0x%p", log); - jfs_flush_journal(log, 1); + jfs_flush_journal(log, 2); /* * We need to make sure all of the "written" metapages diff -Nru a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h --- a/fs/jfs/jfs_logmgr.h Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/jfs_logmgr.h Mon Feb 17 14:57:27 2003 @@ -403,6 +403,7 @@ struct tblock *head; struct tblock *tail; } cqueue; + struct tblock *flush_tblk; /* tblk we're waiting on for flush */ int gcrtc; /* 4: GC_READY transaction count */ struct tblock *gclrt; /* 4: latest GC_READY transaction */ spinlock_t gclock; /* 4: group commit lock */ diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c --- a/fs/jfs/jfs_txnmgr.c Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/jfs_txnmgr.c Mon Feb 17 14:57:27 2003 @@ -2741,8 +2741,7 @@ if (tblk->flag & tblkGC_READY) log->gcrtc--; - if (tblk->flag & tblkGC_READY) - wake_up(&tblk->gcwait); // LOGGC_WAKEUP + wake_up_all(&tblk->gcwait); // LOGGC_WAKEUP /* * Can't release log->gclock until we've tested tblk->flag diff -Nru a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c --- a/fs/jfs/jfs_umount.c Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/jfs_umount.c Mon Feb 17 14:57:27 2003 @@ -69,7 +69,7 @@ /* * Wait for outstanding transactions to be written to log: */ - jfs_flush_journal(log, 1); + jfs_flush_journal(log, 2); /* * close fileset inode allocation map (aka fileset inode) @@ -149,7 +149,7 @@ * * remove file system from log active file system list. */ - jfs_flush_journal(log, 1); + jfs_flush_journal(log, 2); /* * Make sure all metadata makes it to disk diff -Nru a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h --- a/fs/jfs/jfs_xattr.h Mon Feb 17 14:57:28 2003 +++ b/fs/jfs/jfs_xattr.h Mon Feb 17 14:57:28 2003 @@ -57,8 +57,8 @@ extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); -extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); -extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); -extern int jfs_removexattr(struct dentry *, const char *); +extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t, int); +extern ssize_t jfs_listxattr(struct dentry *, char *, size_t, int); +extern int jfs_removexattr(struct dentry *, const char *, int); #endif /* H_JFS_XATTR */ diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c --- a/fs/jfs/xattr.c Mon Feb 17 14:57:27 2003 +++ b/fs/jfs/xattr.c Mon Feb 17 14:57:27 2003 @@ -962,12 +962,13 @@ } ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, - size_t buf_size) + size_t buf_size, int flags) { return __jfs_getxattr(dentry->d_inode, name, data, buf_size); } -ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) +ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size, + int flags) { struct inode *inode = dentry->d_inode; char *buffer; @@ -1013,7 +1014,7 @@ return size; } -int jfs_removexattr(struct dentry *dentry, const char *name) +int jfs_removexattr(struct dentry *dentry, const char *name, int flags) { return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE); } diff -Nru a/fs/locks.c b/fs/locks.c --- a/fs/locks.c Mon Feb 17 14:57:28 2003 +++ b/fs/locks.c Mon Feb 17 14:57:28 2003 @@ -652,63 +652,6 @@ return 0; } -int locks_mandatory_locked(struct inode *inode) -{ - fl_owner_t owner = current->files; - struct file_lock *fl; - - /* - * Search the lock list for this inode for any POSIX locks. - */ - lock_kernel(); - for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { - if (!IS_POSIX(fl)) - continue; - if (fl->fl_owner != owner) - break; - } - unlock_kernel(); - return fl ? -EAGAIN : 0; -} - -int locks_mandatory_area(int read_write, struct inode *inode, - struct file *filp, loff_t offset, - size_t count) -{ - struct file_lock fl; - int error; - - fl.fl_owner = current->files; - fl.fl_pid = current->tgid; - fl.fl_file = filp; - fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP; - fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; - fl.fl_start = offset; - fl.fl_end = offset + count - 1; - - for (;;) { - error = posix_lock_file(filp, &fl); - if (error != -EAGAIN) - break; - error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); - if (!error) { - /* - * If we've been sleeping someone might have - * changed the permissions behind our back. - */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) - continue; - } - - lock_kernel(); - locks_delete_block(&fl); - unlock_kernel(); - break; - } - - return error; -} - /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks * at the head of the list, but that's secret knowledge known only to * flock_lock_file and posix_lock_file. @@ -770,32 +713,13 @@ return error; } -/** - * posix_lock_file: - * @filp: The file to apply the lock to - * @caller: The lock to be applied - * @wait: 1 to retry automatically, 0 to return -EAGAIN - * - * Add a POSIX style lock to a file. - * We merge adjacent locks whenever possible. POSIX locks are sorted by owner - * task, then by starting address - * - * Kai Petzke writes: - * To make freeing a lock much faster, we keep a pointer to the lock before the - * actual one. But the real gain of the new coding was, that lock_it() and - * unlock_it() became one function. - * - * To all purists: Yes, I use a few goto's. Just pass on to the next function. - */ - -int posix_lock_file(struct file *filp, struct file_lock *request) +static int __posix_lock_file(struct inode *inode, struct file_lock *request) { struct file_lock *fl; struct file_lock *new_fl, *new_fl2; struct file_lock *left = NULL; struct file_lock *right = NULL; struct file_lock **before; - struct inode * inode = filp->f_dentry->d_inode; int error, added = 0; /* @@ -804,9 +728,6 @@ */ new_fl = locks_alloc_lock(0); new_fl2 = locks_alloc_lock(0); - error = -ENOLCK; /* "no luck" */ - if (!(new_fl && new_fl2)) - goto out_nolock; lock_kernel(); if (request->fl_type != F_UNLCK) { @@ -829,9 +750,14 @@ } /* If we're just looking for a conflict, we're done. */ + error = 0; if (request->fl_flags & FL_ACCESS) goto out; + error = -ENOLCK; /* "no luck" */ + if (!(new_fl && new_fl2)) + goto out; + /* * We've allocated the new locks in advance, so there are no * errors possible (and no blocking operations) from here on. @@ -952,9 +878,8 @@ left->fl_end = request->fl_start - 1; locks_wake_up_blocks(left); } -out: + out: unlock_kernel(); -out_nolock: /* * Free any unused locks. */ @@ -965,6 +890,102 @@ return error; } +/** + * posix_lock_file - Apply a POSIX-style lock to a file + * @filp: The file to apply the lock to + * @fl: The lock to be applied + * + * Add a POSIX style lock to a file. + * We merge adjacent & overlapping locks whenever possible. + * POSIX locks are sorted by owner task, then by starting address + */ +int posix_lock_file(struct file *filp, struct file_lock *fl) +{ + return __posix_lock_file(filp->f_dentry->d_inode, fl); +} + +/** + * locks_mandatory_locked - Check for an active lock + * @inode: the file to check + * + * Searches the inode's list of locks to find any POSIX locks which conflict. + * This function is called from locks_verify_locked() only. + */ +int locks_mandatory_locked(struct inode *inode) +{ + fl_owner_t owner = current->files; + struct file_lock *fl; + + /* + * Search the lock list for this inode for any POSIX locks. + */ + lock_kernel(); + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!IS_POSIX(fl)) + continue; + if (fl->fl_owner != owner) + break; + } + unlock_kernel(); + return fl ? -EAGAIN : 0; +} + +/** + * locks_mandatory_area - Check for a conflicting lock + * @read_write: %FLOCK_VERIFY_WRITE for exclusive access, %FLOCK_VERIFY_READ + * for shared + * @inode: the file to check + * @file: how the file was opened (if it was) + * @offset: start of area to check + * @count: length of area to check + * + * Searches the inode's list of locks to find any POSIX locks which conflict. + * This function is called from locks_verify_area() and + * locks_verify_truncate(). + */ +int locks_mandatory_area(int read_write, struct inode *inode, + struct file *filp, loff_t offset, + size_t count) +{ + struct file_lock fl; + int error; + + locks_init_lock(&fl); + fl.fl_owner = current->files; + fl.fl_pid = current->tgid; + fl.fl_file = filp; + fl.fl_flags = FL_POSIX | FL_ACCESS; + if (filp && !(filp->f_flags & O_NONBLOCK)) + fl.fl_flags |= FL_SLEEP; + fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; + fl.fl_start = offset; + fl.fl_end = offset + count - 1; + + for (;;) { + error = __posix_lock_file(inode, &fl); + if (error != -EAGAIN) + break; + if (!(fl.fl_flags & FL_SLEEP)) + break; + error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); + if (!error) { + /* + * If we've been sleeping someone might have + * changed the permissions behind our back. + */ + if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + continue; + } + + lock_kernel(); + locks_delete_block(&fl); + unlock_kernel(); + break; + } + + return error; +} + /* We already had a lease on this file; just change its type */ static int lease_modify(struct file_lock **before, int arg) { @@ -1460,7 +1481,7 @@ } for (;;) { - error = posix_lock_file(filp, file_lock); + error = __posix_lock_file(inode, file_lock); if ((error != -EAGAIN) || (cmd == F_SETLK)) break; error = wait_event_interruptible(file_lock->fl_wait, @@ -1600,7 +1621,7 @@ } for (;;) { - error = posix_lock_file(filp, file_lock); + error = __posix_lock_file(inode, file_lock); if ((error != -EAGAIN) || (cmd == F_SETLK64)) break; error = wait_event_interruptible(file_lock->fl_wait, diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Mon Feb 17 14:57:27 2003 +++ b/fs/namei.c Mon Feb 17 14:57:27 2003 @@ -286,27 +286,6 @@ return dentry; } -/*for fastwalking*/ -static inline void unlock_nd(struct nameidata *nd) -{ - struct vfsmount *mnt = nd->old_mnt; - struct dentry *dentry = nd->old_dentry; - mntget(nd->mnt); - dget_locked(nd->dentry); - nd->old_mnt = NULL; - nd->old_dentry = NULL; - spin_unlock(&dcache_lock); - dput(dentry); - mntput(mnt); -} - -static inline void lock_nd(struct nameidata *nd) -{ - spin_lock(&dcache_lock); - nd->old_mnt = nd->mnt; - nd->old_dentry = nd->dentry; -} - /* * Short-cut version of permission(), for calling by * path_walk(), when dcache lock is held. Combines parts @@ -451,11 +430,18 @@ { int res = 0; while (d_mountpoint(*dentry)) { - struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); - if (!mounted) + struct vfsmount *mounted; + spin_lock(&dcache_lock); + mounted = lookup_mnt(*mnt, *dentry); + if (!mounted) { + spin_unlock(&dcache_lock); break; - *mnt = mounted; - *dentry = mounted->mnt_root; + } + *mnt = mntget(mounted); + spin_unlock(&dcache_lock); + dput(*dentry); + mntput(mounted->mnt_parent); + *dentry = dget(mounted->mnt_root); res = 1; } return res; @@ -488,17 +474,32 @@ { while(1) { struct vfsmount *parent; + struct dentry *old = *dentry; + + read_lock(¤t->fs->lock); if (*dentry == current->fs->root && - *mnt == current->fs->rootmnt) + *mnt == current->fs->rootmnt) { + read_unlock(¤t->fs->lock); break; + } + read_unlock(¤t->fs->lock); + spin_lock(&dcache_lock); if (*dentry != (*mnt)->mnt_root) { - *dentry = (*dentry)->d_parent; + *dentry = dget((*dentry)->d_parent); + spin_unlock(&dcache_lock); + dput(old); break; } - parent=(*mnt)->mnt_parent; - if (parent == *mnt) + parent = (*mnt)->mnt_parent; + if (parent == *mnt) { + spin_unlock(&dcache_lock); break; - *dentry=(*mnt)->mnt_mountpoint; + } + mntget(parent); + *dentry = dget((*mnt)->mnt_mountpoint); + spin_unlock(&dcache_lock); + dput(old); + mntput(*mnt); *mnt = parent; } follow_mount(mnt, dentry); @@ -515,14 +516,13 @@ * It _is_ time-critical. */ static int do_lookup(struct nameidata *nd, struct qstr *name, - struct path *path, struct path *cached_path, - int flags) + struct path *path, int flags) { struct vfsmount *mnt = nd->mnt; - struct dentry *dentry = __d_lookup(nd->dentry, name); + struct dentry *dentry = d_lookup(nd->dentry, name); if (!dentry) - goto dcache_miss; + goto need_lookup; if (dentry->d_op && dentry->d_op->d_revalidate) goto need_revalidate; done: @@ -530,36 +530,21 @@ path->dentry = dentry; return 0; -dcache_miss: - unlock_nd(nd); - need_lookup: dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE); if (IS_ERR(dentry)) goto fail; - mntget(mnt); -relock: - dput(cached_path->dentry); - mntput(cached_path->mnt); - cached_path->mnt = mnt; - cached_path->dentry = dentry; - lock_nd(nd); goto done; need_revalidate: - mntget(mnt); - dget_locked(dentry); - unlock_nd(nd); if (dentry->d_op->d_revalidate(dentry, flags)) - goto relock; + goto done; if (d_invalidate(dentry)) - goto relock; + goto done; dput(dentry); - mntput(mnt); goto need_lookup; fail: - lock_nd(nd); return PTR_ERR(dentry); } @@ -573,7 +558,7 @@ */ int link_path_walk(const char * name, struct nameidata *nd) { - struct path next, pinned = {NULL, NULL}; + struct path next; struct inode *inode; int err; unsigned int lookup_flags = nd->flags; @@ -594,10 +579,8 @@ unsigned int c; err = exec_permission_lite(inode); - if (err == -EAGAIN) { - unlock_nd(nd); + if (err == -EAGAIN) { err = permission(inode, MAY_EXEC); - lock_nd(nd); } if (err) break; @@ -648,7 +631,7 @@ break; } /* This does the actual lookups.. */ - err = do_lookup(nd, &this, &next, &pinned, LOOKUP_CONTINUE); + err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE); if (err) break; /* Check mountpoints.. */ @@ -657,21 +640,18 @@ err = -ENOENT; inode = next.dentry->d_inode; if (!inode) - break; + goto out_dput; err = -ENOTDIR; if (!inode->i_op) - break; + goto out_dput; if (inode->i_op->follow_link) { mntget(next.mnt); - dget_locked(next.dentry); - unlock_nd(nd); err = do_follow_link(next.dentry, nd); dput(next.dentry); mntput(next.mnt); if (err) goto return_err; - lock_nd(nd); err = -ENOENT; inode = nd->dentry->d_inode; if (!inode) @@ -680,6 +660,7 @@ if (!inode->i_op) break; } else { + dput(nd->dentry); nd->mnt = next.mnt; nd->dentry = next.dentry; } @@ -711,7 +692,7 @@ if (err < 0) break; } - err = do_lookup(nd, &this, &next, &pinned, 0); + err = do_lookup(nd, &this, &next, 0); if (err) break; follow_mount(&next.mnt, &next.dentry); @@ -719,16 +700,14 @@ if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) { mntget(next.mnt); - dget_locked(next.dentry); - unlock_nd(nd); err = do_follow_link(next.dentry, nd); dput(next.dentry); mntput(next.mnt); if (err) goto return_err; inode = nd->dentry->d_inode; - lock_nd(nd); } else { + dput(nd->dentry); nd->mnt = next.mnt; nd->dentry = next.dentry; } @@ -751,23 +730,19 @@ else if (this.len == 2 && this.name[1] == '.') nd->last_type = LAST_DOTDOT; return_base: - unlock_nd(nd); - dput(pinned.dentry); - mntput(pinned.mnt); return 0; +out_dput: + dput(next.dentry); + break; } - unlock_nd(nd); path_release(nd); return_err: - dput(pinned.dentry); - mntput(pinned.mnt); return err; } int path_walk(const char * name, struct nameidata *nd) { current->total_link_count = 0; - lock_nd(nd); return link_path_walk(name, nd); } @@ -855,28 +830,24 @@ { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; + + read_lock(¤t->fs->lock); if (*name=='/') { - read_lock(¤t->fs->lock); if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { nd->mnt = mntget(current->fs->altrootmnt); nd->dentry = dget(current->fs->altroot); read_unlock(¤t->fs->lock); if (__emul_lookup_dentry(name,nd)) return 0; - } else { - read_unlock(¤t->fs->lock); } - spin_lock(&dcache_lock); - nd->mnt = current->fs->rootmnt; - nd->dentry = current->fs->root; + nd->mnt = mntget(current->fs->rootmnt); + nd->dentry = dget(current->fs->root); } else{ - spin_lock(&dcache_lock); - nd->mnt = current->fs->pwdmnt; - nd->dentry = current->fs->pwd; + nd->mnt = mntget(current->fs->pwdmnt); + nd->dentry = dget(current->fs->pwd); } - nd->old_mnt = NULL; - nd->old_dentry = NULL; + read_unlock(¤t->fs->lock); current->total_link_count = 0; return link_path_walk(name, nd); } @@ -2129,7 +2100,6 @@ /* weird __emul_prefix() stuff did it */ goto out; } - lock_nd(nd); res = link_path_walk(link, nd); out: if (current->link_count || res || nd->last_type!=LAST_NORM) diff -Nru a/fs/namespace.c b/fs/namespace.c --- a/fs/namespace.c Mon Feb 17 14:57:27 2003 +++ b/fs/namespace.c Mon Feb 17 14:57:27 2003 @@ -892,12 +892,10 @@ struct dentry *old_root; struct vfsmount *old_rootmnt; write_lock(&fs->lock); - spin_lock(&dcache_lock); old_root = fs->root; old_rootmnt = fs->rootmnt; fs->rootmnt = mntget(mnt); fs->root = dget(dentry); - spin_unlock(&dcache_lock); write_unlock(&fs->lock); if (old_root) { dput(old_root); @@ -916,12 +914,10 @@ struct vfsmount *old_pwdmnt; write_lock(&fs->lock); - spin_lock(&dcache_lock); old_pwd = fs->pwd; old_pwdmnt = fs->pwdmnt; fs->pwdmnt = mntget(mnt); fs->pwd = dget(dentry); - spin_unlock(&dcache_lock); write_unlock(&fs->lock); if (old_pwd) { diff -Nru a/fs/proc/array.c b/fs/proc/array.c --- a/fs/proc/array.c Mon Feb 17 14:57:27 2003 +++ b/fs/proc/array.c Mon Feb 17 14:57:27 2003 @@ -180,51 +180,74 @@ return buffer; } +static char * render_sigset_t(const char *header, sigset_t *set, char *buffer) +{ + int i, len; + + len = strlen(header); + memcpy(buffer, header, len); + buffer += len; + + i = _NSIG; + do { + int x = 0; + + i -= 4; + if (sigismember(set, i+1)) x |= 1; + if (sigismember(set, i+2)) x |= 2; + if (sigismember(set, i+3)) x |= 4; + if (sigismember(set, i+4)) x |= 8; + *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; + } while (i >= 4); + + *buffer++ = '\n'; + *buffer = 0; + return buffer; +} + static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, sigset_t *catch) { struct k_sigaction *k; int i; - sigemptyset(ign); - sigemptyset(catch); + k = p->sighand->action; + for (i = 1; i <= _NSIG; ++i, ++k) { + if (k->sa.sa_handler == SIG_IGN) + sigaddset(ign, i); + else if (k->sa.sa_handler != SIG_DFL) + sigaddset(catch, i); + } +} + +static inline char * task_sig(struct task_struct *p, char *buffer) +{ + sigset_t pending, shpending, blocked, ignored, caught; + + sigemptyset(&pending); + sigemptyset(&shpending); + sigemptyset(&blocked); + sigemptyset(&ignored); + sigemptyset(&caught); + /* Gather all the data with the appropriate locks held */ read_lock(&tasklist_lock); if (p->sighand) { spin_lock_irq(&p->sighand->siglock); - k = p->sighand->action; - for (i = 1; i <= _NSIG; ++i, ++k) { - if (k->sa.sa_handler == SIG_IGN) - sigaddset(ign, i); - else if (k->sa.sa_handler != SIG_DFL) - sigaddset(catch, i); - } + pending = p->pending.signal; + shpending = p->signal->shared_pending.signal; + blocked = p->blocked; + collect_sigign_sigcatch(p, &ignored, &caught); spin_unlock_irq(&p->sighand->siglock); } read_unlock(&tasklist_lock); -} - -static inline char * task_sig(struct task_struct *p, char *buffer) -{ - sigset_t ign, catch; - - buffer += sprintf(buffer, "SigPnd:\t"); - buffer = render_sigset_t(&p->pending.signal, buffer); - *buffer++ = '\n'; - buffer += sprintf(buffer, "ShdPnd:\t"); - buffer = render_sigset_t(&p->signal->shared_pending.signal, buffer); - *buffer++ = '\n'; - buffer += sprintf(buffer, "SigBlk:\t"); - buffer = render_sigset_t(&p->blocked, buffer); - *buffer++ = '\n'; - collect_sigign_sigcatch(p, &ign, &catch); - buffer += sprintf(buffer, "SigIgn:\t"); - buffer = render_sigset_t(&ign, buffer); - *buffer++ = '\n'; - buffer += sprintf(buffer, "SigCgt:\t"); /* Linux 2.0 uses "SigCgt" */ - buffer = render_sigset_t(&catch, buffer); - *buffer++ = '\n'; + /* render them all */ + buffer = render_sigset_t("SigPnd:\t", &pending, buffer); + buffer = render_sigset_t("ShdPnd:\t", &shpending, buffer); + buffer = render_sigset_t("SigBlk:\t", &blocked, buffer); + buffer = render_sigset_t("SigIgn:\t", &ignored, buffer); + buffer = render_sigset_t("SigCgt:\t", &caught, buffer); return buffer; } @@ -293,7 +316,15 @@ wchan = get_wchan(task); - collect_sigign_sigcatch(task, &sigign, &sigcatch); + sigemptyset(&sigign); + sigemptyset(&sigcatch); + read_lock(&tasklist_lock); + if (task->sighand) { + spin_lock_irq(&task->sighand->siglock); + collect_sigign_sigcatch(task, &sigign, &sigcatch); + spin_unlock_irq(&task->sighand->siglock); + } + read_unlock(&tasklist_lock); /* scale priority and nice values from timeslices to -20..20 */ /* to make it look like a "normal" Unix priority/nice value */ diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c Mon Feb 17 14:57:27 2003 +++ b/fs/proc/base.c Mon Feb 17 14:57:27 2003 @@ -31,6 +31,7 @@ #include #include #include +#include /* * For hysterical raisins we keep the same inumbers as in the old procfs. diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c Mon Feb 17 14:57:27 2003 +++ b/fs/proc/proc_misc.c Mon Feb 17 14:57:27 2003 @@ -356,7 +356,7 @@ } len += sprintf(page + len, "intr %u", sum); -#if !defined(CONFIG_ARCH_S390) +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC64) for (i = 0 ; i < NR_IRQS ; i++) len += sprintf(page + len, " %u", kstat_irqs(i)); #endif diff -Nru a/fs/xattr.c b/fs/xattr.c --- a/fs/xattr.c Mon Feb 17 14:57:27 2003 +++ b/fs/xattr.c Mon Feb 17 14:57:27 2003 @@ -160,7 +160,7 @@ if (error) goto out; down(&d->d_inode->i_sem); - error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); + error = d->d_inode->i_op->getxattr(d, kname, kvalue, size, 0); up(&d->d_inode->i_sem); } @@ -233,7 +233,7 @@ if (error) goto out; down(&d->d_inode->i_sem); - error = d->d_inode->i_op->listxattr(d, klist, size); + error = d->d_inode->i_op->listxattr(d, klist, size, 0); up(&d->d_inode->i_sem); } @@ -308,7 +308,7 @@ if (error) goto out; down(&d->d_inode->i_sem); - error = d->d_inode->i_op->removexattr(d, kname); + error = d->d_inode->i_op->removexattr(d, kname, 0); up(&d->d_inode->i_sem); } out: diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c --- a/fs/xfs/linux/xfs_iops.c Mon Feb 17 14:57:27 2003 +++ b/fs/xfs/linux/xfs_iops.c Mon Feb 17 14:57:27 2003 @@ -640,7 +640,8 @@ struct dentry *dentry, const char *name, void *data, - size_t size) + size_t size, + int flags) { ssize_t error; int xflags = 0; @@ -697,7 +698,8 @@ linvfs_listxattr( struct dentry *dentry, char *data, - size_t size) + size_t size, + int flags) { ssize_t error; int result = 0; @@ -741,7 +743,8 @@ STATIC int linvfs_removexattr( struct dentry *dentry, - const char *name) + const char *name, + int flags) { int error; int xflags = 0; diff -Nru a/include/asm-alpha/io.h b/include/asm-alpha/io.h --- a/include/asm-alpha/io.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-alpha/io.h Mon Feb 17 14:57:28 2003 @@ -462,6 +462,9 @@ #define eth_io_copy_and_sum(skb,src,len,unused) \ memcpy_fromio((skb)->data,(src),(len)) +#define isa_eth_io_copy_and_sum(skb,src,len,unused) \ + isa_memcpy_fromio((skb)->data,(src),(len)) + static inline int check_signature(unsigned long io_addr, const unsigned char *signature, int length) diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h --- a/include/asm-alpha/unistd.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-alpha/unistd.h Mon Feb 17 14:57:27 2003 @@ -348,7 +348,8 @@ #define __NR_remap_file_pages 410 #define __NR_set_tid_address 411 #define __NR_restart_syscall 412 -#define NR_SYSCALLS 413 +#define __NR_fadvise64 413 +#define NR_SYSCALLS 414 #if defined(__GNUC__) diff -Nru a/include/asm-arm/arch-iop310/serial.h b/include/asm-arm/arch-iop310/serial.h --- a/include/asm-arm/arch-iop310/serial.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-arm/arch-iop310/serial.h Mon Feb 17 14:57:28 2003 @@ -24,8 +24,8 @@ #define STD_SERIAL_PORT_DEFNS \ /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0xfe810000, IRQ_UART2, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS } /* ttyS1 */ + { 0, BASE_BAUD, IQ80310_UART2, IRQ_UART2, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, IQ80310_UART1, IRQ_UART1, STD_COM_FLAGS } /* ttyS1 */ #endif // CONFIG_ARCH_IQ80310 diff -Nru a/include/asm-arm/arch-pxa/time.h b/include/asm-arm/arch-pxa/time.h --- a/include/asm-arm/arch-pxa/time.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-arm/arch-pxa/time.h Mon Feb 17 14:57:27 2003 @@ -53,7 +53,7 @@ int next_match; /* Loop until we get ahead of the free running timer. - * This ensures an exact clock tick count and time acuracy. + * This ensures an exact clock tick count and time accuracy. * IRQs are disabled inside the loop to ensure coherence between * lost_ticks (updated in do_timer()) and the match reg value, so we * can use do_gettimeofday() from interrupt handlers. diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h --- a/include/asm-arm/arch-sa1100/time.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-arm/arch-sa1100/time.h Mon Feb 17 14:57:28 2003 @@ -67,7 +67,7 @@ * We will be entered with IRQs enabled. * * Loop until we get ahead of the free running timer. - * This ensures an exact clock tick count and time acuracy. + * This ensures an exact clock tick count and time accuracy. * IRQs are disabled inside the loop to ensure coherence between * lost_ticks (updated in do_timer()) and the match reg value, so we * can use do_gettimeofday() from interrupt handlers. diff -Nru a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h --- a/include/asm-arm/mach/irq.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-arm/mach/irq.h Mon Feb 17 14:57:27 2003 @@ -33,9 +33,12 @@ */ void (*unmask)(unsigned int); /* - * Re-run the IRQ + * Ask the hardware to re-trigger the IRQ. + * Note: This method _must_ _not_ call the interrupt handler. + * If you are unable to retrigger the interrupt, do not + * provide a function, or if you do, return non-zero. */ - void (*rerun)(unsigned int); + int (*retrigger)(unsigned int); /* * Set the type of the IRQ. */ @@ -50,6 +53,7 @@ irq_handler_t handle; struct irqchip *chip; struct irqaction *action; + struct list_head pend; unsigned int disable_depth; unsigned int triggered: 1; /* IRQ has occurred */ diff -Nru a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h --- a/include/asm-arm/proc-armv/processor.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-arm/proc-armv/processor.h Mon Feb 17 14:57:28 2003 @@ -23,7 +23,7 @@ #define KERNEL_STACK_SIZE PAGE_SIZE #define INIT_EXTRA_THREAD_INFO \ - .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \ + .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ domain_val(DOMAIN_IO, DOMAIN_CLIENT) diff -Nru a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h --- a/include/asm-arm/proc-armv/system.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-arm/proc-armv/system.h Mon Feb 17 14:57:26 2003 @@ -14,9 +14,14 @@ #define set_cr(x) \ __asm__ __volatile__( \ - "mcr p15, 0, %0, c1, c0 @ set CR" \ + "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ : : "r" (x)) +#define get_cr(x) \ + __asm__ __volatile__( \ + "mrc p15, 0, %0, c1, c0, 0 @ get CR" \ + : "=r" (x)) + #define CR_M (1 << 0) /* MMU enable */ #define CR_A (1 << 1) /* Alignment abort enable */ #define CR_C (1 << 2) /* Dcache enable */ @@ -24,9 +29,9 @@ #define CR_P (1 << 4) /* 32-bit exception handler */ #define CR_D (1 << 5) /* 32-bit data address range */ #define CR_L (1 << 6) /* Implementation defined */ -#define CD_B (1 << 7) /* Big endian */ +#define CR_B (1 << 7) /* Big endian */ #define CR_S (1 << 8) /* System MMU protection */ -#define CD_R (1 << 9) /* ROM MMU protection */ +#define CR_R (1 << 9) /* ROM MMU protection */ #define CR_F (1 << 10) /* Implementation defined */ #define CR_Z (1 << 11) /* Implementation defined */ #define CR_I (1 << 12) /* Icache enable */ diff -Nru a/include/asm-arm/signal.h b/include/asm-arm/signal.h --- a/include/asm-arm/signal.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-arm/signal.h Mon Feb 17 14:57:27 2003 @@ -184,9 +184,7 @@ #ifdef __KERNEL__ #include - -#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER - +#define ptrace_signal_deliver(regs, cookie) do { } while (0) #endif #endif diff -Nru a/include/asm-i386/module.h b/include/asm-i386/module.h --- a/include/asm-i386/module.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-i386/module.h Mon Feb 17 14:57:26 2003 @@ -12,39 +12,39 @@ #ifdef CONFIG_M386 #define MODULE_PROC_FAMILY "386 " -#elif CONFIG_M486 +#elif defined CONFIG_M486 #define MODULE_PROC_FAMILY "486 " -#elif CONFIG_M586 +#elif defined CONFIG_M586 #define MODULE_PROC_FAMILY "586 " -#elif CONFIG_M586TSC +#elif defined CONFIG_M586TSC #define MODULE_PROC_FAMILY "586TSC " -#elif CONFIG_M586MMX +#elif defined CONFIG_M586MMX #define MODULE_PROC_FAMILY "586MMX " -#elif CONFIG_M686 +#elif defined CONFIG_M686 #define MODULE_PROC_FAMILY "686 " -#elif CONFIG_MPENTIUMII +#elif defined CONFIG_MPENTIUMII #define MODULE_PROC_FAMILY "PENTIUMII " -#elif CONFIG_MPENTIUMIII +#elif defined CONFIG_MPENTIUMIII #define MODULE_PROC_FAMILY "PENTIUMIII " -#elif CONFIG_MPENTIUM4 +#elif defined CONFIG_MPENTIUM4 #define MODULE_PROC_FAMILY "PENTIUM4 " -#elif CONFIG_MK6 +#elif defined CONFIG_MK6 #define MODULE_PROC_FAMILY "K6 " -#elif CONFIG_MK7 +#elif defined CONFIG_MK7 #define MODULE_PROC_FAMILY "K7 " -#elif CONFIG_MK8 +#elif defined CONFIG_MK8 #define MODULE_PROC_FAMILY "K8 " -#elif CONFIG_MELAN +#elif defined CONFIG_MELAN #define MODULE_PROC_FAMILY "ELAN " -#elif CONFIG_MCRUSOE +#elif defined CONFIG_MCRUSOE #define MODULE_PROC_FAMILY "CRUSOE " -#elif CONFIG_MWINCHIPC6 +#elif defined CONFIG_MWINCHIPC6 #define MODULE_PROC_FAMILY "WINCHIPC6 " -#elif CONFIG_MWINCHIP2 +#elif defined CONFIG_MWINCHIP2 #define MODULE_PROC_FAMILY "WINCHIP2 " -#elif CONFIG_MWINCHIP3D +#elif defined CONFIG_MWINCHIP3D #define MODULE_PROC_FAMILY "WINCHIP3D " -#elif CONFIG_MCYRIXIII +#elif defined CONFIG_MCYRIXIII #define MODULE_PROC_FAMILY "CYRIXIII " #elif CONFIG_MVIAC3_2 #define MODULE_PROC_FAMILY "VIAC3-2 " diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h --- a/include/asm-i386/page.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-i386/page.h Mon Feb 17 14:57:27 2003 @@ -39,7 +39,7 @@ /* * These are used to make use of C type-checking.. */ -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE typedef struct { unsigned long pte_low, pte_high; } pte_t; typedef struct { unsigned long long pmd; } pmd_t; typedef struct { unsigned long long pgd; } pgd_t; diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h --- a/include/asm-i386/pgtable.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-i386/pgtable.h Mon Feb 17 14:57:28 2003 @@ -39,7 +39,7 @@ * newer 3-level PAE-mode page tables. */ #ifndef __ASSEMBLY__ -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE # include #else # include @@ -79,7 +79,7 @@ #define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \ ~(VMALLOC_OFFSET-1)) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) #else # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h --- a/include/asm-i386/processor.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-i386/processor.h Mon Feb 17 14:57:26 2003 @@ -483,7 +483,7 @@ __asm__ __volatile__ ("prefetchnta (%0)" : : "r"(x)); } -#elif CONFIG_X86_USE_3DNOW +#elif defined CONFIG_X86_USE_3DNOW #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW diff -Nru a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h --- a/include/asm-i386/semaphore.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-i386/semaphore.h Mon Feb 17 14:57:27 2003 @@ -45,12 +45,12 @@ atomic_t count; int sleepers; wait_queue_head_t wait; -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG long __magic; #endif }; -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG # define __SEM_DEBUG_INIT(name) \ , (int)&(name).__magic #else @@ -81,7 +81,7 @@ atomic_set(&sem->count, val); sem->sleepers = 0; init_waitqueue_head(&sem->wait); -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG sem->__magic = (int)&sem->__magic; #endif } @@ -113,7 +113,7 @@ */ static inline void down(struct semaphore * sem) { -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif might_sleep(); @@ -139,7 +139,7 @@ { int result; -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif might_sleep(); @@ -167,7 +167,7 @@ { int result; -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif @@ -195,7 +195,7 @@ */ static inline void up(struct semaphore * sem) { -#if WAITQUEUE_DEBUG +#ifdef WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif __asm__ __volatile__( diff -Nru a/include/asm-ia64/sn/ioerror.h b/include/asm-ia64/sn/ioerror.h --- a/include/asm-ia64/sn/ioerror.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-ia64/sn/ioerror.h Mon Feb 17 14:57:28 2003 @@ -108,7 +108,7 @@ * we have a single structure, and the appropriate fields get filled in * at each layer. * - This provides a way to dump all error related information in any layer - * of erorr handling (debugging aid). + * of error handling (debugging aid). * * A second possibility is to allow each layer to define its own error * data structure, and fill in the proper fields. This has the advantage diff -Nru a/include/asm-ia64/sn/router.h b/include/asm-ia64/sn/router.h --- a/include/asm-ia64/sn/router.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ia64/sn/router.h Mon Feb 17 14:57:27 2003 @@ -500,7 +500,7 @@ /* * Everything below here is for kernel use only and may change at - * at any time with or without a change in teh revision number + * at any time with or without a change in the revision number * * Any pointers or things that come and go with DEBUG must go at * the bottom of the structure, below the user stuff. diff -Nru a/include/asm-m68knommu/mcfne.h b/include/asm-m68knommu/mcfne.h --- a/include/asm-m68knommu/mcfne.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-m68knommu/mcfne.h Mon Feb 17 14:57:28 2003 @@ -261,7 +261,7 @@ /* * Lastly the interrupt set up code... - * Minor diferences between the different board types. + * Minor differences between the different board types. */ #if defined(CONFIG_M5206) && defined(CONFIG_ARNEWSH) diff -Nru a/include/asm-mips64/sn/launch.h b/include/asm-mips64/sn/launch.h --- a/include/asm-mips64/sn/launch.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-mips64/sn/launch.h Mon Feb 17 14:57:28 2003 @@ -52,7 +52,7 @@ /* * The launch routine is called only if the complement address is correct. * - * Before control is transferred to a routine, the compliment address + * Before control is transferred to a routine, the complement address * is zeroed (invalidated) to prevent an accidental call from a spurious * interrupt. * diff -Nru a/include/asm-mips64/sn/nmi.h b/include/asm-mips64/sn/nmi.h --- a/include/asm-mips64/sn/nmi.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-mips64/sn/nmi.h Mon Feb 17 14:57:27 2003 @@ -42,7 +42,7 @@ * The NMI routine is called only if the complement address is * correct. * - * Before control is transferred to a routine, the compliment address + * Before control is transferred to a routine, the complement address * is zeroed (invalidated) to prevent an accidental call from a spurious * interrupt. * diff -Nru a/include/asm-ppc/gt64260.h b/include/asm-ppc/gt64260.h --- a/include/asm-ppc/gt64260.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ppc/gt64260.h Mon Feb 17 14:57:27 2003 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/gt64260_defs.h b/include/asm-ppc/gt64260_defs.h --- a/include/asm-ppc/gt64260_defs.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-ppc/gt64260_defs.h Mon Feb 17 14:57:28 2003 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/harrier.h b/include/asm-ppc/harrier.h --- a/include/asm-ppc/harrier.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-ppc/harrier.h Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * dale.farnsworth@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/ibm403.h b/include/asm-ppc/ibm403.h --- a/include/asm-ppc/ibm403.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-ppc/ibm403.h Mon Feb 17 14:57:26 2003 @@ -2,7 +2,7 @@ * Authors: Armin Kuster and Tom Rini * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/ibm405.h b/include/asm-ppc/ibm405.h --- a/include/asm-ppc/ibm405.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-ppc/ibm405.h Mon Feb 17 14:57:26 2003 @@ -2,7 +2,7 @@ * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/ibm_ocp_pci.h b/include/asm-ppc/ibm_ocp_pci.h --- a/include/asm-ppc/ibm_ocp_pci.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-ppc/ibm_ocp_pci.h Mon Feb 17 14:57:28 2003 @@ -2,7 +2,7 @@ * Author: Armin Kuster * * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h --- a/include/asm-ppc/mpc10x.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ppc/mpc10x.h Mon Feb 17 14:57:27 2003 @@ -8,7 +8,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/ppc405_dma.h b/include/asm-ppc/ppc405_dma.h --- a/include/asm-ppc/ppc405_dma.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ppc/ppc405_dma.h Mon Feb 17 14:57:27 2003 @@ -2,7 +2,7 @@ * Author: Pete Popov * * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/include/asm-ppc/pplus.h b/include/asm-ppc/pplus.h --- a/include/asm-ppc/pplus.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ppc/pplus.h Mon Feb 17 14:57:27 2003 @@ -7,7 +7,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/rtc.h b/include/asm-ppc/rtc.h --- a/include/asm-ppc/rtc.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-ppc/rtc.h Mon Feb 17 14:57:26 2003 @@ -4,7 +4,7 @@ * Author: Tom Rini * * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * diff -Nru a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h --- a/include/asm-ppc/todc.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-ppc/todc.h Mon Feb 17 14:57:28 2003 @@ -8,7 +8,7 @@ * mgreer@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2.1. This program + * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h --- a/include/asm-ppc/unistd.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-ppc/unistd.h Mon Feb 17 14:57:27 2003 @@ -236,6 +236,8 @@ #define __NR_io_getevents 229 #define __NR_io_submit 230 #define __NR_io_cancel 231 +#define __NR_set_tid_address 232 +#define __NR_fadvise64 233 #define __NR_exit_group 234 #define __NR_lookup_dcookie 235 #define __NR_epoll_create 236 diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h --- a/include/asm-ppc64/rtas.h Mon Feb 17 14:57:28 2003 +++ b/include/asm-ppc64/rtas.h Mon Feb 17 14:57:28 2003 @@ -168,5 +168,13 @@ extern struct proc_dir_entry *rtas_proc_dir; +/* Some RTAS ops require a data buffer and that buffer must be < 4G. + * Rather than having a memory allocator, just use this buffer + * (get the lock first), make the RTAS call. Copy the data instead + * of holding the buffer for long. + */ +#define RTAS_DATA_BUF_SIZE 1024 +extern spinlock_t rtas_data_buf_lock; +extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; #endif /* _PPC64_RTAS_H */ diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h --- a/include/asm-ppc64/unistd.h Mon Feb 17 14:57:26 2003 +++ b/include/asm-ppc64/unistd.h Mon Feb 17 14:57:26 2003 @@ -242,7 +242,8 @@ #define __NR_io_getevents 229 #define __NR_io_submit 230 #define __NR_io_cancel 231 -/* 223 + 224 currently unused */ +#define __NR_set_tid_address 232 +#define __NR_fadvise64 233 #define __NR_exit_group 234 #define __NR_lookup_dcookie 235 #define __NR_sys_epoll_create 236 diff -Nru a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h --- a/include/asm-sparc64/ptrace.h Mon Feb 17 14:57:27 2003 +++ b/include/asm-sparc64/ptrace.h Mon Feb 17 14:57:27 2003 @@ -268,7 +268,7 @@ #define PTRACE_SETFPAREGS 21 /* There are for debugging 64-bit processes, either from a 32 or 64 bit - * parent. Thus their compliments are for debugging 32-bit processes only. + * parent. Thus their complements are for debugging 32-bit processes only. */ #define PTRACE_GETREGS64 22 diff -Nru a/include/linux/com20020.h b/include/linux/com20020.h --- a/include/linux/com20020.h Mon Feb 17 14:57:26 2003 +++ b/include/linux/com20020.h Mon Feb 17 14:57:26 2003 @@ -32,7 +32,7 @@ void com20020_remove(struct net_device *dev); /* The number of low I/O ports used by the card. */ -#define ARCNET_TOTAL_SIZE 9 +#define ARCNET_TOTAL_SIZE 8 /* various register addresses */ #define _INTMASK (ioaddr+0) /* writable */ @@ -59,6 +59,8 @@ /* in SETUP register */ #define PROMISCset 0x10 /* enable RCV_ALL */ +#define P1MODE 0x80 /* enable P1-MODE for Backplane */ +#define SLOWARB 0x01 /* enable Slow Arbitration for >=5Mbps */ /* COM2002x */ #define SUB_TENTATIVE 0 /* tentative node ID */ diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h --- a/include/linux/cpufreq.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/cpufreq.h Mon Feb 17 14:57:27 2003 @@ -205,6 +205,8 @@ int cpufreq_restore(void); #endif +/* the proc_intf.c needs this */ +int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor); #ifdef CONFIG_CPU_FREQ_24_API /********************************************************************* @@ -297,6 +299,7 @@ #endif /* CONFIG_CPU_FREQ_24_API */ + /********************************************************************* * FREQUENCY TABLE HELPERS * *********************************************************************/ @@ -310,6 +313,7 @@ * order */ }; +#if defined(CONFIG_CPU_FREQ_TABLE) || defined(CONFIG_CPU_FREQ_TABLE_MODULE) int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); @@ -325,5 +329,7 @@ unsigned int target_freq, unsigned int relation, unsigned int *index); + +#endif /* CONFIG_CPU_FREQ_TABLE */ #endif /* _LINUX_CPUFREQ_H */ diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h --- a/include/linux/dcache.h Mon Feb 17 14:57:28 2003 +++ b/include/linux/dcache.h Mon Feb 17 14:57:28 2003 @@ -7,6 +7,7 @@ #include #include #include +#include #include struct vfsmount; @@ -30,6 +31,7 @@ const unsigned char * name; unsigned int len; unsigned int hash; + char name_str[0]; }; struct dentry_stat_t { @@ -72,21 +74,26 @@ struct dentry { atomic_t d_count; + unsigned long d_vfs_flags; /* moved here to be on same cacheline */ + spinlock_t d_lock; /* per dentry lock */ unsigned int d_flags; + unsigned long d_move_count; /* to indicated moved dentry while lockless lookup */ struct inode * d_inode; /* Where the name belongs to - NULL is negative */ struct dentry * d_parent; /* parent directory */ + struct list_head * d_bucket; /* lookup hash bucket */ struct list_head d_hash; /* lookup hash list */ - struct list_head d_lru; /* d_count = 0 LRU list */ + struct list_head d_lru; /* LRU list */ struct list_head d_child; /* child of parent list */ struct list_head d_subdirs; /* our children */ struct list_head d_alias; /* inode alias list */ int d_mounted; struct qstr d_name; + struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */ unsigned long d_time; /* used by d_revalidate */ struct dentry_operations *d_op; struct super_block * d_sb; /* The root of the dentry tree */ - unsigned long d_vfs_flags; void * d_fsdata; /* fs-specific data */ + struct rcu_head d_rcu; struct dcookie_struct * d_cookie; /* cookie, if any */ unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ } ____cacheline_aligned; @@ -139,6 +146,7 @@ */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ +#define DCACHE_UNHASHED 0x0010 extern spinlock_t dcache_lock; extern rwlock_t dparent_lock; @@ -162,7 +170,8 @@ static __inline__ void __d_drop(struct dentry * dentry) { - list_del_init(&dentry->d_hash); + dentry->d_vfs_flags |= DCACHE_UNHASHED; + list_del_rcu(&dentry->d_hash); } static __inline__ void d_drop(struct dentry * dentry) @@ -229,7 +238,6 @@ /* appendix may either be NULL or be used for transname suffixes */ extern struct dentry * d_lookup(struct dentry *, struct qstr *); -extern struct dentry * __d_lookup(struct dentry *, struct qstr *); /* validate "insecure" dentry pointer */ extern int d_validate(struct dentry *, struct dentry *); @@ -254,9 +262,8 @@ static __inline__ struct dentry * dget(struct dentry *dentry) { if (dentry) { - if (!atomic_read(&dentry->d_count)) - BUG(); atomic_inc(&dentry->d_count); + dentry->d_vfs_flags |= DCACHE_REFERENCED; } return dentry; } @@ -272,7 +279,7 @@ static __inline__ int d_unhashed(struct dentry *dentry) { - return list_empty(&dentry->d_hash); + return (dentry->d_vfs_flags & DCACHE_UNHASHED); } extern void dput(struct dentry *); diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h --- a/include/linux/eisa.h Mon Feb 17 14:57:28 2003 +++ b/include/linux/eisa.h Mon Feb 17 14:57:28 2003 @@ -24,7 +24,8 @@ }; /* There is not much we can say about an EISA device, apart from - * signature, slot number, and base address */ + * signature, slot number, and base address. */ + struct eisa_device { struct eisa_device_id id; int slot; @@ -56,5 +57,19 @@ { edev->dev.driver_data = data; } + +/* The EISA root device. There's rumours about machines with multiple + * busses (PA-RISC ?), so we try to handle that. */ + +struct eisa_root_device { + struct list_head node; + struct device *dev; /* Pointer to bridge device */ + struct resource *res; + unsigned long bus_base_addr; + int slots; /* Max slot number */ + int bus_nr; /* Set by eisa_root_register */ +}; + +int eisa_root_register (struct eisa_root_device *root); #endif diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/fs.h Mon Feb 17 14:57:27 2003 @@ -743,9 +743,9 @@ int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); - ssize_t (*listxattr) (struct dentry *, char *, size_t); - int (*removexattr) (struct dentry *, const char *); + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,int); + ssize_t (*listxattr) (struct dentry *, char *, size_t, int); + int (*removexattr) (struct dentry *, const char *, int); }; struct seq_file; @@ -1195,6 +1195,8 @@ extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); +int generic_write_checks(struct inode *inode, struct file *file, + loff_t *pos, size_t *count, int isblk); extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t); extern ssize_t generic_file_aio_write(struct kiocb *, const char *, size_t, loff_t); diff -Nru a/include/linux/futex.h b/include/linux/futex.h --- a/include/linux/futex.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/futex.h Mon Feb 17 14:57:27 2003 @@ -6,6 +6,6 @@ #define FUTEX_WAKE (1) #define FUTEX_FD (2) -extern asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec *utime); +extern asmlinkage long sys_futex(u32 *uaddr, int op, int val, struct timespec *utime); #endif diff -Nru a/include/linux/kmod.h b/include/linux/kmod.h --- a/include/linux/kmod.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/kmod.h Mon Feb 17 14:57:27 2003 @@ -21,6 +21,7 @@ #include #include +#include #ifdef CONFIG_KMOD extern int request_module(const char * name); @@ -29,8 +30,7 @@ #endif #define try_then_request_module(x, mod) ((x) ?: request_module(mod), (x)) -extern int exec_usermodehelper(char *program_path, char *argv[], char *envp[]); -extern int call_usermodehelper(char *path, char *argv[], char *envp[]); +extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); #ifdef CONFIG_HOTPLUG extern char hotplug_path []; diff -Nru a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/mod_devicetable.h Mon Feb 17 14:57:28 2003 @@ -0,0 +1,117 @@ +/* + * Device tables which are exported to userspace via + * scripts/table2alias.c. You must keep that file in sync with this + * header. + */ + +#ifndef LINUX_MOD_DEVICETABLE_H +#define LINUX_MOD_DEVICETABLE_H + +#ifdef __KERNEL__ +#include +typedef unsigned long kernel_ulong_t; +#endif + +#define PCI_ANY_ID (~0) + +struct pci_device_id { + __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ + __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ + __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +/* + * Device table entry for "new style" table-driven USB drivers. + * User mode code can read these tables to choose which modules to load. + * Declare the table as a MODULE_DEVICE_TABLE. + * + * A probe() parameter will point to a matching entry from this table. + * Use the driver_info field for each match to hold information tied + * to that match: device quirks, etc. + * + * Terminate the driver's table with an all-zeroes entry. + * Use the flag values to control which fields are compared. + */ + +/** + * struct usb_device_id - identifies USB devices for probing and hotplugging + * @match_flags: Bit mask controlling of the other fields are used to match + * against new devices. Any field except for driver_info may be used, + * although some only make sense in conjunction with other fields. + * This is usually set by a USB_DEVICE_*() macro, which sets all + * other fields in this structure except for driver_info. + * @idVendor: USB vendor ID for a device; numbers are assigned + * by the USB forum to its members. + * @idProduct: Vendor-assigned product ID. + * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers. + * This is also used to identify individual product versions, for + * a range consisting of a single device. + * @bcdDevice_hi: High end of version number range. The range of product + * versions is inclusive. + * @bDeviceClass: Class of device; numbers are assigned + * by the USB forum. Products may choose to implement classes, + * or be vendor-specific. Device classes specify behavior of all + * the interfaces on a devices. + * @bDeviceSubClass: Subclass of device; associated with bDeviceClass. + * @bDeviceProtocol: Protocol of device; associated with bDeviceClass. + * @bInterfaceClass: Class of interface; numbers are assigned + * by the USB forum. Products may choose to implement classes, + * or be vendor-specific. Interface classes specify behavior only + * of a given interface; other interfaces may support other classes. + * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass. + * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass. + * @driver_info: Holds information used by the driver. Usually it holds + * a pointer to a descriptor understood by the driver, or perhaps + * device flags. + * + * In most cases, drivers will create a table of device IDs by using + * USB_DEVICE(), or similar macros designed for that purpose. + * They will then export it to userspace using MODULE_DEVICE_TABLE(), + * and provide it to the USB core through their usb_driver structure. + * + * See the usb_match_id() function for information about how matches are + * performed. Briefly, you will normally use one of several macros to help + * construct these entries. Each entry you provide will either identify + * one or more specific products, or will identify a class of products + * which have agreed to behave the same. You should put the more specific + * matches towards the beginning of your table, so that driver_info can + * record quirks of specific products. + */ +struct usb_device_id { + /* which fields to match against? */ + __u16 match_flags; + + /* Used for product specific matches; range is inclusive */ + __u16 idVendor; + __u16 idProduct; + __u16 bcdDevice_lo; + __u16 bcdDevice_hi; + + /* Used for device class matches */ + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + + /* Used for interface class matches */ + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + + /* not matched against */ + kernel_ulong_t driver_info; +}; + +/* Some useful macros to use to create struct usb_device_id */ +#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 +#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 +#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 +#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 +#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 +#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 +#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 + +#endif /* LINUX_MOD_DEVICETABLE_H */ diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h Mon Feb 17 14:57:28 2003 +++ b/include/linux/module.h Mon Feb 17 14:57:28 2003 @@ -57,13 +57,14 @@ unsigned long value); #ifdef MODULE +#define ___module_cat(a,b) a ## b +#define __module_cat(a,b) ___module_cat(a,b) +/* For userspace: you can also call me... */ +#define MODULE_ALIAS(alias) \ + static const char __module_cat(__alias_,__LINE__)[] \ + __attribute__((section(".modinfo"),unused)) = "alias=" alias -/* For replacement modutils, use an alias not a pointer. */ #define MODULE_GENERIC_TABLE(gtype,name) \ -static const unsigned long __module_##gtype##_size \ - __attribute__ ((unused)) = sizeof(struct gtype##_id); \ -static const struct gtype##_id * __module_##gtype##_table \ - __attribute__ ((unused)) = name; \ extern const struct gtype##_id __mod_##gtype##_table \ __attribute__ ((unused, alias(__stringify(name)))) @@ -103,6 +104,7 @@ #else /* !MODULE */ +#define MODULE_ALIAS(alias) #define MODULE_GENERIC_TABLE(gtype,name) #define THIS_MODULE ((struct module *)0) #define MOD_INC_USE_COUNT do { } while (0) diff -Nru a/include/linux/namei.h b/include/linux/namei.h --- a/include/linux/namei.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/namei.h Mon Feb 17 14:57:27 2003 @@ -11,8 +11,6 @@ struct qstr last; unsigned int flags; int last_type; - struct dentry *old_dentry; - struct vfsmount *old_mnt; }; /* diff -Nru a/include/linux/pagemap.h b/include/linux/pagemap.h --- a/include/linux/pagemap.h Mon Feb 17 14:57:26 2003 +++ b/include/linux/pagemap.h Mon Feb 17 14:57:26 2003 @@ -8,6 +8,7 @@ #include #include #include +#include /* * The page cache can done in larger chunks than @@ -122,4 +123,49 @@ } extern void end_page_writeback(struct page *page); + +/* + * Fault a userspace page into pagetables. Return non-zero on a fault. + * + * FIXME: this assumes that two userspace pages are always sufficient. That's + * not true if PAGE_CACHE_SIZE > PAGE_SIZE. + */ +static inline int fault_in_pages_writeable(char *uaddr, int size) +{ + int ret; + + /* + * Writing zeroes into userspace here is OK, because we know that if + * the zero gets there, we'll be overwriting it. + */ + ret = __put_user(0, uaddr); + if (ret == 0) { + char *end = uaddr + size - 1; + + /* + * If the page was already mapped, this will get a cache miss + * for sure, so try to avoid doing it. + */ + if (((unsigned long)uaddr & PAGE_MASK) != + ((unsigned long)end & PAGE_MASK)) + ret = __put_user(0, end); + } + return ret; +} + +static inline void fault_in_pages_readable(const char *uaddr, int size) +{ + volatile char c; + int ret; + + ret = __get_user(c, (char *)uaddr); + if (ret == 0) { + const char *end = uaddr + size - 1; + + if (((unsigned long)uaddr & PAGE_MASK) != + ((unsigned long)end & PAGE_MASK)) + __get_user(c, (char *)end); + } +} + #endif /* _LINUX_PAGEMAP_H */ diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/pci.h Mon Feb 17 14:57:27 2003 @@ -17,6 +17,8 @@ #ifndef LINUX_PCI_H #define LINUX_PCI_H +#include + /* * Under PCI, each device has 256 bytes of configuration address space, * of which the first 64 bytes are standardized as follows: @@ -359,8 +361,6 @@ #define DEVICE_COUNT_DMA 2 #define DEVICE_COUNT_RESOURCE 12 -#define PCI_ANY_ID (~0) - /* * The pci_dev structure is used to describe PCI devices. */ @@ -489,13 +489,6 @@ unsigned long io_start, io_end; unsigned long mem_start, mem_end; unsigned long prefetch_start, prefetch_end; -}; - -struct pci_device_id { - unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ - unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ - unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ - unsigned long driver_data; /* Data private to the driver */ }; struct pci_driver { diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h --- a/include/linux/ptrace.h Mon Feb 17 14:57:26 2003 +++ b/include/linux/ptrace.h Mon Feb 17 14:57:26 2003 @@ -3,8 +3,6 @@ /* ptrace.h */ /* structs and defines to help the user use the ptrace system call. */ -#include - /* has the defines to get at the registers. */ #define PTRACE_TRACEME 0 @@ -38,6 +36,8 @@ #define PTRACE_O_TRACEVFORKDONE 0x00000020 #define PTRACE_O_TRACEEXIT 0x00000040 +#define PTRACE_O_MASK 0x0000007f + /* Wait extended result codes for the above trace options. */ #define PTRACE_EVENT_FORK 1 #define PTRACE_EVENT_VFORK 2 @@ -47,7 +47,27 @@ #define PTRACE_EVENT_EXIT 6 #include -#include + +#ifdef __KERNEL__ +/* + * Ptrace flags + */ + +#define PT_PTRACED 0x00000001 +#define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ +#define PT_TRACESYSGOOD 0x00000004 +#define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ +#define PT_TRACE_FORK 0x00000010 +#define PT_TRACE_VFORK 0x00000020 +#define PT_TRACE_CLONE 0x00000040 +#define PT_TRACE_EXEC 0x00000080 +#define PT_TRACE_VFORK_DONE 0x00000100 +#define PT_TRACE_EXIT 0x00000200 + +#define PT_TRACE_MASK 0x000003f4 + +#include /* For unlikely. */ +#include /* For struct task_struct. */ extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len); @@ -58,11 +78,11 @@ extern int ptrace_request(struct task_struct *child, long request, long addr, long data); extern void ptrace_notify(int exit_code); extern void __ptrace_link(struct task_struct *child, - struct task_struct *new_parent); + struct task_struct *new_parent); extern void __ptrace_unlink(struct task_struct *child); static inline void ptrace_link(struct task_struct *child, - struct task_struct *new_parent) + struct task_struct *new_parent) { if (unlikely(child->ptrace)) __ptrace_link(child, new_parent); @@ -72,5 +92,6 @@ if (unlikely(child->ptrace)) __ptrace_unlink(child); } +#endif #endif diff -Nru a/include/linux/rtc.h b/include/linux/rtc.h --- a/include/linux/rtc.h Mon Feb 17 14:57:26 2003 +++ b/include/linux/rtc.h Mon Feb 17 14:57:26 2003 @@ -57,8 +57,8 @@ int pll_value; /* get/set correction value */ int pll_max; /* max +ve (faster) adjustment value */ int pll_min; /* max -ve (slower) adjustment value */ - int pll_posmult; /* factor for +ve corection */ - int pll_negmult; /* factor for -ve corection */ + int pll_posmult; /* factor for +ve correction */ + int pll_negmult; /* factor for -ve correction */ long pll_clock; /* base PLL frequency */ }; diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Mon Feb 17 14:57:26 2003 +++ b/include/linux/sched.h Mon Feb 17 14:57:26 2003 @@ -446,21 +446,6 @@ #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ #define PF_KSWAPD 0x00040000 /* I am kswapd */ -/* - * Ptrace flags - */ - -#define PT_PTRACED 0x00000001 -#define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ -#define PT_TRACESYSGOOD 0x00000004 -#define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ -#define PT_TRACE_FORK 0x00000010 -#define PT_TRACE_VFORK 0x00000020 -#define PT_TRACE_CLONE 0x00000040 -#define PT_TRACE_EXEC 0x00000080 -#define PT_TRACE_VFORK_DONE 0x00000100 -#define PT_TRACE_EXIT 0x00000200 - #if CONFIG_SMP extern void set_cpus_allowed(task_t *p, unsigned long new_mask); #else diff -Nru a/include/linux/signal.h b/include/linux/signal.h --- a/include/linux/signal.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/signal.h Mon Feb 17 14:57:27 2003 @@ -151,8 +151,6 @@ } } -extern char * render_sigset_t(sigset_t *set, char *buffer); - /* Some extensions for manipulating the low 32 signals in particular. */ static inline void sigaddsetmask(sigset_t *set, unsigned long mask) diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/usb.h Mon Feb 17 14:57:27 2003 @@ -1,6 +1,7 @@ #ifndef __LINUX_USB_H #define __LINUX_USB_H +#include #include #define USB_MAJOR 180 @@ -313,99 +314,6 @@ } /*-------------------------------------------------------------------------*/ - -/* - * Device table entry for "new style" table-driven USB drivers. - * User mode code can read these tables to choose which modules to load. - * Declare the table as a MODULE_DEVICE_TABLE. - * - * A probe() parameter will point to a matching entry from this table. - * Use the driver_info field for each match to hold information tied - * to that match: device quirks, etc. - * - * Terminate the driver's table with an all-zeroes entry. - * Use the flag values to control which fields are compared. - */ - -/** - * struct usb_device_id - identifies USB devices for probing and hotplugging - * @match_flags: Bit mask controlling of the other fields are used to match - * against new devices. Any field except for driver_info may be used, - * although some only make sense in conjunction with other fields. - * This is usually set by a USB_DEVICE_*() macro, which sets all - * other fields in this structure except for driver_info. - * @idVendor: USB vendor ID for a device; numbers are assigned - * by the USB forum to its members. - * @idProduct: Vendor-assigned product ID. - * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers. - * This is also used to identify individual product versions, for - * a range consisting of a single device. - * @bcdDevice_hi: High end of version number range. The range of product - * versions is inclusive. - * @bDeviceClass: Class of device; numbers are assigned - * by the USB forum. Products may choose to implement classes, - * or be vendor-specific. Device classes specify behavior of all - * the interfaces on a devices. - * @bDeviceSubClass: Subclass of device; associated with bDeviceClass. - * @bDeviceProtocol: Protocol of device; associated with bDeviceClass. - * @bInterfaceClass: Class of interface; numbers are assigned - * by the USB forum. Products may choose to implement classes, - * or be vendor-specific. Interface classes specify behavior only - * of a given interface; other interfaces may support other classes. - * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass. - * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass. - * @driver_info: Holds information used by the driver. Usually it holds - * a pointer to a descriptor understood by the driver, or perhaps - * device flags. - * - * In most cases, drivers will create a table of device IDs by using - * USB_DEVICE(), or similar macros designed for that purpose. - * They will then export it to userspace using MODULE_DEVICE_TABLE(), - * and provide it to the USB core through their usb_driver structure. - * - * See the usb_match_id() function for information about how matches are - * performed. Briefly, you will normally use one of several macros to help - * construct these entries. Each entry you provide will either identify - * one or more specific products, or will identify a class of products - * which have agreed to behave the same. You should put the more specific - * matches towards the beginning of your table, so that driver_info can - * record quirks of specific products. - */ -struct usb_device_id { - /* which fields to match against? */ - __u16 match_flags; - - /* Used for product specific matches; range is inclusive */ - __u16 idVendor; - __u16 idProduct; - __u16 bcdDevice_lo; - __u16 bcdDevice_hi; - - /* Used for device class matches */ - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - - /* Used for interface class matches */ - __u8 bInterfaceClass; - __u8 bInterfaceSubClass; - __u8 bInterfaceProtocol; - - /* not matched against */ - unsigned long driver_info; -}; - -/* Some useful macros to use to create struct usb_device_id */ -#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 -#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 -#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 -#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 -#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 -#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 -#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 -#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 -#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 -#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #define USB_DEVICE_ID_MATCH_DEVICE (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) #define USB_DEVICE_ID_MATCH_DEV_RANGE (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI) diff -Nru a/include/linux/vermagic.h b/include/linux/vermagic.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/vermagic.h Mon Feb 17 14:57:28 2003 @@ -0,0 +1,23 @@ +#include +#include + +/* Simply sanity version stamp for modules. */ +#ifdef CONFIG_SMP +#define MODULE_VERMAGIC_SMP "SMP " +#else +#define MODULE_VERMAGIC_SMP "" +#endif +#ifdef CONFIG_PREEMPT +#define MODULE_VERMAGIC_PREEMPT "preempt " +#else +#define MODULE_VERMAGIC_PREEMPT "" +#endif +#ifndef MODULE_ARCH_VERMAGIC +#define MODULE_ARCH_VERMAGIC "" +#endif + +#define VERMAGIC_STRING \ + UTS_RELEASE " " \ + MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ + MODULE_ARCH_VERMAGIC \ + "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) diff -Nru a/include/linux/wireless.h b/include/linux/wireless.h --- a/include/linux/wireless.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/wireless.h Mon Feb 17 14:57:27 2003 @@ -294,7 +294,7 @@ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ -#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ +#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ diff -Nru a/include/linux/xattr.h b/include/linux/xattr.h --- a/include/linux/xattr.h Mon Feb 17 14:57:27 2003 +++ b/include/linux/xattr.h Mon Feb 17 14:57:27 2003 @@ -9,7 +9,8 @@ #ifndef _LINUX_XATTR_H #define _LINUX_XATTR_H -#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ -#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#define XATTR_CREATE 0x1 /* fail if attr already exists */ +#define XATTR_REPLACE 0x2 /* fail if attr does not exist */ +#define XATTR_KERNEL_CONTEXT 0x4 /* called from kernel context */ #endif /* _LINUX_XATTR_H */ diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h --- a/include/pcmcia/ss.h Mon Feb 17 14:57:28 2003 +++ b/include/pcmcia/ss.h Mon Feb 17 14:57:28 2003 @@ -31,6 +31,7 @@ #define _LINUX_SS_H #include +#include /* Definitions for card status flags for GetStatus */ #define SS_WRPROT 0x0001 @@ -142,7 +143,16 @@ /* * Calls to set up low-level "Socket Services" drivers */ -extern int register_ss_entry(int nsock, struct pccard_operations *ops); -extern void unregister_ss_entry(struct pccard_operations *ops); + +#define MAX_SOCKETS_PER_DEV 8 + +struct pcmcia_socket_class_data { + unsigned int nsock; /* number of sockets */ + struct pccard_operations *ops; /* see above */ + void *s_info[MAX_SOCKETS_PER_DEV]; /* socket_info_t */ + unsigned int use_bus_pm; +}; + +extern struct device_class pcmcia_socket_class; #endif /* _LINUX_SS_H */ diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h --- a/include/sound/ac97_codec.h Mon Feb 17 14:57:27 2003 +++ b/include/sound/ac97_codec.h Mon Feb 17 14:57:27 2003 @@ -291,4 +291,14 @@ void snd_ac97_resume(ac97_t *ac97); #endif +enum { AC97_TUNE_HP_ONLY, AC97_TUNE_SWAP_HP }; + +struct ac97_quirk { + unsigned short vendor; + unsigned short device; + int type; +}; + +int snd_ac97_tune_hardware(ac97_t *ac97, struct pci_dev *pci, struct ac97_quirk *quirk); + #endif /* __SOUND_AC97_CODEC_H */ diff -Nru a/include/sound/pcm.h b/include/sound/pcm.h --- a/include/sound/pcm.h Mon Feb 17 14:57:27 2003 +++ b/include/sound/pcm.h Mon Feb 17 14:57:27 2003 @@ -281,6 +281,13 @@ unsigned int mask; } snd_pcm_hw_constraint_list_t; +struct snd_pcm_dma_buffer { + unsigned char *area; + dma_addr_t addr; + unsigned long bytes; + void *private_data; /* for allocator */ +}; + struct _snd_pcm_runtime { /* -- Status -- */ snd_pcm_substream_t *trigger_master; @@ -355,6 +362,7 @@ unsigned char *dma_area; /* DMA area */ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ unsigned long dma_bytes; /* size of DMA area */ + void *dma_private; /* private DMA data for the memory allocator */ #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) /* -- OSS things -- */ @@ -371,9 +379,7 @@ int stream; /* stream (direction) */ size_t buffer_bytes_max; /* limit ring buffer size */ int dma_type; - void *dma_area; - dma_addr_t dma_addr; - size_t dma_bytes; + struct snd_pcm_dma_buffer dma_buffer; size_t dma_max; void *dma_private; /* -- hardware operations -- */ @@ -815,7 +821,7 @@ int snd_pcm_capture_xrun_check(snd_pcm_substream_t *substream); int snd_pcm_playback_xrun_asap(snd_pcm_substream_t *substream); int snd_pcm_capture_xrun_asap(snd_pcm_substream_t *substream); -void snd_pcm_playback_silence(snd_pcm_substream_t *substream); +void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr); int snd_pcm_playback_ready(snd_pcm_substream_t *substream); int snd_pcm_capture_ready(snd_pcm_substream_t *substream); long snd_pcm_playback_ready_jiffies(snd_pcm_substream_t *substream); diff -Nru a/include/sound/pcm_sgbuf.h b/include/sound/pcm_sgbuf.h --- a/include/sound/pcm_sgbuf.h Mon Feb 17 14:57:28 2003 +++ b/include/sound/pcm_sgbuf.h Mon Feb 17 14:57:28 2003 @@ -54,15 +54,13 @@ return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE; } -struct snd_sg_buf *snd_pcm_sgbuf_init(struct pci_dev *pci); -void snd_pcm_sgbuf_delete(struct snd_sg_buf *sgbuf); -void *snd_pcm_sgbuf_alloc_pages(struct snd_sg_buf *sgbuf, size_t size); -int snd_pcm_sgbuf_free_pages(struct snd_sg_buf *sgbuf, void *vmaddr); +void *snd_pcm_sgbuf_alloc_pages(struct pci_dev *pci, size_t size, struct snd_pcm_dma_buffer *dmab); +int snd_pcm_sgbuf_free_pages(struct snd_pcm_dma_buffer *dmab); -int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, snd_pcm_substream_t *substream); -int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, snd_pcm_t *pcm); +int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, snd_pcm_substream_t *substream, size_t size, size_t max); +int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, snd_pcm_t *pcm, size_t size, size_t max); -#define _snd_pcm_substream_sgbuf(substream) ((substream)->dma_private) +#define _snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private) #define snd_pcm_substream_sgbuf(substream) snd_magic_cast(snd_pcm_sgbuf_t, _snd_pcm_substream_sgbuf(substream), return -ENXIO) struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset); diff -Nru a/include/sound/version.h b/include/sound/version.h --- a/include/sound/version.h Mon Feb 17 14:57:27 2003 +++ b/include/sound/version.h Mon Feb 17 14:57:27 2003 @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ #define CONFIG_SND_VERSION "0.9.0rc7" -#define CONFIG_SND_DATE " (Sun Feb 09 18:00:12 2003 UTC)" +#define CONFIG_SND_DATE " (Sat Feb 15 15:01:21 2003 UTC)" diff -Nru a/init/Makefile b/init/Makefile --- a/init/Makefile Mon Feb 17 14:57:27 2003 +++ b/init/Makefile Mon Feb 17 14:57:27 2003 @@ -3,7 +3,6 @@ # obj-y := main.o version.o do_mounts.o initramfs.o -obj-$(CONFIG_MODULES) += vermagic.o # files to be removed upon make clean clean-files := ../include/linux/compile.h diff -Nru a/init/vermagic.c b/init/vermagic.c --- a/init/vermagic.c Mon Feb 17 14:57:28 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -#include -#include - -/* Simply sanity version stamp for modules. */ -#ifdef CONFIG_SMP -#define MODULE_VERMAGIC_SMP "SMP " -#else -#define MODULE_VERMAGIC_SMP "" -#endif -#ifdef CONFIG_PREEMPT -#define MODULE_VERMAGIC_PREEMPT "preempt " -#else -#define MODULE_VERMAGIC_PREEMPT "" -#endif -#ifndef MODULE_ARCH_VERMAGIC -#define MODULE_ARCH_VERMAGIC "" -#endif - -const char vermagic[] __attribute__((section("__vermagic"))) = - UTS_RELEASE " " - MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT MODULE_ARCH_VERMAGIC - "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__); diff -Nru a/kernel/compat.c b/kernel/compat.c --- a/kernel/compat.c Mon Feb 17 14:57:27 2003 +++ b/kernel/compat.c Mon Feb 17 14:57:27 2003 @@ -16,6 +16,8 @@ #include #include #include +#include /* for MAX_SCHEDULE_TIMEOUT */ +#include /* for FUTEX_WAIT */ #include @@ -207,4 +209,20 @@ if (ret == 0) ret = put_user(s, oset); return ret; +} + +extern long do_futex(unsigned long, int, int, unsigned long); + +asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val, + struct compat_timespec *utime) +{ + struct timespec t; + unsigned long timeout = MAX_SCHEDULE_TIMEOUT; + + if ((op == FUTEX_WAIT) && utime) { + if (get_compat_timespec(&t, utime)) + return -EFAULT; + timeout = timespec_to_jiffies(&t) + 1; + } + return do_futex((unsigned long)uaddr, op, val, timeout); } diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c --- a/kernel/cpufreq.c Mon Feb 17 14:57:27 2003 +++ b/kernel/cpufreq.c Mon Feb 17 14:57:27 2003 @@ -23,12 +23,6 @@ #include #include -#ifdef CONFIG_CPU_FREQ_PROC_INTF -#include -#include -#include -#endif - #ifdef CONFIG_CPU_FREQ_24_API #include #include @@ -77,7 +71,7 @@ /** * cpufreq_parse_governor - parse a governor string */ -static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) +int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; @@ -103,6 +97,7 @@ } return -EINVAL; } +EXPORT_SYMBOL_GPL(cpufreq_parse_governor); /* forward declarations */ @@ -430,241 +425,6 @@ /********************************************************************* - * /proc/cpufreq INTERFACE * - *********************************************************************/ - -#ifdef CONFIG_CPU_FREQ_PROC_INTF - -/** - * cpufreq_parse_policy - parse a policy string - * @input_string: the string to parse. - * @policy: the policy written inside input_string - * - * This function parses a "policy string" - something the user echo'es into - * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy. - * If there are invalid/missing entries, they are replaced with current - * cpufreq policy. - */ -static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy) -{ - unsigned int min = 0; - unsigned int max = 0; - unsigned int cpu = 0; - char str_governor[16]; - struct cpufreq_policy current_policy; - unsigned int result = -EFAULT; - - if (!policy) - return -EINVAL; - - policy->min = 0; - policy->max = 0; - policy->policy = 0; - policy->cpu = CPUFREQ_ALL_CPUS; - - if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4) - { - policy->min = min; - policy->max = max; - policy->cpu = cpu; - result = 0; - goto scan_policy; - } - if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4) - { - if (!cpufreq_get_policy(¤t_policy, cpu)) { - policy->min = (min * current_policy.cpuinfo.max_freq) / 100; - policy->max = (max * current_policy.cpuinfo.max_freq) / 100; - policy->cpu = cpu; - result = 0; - goto scan_policy; - } - } - - if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3) - { - policy->min = min; - policy->max = max; - result = 0; - goto scan_policy; - } - - if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3) - { - if (!cpufreq_get_policy(¤t_policy, cpu)) { - policy->min = (min * current_policy.cpuinfo.max_freq) / 100; - policy->max = (max * current_policy.cpuinfo.max_freq) / 100; - result = 0; - goto scan_policy; - } - } - - return -EINVAL; - -scan_policy: - result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor); - - return result; -} - -/** - * cpufreq_proc_read - read /proc/cpufreq - * - * This function prints out the current cpufreq policy. - */ -static int cpufreq_proc_read ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - char *p = page; - int len = 0; - struct cpufreq_policy policy; - unsigned int min_pctg = 0; - unsigned int max_pctg = 0; - unsigned int i = 0; - - if (off != 0) - goto end; - - p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); - for (i=0;iname); - break; - default: - p += sprintf(p, "INVALID\n"); - break; - } - } -end: - len = (p - page); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len>count) - len = count; - if (len<0) - len = 0; - - return len; -} - - -/** - * cpufreq_proc_write - handles writing into /proc/cpufreq - * - * This function calls the parsing script and then sets the policy - * accordingly. - */ -static int cpufreq_proc_write ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - char proc_string[42] = {'\0'}; - struct cpufreq_policy policy; - unsigned int i = 0; - - - if ((count > sizeof(proc_string) - 1)) - return -EINVAL; - - if (copy_from_user(proc_string, buffer, count)) - return -EFAULT; - - proc_string[count] = '\0'; - - result = cpufreq_parse_policy(proc_string, &policy); - if (result) - return -EFAULT; - - if (policy.cpu == CPUFREQ_ALL_CPUS) - { - for (i=0; iread_proc = cpufreq_proc_read; - entry->write_proc = cpufreq_proc_write; - } - - return 0; -} - - -/** - * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory. - * - * This function removes "cpufreq" from the /proc root directory. - */ -static void cpufreq_proc_exit (void) -{ - remove_proc_entry("cpufreq", &proc_root); - return; -} -#else -#define cpufreq_proc_init() do {} while(0) -#define cpufreq_proc_exit() do {} while(0) -#endif /* CONFIG_CPU_FREQ_PROC_INTF */ - - - -/********************************************************************* * /proc/sys/cpu/ INTERFACE * *********************************************************************/ @@ -1485,8 +1245,6 @@ up(&cpufreq_driver_sem); - cpufreq_proc_init(); - #ifdef CONFIG_CPU_FREQ_24_API cpufreq_sysctl_init(); #endif @@ -1516,8 +1274,6 @@ return -EINVAL; } - cpufreq_proc_exit(); - #ifdef CONFIG_CPU_FREQ_24_API cpufreq_sysctl_exit(); #endif @@ -1582,191 +1338,3 @@ #else #define cpufreq_restore() do {} while (0) #endif /* CONFIG_PM */ - - -/********************************************************************* - * FREQUENCY TABLE HELPERS * - *********************************************************************/ - -int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table) -{ - unsigned int min_freq = ~0; - unsigned int max_freq = 0; - unsigned int i = 0; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if (freq < min_freq) - min_freq = freq; - if (freq > max_freq) - max_freq = freq; - } - - policy->min = policy->cpuinfo.min_freq = min_freq; - policy->max = policy->cpuinfo.max_freq = max_freq; - - if (policy->min == ~0) - return -EINVAL; - else - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); - - -int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table) -{ - unsigned int next_larger = ~0; - unsigned int i = 0; - unsigned int count = 0; - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq >= policy->min) && (freq <= policy->max)) - count++; - else if ((next_larger > freq) && (freq > policy->max)) - next_larger = freq; - } - - if (!count) - policy->max = next_larger; - - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); - - -int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, - unsigned int *index) -{ - struct cpufreq_frequency_table optimal = { .index = ~0, }; - unsigned int i; - - switch (policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - optimal.frequency = 0; - break; - case CPUFREQ_POLICY_POWERSAVE: - optimal.frequency = ~0; - break; - } - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq < policy->min) || (freq > policy->max)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - if (optimal.frequency <= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - case CPUFREQ_POLICY_POWERSAVE: - if (optimal.frequency >= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - } - } - if (optimal.index > i) - return -EINVAL; - - *index = optimal.index; - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy); - -int cpufreq_frequency_table_target(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, - unsigned int target_freq, - unsigned int relation, - unsigned int *index) -{ - struct cpufreq_frequency_table optimal = { .index = ~0, }; - struct cpufreq_frequency_table suboptimal = { .index = ~0, }; - unsigned int i; - - switch (relation) { - case CPUFREQ_RELATION_H: - optimal.frequency = 0; - suboptimal.frequency = ~0; - break; - case CPUFREQ_RELATION_L: - optimal.frequency = ~0; - suboptimal.frequency = 0; - break; - } - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq < policy->min) || (freq > policy->max)) - continue; - switch(relation) { - case CPUFREQ_RELATION_H: - if (freq <= target_freq) { - if (freq >= optimal.frequency) { - optimal.frequency = freq; - optimal.index = i; - } - } else { - if (freq <= suboptimal.frequency) { - suboptimal.frequency = freq; - suboptimal.index = i; - } - } - break; - case CPUFREQ_RELATION_L: - if (freq >= target_freq) { - if (freq <= optimal.frequency) { - optimal.frequency = freq; - optimal.index = i; - } - } else { - if (freq >= suboptimal.frequency) { - suboptimal.frequency = freq; - suboptimal.index = i; - } - } - break; - } - } - if (optimal.index > i) { - if (suboptimal.index > i) - return -EINVAL; - *index = suboptimal.index; - } else - *index = optimal.index; - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); diff -Nru a/kernel/dma.c b/kernel/dma.c --- a/kernel/dma.c Mon Feb 17 14:57:27 2003 +++ b/kernel/dma.c Mon Feb 17 14:57:27 2003 @@ -98,6 +98,22 @@ } /* free_dma */ +#else + +int request_dma(unsigned int dmanr, const char *device_id) +{ + return -EINVAL; +} + +void free_dma(unsigned int dmanr) +{ +} + +#endif + +#ifdef CONFIG_PROC_FS + +#ifdef MAX_DMA_CHANNELS static int proc_dma_show(struct seq_file *m, void *v) { int i; @@ -110,27 +126,14 @@ } return 0; } - #else - -int request_dma(unsigned int dmanr, const char *device_id) -{ - return -EINVAL; -} - -void free_dma(unsigned int dmanr) -{ -} - static int proc_dma_show(struct seq_file *m, void *v) { seq_puts(m, "No DMA\n"); return 0; } +#endif /* MAX_DMA_CHANNELS */ -#endif - -#ifdef CONFIG_PROC_FS static int proc_dma_open(struct inode *inode, struct file *file) { char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); diff -Nru a/kernel/exit.c b/kernel/exit.c --- a/kernel/exit.c Mon Feb 17 14:57:28 2003 +++ b/kernel/exit.c Mon Feb 17 14:57:28 2003 @@ -694,10 +694,8 @@ * only has special meaning to our real parent. */ if (tsk->exit_signal != -1) { - if (tsk->parent == tsk->real_parent) - do_notify_parent(tsk, tsk->exit_signal); - else - do_notify_parent(tsk, SIGCHLD); + int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD; + do_notify_parent(tsk, signal); } tsk->state = TASK_ZOMBIE; @@ -731,8 +729,10 @@ profile_exit_task(tsk); - if (unlikely(current->ptrace & PT_TRACE_EXIT)) + if (unlikely(current->ptrace & PT_TRACE_EXIT)) { + current->ptrace_message = code; ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); + } acct_process(code); __exit_mm(tsk); diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Mon Feb 17 14:57:26 2003 +++ b/kernel/fork.c Mon Feb 17 14:57:26 2003 @@ -427,7 +427,7 @@ complete(vfork_done); } if (tsk->clear_child_tid && atomic_read(&mm->mm_users) > 1) { - int * tidptr = tsk->clear_child_tid; + u32 * tidptr = tsk->clear_child_tid; tsk->clear_child_tid = NULL; /* @@ -435,7 +435,7 @@ * not set up a proper pointer then tough luck. */ put_user(0, tidptr); - sys_futex((unsigned long)tidptr, FUTEX_WAKE, 1, NULL); + sys_futex(tidptr, FUTEX_WAKE, 1, NULL); } } diff -Nru a/kernel/futex.c b/kernel/futex.c --- a/kernel/futex.c Mon Feb 17 14:57:27 2003 +++ b/kernel/futex.c Mon Feb 17 14:57:27 2003 @@ -315,23 +315,6 @@ return ret; } -static inline int futex_wait_utime(unsigned long uaddr, - int offset, - int val, - struct timespec* utime) -{ - unsigned long time = MAX_SCHEDULE_TIMEOUT; - - if (utime) { - struct timespec t; - if (copy_from_user(&t, utime, sizeof(t)) != 0) - return -EFAULT; - time = timespec_to_jiffies(&t) + 1; - } - - return futex_wait(uaddr, offset, val, time); -} - static int futex_close(struct inode *inode, struct file *filp) { struct futex_q *q = filp->private_data; @@ -437,7 +420,7 @@ return ret; } -asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec *utime) +long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout) { unsigned long pos_in_page; int ret; @@ -445,12 +428,12 @@ pos_in_page = uaddr % PAGE_SIZE; /* Must be "naturally" aligned */ - if (pos_in_page % sizeof(int)) + if (pos_in_page % sizeof(u32)) return -EINVAL; switch (op) { case FUTEX_WAIT: - ret = futex_wait_utime(uaddr, pos_in_page, val, utime); + ret = futex_wait(uaddr, pos_in_page, val, timeout); break; case FUTEX_WAKE: ret = futex_wake(uaddr, pos_in_page, val); @@ -463,6 +446,19 @@ ret = -EINVAL; } return ret; +} + +asmlinkage long sys_futex(u32 *uaddr, int op, int val, struct timespec *utime) +{ + struct timespec t; + unsigned long timeout = MAX_SCHEDULE_TIMEOUT; + + if ((op == FUTEX_WAIT) && utime) { + if (copy_from_user(&t, utime, sizeof(t)) != 0) + return -EFAULT; + timeout = timespec_to_jiffies(&t) + 1; + } + return do_futex((unsigned long)uaddr, op, val, timeout); } static struct super_block * diff -Nru a/kernel/kmod.c b/kernel/kmod.c --- a/kernel/kmod.c Mon Feb 17 14:57:27 2003 +++ b/kernel/kmod.c Mon Feb 17 14:57:27 2003 @@ -14,8 +14,10 @@ Unblock all signals when we exec a usermode process. Shuu Yamaguchi December 2000 -*/ + call_usermodehelper wait flag, and remove exec_usermodehelper. + Rusty Russell Jan 2003 +*/ #define __KERNEL_SYSCALLS__ #include @@ -31,112 +33,11 @@ #include #include #include +#include #include extern int max_threads, system_running; -static inline void -use_init_fs_context(void) -{ - struct fs_struct *our_fs, *init_fs; - struct dentry *root, *pwd; - struct vfsmount *rootmnt, *pwdmnt; - struct namespace *our_ns, *init_ns; - - /* - * Make modprobe's fs context be a copy of init's. - * - * We cannot use the user's fs context, because it - * may have a different root than init. - * Since init was created with CLONE_FS, we can grab - * its fs context from "init_task". - * - * The fs context has to be a copy. If it is shared - * with init, then any chdir() call in modprobe will - * also affect init and the other threads sharing - * init_task's fs context. - * - * We created the exec_modprobe thread without CLONE_FS, - * so we can update the fields in our fs context freely. - */ - - init_fs = init_task.fs; - init_ns = init_task.namespace; - get_namespace(init_ns); - our_ns = current->namespace; - current->namespace = init_ns; - put_namespace(our_ns); - read_lock(&init_fs->lock); - rootmnt = mntget(init_fs->rootmnt); - root = dget(init_fs->root); - pwdmnt = mntget(init_fs->pwdmnt); - pwd = dget(init_fs->pwd); - read_unlock(&init_fs->lock); - - /* FIXME - unsafe ->fs access */ - our_fs = current->fs; - our_fs->umask = init_fs->umask; - set_fs_root(our_fs, rootmnt, root); - set_fs_pwd(our_fs, pwdmnt, pwd); - write_lock(&our_fs->lock); - if (our_fs->altroot) { - struct vfsmount *mnt = our_fs->altrootmnt; - struct dentry *dentry = our_fs->altroot; - our_fs->altrootmnt = NULL; - our_fs->altroot = NULL; - write_unlock(&our_fs->lock); - dput(dentry); - mntput(mnt); - } else - write_unlock(&our_fs->lock); - dput(root); - mntput(rootmnt); - dput(pwd); - mntput(pwdmnt); -} - -int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) -{ - int i; - struct task_struct *curtask = current; - - set_special_pids(1, 1); - - use_init_fs_context(); - - /* Prevent parent user process from sending signals to child. - Otherwise, if the modprobe program does not exist, it might - be possible to get a user defined signal handler to execute - as the super user right after the execve fails if you time - the signal just right. - */ - flush_signals(curtask); - flush_signal_handlers(curtask); - spin_lock_irq(&curtask->sighand->siglock); - sigemptyset(&curtask->blocked); - recalc_sigpending(); - spin_unlock_irq(&curtask->sighand->siglock); - - for (i = 0; i < curtask->files->max_fds; i++ ) { - if (curtask->files->fd[i]) close(i); - } - - switch_uid(INIT_USER); - - /* Give kmod all effective privileges.. */ - curtask->euid = curtask->fsuid = 0; - curtask->egid = curtask->fsgid = 0; - security_task_kmod_set_label(); - - /* Allow execve args to be in kernel space. */ - set_fs(KERNEL_DS); - - /* Go, go, go... */ - if (execve(program_path, argv, envp) < 0) - return -errno; - return 0; -} - #ifdef CONFIG_KMOD /* @@ -144,29 +45,6 @@ */ char modprobe_path[256] = "/sbin/modprobe"; -static int exec_modprobe(void * module_name) -{ - static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - char *argv[] = { modprobe_path, "--", (char*)module_name, NULL }; - int ret; - - if (!system_running) - return -EBUSY; - - ret = exec_usermodehelper(modprobe_path, argv, envp); - if (ret) { - static unsigned long last; - unsigned long now = jiffies; - if (now - last > HZ) { - last = now; - printk(KERN_DEBUG - "kmod: failed to exec %s -s -k %s, errno = %d\n", - modprobe_path, (char*) module_name, errno); - } - } - return ret; -} - /** * request_module - try to load a kernel module * @module_name: Name of module @@ -180,24 +58,18 @@ * If module auto-loading support is disabled then this function * becomes a no-operation. */ -int request_module(const char * module_name) +int request_module(const char *module_name) { - pid_t pid; - int waitpid_result; - sigset_t tmpsig; - int i, ret; + unsigned int max_modprobes; + int ret; + char *argv[] = { modprobe_path, "--", (char*)module_name, NULL }; + static char *envp[] = { "HOME=/", + "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", + NULL }; static atomic_t kmod_concurrent = ATOMIC_INIT(0); #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ static int kmod_loop_msg; - unsigned long saved_policy = current->policy; - - current->policy = SCHED_NORMAL; - /* Don't allow request_module() when the system isn't set up */ - if ( ! system_running ) { - printk(KERN_ERR "request_module[%s]: not ready\n", module_name); - ret = -EPERM; - goto out; - } /* If modprobe needs a service that is in a module, we get a recursive * loop. Limit the number of running kmod threads to max_threads/2 or @@ -207,61 +79,44 @@ * process tables to get the command line, proc_pid_cmdline is static * and it is not worth changing the proc code just to handle this case. * KAO. + * + + * "trace the ppid" is simple, but will fail if someone's + * parent exits. I think this is as good as it gets. --RR */ - i = max_threads/2; - if (i > MAX_KMOD_CONCURRENT) - i = MAX_KMOD_CONCURRENT; + max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT); atomic_inc(&kmod_concurrent); - if (atomic_read(&kmod_concurrent) > i) { + if (atomic_read(&kmod_concurrent) > max_modprobes) { + /* We may be blaming an innocent here, but unlikely */ if (kmod_loop_msg++ < 5) printk(KERN_ERR - "kmod: runaway modprobe loop assumed and stopped\n"); + "request_module: runaway loop modprobe %s\n", + module_name); atomic_dec(&kmod_concurrent); - ret = -ENOMEM; - goto out; + return -ENOMEM; } - pid = kernel_thread(exec_modprobe, (void*) module_name, 0); - if (pid < 0) { - printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid); - atomic_dec(&kmod_concurrent); - ret = pid; - goto out; + ret = call_usermodehelper(modprobe_path, argv, envp, 1); + if (ret != 0) { + static unsigned long last; + unsigned long now = jiffies; + if (now - last > HZ) { + last = now; + printk(KERN_DEBUG + "request_module: failed %s -- %s. error = %d\n", + modprobe_path, module_name, ret); + } } - - /* Block everything but SIGKILL/SIGSTOP */ - spin_lock_irq(¤t->sighand->siglock); - tmpsig = current->blocked; - siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - waitpid_result = waitpid(pid, NULL, __WCLONE); atomic_dec(&kmod_concurrent); - - /* Allow signals again.. */ - spin_lock_irq(¤t->sighand->siglock); - current->blocked = tmpsig; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (waitpid_result != pid) { - printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n", - module_name, pid, -waitpid_result); - } - ret = 0; -out: - current->policy = saved_policy; return ret; } #endif /* CONFIG_KMOD */ - #ifdef CONFIG_HOTPLUG /* hotplug path is set via /proc/sys invoked by hotplug-aware bus drivers, - with exec_usermodehelper and some thread-spawner + with call_usermodehelper argv [0] = hotplug_path; argv [1] = "usb", "scsi", "pci", "network", etc; @@ -285,7 +140,8 @@ char *path; char **argv; char **envp; - pid_t retval; + int wait; + int retval; }; /* @@ -298,13 +154,30 @@ retval = -EPERM; if (current->fs->root) - retval = exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp); + retval = execve(sub_info->path, sub_info->argv,sub_info->envp); /* Exec failed? */ - sub_info->retval = (pid_t)retval; + sub_info->retval = retval; do_exit(0); } +/* Keventd can't block, but this (a child) can. */ +static int wait_for_helper(void *data) +{ + struct subprocess_info *sub_info = data; + pid_t pid; + + pid = kernel_thread(____call_usermodehelper, sub_info, + CLONE_VFORK | SIGCHLD); + if (pid < 0) + sub_info->retval = pid; + else + sys_wait4(pid, (unsigned int *)&sub_info->retval, 0, NULL); + + complete(sub_info->complete); + return 0; +} + /* * This is run by keventd. */ @@ -313,14 +186,21 @@ struct subprocess_info *sub_info = data; pid_t pid; - /* - * CLONE_VFORK: wait until the usermode helper has execve'd successfully - * We need the data structures to stay around until that is done. - */ - pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD); - if (pid < 0) + /* CLONE_VFORK: wait until the usermode helper has execve'd + * successfully We need the data structures to stay around + * until that is done. */ + if (sub_info->wait) + pid = kernel_thread(wait_for_helper, sub_info, + CLONE_KERNEL | SIGCHLD); + else + pid = kernel_thread(____call_usermodehelper, sub_info, + CLONE_VFORK | SIGCHLD); + + if (pid < 0) { sub_info->retval = pid; - complete(sub_info->complete); + complete(sub_info->complete); + } else if (!sub_info->wait) + complete(sub_info->complete); } /** @@ -328,15 +208,17 @@ * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list + * @wait: wait for the application to finish and return status. * - * Runs a user-space application. The application is started asynchronously. It - * runs as a child of keventd. It runs with full root capabilities. keventd silently - * reaps the child when it exits. + * Runs a user-space application. The application is started + * asynchronously if wait is not set, and runs as a child of keventd. + * (ie. it runs with full root capabilities). * - * Must be called from process context. Returns zero on success, else a negative - * error code. + * Must be called from process context. Returns a negative error code + * if program was not execed successfully, or (exitcode << 8 + signal) + * of the application (0 if wait is not set). */ -int call_usermodehelper(char *path, char **argv, char **envp) +int call_usermodehelper(char *path, char **argv, char **envp, int wait) { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { @@ -344,6 +226,7 @@ .path = path, .argv = argv, .envp = envp, + .wait = wait, .retval = 0, }; DECLARE_WORK(work, __call_usermodehelper, &sub_info); @@ -381,7 +264,6 @@ up(&dev_probe_sem); } -EXPORT_SYMBOL(exec_usermodehelper); EXPORT_SYMBOL(call_usermodehelper); #ifdef CONFIG_KMOD diff -Nru a/kernel/module.c b/kernel/module.c --- a/kernel/module.c Mon Feb 17 14:57:27 2003 +++ b/kernel/module.c Mon Feb 17 14:57:27 2003 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -725,6 +726,8 @@ } #endif /* CONFIG_OBSOLETE_MODPARM */ +static const char vermagic[] = VERMAGIC_STRING; + #ifdef CONFIG_MODVERSIONS static int check_version(Elf_Shdr *sechdrs, unsigned int versindex, @@ -768,6 +771,18 @@ return 1; } +static inline int check_modstruct_version(Elf_Shdr *sechdrs, + unsigned int versindex, + struct module *mod) +{ + unsigned int i; + struct kernel_symbol_group *ksg; + + if (!__find_symbol("struct_module", &ksg, &i, 1)) + BUG(); + return check_version(sechdrs, versindex, "struct_module", mod, ksg, i); +} + /* First part is kernel version, which we ignore. */ static inline int same_magic(const char *amagic, const char *bmagic) { @@ -786,6 +801,13 @@ return 1; } +static inline int check_modstruct_version(Elf_Shdr *sechdrs, + unsigned int versindex, + struct module *mod) +{ + return 1; +} + static inline int same_magic(const char *amagic, const char *bmagic) { return strcmp(amagic, bmagic) == 0; @@ -1036,9 +1058,6 @@ } } -/* From init/vermagic.o */ -extern char vermagic[]; - /* Allocate and load the module: note that size of section 0 is always zero, and we rely on this for optional sections. */ static struct module *load_module(void *umod, @@ -1185,6 +1204,12 @@ } mod = (void *)sechdrs[modindex].sh_addr; + /* Check module struct version now, before we try to use module. */ + if (!check_modstruct_version(sechdrs, versindex, mod)) { + err = -ENOEXEC; + goto free_hdr; + } + /* This is allowed: modprobe --force will invalidate it. */ if (!vmagindex) { tainted |= TAINT_FORCED_MODULE; @@ -1455,9 +1480,9 @@ /* At worse, next value is at end of module */ if (within(addr, mod->module_init, mod->init_size)) - nextval = (unsigned long)mod->module_core+mod->core_size; + nextval = (unsigned long)mod->module_init + mod->init_size; else - nextval = (unsigned long)mod->module_init+mod->init_size; + nextval = (unsigned long)mod->module_core + mod->core_size; /* Scan for closest preceeding symbol, and next symbol. (ELF starts real symbols at 1). */ @@ -1630,3 +1655,9 @@ } __initcall(symbols_init); + +#ifdef CONFIG_MODVERSIONS +/* Generate the signature for struct module here, too, for modversions. */ +void struct_module(struct module *mod) { return; } +EXPORT_SYMBOL(struct_module); +#endif diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c --- a/kernel/ptrace.c Mon Feb 17 14:57:28 2003 +++ b/kernel/ptrace.c Mon Feb 17 14:57:28 2003 @@ -252,49 +252,30 @@ static int ptrace_setoptions(struct task_struct *child, long data) { + child->ptrace &= ~PT_TRACE_MASK; + if (data & PTRACE_O_TRACESYSGOOD) child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; if (data & PTRACE_O_TRACEFORK) child->ptrace |= PT_TRACE_FORK; - else - child->ptrace &= ~PT_TRACE_FORK; if (data & PTRACE_O_TRACEVFORK) child->ptrace |= PT_TRACE_VFORK; - else - child->ptrace &= ~PT_TRACE_VFORK; if (data & PTRACE_O_TRACECLONE) child->ptrace |= PT_TRACE_CLONE; - else - child->ptrace &= ~PT_TRACE_CLONE; if (data & PTRACE_O_TRACEEXEC) child->ptrace |= PT_TRACE_EXEC; - else - child->ptrace &= ~PT_TRACE_EXEC; if (data & PTRACE_O_TRACEVFORKDONE) child->ptrace |= PT_TRACE_VFORK_DONE; - else - child->ptrace &= ~PT_TRACE_VFORK_DONE; if (data & PTRACE_O_TRACEEXIT) child->ptrace |= PT_TRACE_EXIT; - else - child->ptrace &= ~PT_TRACE_EXIT; - - if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK - | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE - | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT - | PTRACE_O_TRACEVFORKDONE)) - != data) - return -EINVAL; - return 0; + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } static int ptrace_getsiginfo(struct task_struct *child, long data) diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Mon Feb 17 14:57:28 2003 +++ b/kernel/sched.c Mon Feb 17 14:57:28 2003 @@ -2095,21 +2095,6 @@ } } -char * render_sigset_t(sigset_t *set, char *buffer) -{ - int i = _NSIG, x; - do { - i -= 4, x = 0; - if (sigismember(set, i+1)) x |= 1; - if (sigismember(set, i+2)) x |= 2; - if (sigismember(set, i+3)) x |= 4; - if (sigismember(set, i+4)) x |= 8; - *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; - } while (i >= 4); - *buffer = 0; - return buffer; -} - void show_state(void) { task_t *g, *p; diff -Nru a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c Mon Feb 17 14:57:27 2003 +++ b/kernel/signal.c Mon Feb 17 14:57:27 2003 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1108,21 +1109,31 @@ * These are for backward compatibility with the rest of the kernel source. */ +/* + * XXX should probably nix these interfaces and update the kernel + * to specify explicitly whether the signal is a group signal or + * specific to a thread. + */ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p) { int ret; - /* XXX should nix these interfaces and update the kernel */ + /* + * We need the tasklist lock even for the specific + * thread case (when we don't need to follow the group + * lists) in order to avoid races with "p->sighand" + * going away or changing from under us. + */ + read_lock(&tasklist_lock); if (T(sig, SIG_KERNEL_BROADCAST_MASK)) { - read_lock(&tasklist_lock); ret = group_send_sig_info(sig, info, p); - read_unlock(&tasklist_lock); } else { spin_lock_irq(&p->sighand->siglock); ret = specific_send_sig_info(sig, info, p); spin_unlock_irq(&p->sighand->siglock); } + read_unlock(&tasklist_lock); return ret; } diff -Nru a/lib/crc32.c b/lib/crc32.c --- a/lib/crc32.c Mon Feb 17 14:57:26 2003 +++ b/lib/crc32.c Mon Feb 17 14:57:26 2003 @@ -87,55 +87,51 @@ { # if CRC_LE_BITS == 8 const u32 *b =(u32 *)p; - const u32 *e; - /* load data 32 bits wide, xor data 32 bits wide. */ + const u32 *tab = crc32table_le; - crc = __cpu_to_le32(crc); - /* Align it */ - for ( ; ((long)b)&3 && len ; len--){ -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_le[ crc>>24 ^ *((u8 *)b)++ ]; -# endif - } - e = (u32 *) ( (u8 *)b + (len & ~7)); - while (b < e) { - crc ^= *b++; -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; -# endif - crc ^= *b++; # ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_le[ crc & 0xff ]; +# define DO_CRC crc = (crc>>8) ^ tab[ crc & 255 ] +# define ENDIAN_SHIFT 0 # else - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_le[ crc >> 24 ]; +# define DO_CRC crc = (crc<<8) ^ tab[ crc >> 24 ] +# define ENDIAN_SHIFT 24 # endif + + crc = __cpu_to_le32(crc); + /* Align it */ + if(unlikely(((long)b)&3 && len)){ + do { + crc ^= *((u8 *)b)++ << ENDIAN_SHIFT; + DO_CRC; + } while ((--len) && ((long)b)&3 ); + } + if(likely(len >= 4)){ + /* load data 32 bits wide, xor data 32 bits wide. */ + size_t save_len = len & 3; + len = len >> 2; + --b; /* use pre increment below(*++b) for speed */ + do { + crc ^= *++b; + DO_CRC; + DO_CRC; + DO_CRC; + DO_CRC; + } while (--len); + b++; /* point to next byte(s) */ + len = save_len; } /* And the last few bytes */ - e = (u32 *)((u8 *)b + (len & 7)); - while (b < e){ -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_le[ crc>>24 ^ *((u8 *)b)++ ]; -# endif + if(len){ + do { + crc ^= *((u8 *)b)++ << ENDIAN_SHIFT; + DO_CRC; + } while (--len); } - return __le32_to_cpu(crc) ; + + return __le32_to_cpu(crc); +#undef ENDIAN_SHIFT +#undef DO_CRC + # elif CRC_LE_BITS == 4 while (len--) { crc ^= *p++; @@ -196,55 +192,50 @@ { # if CRC_BE_BITS == 8 const u32 *b =(u32 *)p; - const u32 *e; - /* load data 32 bits wide, xor data 32 bits wide. */ + const u32 *tab = crc32table_be; - crc = __cpu_to_be32(crc); - /* Align it */ - for ( ; ((long)b)&3 && len ; len--){ -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_be[ crc>>24 ^ *((u8 *)b)++ ]; -# endif - } - e = (u32 *) ( (u8 *)b + (len & ~7)); - while (b < e) { - crc ^= *b++; -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; -# endif - crc ^= *b++; # ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; - crc = (crc>>8) ^ crc32table_be[ crc & 0xff ]; +# define DO_CRC crc = (crc>>8) ^ tab[ crc & 255 ] +# define ENDIAN_SHIFT 24 # else - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; - crc = (crc<<8) ^ crc32table_be[ crc >> 24 ]; +# define DO_CRC crc = (crc<<8) ^ tab[ crc >> 24 ] +# define ENDIAN_SHIFT 0 # endif + + crc = __cpu_to_be32(crc); + /* Align it */ + if(unlikely(((long)b)&3 && len)){ + do { + crc ^= *((u8 *)b)++ << ENDIAN_SHIFT; + DO_CRC; + } while ((--len) && ((long)b)&3 ); + } + if(likely(len >= 4)){ + /* load data 32 bits wide, xor data 32 bits wide. */ + size_t save_len = len & 3; + len = len >> 2; + --b; /* use pre increment below(*++b) for speed */ + do { + crc ^= *++b; + DO_CRC; + DO_CRC; + DO_CRC; + DO_CRC; + } while (--len); + b++; /* point to next byte(s) */ + len = save_len; } /* And the last few bytes */ - e = (u32 *)((u8 *)b + (len & 7)); - while (b < e){ -# ifdef __LITTLE_ENDIAN - crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ]; -# else - crc = (crc<<8) ^ crc32table_be[ crc>>24 ^ *((u8 *)b)++ ]; -# endif - } - return __be32_to_cpu(crc) ; + if(len){ + do { + crc ^= *((u8 *)b)++ << ENDIAN_SHIFT; + DO_CRC; + } while (--len); + } + return __be32_to_cpu(crc); +#undef ENDIAN_SHIFT +#undef DO_CRC + # elif CRC_BE_BITS == 4 while (len--) { crc ^= *p++ << 24; diff -Nru a/lib/radix-tree.c b/lib/radix-tree.c --- a/lib/radix-tree.c Mon Feb 17 14:57:27 2003 +++ b/lib/radix-tree.c Mon Feb 17 14:57:27 2003 @@ -46,6 +46,8 @@ #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) +static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH]; + /* * Radix tree node cache. */ @@ -126,12 +128,7 @@ */ static inline unsigned long radix_tree_maxindex(unsigned int height) { - unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; - unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; - - if (tmp >= RADIX_TREE_INDEX_BITS) - index = ~0UL; - return index; + return height_to_maxindex[height]; } /* @@ -401,6 +398,24 @@ memset(node, 0, sizeof(struct radix_tree_node)); } +static __init unsigned long __maxindex(unsigned int height) +{ + unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; + unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; + + if (tmp >= RADIX_TREE_INDEX_BITS) + index = ~0UL; + return index; +} + +static __init void radix_tree_init_maxindex(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) + height_to_maxindex[i] = __maxindex(i); +} + void __init radix_tree_init(void) { radix_tree_node_cachep = kmem_cache_create("radix_tree_node", @@ -408,4 +423,5 @@ 0, radix_tree_node_ctor, NULL); if (!radix_tree_node_cachep) panic ("Failed to create radix_tree_node cache\n"); + radix_tree_init_maxindex(); } diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c Mon Feb 17 14:57:27 2003 +++ b/mm/filemap.c Mon Feb 17 14:57:27 2003 @@ -678,50 +678,6 @@ UPDATE_ATIME(inode); } -/* - * Fault a userspace page into pagetables. Return non-zero on a fault. - * - * FIXME: this assumes that two userspace pages are always sufficient. That's - * not true if PAGE_CACHE_SIZE > PAGE_SIZE. - */ -static inline int fault_in_pages_writeable(char *uaddr, int size) -{ - int ret; - - /* - * Writing zeroes into userspace here is OK, because we know that if - * the zero gets there, we'll be overwriting it. - */ - ret = __put_user(0, uaddr); - if (ret == 0) { - char *end = uaddr + size - 1; - - /* - * If the page was already mapped, this will get a cache miss - * for sure, so try to avoid doing it. - */ - if (((unsigned long)uaddr & PAGE_MASK) != - ((unsigned long)end & PAGE_MASK)) - ret = __put_user(0, end); - } - return ret; -} - -static void fault_in_pages_readable(const char *uaddr, int size) -{ - volatile char c; - int ret; - - ret = __get_user(c, (char *)uaddr); - if (ret == 0) { - const char *end = uaddr + size - 1; - - if (((unsigned long)uaddr & PAGE_MASK) != - ((unsigned long)end & PAGE_MASK)) - __get_user(c, (char *)end); - } -} - int file_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long size) { @@ -805,13 +761,8 @@ goto out; /* skip atime */ size = inode->i_size; if (pos < size) { - if (pos + count > size) { - count = size - pos; - nr_segs = iov_shorten((struct iovec *)iov, - nr_segs, count); - } retval = generic_file_direct_IO(READ, iocb, - iov, pos, nr_segs); + iov, pos, nr_segs); if (retval >= 0 && !is_sync_kiocb(iocb)) retval = -EIOCBQUEUED; if (retval > 0) @@ -1530,6 +1481,91 @@ *basep = base; } +/* + * Performs necessary checks before doing a write + * + * Can adjust writing position aor amount of bytes to write. + * Returns appropriate error code that caller should return or + * zero in case that write should be allowed. + */ +inline int generic_write_checks(struct inode *inode, + struct file *file, loff_t *pos, size_t *count, int isblk) +{ + unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; + + if (unlikely(*pos < 0)) + return -EINVAL; + + if (unlikely(file->f_error)) { + int err = file->f_error; + file->f_error = 0; + return err; + } + + if (!isblk) { + /* FIXME: this is for backwards compatibility with 2.4 */ + if (file->f_flags & O_APPEND) + *pos = inode->i_size; + + if (limit != RLIM_INFINITY) { + if (*pos >= limit) { + send_sig(SIGXFSZ, current, 0); + return -EFBIG; + } + if (*pos > 0xFFFFFFFFULL || *count > limit-(u32)*pos) { + /* send_sig(SIGXFSZ, current, 0); */ + *count = limit - (u32)*pos; + } + } + } + + /* + * LFS rule + */ + if (unlikely(*pos + *count > MAX_NON_LFS && + !(file->f_flags & O_LARGEFILE))) { + if (*pos >= MAX_NON_LFS) { + send_sig(SIGXFSZ, current, 0); + return -EFBIG; + } + if (*count > MAX_NON_LFS - (u32)*pos) { + /* send_sig(SIGXFSZ, current, 0); */ + *count = MAX_NON_LFS - (u32)*pos; + } + } + + /* + * Are we about to exceed the fs block limit ? + * + * If we have written data it becomes a short write. If we have + * exceeded without writing data we send a signal and return EFBIG. + * Linus frestrict idea will clean these up nicely.. + */ + if (likely(!isblk)) { + if (unlikely(*pos >= inode->i_sb->s_maxbytes)) { + if (*count || *pos > inode->i_sb->s_maxbytes) { + send_sig(SIGXFSZ, current, 0); + return -EFBIG; + } + /* zero-length writes at ->s_maxbytes are OK */ + } + + if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) + *count = inode->i_sb->s_maxbytes - *pos; + } else { + if (bdev_read_only(inode->i_bdev)) + return -EPERM; + if (*pos >= inode->i_size) { + if (*count || *pos > inode->i_size) + return -ENOSPC; + } + + if (*pos + *count > inode->i_size) + *count = inode->i_size - *pos; + } + return 0; +} +EXPORT_SYMBOL(generic_write_checks); /* * Write to a file through the page cache. @@ -1550,12 +1586,11 @@ size_t ocount; /* original count */ size_t count; /* after file limit checks */ struct inode *inode = mapping->host; - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - const int isblk = S_ISBLK(inode->i_mode); long status = 0; loff_t pos; struct page *page; struct page *cached_page = NULL; + const int isblk = S_ISBLK(inode->i_mode); ssize_t written; ssize_t err; size_t bytes; @@ -1584,95 +1619,20 @@ ocount -= iv->iov_len; /* This segment is no good */ break; } - count = ocount; + count = ocount; pos = *ppos; - if (unlikely(pos < 0)) - return -EINVAL; + pagevec_init(&lru_pvec, 0); /* We can write back this queue in page reclaim */ current->backing_dev_info = mapping->backing_dev_info; - - pagevec_init(&lru_pvec, 0); - - if (unlikely(file->f_error)) { - err = file->f_error; - file->f_error = 0; - goto out; - } - written = 0; - if (!isblk) { - /* FIXME: this is for backwards compatibility with 2.4 */ - if (file->f_flags & O_APPEND) - pos = inode->i_size; - - if (limit != RLIM_INFINITY) { - if (pos >= limit) { - send_sig(SIGXFSZ, current, 0); - err = -EFBIG; - goto out; - } - if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) { - /* send_sig(SIGXFSZ, current, 0); */ - count = limit - (u32)pos; - } - } - } - - /* - * LFS rule - */ - if (unlikely(pos + count > MAX_NON_LFS && - !(file->f_flags & O_LARGEFILE))) { - if (pos >= MAX_NON_LFS) { - send_sig(SIGXFSZ, current, 0); - err = -EFBIG; - goto out; - } - if (count > MAX_NON_LFS - (u32)pos) { - /* send_sig(SIGXFSZ, current, 0); */ - count = MAX_NON_LFS - (u32)pos; - } - } - - /* - * Are we about to exceed the fs block limit ? - * - * If we have written data it becomes a short write. If we have - * exceeded without writing data we send a signal and return EFBIG. - * Linus frestrict idea will clean these up nicely.. - */ - if (likely(!isblk)) { - if (unlikely(pos >= inode->i_sb->s_maxbytes)) { - if (count || pos > inode->i_sb->s_maxbytes) { - send_sig(SIGXFSZ, current, 0); - err = -EFBIG; - goto out; - } - /* zero-length writes at ->s_maxbytes are OK */ - } - - if (unlikely(pos + count > inode->i_sb->s_maxbytes)) - count = inode->i_sb->s_maxbytes - pos; - } else { - if (bdev_read_only(inode->i_bdev)) { - err = -EPERM; - goto out; - } - if (pos >= inode->i_size) { - if (count || pos > inode->i_size) { - err = -ENOSPC; - goto out; - } - } + err = generic_write_checks(inode, file, &pos, &count, isblk); + if (err) + goto out; - if (pos + count > inode->i_size) - count = inode->i_size - pos; - } - err = 0; if (count == 0) goto out; diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c --- a/mm/page-writeback.c Mon Feb 17 14:57:27 2003 +++ b/mm/page-writeback.c Mon Feb 17 14:57:27 2003 @@ -301,7 +301,7 @@ writeback_inodes(&wbc); if (wbc.nr_to_write > 0) { if (wbc.encountered_congestion) - blk_congestion_wait(WRITE, HZ); + blk_congestion_wait(WRITE, HZ/10); else break; /* All the old data is written */ } diff -Nru a/mm/slab.c b/mm/slab.c --- a/mm/slab.c Mon Feb 17 14:57:28 2003 +++ b/mm/slab.c Mon Feb 17 14:57:28 2003 @@ -438,7 +438,6 @@ /* internal cache of cache description objs */ static kmem_cache_t cache_cache = { .lists = LIST3_INIT(cache_cache.lists), - /* Allow for boot cpu != 0 */ .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .objsize = sizeof(kmem_cache_t), diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Mon Feb 17 14:57:27 2003 +++ b/mm/vmscan.c Mon Feb 17 14:57:27 2003 @@ -835,7 +835,7 @@ wakeup_bdflush(total_scanned); /* Take a nap, wait for some writeback to complete */ - blk_congestion_wait(WRITE, HZ/4); + blk_congestion_wait(WRITE, HZ/10); shrink_slab(total_scanned, gfp_mask); } if (gfp_mask & __GFP_FS) @@ -904,7 +904,7 @@ } if (all_zones_ok) break; - blk_congestion_wait(WRITE, HZ/4); + blk_congestion_wait(WRITE, HZ/10); } return nr_pages - to_free; } diff -Nru a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c --- a/net/bluetooth/hci_core.c Mon Feb 17 14:57:27 2003 +++ b/net/bluetooth/hci_core.c Mon Feb 17 14:57:27 2003 @@ -114,7 +114,7 @@ envp[3] = astr; envp[4] = NULL; - return call_usermodehelper(argv[0], argv, envp); + return call_usermodehelper(argv[0], argv, envp, 0); } #else #define hci_run_hotplug(A...) diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Mon Feb 17 14:57:27 2003 +++ b/net/core/dev.c Mon Feb 17 14:57:27 2003 @@ -2942,6 +2942,6 @@ envp [i++] = action_str; envp [i] = 0; - return call_usermodehelper(argv [0], argv, envp); + return call_usermodehelper(argv [0], argv, envp, 0); } #endif diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c --- a/net/ipv4/ip_gre.c Mon Feb 17 14:57:28 2003 +++ b/net/ipv4/ip_gre.c Mon Feb 17 14:57:28 2003 @@ -454,7 +454,7 @@ /* Impossible event. */ return; case ICMP_FRAG_NEEDED: - /* And it is the only really necesary thing :-) */ + /* And it is the only really necessary thing :-) */ rel_info = ntohs(skb->h.icmph->un.frag.mtu); if (rel_info < grehlen+68) return; diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c --- a/net/ipv4/ipip.c Mon Feb 17 14:57:28 2003 +++ b/net/ipv4/ipip.c Mon Feb 17 14:57:28 2003 @@ -383,7 +383,7 @@ /* Impossible event. */ return; case ICMP_FRAG_NEEDED: - /* And it is the only really necesary thing :-) */ + /* And it is the only really necessary thing :-) */ rel_info = ntohs(skb->h.icmph->un.frag.mtu); if (rel_info < hlen+68) return; diff -Nru a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c --- a/net/sched/sch_cbq.c Mon Feb 17 14:57:26 2003 +++ b/net/sched/sch_cbq.c Mon Feb 17 14:57:26 2003 @@ -797,7 +797,7 @@ That is not all. To maintain the rate allocated to the class, we add to undertime virtual clock, - necesary to complete transmitted packet. + necessary to complete transmitted packet. (len/phys_bandwidth has been already passed to the moment of cbq_update) */ diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c --- a/net/sunrpc/clnt.c Mon Feb 17 14:57:27 2003 +++ b/net/sunrpc/clnt.c Mon Feb 17 14:57:27 2003 @@ -67,7 +67,6 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) { static uint32_t clntid; - int maxlen = sizeof(clnt->cl_pathname); int error; if (dir_name == NULL) diff -Nru a/scripts/Makefile b/scripts/Makefile --- a/scripts/Makefile Mon Feb 17 14:57:27 2003 +++ b/scripts/Makefile Mon Feb 17 14:57:27 2003 @@ -8,11 +8,26 @@ # docproc: Preprocess .tmpl file in order to generate .sgml documentation # conmakehash: Create arrays for initializing the kernel console tables -host-progs := fixdep split-include conmakehash docproc kallsyms -build-targets := $(host-progs) +host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ + mk_elfconfig +build-targets := $(host-progs) empty.o + +modpost-objs := modpost.o file2alias.o # Let clean descend into subdirs subdir- := lxdialog kconfig # fixdep is needed to compile other host programs -$(addprefix $(obj)/,$(filter-out fixdep,$(host-progs))): $(obj)/fixdep +$(addprefix $(obj)/,$(filter-out fixdep,$(build-targets))): $(obj)/fixdep + +# dependencies on generated files need to be listed explicitly + +$(obj)/modpost.o $(obj)/file2alias.o: $(obj)/elfconfig.h + +quiet_cmd_elfconfig = MKELF $@ + cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@ + +$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE + $(call if_changed,elfconfig) + +targets += $(obj)/elfconfig.h diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build --- a/scripts/Makefile.build Mon Feb 17 14:57:28 2003 +++ b/scripts/Makefile.build Mon Feb 17 14:57:28 2003 @@ -49,15 +49,12 @@ endif endif -ifdef CONFIG_MODVERSIONS -modules := $(obj-m) -touch-module = @echo $(@:.o=.ko) > .tmp_versions/$(@F:.o=.mod) -else -modules := $(obj-m:.o=.ko) -endif +# We keep a list of all modules in $(MODVERDIR) + +touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod) __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \ - $(if $(KBUILD_MODULES),$(modules)) \ + $(if $(KBUILD_MODULES),$(obj-m)) \ $(subdir-ym) $(build-targets) @: @@ -155,6 +152,8 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +# Built-in and composite module parts + %.o: %.c FORCE ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) @@ -162,13 +161,14 @@ $(call if_changed_dep,cc_o_c) endif -# For modversioning, we need to special case single-part modules -# to mark them in $(MODVERDIR) +# Single-part modules are special since we need to mark them in $(MODVERDIR) -ifdef CONFIG_MODVERSIONS $(single-used-m): %.o: %.c FORCE $(touch-module) +ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) +else + $(call if_changed_dep,cc_o_c) endif quiet_cmd_cc_lst_c = MKLST $@ @@ -199,7 +199,8 @@ %.o: %.S FORCE $(call if_changed_dep,as_o_S) -targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) +targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \ + $(build-targets) # Build the compiled-in targets # --------------------------------------------------------------------------- @@ -266,29 +267,6 @@ $(call if_changed,link_multi-m) targets += $(multi-used-y) $(multi-used-m) - -# -# Rule to link modules ( .o -> .ko ) -# - -# With CONFIG_MODVERSIONS, generation of the final .ko is handled -# by scripts/Makefile.modver -ifndef CONFIG_MODVERSIONS - -quiet_cmd_link_module = LD [M] $@ -cmd_link_module = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o - -# Don't rebuilt vermagic.o unless we actually are in the init/ dir -ifneq ($(obj),init) -init/vermagic.o: ; -endif - -$(single-used-m:.o=.ko) $(multi-used-m:.o=.ko): %.ko: %.o init/vermagic.o FORCE - $(call if_changed,link_module) - -targets += $(single-used-m:.o=.ko) $(multi-used-m:.o=.ko) - -endif # Compile programs on the host # =========================================================================== diff -Nru a/scripts/Makefile.modinst b/scripts/Makefile.modinst --- a/scripts/Makefile.modinst Mon Feb 17 14:57:27 2003 +++ b/scripts/Makefile.modinst Mon Feb 17 14:57:27 2003 @@ -2,33 +2,38 @@ # Installing modules # ========================================================================== -src := $(obj) +.PHONY: __modinst +__modinst: -.PHONY: modules_install -modules_install: +include scripts/Makefile.lib -include .config +# -include $(obj)/Makefile +__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod)) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) -include scripts/Makefile.lib +ifneq ($(filter-out $(modules),$(__modules)),) + $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS, do not complain if something goes wrong.) +endif + +.PHONY: $(modules) +__modinst: $(modules) + @: -# ========================================================================== +# Modules built within the kernel tree -quiet_cmd_modules_install = INSTALL $(obj-m:.o=.ko) - cmd_modules_install = mkdir -p $(MODLIB)/kernel/$(obj); \ - cp $(obj-m:.o=.ko) $(MODLIB)/kernel/$(obj) +quiet_cmd_modules_install = INSTALL $@ + cmd_modules_install = mkdir -p $(MODLIB)/kernel/$(@D); \ + cp $@ $(MODLIB)/kernel/$(@D) -modules_install: $(subdir-ym) -ifneq ($(obj-m:.o=.ko),) +$(filter-out ../% /%,$(modules)): $(call cmd,modules_install) -else - @: -endif -# Descending -# --------------------------------------------------------------------------- +# Modules built outside just go into extra + +quiet_cmd_modules_install_extra = INSTALL $(obj-m:.o=.ko) + cmd_modules_install_extra = mkdir -p $(MODLIB)/extra; \ + cp $@ $(MODLIB)/extra -.PHONY: $(subdir-ym) -$(subdir-ym): - $(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$@ +$(filter ../% /%,$(modules)): + $(call cmd,modules_install_extra) diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/Makefile.modpost Mon Feb 17 14:57:28 2003 @@ -0,0 +1,81 @@ +# =========================================================================== +# Module versions +# =========================================================================== + +.PHONY: __modversions +__modversions: + +include .config +include scripts/Makefile.lib + +# + +__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod)) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) + +ifneq ($(filter-out $(modules),$(__modules)),) + $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,) + $(warning do not complain if something goes wrong.) +endif + +__modversions: $(modules) + @: + +# The final module link + +quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \ + $(filter-out FORCE,$^) + +$(modules): %.ko :%.o %.mod.o FORCE + $(call if_changed,ld_ko_o) + +targets += $(modules) + +# Compile version info for unresolved symbols + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $< + +# We have a fake dependency on compile.h to make sure that we +# notice if the compiler version changes under us. + +$(modules:.ko=.mod.o): %.mod.o: %.mod.c include/linux/compile.h FORCE + $(call if_changed,cc_o_c) + +targets += $(modules:.ko=.mod.o) + +# All the .mod.c files are generated using the helper "modpost" + +.PHONY: __modpost + +$(modules:.ko=.mod.c): __modpost ; + +# Extract all checksums for all exported symbols + +quiet_cmd_modpost = MODPOST + cmd_modpost = scripts/modpost $^ + +__modpost: $(wildcard vmlinux) $(modules:.ko=.o) + $(call if_changed,modpost) + +targets += __modpost + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +.PHONY: FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif diff -Nru a/scripts/Makefile.modver b/scripts/Makefile.modver --- a/scripts/Makefile.modver Mon Feb 17 14:57:27 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,105 +0,0 @@ -# =========================================================================== -# Module versions -# =========================================================================== - -.PHONY: __modversions -__modversions: - -include scripts/Makefile.lib - -# - -__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod)) -modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) - -ifneq ($(filter-out $(modules),$(__modules)),) - $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,) - $(warning do not complain if something goes wrong.) -endif - -__modversions: $(modules) - @: - -# The final module link - -quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \ - $(filter-out FORCE,$^) - -init/vermagic.o: ; - -$(modules): %.ko :%.o %.ver.o init/vermagic.o FORCE - $(call if_changed,ld_ko_o) - -targets += $(modules) - -# Compile version info for unresolved symbols - -quiet_cmd_cc_o_c = CC $@ - cmd_cc_o_c = $(CC) $(CFLAGS) -c -o $@ $< - -$(modules:.ko=.ver.o): %.ver.o: %.ver.c FORCE - $(call if_changed,cc_o_c) - -targets += $(modules:.ko=.ver.o) - -# Generate C source with version info for unresolved symbols - -define rule_mkver_o_c - echo ' MKVER $@'; \ - ( echo "#include "; \ - echo ""; \ - echo "static const struct modversion_info ____versions[]"; \ - echo "__attribute__((section(\"__versions\"))) = {"; \ - for sym in `nm -u $<`; do \ - grep "\"$$sym\"" .tmp_all-versions \ - || echo "*** Warning: $(<:.o=.ko): \"$$sym\" unresolved!" >&2;\ - done; \ - echo "};"; \ - ) > $@ -endef - -$(modules:.ko=.ver.c): %.ver.c: %.o .tmp_all-versions FORCE - $(call if_changed_rule,mkver_o_c) - -targets += $(modules:.ko=.ver.c)) - -# Extract all checksums for all exported symbols - -export-objs := $(shell for m in vmlinux $(modules:.ko=.o); do objdump -h $$m | grep -q __ksymtab && echo $$m; done) - -cmd_gen-all-versions = mksyms $(export-objs) -define rule_gen-all-versions - echo ' MKSYMS $@'; \ - for mod in $(export-objs); do \ - modname=`basename $$mod`; \ - nm $$mod \ - | grep ' __crc_' \ - | sed "s/\([^ ]*\) A __crc_\(.*\)/{ 0x\1, \"\2\" }, \/* $$modname *\//g;s/.* w __crc_\(.*\)/{ 0x0 , \"\1\" }, \/* $$modname *\//g"; \ - done > $@; \ - echo 'cmd_$@ := $(cmd_$(1))' > $(@D)/.$(@F).cmd -endef - -.tmp_all-versions: $(export-objs) FORCE - $(call if_changed_rule,gen-all-versions) - -targets += .tmp_all-versions - -# Add FORCE to the prequisites of a target to force it to be always rebuilt. -# --------------------------------------------------------------------------- - -.PHONY: FORCE - -FORCE: - -# Read all saved command lines and dependencies for the $(targets) we -# may be building above, using $(if_changed{,_dep}). As an -# optimization, we don't need to read them if the target does not -# exist, we will rebuild anyway in that case. - -targets := $(wildcard $(sort $(targets))) -cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) - -ifneq ($(cmd_files),) - include $(cmd_files) -endif diff -Nru a/scripts/empty.c b/scripts/empty.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/empty.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1 @@ +/* empty file to figure out endianness / word size */ diff -Nru a/scripts/file2alias.c b/scripts/file2alias.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/file2alias.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,178 @@ +/* Simple code to turn various tables in an ELF file into alias definitions. + * This deals with kernel datastructures where they should be + * dealt with: in the kernel source. + * + * Copyright 2002-2003 Rusty Russell, IBM Corporation + * 2003 Kai Germaschewski + * + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include "modpost.h" + +/* We use the ELF typedefs, since we can't rely on stdint.h being present. */ + +#if KERNEL_ELFCLASS == ELFCLASS32 +typedef Elf32_Addr kernel_ulong_t; +#else +typedef Elf64_Addr kernel_ulong_t; +#endif + +typedef Elf32_Word __u32; +typedef Elf32_Half __u16; +typedef unsigned char __u8; + +/* Big exception to the "don't include kernel headers into userspace, which + * even potentially has different endianness and word sizes, since + * we handle those differences explicitly below */ +#include "../include/linux/mod_devicetable.h" + +#define ADD(str, sep, cond, field) \ +do { \ + strcat(str, sep); \ + if (cond) \ + sprintf(str + strlen(str), \ + sizeof(field) == 1 ? "%02X" : \ + sizeof(field) == 2 ? "%04X" : \ + sizeof(field) == 4 ? "%08X" : "", \ + field); \ + else \ + sprintf(str + strlen(str), "*"); \ +} while(0) + +/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */ +static int do_usb_entry(const char *filename, + struct usb_device_id *id, char *alias) +{ + id->match_flags = TO_NATIVE(id->match_flags); + id->idVendor = TO_NATIVE(id->idVendor); + id->idProduct = TO_NATIVE(id->idProduct); + id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo); + id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi); + + strcpy(alias, "usb:"); + ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, + id->idVendor); + ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT, + id->idProduct); + ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO, + id->bcdDevice_lo); + ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI, + id->bcdDevice_hi); + ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, + id->bDeviceClass); + ADD(alias, "dsc", + id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, + id->bDeviceSubClass); + ADD(alias, "dp", + id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, + id->bDeviceProtocol); + ADD(alias, "ic", + id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, + id->bInterfaceClass); + ADD(alias, "isc", + id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, + id->bInterfaceSubClass); + ADD(alias, "ip", + id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, + id->bInterfaceProtocol); + return 1; +} + +/* Looks like: pci:vNdNsvNsdNcN. */ +static int do_pci_entry(const char *filename, + struct pci_device_id *id, char *alias) +{ + id->vendor = TO_NATIVE(id->vendor); + id->device = TO_NATIVE(id->device); + id->subvendor = TO_NATIVE(id->subvendor); + id->subdevice = TO_NATIVE(id->subdevice); + id->class = TO_NATIVE(id->class); + id->class_mask = TO_NATIVE(id->class_mask); + + strcpy(alias, "pci:"); + ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor); + ADD(alias, "d", id->device != PCI_ANY_ID, id->device); + ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor); + ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice); + if (id->class_mask != 0 && id->class_mask != ~0) { + fprintf(stderr, + "*** Warning: Can't handle class_mask in %s:%04X\n", + filename, id->class_mask); + return 0; + } + ADD(alias, "c", id->class_mask == ~0, id->class); + return 1; +} + +/* Ignore any prefix, eg. v850 prepends _ */ +static inline int sym_is(const char *symbol, const char *name) +{ + const char *match; + + match = strstr(symbol, name); + if (!match) + return 0; + return match[strlen(symbol)] == '\0'; +} + +static void do_table(void *symval, unsigned long size, + unsigned long id_size, + void *function, + struct module *mod) +{ + unsigned int i; + char alias[500]; + int (*do_entry)(const char *, void *entry, char *alias) = function; + + if (size % id_size || size < id_size) { + fprintf(stderr, "*** Warning: %s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); + } + /* Leave last one: it's the terminator. */ + size -= id_size; + + for (i = 0; i < size; i += id_size) { + if (do_entry(mod->name, symval+i, alias)) { + /* Always end in a wildcard, for future extension */ + if (alias[strlen(alias)-1] != '*') + strcat(alias, "*"); + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"%s\");\n", alias); + } + } +} + +/* Create MODULE_ALIAS() statements. + * At this time, we cannot write the actual output C source yet, + * so we write into the mod->dev_table_buf buffer. */ +void handle_moddevtable(struct module *mod, struct elf_info *info, + Elf_Sym *sym, const char *symname) +{ + void *symval; + + /* We're looking for a section relative symbol */ + if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum) + return; + + symval = (void *)info->hdr + + info->sechdrs[sym->st_shndx].sh_offset + + sym->st_value; + + if (sym_is(symname, "__mod_pci_device_table")) + do_table(symval, sym->st_size, sizeof(struct pci_device_id), + do_pci_entry, mod); + else if (sym_is(symname, "__mod_usb_device_table")) + do_table(symval, sym->st_size, sizeof(struct usb_device_id), + do_usb_entry, mod); +} + +/* Now add out buffered information to the generated C source */ +void add_moddevtable(struct buffer *buf, struct module *mod) +{ + buf_printf(buf, "\n"); + buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); + free(mod->dev_table_buf.p); +} diff -Nru a/scripts/mk_elfconfig.c b/scripts/mk_elfconfig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/mk_elfconfig.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + unsigned char ei[EI_NIDENT]; + union { short s; char c[2]; } endian_test; + + if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) { + fprintf(stderr, "Error: input truncated\n"); + return 1; + } + if (memcmp(ei, ELFMAG, SELFMAG) != 0) { + fprintf(stderr, "Error: not ELF\n"); + return 1; + } + switch (ei[EI_CLASS]) { + case ELFCLASS32: + printf("#define KERNEL_ELFCLASS ELFCLASS32\n"); + break; + case ELFCLASS64: + printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); + break; + default: + abort(); + } + switch (ei[EI_DATA]) { + case ELFDATA2LSB: + printf("#define KERNEL_ELFDATA ELFDATA2LSB\n"); + break; + case ELFDATA2MSB: + printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); + break; + default: + abort(); + } + + if (sizeof(unsigned long) == 4) { + printf("#define HOST_ELFCLASS ELFCLASS32\n"); + } else if (sizeof(unsigned long) == 8) { + printf("#define HOST_ELFCLASS ELFCLASS64\n"); + } + + endian_test.s = 0x0102; + if (memcmp(endian_test.c, "\x01\x02", 2) == 0) + printf("#define HOST_ELFDATA ELFDATA2MSB\n"); + else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) + printf("#define HOST_ELFDATA ELFDATA2LSB\n"); + else + abort(); + + return 0; +} + diff -Nru a/scripts/modpost.c b/scripts/modpost.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/modpost.c Mon Feb 17 14:57:28 2003 @@ -0,0 +1,541 @@ +/* Postprocess module symbol versions + * + * Copyright 2003 Kai Germaschewski + * 2002-2003 Rusty Russell, IBM Corporation + * + * Based in part on module-init-tools/depmod.c,file2alias + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * Usage: modpost vmlinux module1.o module2.o ... + */ + +#include "modpost.h" + +/* Are we using CONFIG_MODVERSIONS? */ +int modversions = 0; +/* Do we have vmlinux? */ +int have_vmlinux = 0; + +void +fatal(const char *fmt, ...) +{ + va_list arglist; + + fprintf(stderr, "FATAL: "); + + va_start(arglist, fmt); + vfprintf(stderr, fmt, arglist); + va_end(arglist); + + exit(1); +} + +void +warn(const char *fmt, ...) +{ + va_list arglist; + + fprintf(stderr, "WARNING: "); + + va_start(arglist, fmt); + vfprintf(stderr, fmt, arglist); + va_end(arglist); +} + +#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr) + +void *do_nofail(void *ptr, const char *file, int line, const char *expr) +{ + if (!ptr) { + fatal("Memory allocation failure %s line %d: %s.\n", + file, line, expr); + } + return ptr; +} + +/* A list of all modules we processed */ + +static struct module *modules; + +struct module * +new_module(char *modname) +{ + struct module *mod; + char *p; + + /* strip trailing .o */ + p = strstr(modname, ".o"); + if (p) + *p = 0; + + mod = NOFAIL(malloc(sizeof(*mod))); + memset(mod, 0, sizeof(*mod)); + mod->name = modname; + + /* add to list */ + mod->next = modules; + modules = mod; + + return mod; +} + +/* A hash of all exported symbols, + * struct symbol is also used for lists of unresolved symbols */ + +#define SYMBOL_HASH_SIZE 1024 + +struct symbol { + struct symbol *next; + struct module *module; + unsigned int crc; + int crc_valid; + char name[0]; +}; + +static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; + +/* This is based on the hash agorithm from gdbm, via tdb */ +static inline unsigned int tdb_hash(const char *name) +{ + unsigned value; /* Used to compute the hash value. */ + unsigned i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) + value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + +/* Allocate a new symbols for use in the hash of exported symbols or + * the list of unresolved symbols per module */ + +struct symbol * +alloc_symbol(const char *name) +{ + struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); + + memset(s, 0, sizeof(*s)); + strcpy(s->name, name); + return s; +} + +/* For the hash of exported symbols */ + +void +new_symbol(const char *name, struct module *module, unsigned int *crc) +{ + unsigned int hash; + struct symbol *new = alloc_symbol(name); + + new->module = module; + if (crc) { + new->crc = *crc; + new->crc_valid = 1; + } + + hash = tdb_hash(name) % SYMBOL_HASH_SIZE; + new->next = symbolhash[hash]; + symbolhash[hash] = new; +} + +struct symbol * +find_symbol(const char *name) +{ + struct symbol *s; + + /* For our purposes, .foo matches foo. PPC64 needs this. */ + if (name[0] == '.') + name++; + + for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) { + if (strcmp(s->name, name) == 0) + return s; + } + return NULL; +} + +/* Add an exported symbol - it may have already been added without a + * CRC, in this case just update the CRC */ +void +add_exported_symbol(const char *name, struct module *module, unsigned int *crc) +{ + struct symbol *s = find_symbol(name); + + if (!s) { + new_symbol(name, modules, crc); + return; + } + if (crc) { + s->crc = *crc; + s->crc_valid = 1; + } +} + +void * +grab_file(const char *filename, unsigned long *size) +{ + struct stat st; + void *map; + int fd; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + abort(); + } + if (fstat(fd, &st) != 0) { + perror(filename); + abort(); + } + + *size = st.st_size; + map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + if (mmap == MAP_FAILED) { + perror(filename); + abort(); + } + close(fd); + return map; +} + +void +parse_elf(struct elf_info *info, const char *filename) +{ + unsigned int i; + Elf_Ehdr *hdr = info->hdr; + Elf_Shdr *sechdrs; + Elf_Sym *sym; + + hdr = grab_file(filename, &info->size); + info->hdr = hdr; + if (info->size < sizeof(*hdr)) + goto truncated; + + /* Fix endianness in ELF header */ + hdr->e_shoff = TO_NATIVE(hdr->e_shoff); + hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); + hdr->e_shnum = TO_NATIVE(hdr->e_shnum); + sechdrs = (void *)hdr + hdr->e_shoff; + info->sechdrs = sechdrs; + + /* Fix endianness in section headers */ + for (i = 0; i < hdr->e_shnum; i++) { + sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); + sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); + sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); + sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); + } + /* Find symbol table. */ + for (i = 1; i < hdr->e_shnum; i++) { + if (sechdrs[i].sh_offset > info->size) + goto truncated; + if (sechdrs[i].sh_type != SHT_SYMTAB) + continue; + + info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; + info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset + + sechdrs[i].sh_size; + info->strtab = (void *)hdr + + sechdrs[sechdrs[i].sh_link].sh_offset; + } + if (!info->symtab_start) { + fprintf(stderr, "modpost: %s no symtab?\n", filename); + abort(); + } + /* Fix endianness in symbols */ + for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { + sym->st_shndx = TO_NATIVE(sym->st_shndx); + sym->st_name = TO_NATIVE(sym->st_name); + sym->st_value = TO_NATIVE(sym->st_value); + sym->st_size = TO_NATIVE(sym->st_size); + } + return; + + truncated: + fprintf(stderr, "modpost: %s is truncated.\n", filename); + abort(); +} + +void +parse_elf_finish(struct elf_info *info) +{ + munmap(info->hdr, info->size); +} + +void +handle_modversions(struct module *mod, struct elf_info *info, + Elf_Sym *sym, const char *symname) +{ + struct symbol *s; + unsigned int crc; + + switch (sym->st_shndx) { + case SHN_COMMON: + fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n", + symname, mod->name); + break; + case SHN_ABS: + /* CRC'd symbol */ + if (memcmp(symname, "__crc_", 6) == 0) { + crc = (unsigned int) sym->st_value; + add_exported_symbol(symname+6, mod, &crc); + modversions = 1; + } + break; + case SHN_UNDEF: + /* undefined symbol */ + if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) + break; + + s = alloc_symbol(symname); + /* add to list */ + s->next = mod->unres; + mod->unres = s; + break; + default: + /* All exported symbols */ + if (memcmp(symname, "__ksymtab_", 10) == 0) { + add_exported_symbol(symname+10, mod, NULL); + } + break; + } +} + +void +read_symbols(char *modname) +{ + const char *symname; + struct module *mod; + struct elf_info info = { }; + struct symbol *s; + Elf_Sym *sym; + + /* When there's no vmlinux, don't print warnings about + * unresolved symbols (since there'll be too many ;) */ + if (strcmp(modname, "vmlinux") == 0) + have_vmlinux = 1; + + parse_elf(&info, modname); + + mod = new_module(modname); + + for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { + symname = info.strtab + sym->st_name; + + handle_modversions(mod, &info, sym, symname); + handle_moddevtable(mod, &info, sym, symname); + } + parse_elf_finish(&info); + + /* Our trick to get versioning for struct_module - it's + * never passed as an argument to an exported function, so + * the automatic versioning doesn't pick it up, but it's really + * important anyhow */ + if (modversions) { + s = alloc_symbol("struct_module"); + /* add to list */ + s->next = mod->unres; + mod->unres = s; + } +} + +#define SZ 500 + +/* We first write the generated file into memory using the + * following helper, then compare to the file on disk and + * only update the later if anything changed */ + +void __attribute__((format(printf, 2, 3))) +buf_printf(struct buffer *buf, const char *fmt, ...) +{ + char tmp[SZ]; + int len; + va_list ap; + + va_start(ap, fmt); + len = vsnprintf(tmp, SZ, fmt, ap); + if (buf->size - buf->pos < len + 1) { + buf->size += 128; + buf->p = realloc(buf->p, buf->size); + } + strncpy(buf->p + buf->pos, tmp, len + 1); + buf->pos += len; + va_end(ap); +} + +void +buf_write(struct buffer *buf, const char *s, int len) +{ + if (buf->size - buf->pos < len) { + buf->size += len; + buf->p = realloc(buf->p, buf->size); + } + strncpy(buf->p + buf->pos, s, len); + buf->pos += len; +} + +/* Header for the generated file */ + +void +add_header(struct buffer *b) +{ + buf_printf(b, "#include \n"); + buf_printf(b, "#include \n"); + buf_printf(b, "\n"); + buf_printf(b, "const char vermagic[]\n"); + buf_printf(b, "__attribute__((section(\"__vermagic\"))) =\n"); + buf_printf(b, "VERMAGIC_STRING;\n"); +} + +/* Record CRCs for unresolved symbols */ + +void +add_versions(struct buffer *b, struct module *mod) +{ + struct symbol *s, *exp; + + for (s = mod->unres; s; s = s->next) { + exp = find_symbol(s->name); + if (!exp || exp->module == mod) { + if (have_vmlinux) + fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " + "undefined!\n", s->name, mod->name); + continue; + } + s->module = exp->module; + s->crc_valid = exp->crc_valid; + s->crc = exp->crc; + } + + if (!modversions) + return; + + buf_printf(b, "\n"); + buf_printf(b, "static const struct modversion_info ____versions[]\n"); + buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n"); + + for (s = mod->unres; s; s = s->next) { + if (!s->module) { + continue; + } + if (!s->crc_valid) { + fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " + "has no CRC!\n", + s->name, mod->name); + continue; + } + buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name); + } + + buf_printf(b, "};\n"); +} + +void +add_depends(struct buffer *b, struct module *mod, struct module *modules) +{ + struct symbol *s; + struct module *m; + int first = 1; + + for (m = modules; m; m = m->next) { + if (strcmp(m->name, "vmlinux") == 0) + m->seen = 1; + else + m->seen = 0; + } + + buf_printf(b, "\n"); + buf_printf(b, "static const char __module_depends[]\n"); + buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); + buf_printf(b, "\"depends="); + for (s = mod->unres; s; s = s->next) { + if (!s->module) + continue; + + if (s->module->seen) + continue; + + s->module->seen = 1; + buf_printf(b, "%s%s", first ? "" : ",", + strrchr(s->module->name, '/') + 1); + first = 0; + } + buf_printf(b, "\";\n"); +} + +void +write_if_changed(struct buffer *b, const char *fname) +{ + char *tmp; + FILE *file; + struct stat st; + + file = fopen(fname, "r"); + if (!file) + goto write; + + if (fstat(fileno(file), &st) < 0) + goto close_write; + + if (st.st_size != b->pos) + goto close_write; + + tmp = NOFAIL(malloc(b->pos)); + if (fread(tmp, 1, b->pos, file) != b->pos) + goto free_write; + + if (memcmp(tmp, b->p, b->pos) != 0) + goto free_write; + + free(tmp); + fclose(file); + return; + + free_write: + free(tmp); + close_write: + fclose(file); + write: + file = fopen(fname, "w"); + if (!file) { + perror(fname); + exit(1); + } + if (fwrite(b->p, 1, b->pos, file) != b->pos) { + perror(fname); + exit(1); + } + fclose(file); +} + +int +main(int argc, char **argv) +{ + struct module *mod; + struct buffer buf = { }; + char fname[SZ]; + + for (; argv[1]; argv++) { + read_symbols(argv[1]); + } + + for (mod = modules; mod; mod = mod->next) { + if (strcmp(mod->name, "vmlinux") == 0) + continue; + + buf.pos = 0; + + add_header(&buf); + add_versions(&buf, mod); + add_depends(&buf, mod, modules); + add_moddevtable(&buf, mod); + + sprintf(fname, "%s.mod.c", mod->name); + write_if_changed(&buf, fname); + } + return 0; +} + diff -Nru a/scripts/modpost.h b/scripts/modpost.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/modpost.h Mon Feb 17 14:57:28 2003 @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elfconfig.h" + +#if KERNEL_ELFCLASS == ELFCLASS32 + +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define ELF_ST_BIND ELF32_ST_BIND + +#else + +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define ELF_ST_BIND ELF64_ST_BIND + +#endif + +#if KERNEL_ELFDATA != HOST_ELFDATA + +static void __endian(const void *src, void *dest, unsigned int size) +{ + unsigned int i; + for (i = 0; i < size; i++) + ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; +} + + + +#define TO_NATIVE(x) \ +({ \ + typeof(x) __x; \ + __endian(&(x), &(__x), sizeof(__x)); \ + __x; \ +}) + +#else /* endianness matches */ + +#define TO_NATIVE(x) (x) + +#endif + +struct buffer { + char *p; + int pos; + int size; +}; + +void __attribute__((format(printf, 2, 3))) +buf_printf(struct buffer *buf, const char *fmt, ...); + +void +buf_write(struct buffer *buf, const char *s, int len); + +struct module { + struct module *next; + const char *name; + struct symbol *unres; + int seen; + struct buffer dev_table_buf; +}; + +struct elf_info { + unsigned long size; + Elf_Ehdr *hdr; + Elf_Shdr *sechdrs; + Elf_Sym *symtab_start; + Elf_Sym *symtab_stop; + const char *strtab; +}; + +void handle_moddevtable(struct module *mod, struct elf_info *info, + Elf_Sym *sym, const char *symname); + +void add_moddevtable(struct buffer *buf, struct module *mod); diff -Nru a/security/capability.c b/security/capability.c --- a/security/capability.c Mon Feb 17 14:57:27 2003 +++ b/security/capability.c Mon Feb 17 14:57:27 2003 @@ -18,6 +18,7 @@ #include #include #include +#include int cap_capable (struct task_struct *tsk, int cap) { diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c --- a/sound/arm/sa11xx-uda1341.c Mon Feb 17 14:57:26 2003 +++ b/sound/arm/sa11xx-uda1341.c Mon Feb 17 14:57:26 2003 @@ -7,7 +7,7 @@ * * History: * - * 2002-03-13 Tomas Kasparek Initial release - based on h3600-uda1341.c from OSS + * 2002-03-13 Tomas Kasparek initial release - based on h3600-uda1341.c from OSS * 2002-03-20 Tomas Kasparek playback over ALSA is working * 2002-03-28 Tomas Kasparek playback over OSS emulation is working * 2002-03-29 Tomas Kasparek basic capture is working (native ALSA) @@ -15,7 +15,7 @@ * 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates) */ -/* $Id: sa11xx-uda1341.c,v 1.6 2002/12/04 18:52:05 perex Exp $ */ +/* $Id: sa11xx-uda1341.c,v 1.7 2003/02/13 19:19:18 perex Exp $ */ #include #include @@ -444,7 +444,7 @@ DEBUG(KERN_DEBUG "----> period done <----\n"); #ifdef DEBUG_MODE printk(KERN_DEBUG " dma_area:"); - buf = s->stream->runtime->dma_addr + + buf = (char *)s->stream->runtime->dma_addr + ((s->sent_periods - 1 ) * (s->stream->runtime->period_size << SHIFT_16_STEREO)); for (i=0; i < 32; i++) { diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c --- a/sound/core/hwdep.c Mon Feb 17 14:57:26 2003 +++ b/sound/core/hwdep.c Mon Feb 17 14:57:26 2003 @@ -334,7 +334,7 @@ if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device, &snd_hwdep_reg, name)) < 0) { - snd_printk(KERN_ERR "unable to register hardware dependant device %i:%i\n", + snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", hwdep->card->number, hwdep->device); snd_hwdep_devices[idx] = NULL; up(®ister_mutex); diff -Nru a/sound/core/isadma.c b/sound/core/isadma.c --- a/sound/core/isadma.c Mon Feb 17 14:57:28 2003 +++ b/sound/core/isadma.c Mon Feb 17 14:57:28 2003 @@ -96,5 +96,5 @@ if (result > size) snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); #endif - return result >= size ? 0 : result; + return result >= size ? 0 : size - result; } diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c --- a/sound/core/oss/pcm_oss.c Mon Feb 17 14:57:28 2003 +++ b/sound/core/oss/pcm_oss.c Mon Feb 17 14:57:28 2003 @@ -256,7 +256,7 @@ { snd_interval_t *it; snd_pcm_hw_params_t *save; - unsigned int rate; + unsigned int rate, prev; save = kmalloc(sizeof(*save), GFP_KERNEL); if (save == NULL) @@ -280,7 +280,10 @@ } *params = *save; } + prev = rate; rate += best_rate; + if (rate <= prev) + break; } /* not found, use the nearest rate */ diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c --- a/sound/core/pcm_lib.c Mon Feb 17 14:57:27 2003 +++ b/sound/core/pcm_lib.c Mon Feb 17 14:57:27 2003 @@ -30,35 +30,67 @@ #include #include -void snd_pcm_playback_silence(snd_pcm_substream_t *substream) +/* + * fill ring buffer with silence + * runtime->silenced_start: starting pointer to silence area + * runtime->silenced_size: size filled with silence + * runtime->silence_threshold: threshold from application + * runtime->silence_size: maximal size from application + * + * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately + */ +void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_uframes_t frames, ofs, transfer; - snd_pcm_sframes_t noise_dist; - if (runtime->silenced_start != runtime->control->appl_ptr) { - snd_pcm_sframes_t n = runtime->control->appl_ptr - runtime->silenced_start; - if (n < 0) - n += runtime->boundary; - if ((snd_pcm_uframes_t)n < runtime->silenced_size) - runtime->silenced_size -= n; - else + + if (runtime->silence_size < runtime->boundary) { + snd_pcm_sframes_t noise_dist, n; + if (runtime->silenced_start != runtime->control->appl_ptr) { + n = runtime->control->appl_ptr - runtime->silenced_start; + if (n < 0) + n += runtime->boundary; + if ((snd_pcm_uframes_t)n < runtime->silenced_size) + runtime->silenced_size -= n; + else + runtime->silenced_size = 0; + runtime->silenced_start = runtime->control->appl_ptr; + } + if (runtime->silenced_size == runtime->buffer_size) + return; + snd_assert(runtime->silenced_size <= runtime->buffer_size, return); + noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size; + if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold) + return; + frames = runtime->silence_threshold - noise_dist; + if (frames > runtime->silence_size) + frames = runtime->silence_size; + } else { + if (new_hw_ptr == ULONG_MAX) { /* initialization */ runtime->silenced_size = 0; - runtime->silenced_start = runtime->control->appl_ptr; + runtime->silenced_start = runtime->control->appl_ptr; + } else { + ofs = runtime->status->hw_ptr; + frames = new_hw_ptr - ofs; + if ((snd_pcm_sframes_t)frames < 0) + frames += runtime->boundary; + runtime->silenced_size -= frames; + if ((snd_pcm_sframes_t)runtime->silenced_size < 0) { + runtime->silenced_size = 0; + runtime->silenced_start = (ofs + frames) - runtime->buffer_size; + } else { + runtime->silenced_start = ofs - runtime->silenced_size; + } + if ((snd_pcm_sframes_t)runtime->silenced_start < 0) + runtime->silenced_start += runtime->boundary; + } + frames = runtime->buffer_size; } - if (runtime->silenced_size == runtime->buffer_size) + snd_assert(frames >= runtime->silenced_size, return); + frames -= runtime->silenced_size; + if (frames == 0) return; - snd_assert(runtime->silenced_size <= runtime->buffer_size, return); - noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size; - if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold) - return; - frames = runtime->silence_threshold - noise_dist; - if (frames < runtime->silence_size) - frames = runtime->silence_size; - if (runtime->silenced_size + frames > runtime->buffer_size) - frames = runtime->buffer_size - runtime->silenced_size; - ofs = runtime->silenced_start % runtime->buffer_size + runtime->silenced_size; - if (ofs >= runtime->buffer_size) - ofs -= runtime->buffer_size; + ofs = (runtime->silenced_start + runtime->silenced_size) % runtime->buffer_size; while (frames > 0) { transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || @@ -88,9 +120,10 @@ } } } + runtime->silenced_size += transfer; frames -= transfer; + ofs = 0; } - runtime->silenced_size += frames; } int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream) @@ -128,16 +161,13 @@ runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; } - runtime->status->hw_ptr = new_hw_ptr; - runtime->hw_ptr_interrupt = new_hw_ptr - (runtime->hw_ptr_base + pos) % runtime->period_size; -#if 0 - if (hw_ptr_interrupt == runtime->boundary) - hw_ptr_interrupt = 0; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + runtime->silence_size > 0) + snd_pcm_playback_silence(substream, new_hw_ptr); - if (runtime->hw_ptr_interrupt != hw_ptr_interrupt) - snd_printd("Lost interrupt: hw_ptr = %d expected %d\n", runtime->hw_ptr_interrupt, hw_ptr_interrupt); -#endif + runtime->status->hw_ptr = new_hw_ptr; + runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) avail = snd_pcm_playback_avail(runtime); @@ -153,9 +183,6 @@ } if (avail >= runtime->control->avail_min) wake_up(&runtime->sleep); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream); return 0; } @@ -167,6 +194,7 @@ snd_pcm_uframes_t old_hw_ptr, new_hw_ptr; snd_pcm_uframes_t avail; snd_pcm_sframes_t delta; + old_hw_ptr = runtime->status->hw_ptr; pos = substream->ops->pointer(substream); if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) @@ -192,6 +220,9 @@ runtime->hw_ptr_base = 0; new_hw_ptr = runtime->hw_ptr_base + pos; } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + runtime->silence_size > 0) + snd_pcm_playback_silence(substream, new_hw_ptr); runtime->status->hw_ptr = new_hw_ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -208,9 +239,6 @@ } if (avail >= runtime->control->avail_min) wake_up(&runtime->sleep); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream); return 0; } @@ -1901,7 +1929,9 @@ u_int64_t n; u_int32_t r; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (runtime->silence_size > 0 && + if (runtime->silence_size >= runtime->boundary) { + frames = 1; + } else if (runtime->silence_size > 0 && runtime->silenced_size < runtime->buffer_size) { snd_pcm_sframes_t noise_dist; noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size; diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c --- a/sound/core/pcm_memory.c Mon Feb 17 14:57:27 2003 +++ b/sound/core/pcm_memory.c Mon Feb 17 14:57:27 2003 @@ -47,35 +47,34 @@ * allocate pages on the specified bus */ static int alloc_pcm_pages(snd_pcm_substream_t *substream, size_t size, - void **dma_area, dma_addr_t *dma_addr) + struct snd_pcm_dma_buffer *dmab) { switch (substream->dma_type) { case SNDRV_PCM_DMA_TYPE_CONTINUOUS: - *dma_area = snd_malloc_pages(size, (unsigned int)((unsigned long)substream->dma_private & 0xffffffff)); - *dma_addr = 0UL; /* not valid */ + dmab->area = snd_malloc_pages(size, (unsigned int)((unsigned long)substream->dma_private & 0xffffffff)); + dmab->addr = 0UL; /* not valid */ break; #ifdef CONFIG_ISA case SNDRV_PCM_DMA_TYPE_ISA: - *dma_area = snd_malloc_isa_pages(size, dma_addr); + dmab->area = snd_malloc_isa_pages(size, &dmab->addr); break; #endif #ifdef CONFIG_PCI case SNDRV_PCM_DMA_TYPE_PCI: - *dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, dma_addr); + dmab->area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dmab->addr); break; case SNDRV_PCM_DMA_TYPE_PCI_SG: - *dma_area = snd_pcm_sgbuf_alloc_pages((struct snd_sg_buf *)substream->dma_private, size); - *dma_addr = 0; + snd_pcm_sgbuf_alloc_pages((struct pci_dev *)substream->dma_private, size, dmab); break; #endif #ifdef CONFIG_SBUS case SNDRV_PCM_DMA_TYPE_SBUS: - *dma_area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, dma_addr); + dmab->area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, &dmab->addr); break; #endif default: - *dma_area = NULL; - *dma_addr = 0; + dmab->area = NULL; + dmab->addr = 0; return -ENXIO; } return 0; @@ -87,55 +86,53 @@ * * the minimum size is snd_minimum_buffer. it should be power of 2. */ -static void *alloc_pcm_pages_fallback(snd_pcm_substream_t *substream, - size_t size, dma_addr_t *addrp, - size_t *res_size) +static int alloc_pcm_pages_fallback(snd_pcm_substream_t *substream, + size_t size, + struct snd_pcm_dma_buffer *dmab) { - void *res; - - snd_assert(size > 0, return NULL); - snd_assert(res_size != NULL, return NULL); + int err; + snd_assert(size > 0, return -EINVAL); do { - if (alloc_pcm_pages(substream, size, &res, addrp) < 0) - return NULL; - if (res) { - *res_size = size; - return res; + if ((err = alloc_pcm_pages(substream, size, dmab)) < 0) + return err; + if (dmab->area) { + dmab->bytes = size; + return 0; } size >>= 1; } while (size >= snd_minimum_buffer); - *res_size = 0; /* tell error */ - return NULL; + dmab->bytes = 0; /* tell error */ + return 0; } /* * release the pages on the specified bus */ -static void free_pcm_pages(snd_pcm_substream_t *substream, size_t size, - void *dma_area, dma_addr_t dma_addr) +static void free_pcm_pages(snd_pcm_substream_t *substream, + struct snd_pcm_dma_buffer *dmab) { switch (substream->dma_type) { case SNDRV_PCM_DMA_TYPE_CONTINUOUS: - snd_free_pages(dma_area, size); + snd_free_pages(dmab->area, dmab->bytes); break; #ifdef CONFIG_ISA case SNDRV_PCM_DMA_TYPE_ISA: - snd_free_isa_pages(size, dma_area, dma_addr); + snd_free_isa_pages(dmab->bytes, dmab->area, dmab->addr); break; #endif #ifdef CONFIG_PCI case SNDRV_PCM_DMA_TYPE_PCI: snd_free_pci_pages((struct pci_dev *)substream->dma_private, - size, dma_area, dma_addr); + dmab->bytes, dmab->area, dmab->addr); break; case SNDRV_PCM_DMA_TYPE_PCI_SG: - snd_pcm_sgbuf_free_pages((struct snd_sg_buf *)substream->dma_private, dma_area); + snd_pcm_sgbuf_free_pages(dmab); break; #endif #ifdef CONFIG_SBUS case SNDRV_PCM_DMA_TYPE_SBUS: snd_free_sbus_pages((struct sbus_dev *)substream->dma_private, - size, dma_area, dma_addr); + dmab->bytes, dmab->area, dmab->addr); break; #endif } @@ -146,11 +143,10 @@ */ static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream) { - if (substream->dma_area == NULL) + if (substream->dma_buffer.area == NULL) return; - free_pcm_pages(substream, substream->dma_bytes, - substream->dma_area, substream->dma_addr); - substream->dma_area = NULL; + free_pcm_pages(substream, &substream->dma_buffer); + substream->dma_buffer.area = NULL; } /** @@ -168,10 +164,6 @@ snd_info_unregister(substream->proc_prealloc_entry); substream->proc_prealloc_entry = NULL; } -#ifdef CONFIG_PCI - if (substream->dma_type == SNDRV_PCM_DMA_TYPE_PCI_SG) - snd_pcm_sgbuf_delete((struct snd_sg_buf *)substream->dma_private); -#endif substream->dma_type = SNDRV_PCM_DMA_TYPE_UNKNOWN; return 0; } @@ -204,7 +196,7 @@ snd_info_buffer_t *buffer) { snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data; - snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_bytes / 1024); + snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024); } /* @@ -218,8 +210,7 @@ snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data; char line[64], str[64]; size_t size; - void *dma_area; - dma_addr_t dma_addr; + struct snd_pcm_dma_buffer new_dmab; if (substream->runtime) { buffer->error = -EBUSY; @@ -232,26 +223,22 @@ buffer->error = -EINVAL; return; } - if (substream->dma_bytes == size) + if (substream->dma_buffer.bytes == size) return; + memset(&new_dmab, 0, sizeof(new_dmab)); if (size > 0) { - if (alloc_pcm_pages(substream, size, &dma_area, &dma_addr) < 0) { - dma_area = NULL; - dma_addr = 0UL; - } - if (dma_area == NULL) { + + if (alloc_pcm_pages(substream, size, &new_dmab) < 0 || + new_dmab.area == NULL) { buffer->error = -ENOMEM; return; } substream->buffer_bytes_max = size; } else { - dma_area = NULL; substream->buffer_bytes_max = UINT_MAX; } snd_pcm_lib_preallocate_dma_free(substream); - substream->dma_area = dma_area; - substream->dma_addr = dma_addr; - substream->dma_bytes = size; + substream->dma_buffer = new_dmab; } else { buffer->error = -EINVAL; } @@ -263,18 +250,14 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream, size_t size, size_t max) { - size_t rsize = 0; - void *dma_area = NULL; - dma_addr_t dma_addr = 0UL; snd_info_entry_t *entry; + memset(&substream->dma_buffer, 0, sizeof(substream->dma_buffer)); if (size > 0 && preallocate_dma && substream->number < maximum_substreams) - dma_area = alloc_pcm_pages_fallback(substream, size, &dma_addr, &rsize); - substream->dma_area = dma_area; - substream->dma_addr = dma_addr; - substream->dma_bytes = rsize; - if (rsize > 0) - substream->buffer_bytes_max = rsize; + alloc_pcm_pages_fallback(substream, size, &substream->dma_buffer); + + if (substream->dma_buffer.bytes > 0) + substream->buffer_bytes_max = substream->dma_buffer.bytes; substream->dma_max = max; if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { entry->c.text.read_size = 64; @@ -396,31 +379,32 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size) { snd_pcm_runtime_t *runtime; - void *dma_area = NULL; - dma_addr_t dma_addr = 0UL; + struct snd_pcm_dma_buffer dmab; snd_assert(substream->dma_type != SNDRV_PCM_DMA_TYPE_UNKNOWN, return -EINVAL); snd_assert(substream != NULL, return -EINVAL); runtime = substream->runtime; snd_assert(runtime != NULL, return -EINVAL); + if (runtime->dma_area != NULL) { /* perphaps, we might free the large DMA memory region to save some space here, but the actual solution costs us less time */ if (runtime->dma_bytes >= size) return 0; /* ok, do not change */ - snd_pcm_lib_free_pages(substream); + snd_pcm_lib_free_pages(substream); } - if (substream->dma_area != NULL && substream->dma_bytes >= size) { - dma_area = substream->dma_area; - dma_addr = substream->dma_addr; + if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { + dmab = substream->dma_buffer; } else { - alloc_pcm_pages(substream, size, &dma_area, &dma_addr); + memset(&dmab, 0, sizeof(dmab)); + alloc_pcm_pages(substream, size, &dmab); } - if (! dma_area) + if (! dmab.area) return -ENOMEM; - runtime->dma_area = dma_area; - runtime->dma_addr = dma_addr; + runtime->dma_area = dmab.area; + runtime->dma_addr = dmab.addr; + runtime->dma_private = dmab.private_data; runtime->dma_bytes = size; return 1; /* area was changed */ } @@ -442,12 +426,19 @@ snd_assert(runtime != NULL, return -EINVAL); if (runtime->dma_area == NULL) return 0; - if (runtime->dma_area != substream->dma_area) - free_pcm_pages(substream, runtime->dma_bytes, - runtime->dma_area, runtime->dma_addr); + if (runtime->dma_area != substream->dma_buffer.area) { + struct snd_pcm_dma_buffer dmab; + memset(&dmab, 0, sizeof(dmab)); + dmab.area = runtime->dma_area; + dmab.addr = runtime->dma_addr; + dmab.bytes = runtime->dma_bytes; + dmab.private_data = runtime->dma_private; + free_pcm_pages(substream, &dmab); + } runtime->dma_area = NULL; runtime->dma_addr = 0UL; runtime->dma_bytes = 0; + runtime->dma_private = NULL; return 0; } @@ -553,3 +544,56 @@ } #endif /* CONFIG_SBUS */ + + +#ifdef CONFIG_PCI +/** + * snd_pcm_lib_preallocate_sg_pages - initialize SG-buffer for the PCI bus + * + * @pci: pci device + * @substream: substream to assign the buffer + * @size: the requested pre-allocation size in bytes + * @max: max. buffer size acceptable for the changes via proc file + * + * Initializes SG-buffer for the PCI bus. + * + * Returns zero if successful, or a negative error code on failure. + */ +int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, + snd_pcm_substream_t *substream, + size_t size, size_t max) +{ + substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI_SG; + substream->dma_private = pci; + return snd_pcm_lib_preallocate_pages1(substream, size, max); +} + +/* + * FIXME: the function name is too long for docbook! + * + * snd_pcm_lib_preallocate_sg_pages_for_all - initialize SG-buffer for the PCI bus (all substreams) + * @pci: pci device + * @pcm: pcm to assign the buffer + * @size: the requested pre-allocation size in bytes + * @max: max. buffer size acceptable for the changes via proc file + * + * Initialize the SG-buffer to all substreams of the given pcm for the + * PCI bus. + * + * Returns zero if successful, or a negative error code on failure. + */ +int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, + snd_pcm_t *pcm, + size_t size, size_t max) +{ + snd_pcm_substream_t *substream; + int stream, err; + + for (stream = 0; stream < 2; stream++) + for (substream = pcm->streams[stream].substream; substream; substream = substream->next) + if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream, size, max)) < 0) + return err; + return 0; +} + +#endif /* CONFIG_PCI */ diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c --- a/sound/core/pcm_native.c Mon Feb 17 14:57:27 2003 +++ b/sound/core/pcm_native.c Mon Feb 17 14:57:27 2003 @@ -458,7 +458,8 @@ if (params->xfer_align == 0 || params->xfer_align % runtime->min_align != 0) return -EINVAL; - if (params->silence_threshold + params->silence_size > runtime->buffer_size) + if ((params->silence_threshold != 0 || params->silence_size < runtime->boundary) && + (params->silence_threshold + params->silence_size > runtime->buffer_size)) return -EINVAL; spin_lock_irq(&runtime->lock); runtime->tstamp_mode = params->tstamp_mode; @@ -478,7 +479,7 @@ snd_pcm_tick_set(substream, 0); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) - snd_pcm_playback_silence(substream); + snd_pcm_playback_silence(substream, ULONG_MAX); wake_up(&runtime->sleep); } spin_unlock_irq(&runtime->lock); @@ -671,7 +672,7 @@ runtime->status->state = SNDRV_PCM_STATE_RUNNING; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) - snd_pcm_playback_silence(substream); + snd_pcm_playback_silence(substream, ULONG_MAX); if (runtime->sleep_min) snd_pcm_tick_prepare(substream); } @@ -938,9 +939,11 @@ int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, 0); if (err < 0) return err; - snd_assert(runtime->status->hw_ptr < runtime->buffer_size, ); + // snd_assert(runtime->status->hw_ptr < runtime->buffer_size, ); runtime->hw_ptr_base = 0; runtime->hw_ptr_interrupt = runtime->status->hw_ptr - runtime->status->hw_ptr % runtime->period_size; + runtime->silenced_start = runtime->status->hw_ptr; + runtime->silenced_size = 0; return 0; } @@ -948,7 +951,9 @@ { snd_pcm_runtime_t *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + runtime->silence_size > 0) + snd_pcm_playback_silence(substream, ULONG_MAX); } static int snd_pcm_reset(snd_pcm_substream_t *substream) diff -Nru a/sound/core/pcm_sgbuf.c b/sound/core/pcm_sgbuf.c --- a/sound/core/pcm_sgbuf.c Mon Feb 17 14:57:28 2003 +++ b/sound/core/pcm_sgbuf.c Mon Feb 17 14:57:28 2003 @@ -32,60 +32,32 @@ #define sgbuf_align_table(tbl) ((((tbl) + SGBUF_TBL_ALIGN - 1) / SGBUF_TBL_ALIGN) * SGBUF_TBL_ALIGN) -/* - * snd_pcm_sgbuf_new - constructor of the sgbuf instance - * @pci: pci device pointer - * - * Initializes the SG-buffer instance to be assigned to - * substream->dma_private. - * - * Returns the pointer of the instance, or NULL at error. - */ -struct snd_sg_buf *snd_pcm_sgbuf_new(struct pci_dev *pci) -{ - struct snd_sg_buf *sgbuf; - - sgbuf = snd_magic_kcalloc(snd_pcm_sgbuf_t, 0, GFP_KERNEL); - if (! sgbuf) - return NULL; - sgbuf->pci = pci; - sgbuf->pages = 0; - sgbuf->tblsize = 0; - - return sgbuf; -} - -/* - * snd_pcm_sgbuf_delete - destructor of sgbuf instance - * @sgbuf: the SG-buffer instance - * - * Destructor Releaes all pages and free the sgbuf instance. - */ -void snd_pcm_sgbuf_delete(struct snd_sg_buf *sgbuf) -{ - snd_pcm_sgbuf_free_pages(sgbuf, NULL); - snd_magic_kfree(sgbuf); -} - /** * snd_pcm_sgbuf_alloc_pages - allocate the pages for the SG buffer - * @sgbuf: the sgbuf instance + * @pci: the pci device pointer * @size: the requested buffer size in bytes + * @dmab: the dma-buffer record to store * - * Allocates the buffer pages for the given size and updates the - * sg buffer table. The pages are mapped to the virtually continuous - * memory. + * Initializes the SG-buffer table and allocates the buffer pages + * for the given size. + * The pages are mapped to the virtually continuous memory. * * This function is usually called from snd_pcm_lib_malloc_pages(). * * Returns the mapped virtual address of the buffer if allocation was * successful, or NULL at error. */ -void *snd_pcm_sgbuf_alloc_pages(struct snd_sg_buf *sgbuf, size_t size) +void *snd_pcm_sgbuf_alloc_pages(struct pci_dev *pci, size_t size, struct snd_pcm_dma_buffer *dmab) { + struct snd_sg_buf *sgbuf; unsigned int i, pages; - void *vmaddr; + dmab->area = NULL; + dmab->addr = 0; + dmab->private_data = sgbuf = snd_magic_kcalloc(snd_pcm_sgbuf_t, 0, GFP_KERNEL); + if (! sgbuf) + return NULL; + sgbuf->pci = pci; pages = snd_pcm_sgbuf_pages(size); sgbuf->tblsize = sgbuf_align_table(pages); sgbuf->table = snd_kcalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL); @@ -109,46 +81,43 @@ } sgbuf->size = size; - vmaddr = vmap(sgbuf->page_table, sgbuf->pages); - if (! vmaddr) + dmab->area = vmap(sgbuf->page_table, sgbuf->pages); + if (! dmab->area) goto _failed; - return vmaddr; + return dmab->area; _failed: - snd_pcm_sgbuf_free_pages(sgbuf, NULL); /* free the table */ + snd_pcm_sgbuf_free_pages(dmab); /* free the table */ return NULL; } /** * snd_pcm_sgbuf_free_pages - free the sg buffer - * @sgbuf: the sgbuf instance - * @vmaddr: the mapped virtual address + * @dmab: dma buffer record * - * Releases the pages and the mapped tables. + * Releases the pages and the SG-buffer table. * * This function is called usually from snd_pcm_lib_free_pages(). * * Returns zero if successful, or a negative error code on failure. */ -int snd_pcm_sgbuf_free_pages(struct snd_sg_buf *sgbuf, void *vmaddr) +int snd_pcm_sgbuf_free_pages(struct snd_pcm_dma_buffer *dmab) { - if (vmaddr) - vunmap(vmaddr); + struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, dmab->private_data, return -EINVAL); + int i; + + for (i = 0; i < sgbuf->pages; i++) + snd_free_pci_page(sgbuf->pci, sgbuf->table[i].buf, sgbuf->table[i].addr); + if (dmab->area) + vunmap(dmab->area); + dmab->area = NULL; - while (sgbuf->pages > 0) { - sgbuf->pages--; - snd_free_pci_page(sgbuf->pci, sgbuf->table[sgbuf->pages].buf, - sgbuf->table[sgbuf->pages].addr); - } if (sgbuf->table) kfree(sgbuf->table); - sgbuf->table = NULL; if (sgbuf->page_table) kfree(sgbuf->page_table); - sgbuf->page_table = NULL; - sgbuf->tblsize = 0; - sgbuf->pages = 0; - sgbuf->size = 0; + snd_magic_kfree(sgbuf); + dmab->private_data = NULL; return 0; } @@ -163,62 +132,12 @@ */ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset) { - struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return NULL); + struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, _snd_pcm_substream_sgbuf(substream), return NULL); unsigned int idx = offset >> PAGE_SHIFT; if (idx >= (unsigned int)sgbuf->pages) return NULL; return sgbuf->page_table[idx]; -} - - -/** - * snd_pcm_lib_preallocate_sg_pages - initialize SG-buffer for the PCI bus - * - * @pci: pci device - * @substream: substream to assign the buffer - * - * Initializes SG-buffer for the PCI bus. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, - snd_pcm_substream_t *substream) -{ - if ((substream->dma_private = snd_pcm_sgbuf_new(pci)) == NULL) - return -ENOMEM; - substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI_SG; - substream->dma_area = 0; - substream->dma_addr = 0; - substream->dma_bytes = 0; - substream->buffer_bytes_max = UINT_MAX; - substream->dma_max = 0; - return 0; -} - -/* - * FIXME: the function name is too long for docbook! - * - * snd_pcm_lib_preallocate_sg_pages_for_all - initialize SG-buffer for the PCI bus (all substreams) - * @pci: pci device - * @pcm: pcm to assign the buffer - * - * Initialize the SG-buffer to all substreams of the given pcm for the - * PCI bus. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, - snd_pcm_t *pcm) -{ - snd_pcm_substream_t *substream; - int stream, err; - - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream)) < 0) - return err; - return 0; } diff -Nru a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c --- a/sound/core/seq/seq_device.c Mon Feb 17 14:57:27 2003 +++ b/sound/core/seq/seq_device.c Mon Feb 17 14:57:27 2003 @@ -19,7 +19,7 @@ * *---------------------------------------------------------------- * - * This device handler seperates the card driver module from sequencer + * This device handler separates the card driver module from sequencer * stuff (sequencer core, synth drivers, etc), so that user can avoid * to spend unnecessary resources e.g. if he needs only listening to * MP3s. diff -Nru a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c --- a/sound/core/seq/seq_midi_emul.c Mon Feb 17 14:57:28 2003 +++ b/sound/core/seq/seq_midi_emul.c Mon Feb 17 14:57:28 2003 @@ -60,7 +60,7 @@ /* - * Process an event in a driver independant way. This means dealing + * Process an event in a driver independent way. This means dealing * with RPN, NRPN, SysEx etc that are defined for common midi applications * such as GM, GS and XG. * There modes that this module will run in are: @@ -258,7 +258,7 @@ } /* - * Do all driver independant operations for this controler and pass + * Do all driver independent operations for this controler and pass * events that need to take place immediately to the driver. */ static void diff -Nru a/sound/core/timer.c b/sound/core/timer.c --- a/sound/core/timer.c Mon Feb 17 14:57:27 2003 +++ b/sound/core/timer.c Mon Feb 17 14:57:27 2003 @@ -1298,7 +1298,7 @@ { snd_timer_user_t *tu; long result = 0; - int err = 0; + int err = 0; tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO); spin_lock_irq(&tu->qlock); @@ -1307,7 +1307,6 @@ wait_queue_t wait; if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { - spin_unlock_irq(&tu->qlock); err = -EAGAIN; break; } diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c --- a/sound/drivers/mtpav.c Mon Feb 17 14:57:28 2003 +++ b/sound/drivers/mtpav.c Mon Feb 17 14:57:28 2003 @@ -135,6 +135,7 @@ u8 number; u8 hwport; u8 mode; + u8 running_status; snd_rawmidi_substream_t *input; snd_rawmidi_substream_t *output; } mtpav_port_t; @@ -301,6 +302,11 @@ { u8 outbyte; + // Get the outbyte first, so we can emulate running status if + // necessary + if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1) + return; + // send port change command if necessary if (port->hwport != mtp_card->outmidihwport) { @@ -310,12 +316,18 @@ snd_mtpav_send_byte(mtp_card, port->hwport); //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport); + if (!(outbyte & 0x80) && port->running_status) + snd_mtpav_send_byte(mtp_card, port->running_status); } // send data - while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1) + do { + if (outbyte & 0x80) + port->running_status = outbyte; + snd_mtpav_send_byte(mtp_card, outbyte); + } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); } static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream) @@ -682,7 +694,7 @@ static mtpav_t *new_mtpav(void) { - mtpav_t *ncrd = (mtpav_t *) snd_kcalloc(sizeof(mtpav_t), GFP_KERNEL); + mtpav_t *ncrd = (mtpav_t *) snd_magic_kcalloc(mtpav_t, 0, GFP_KERNEL); if (ncrd != NULL) { spin_lock_init(&ncrd->spinlock); @@ -715,8 +727,7 @@ release_resource(crd->res_port); kfree_nocheck(crd->res_port); } - if (crd != NULL) - kfree(crd); + snd_magic_kfree(crd); } /* diff -Nru a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c --- a/sound/i2c/l3/uda1341.c Mon Feb 17 14:57:27 2003 +++ b/sound/i2c/l3/uda1341.c Mon Feb 17 14:57:27 2003 @@ -9,14 +9,15 @@ * * History: * - * 2002-03-13 Tomas Kasparek Initial release - based on uda1341.c from OSS + * 2002-03-13 Tomas Kasparek initial release - based on uda1341.c from OSS * 2002-03-28 Tomas Kasparek basic mixer is working (volume, bass, treble) - * 2002-03-30 Tomas Kasparek Proc filesystem support, complete mixer and DSP + * 2002-03-30 Tomas Kasparek proc filesystem support, complete mixer and DSP * features support - * 2002-04-12 Tomas Kasparek Proc interface update, code cleanup + * 2002-04-12 Tomas Kasparek proc interface update, code cleanup + * 2002-05-12 Tomas Kasparek another code cleanup */ -/* $Id: uda1341.c,v 1.6 2003/01/07 10:36:28 tiwai Exp $ */ +/* $Id: uda1341.c,v 1.7 2003/02/13 19:19:19 perex Exp $ */ #include #include @@ -25,7 +26,6 @@ #include #include #include -#include #include @@ -422,7 +422,7 @@ #define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \ .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \ - .private_value = where | reg << 5 | (shift << 9) | (mask << 12) | (invert << 18) \ + .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ } static int snd_uda1341_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) @@ -484,7 +484,7 @@ #define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \ .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \ - .private_value = where | reg << 5 | (shift << 9) | (mask << 12) | (invert << 18) \ + .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ } static int snd_uda1341_info_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c --- a/sound/isa/cs423x/cs4231_lib.c Mon Feb 17 14:57:27 2003 +++ b/sound/isa/cs423x/cs4231_lib.c Mon Feb 17 14:57:27 2003 @@ -392,26 +392,34 @@ #if 0 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); #endif - time = HZ / 4; + timeout = HZ / 4 / 2; + time = 2; while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { - if (time <= 0) { + set_current_state(TASK_INTERRUPTIBLE); + time = schedule_timeout(time); + if (time > 0) + continue; + time = 2; + if (--timeout < 0) { snd_printk("mce_down - auto calibration time out (2)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); } #if 0 printk("(3) jiffies = %li\n", jiffies); #endif - time = HZ / 10; + timeout = HZ / 10 / 2; + time = 2; while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - if (time <= 0) { + set_current_state(TASK_INTERRUPTIBLE); + time = schedule_timeout(time); + if (time > 0) + continue; + time = 2; + if (--timeout < 0) { snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); } #if 0 printk("(4) jiffies = %li\n", jiffies); @@ -575,6 +583,7 @@ snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10); + udelay(100); /* Fixes audible clicks at least on GUS MAX */ full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -1455,6 +1464,7 @@ case CS4231_HW_CS4232: return "CS4232"; case CS4231_HW_CS4232A: return "CS4232A"; case CS4231_HW_CS4235: return "CS4235"; + case CS4231_HW_CS4236: return "CS4236"; case CS4231_HW_CS4236B: return "CS4236B"; case CS4231_HW_CS4237B: return "CS4237B"; case CS4231_HW_CS4238B: return "CS4238B"; diff -Nru a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c --- a/sound/isa/cs423x/cs4236.c Mon Feb 17 14:57:26 2003 +++ b/sound/isa/cs423x/cs4236.c Mon Feb 17 14:57:26 2003 @@ -188,6 +188,8 @@ ISAPNP_CS4232('C','S','C',0x1a32,0x0000,0x0010,0x0003), /* HP Omnibook 5500 onboard */ ISAPNP_CS4232('C','S','C',0x4232,0x0000,0x0002,0x0003), + /* Unnamed CS4236 card (Made in Taiwan) */ + ISAPNP_CS4232('C','S','C',0x4236,0x0000,0x0010,0x0003), /* Turtle Beach TBS-2000 (CS4232) */ ISAPNP_CS4232('C','S','C',0x7532,0x0000,0x0010,0xb006), /* Turtle Beach Tropez Plus (CS4232) */ diff -Nru a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c --- a/sound/isa/cs423x/cs4236_lib.c Mon Feb 17 14:57:27 2003 +++ b/sound/isa/cs423x/cs4236_lib.c Mon Feb 17 14:57:27 2003 @@ -282,7 +282,9 @@ } if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0) return err; + if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) { + snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%lx\n",chip->hardware); snd_device_free(card, chip); return -ENODEV; } diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c --- a/sound/isa/gus/interwave.c Mon Feb 17 14:57:27 2003 +++ b/sound/isa/gus/interwave.c Mon Feb 17 14:57:27 2003 @@ -109,7 +109,7 @@ MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC); MODULE_PARM(joystick_dac, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver."); -MODULE_PARM_SYNTAX(snd_joystic_dac, SNDRV_ENABLED ",allows:{{0,31}}"); +MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}"); MODULE_PARM(midi, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver."); MODULE_PARM_SYNTAX(midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC); diff -Nru a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c --- a/sound/isa/sb/emu8000_pcm.c Mon Feb 17 14:57:28 2003 +++ b/sound/isa/sb/emu8000_pcm.c Mon Feb 17 14:57:28 2003 @@ -592,7 +592,7 @@ return -ENOMEM; rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */ /* at least dma_bytes must be set for non-interleaved mode */ - subs->dma_bytes = params_buffer_bytes(hw_params); + subs->dma_buffer.bytes = params_buffer_bytes(hw_params); return 0; } diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c --- a/sound/oss/trident.c Mon Feb 17 14:57:28 2003 +++ b/sound/oss/trident.c Mon Feb 17 14:57:28 2003 @@ -223,7 +223,7 @@ #define NR_HW_CH 32 -/* maxinum nuber of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only +/* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only have 2 SDATA_IN lines (currently) */ #define NR_AC97 2 diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/ac97/ac97_codec.c Mon Feb 17 14:57:27 2003 @@ -87,6 +87,7 @@ }; static const ac97_codec_id_t snd_ac97_codec_ids[] = { +{ 0x014b0502, 0xffffffff, "NM256AV", NULL }, // FIXME: which real one? { 0x414b4d00, 0xffffffff, "AK4540", NULL }, { 0x414b4d01, 0xffffffff, "AK4542", NULL }, { 0x414b4d02, 0xffffffff, "AK4543", NULL }, @@ -1252,6 +1253,10 @@ return 0; break; } + + if (ac97->limited_regs && test_bit(reg, ac97->reg_accessed)) + return 1; /* allow without check */ + val = snd_ac97_read(ac97, reg); if (!(val & mask)) { /* nothing seems to be here - mute flag is not set */ @@ -1887,7 +1892,7 @@ udelay(50); if (ac97_reset_wait(ac97, HZ/2, 0) < 0 && ac97_reset_wait(ac97, HZ/2, 1) < 0) { - snd_printk("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err); + snd_printk("AC'97 %d:%d does not respond - RESET\n", ac97->num, ac97->addr); snd_ac97_free(ac97); return -ENXIO; } @@ -2418,6 +2423,80 @@ /* + */ +static int remove_ctl(ac97_t *ac97, const char *name) +{ + snd_ctl_elem_id_t id; + memset(&id, 0, sizeof(id)); + strcpy(id.name, name); + return snd_ctl_remove_id(ac97->card, &id); +} + +static int rename_ctl(ac97_t *ac97, const char *src, const char *dst) +{ + snd_ctl_elem_id_t sid, did; + memset(&sid, 0, sizeof(sid)); + strcpy(sid.name, src); + memset(&did, 0, sizeof(did)); + strcpy(did.name, dst); + return snd_ctl_rename_id(ac97->card, &sid, &did); +} + +static int swap_headphone(ac97_t *ac97, int remove_master) +{ + /* FIXME: error checks.. */ + if (remove_master) { + remove_ctl(ac97, "Master Playback Switch"); + remove_ctl(ac97, "Master Playback Volume"); + } else { + rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch"); + rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume"); + } + rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch"); + rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume"); + return 0; +} + + +/** + * snd_ac97_tune_hardware - tune up the hardware + * @ac97: the ac97 instance + * @pci: pci device + * @quirk: quirk list + * + * Do some workaround for each pci device, such as renaming of the + * headphone (true line-out) control as "Master". + * The quirk-list must be terminated with a zero-filled entry. + * + * Returns zero if successful, or a negative error code on failure. + */ + +int snd_ac97_tune_hardware(ac97_t *ac97, struct pci_dev *pci, struct ac97_quirk *quirk) +{ + unsigned short vendor, device; + struct ac97_quirk *q; + + pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor); + pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &device); + + for (; quirk->vendor; quirk++) { + if (quirk->vendor == vendor && quirk->device == device) { + snd_printdd("ac97 quirk for %04x:%04x\n", vendor, device); + switch (quirk->type) { + case AC97_TUNE_HP_ONLY: + return swap_headphone(ac97, 1); + case AC97_TUNE_SWAP_HP: + return swap_headphone(ac97, 0); + } + snd_printk(KERN_ERR "invalid quirk type %d\n", quirk->type); + return -EINVAL; + } + } + return 0; +} + + +/* * Exported symbols */ @@ -2428,6 +2507,7 @@ EXPORT_SYMBOL(snd_ac97_update_bits); EXPORT_SYMBOL(snd_ac97_mixer); EXPORT_SYMBOL(snd_ac97_set_rate); +EXPORT_SYMBOL(snd_ac97_tune_hardware); #ifdef CONFIG_PM EXPORT_SYMBOL(snd_ac97_resume); #endif diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c --- a/sound/pci/ali5451/ali5451.c Mon Feb 17 14:57:28 2003 +++ b/sound/pci/ali5451/ali5451.c Mon Feb 17 14:57:28 2003 @@ -79,7 +79,7 @@ #endif /* - * Constants defination + * Constants definition */ #ifndef PCI_VENDOR_ID_ALI diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c --- a/sound/pci/cs46xx/cs46xx_lib.c Mon Feb 17 14:57:26 2003 +++ b/sound/pci/cs46xx/cs46xx_lib.c Mon Feb 17 14:57:26 2003 @@ -677,6 +677,7 @@ { /* cs46xx_t *chip = snd_pcm_substream_chip(substream); */ snd_pcm_runtime_t *runtime = substream->runtime; + snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; snd_pcm_sframes_t diff; cs46xx_pcm_t * cpcm; int buffer_size; @@ -685,14 +686,14 @@ buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift; - diff = runtime->control->appl_ptr - cpcm->appl_ptr; + diff = appl_ptr - cpcm->appl_ptr; if (diff) { if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) diff += runtime->boundary; - cpcm->sw_ready += diff << cpcm->shift; + frames += diff; } cpcm->sw_ready += frames << cpcm->shift; - cpcm->appl_ptr = runtime->control->appl_ptr + frames; + cpcm->appl_ptr = appl_ptr + frames; while (cpcm->hw_ready < buffer_size && cpcm->sw_ready > 0) { size_t hw_to_end = buffer_size - cpcm->hw_data; @@ -724,15 +725,16 @@ { cs46xx_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - snd_pcm_sframes_t diff = runtime->control->appl_ptr - chip->capt.appl_ptr; + snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; + snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr; int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift; if (diff) { if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) diff += runtime->boundary; - chip->capt.sw_ready -= diff << chip->capt.shift; + frames += diff; } chip->capt.sw_ready -= frames << chip->capt.shift; - chip->capt.appl_ptr = runtime->control->appl_ptr + frames; + chip->capt.appl_ptr = appl_ptr + frames; while (chip->capt.hw_ready > 0 && chip->capt.sw_ready < (int)chip->capt.sw_bufsize) { size_t hw_to_end = buffer_size - chip->capt.hw_data; diff -Nru a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c Mon Feb 17 14:57:28 2003 +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c Mon Feb 17 14:57:28 2003 @@ -1543,7 +1543,7 @@ /* dont touch anything if SPDIF is open */ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) { /* when cs46xx_iec958_post_close(...) is called it - will call this function if necesary depending on + will call this function if necessary depending on this bit */ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c --- a/sound/pci/emu10k1/emufx.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/emu10k1/emufx.c Mon Feb 17 14:57:27 2003 @@ -532,7 +532,7 @@ if (diff) { if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) diff += runtime->boundary; - pcm->sw_ready += diff; + frames += diff; } pcm->sw_ready += frames; pcm->appl_ptr = appl_ptr + frames; diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c --- a/sound/pci/emu10k1/emupcm.c Mon Feb 17 14:57:26 2003 +++ b/sound/pci/emu10k1/emupcm.c Mon Feb 17 14:57:26 2003 @@ -993,7 +993,7 @@ emu->pcm = pcm; for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_sg_pages(emu->pci, substream)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages(emu->pci, substream, 64*1024, 64*1024)) < 0) return err; for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) diff -Nru a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c --- a/sound/pci/emu10k1/memory.c Mon Feb 17 14:57:28 2003 +++ b/sound/pci/emu10k1/memory.c Mon Feb 17 14:57:28 2003 @@ -232,7 +232,7 @@ static int is_valid_page(dma_addr_t addr) { if (addr & ~0x7fffffffUL) { - snd_printk("max memory size is 2GB!!\n"); + snd_printk("max memory size is 2GB (addr = 0x%lx)!!\n", (unsigned long)addr); return 0; } if (addr & (EMUPAGESIZE-1)) { @@ -312,8 +312,18 @@ */ idx = 0; for (page = blk->first_page; page <= blk->last_page; page++, idx++) { - dma_addr_t addr = sgbuf->table[idx].addr; + dma_addr_t addr; +#ifdef CONFIG_SND_DEBUG + if (idx >= sgbuf->pages) { + printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n", + blk->first_page, blk->last_page, sgbuf->pages); + up(&hdr->block_mutex); + return NULL; + } +#endif + addr = sgbuf->table[idx].addr; if (! is_valid_page(addr)) { + printk(KERN_ERR "emu: failure page = %d\n", idx); up(&hdr->block_mutex); return NULL; } diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c --- a/sound/pci/intel8x0.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/intel8x0.c Mon Feb 17 14:57:27 2003 @@ -2011,12 +2011,12 @@ return; /* specified in module option */ subs = chip->pcm->streams[0].substream; - if (! subs || subs->dma_bytes < INTEL8X0_TESTBUF_SIZE) { + if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { snd_printk("no playback buffer allocated - aborting measure ac97 clock\n"); return; } ichdev = &chip->ichd[ICHD_PCMOUT]; - ichdev->physbuf = subs->dma_addr; + ichdev->physbuf = subs->dma_buffer.addr; ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE; ichdev->substream = NULL; /* don't process interrupts */ diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c --- a/sound/pci/maestro3.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/maestro3.c Mon Feb 17 14:57:27 2003 @@ -2542,13 +2542,9 @@ chip->pci = pci; chip->irq = -1; -#ifndef LINUX_2_2 - subsystem_vendor = pci->subsystem_vendor; - subsystem_device = pci->subsystem_device; -#else pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); -#endif + for (quirk = m3_quirk_list; quirk->vendor; quirk++) { if (subsystem_vendor == quirk->vendor && subsystem_device == quirk->device) { diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c --- a/sound/pci/nm256/nm256.c Mon Feb 17 14:57:28 2003 +++ b/sound/pci/nm256/nm256.c Mon Feb 17 14:57:28 2003 @@ -1199,7 +1199,7 @@ AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL, AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL, - AC97_EXTENDED_ID, AC97_EXTENDED_STATUS, + AC97_EXTENDED_ID, AC97_VENDOR_ID1, AC97_VENDOR_ID2, -1 }; diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c --- a/sound/pci/rme9652/hdsp.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/rme9652/hdsp.c Mon Feb 17 14:57:27 2003 @@ -2981,6 +2981,8 @@ switch (rev & 0xff) { case 0xa: + case 0xb: + case 0x64: /* hdsp_initialize_firmware() will reset this */ hdsp->card_name = "RME Hammerfall DSP"; break; diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c --- a/sound/pci/trident/trident_main.c Mon Feb 17 14:57:27 2003 +++ b/sound/pci/trident/trident_main.c Mon Feb 17 14:57:27 2003 @@ -2175,7 +2175,7 @@ trident->pcm = pcm; if (trident->tlb.entries) - snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, pcm); + snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, pcm, 64*1024, 128*1024); else snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, pcm, 64*1024, 128*1024); @@ -2230,7 +2230,7 @@ trident->foldback = foldback; if (trident->tlb.entries) - snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, foldback); + snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, foldback, 0, 128*1024); else snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, foldback, 64*1024, 128*1024); @@ -2274,7 +2274,7 @@ trident->spdif = spdif; if (trident->tlb.entries) - snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, spdif); + snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, spdif, 64*1024, 128*1024); else snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, spdif, 64*1024, 128*1024); diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c --- a/sound/pci/via82xx.c Mon Feb 17 14:57:28 2003 +++ b/sound/pci/via82xx.c Mon Feb 17 14:57:28 2003 @@ -1193,7 +1193,7 @@ /* capture */ init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); - if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0) return err; /* PCM #1: multi-channel playback and 2nd capture */ @@ -1209,7 +1209,7 @@ /* set up capture */ init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 1); - if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0) return err; return 0; @@ -1242,7 +1242,7 @@ /* capture */ init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); - if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0) return err; /* PCM #1: DXS3 playback (for spdif) */ @@ -1255,7 +1255,7 @@ /* set up playback */ init_viadev(chip, chip->playback_devno, 0x30, 0); - if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0) return err; return 0; @@ -1284,7 +1284,7 @@ init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0); init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 1); - if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0) + if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0) return err; return 0; @@ -1437,6 +1437,11 @@ chip->ac97 = NULL; } +static struct ac97_quirk ac97_quirks[] = { + { 0x1106, 0x4161, AC97_TUNE_HP_ONLY }, /* ASRock K7VT2 */ + { } /* terminator */ +}; + static int __devinit snd_via82xx_mixer_new(via82xx_t *chip) { ac97_t ac97; @@ -1452,6 +1457,8 @@ if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0) return err; + snd_ac97_tune_hardware(&chip->ac97, chip->pci, ac97_quirks); + if (chip->chip_type != TYPE_VIA686) { /* use slot 10/11 */ snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4); @@ -1862,7 +1869,7 @@ break; } } - if (chip_type == VIA_REV_8233A) + if (chip_type == TYPE_VIA8233A) strcpy(card->driver, "VIA8233A"); else strcpy(card->driver, "VIA8233"); @@ -1884,7 +1891,7 @@ (err = snd_via686_init_misc(chip, dev)) < 0) goto __error; } else { - if (chip_type == VIA_REV_8233A) { + if (chip_type == TYPE_VIA8233A) { if ((err = snd_via8233a_pcm_new(chip)) < 0) goto __error; } else { diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c --- a/sound/usb/usbaudio.c Mon Feb 17 14:57:27 2003 +++ b/sound/usb/usbaudio.c Mon Feb 17 14:57:27 2003 @@ -2236,10 +2236,49 @@ return 0; } + +/* + * boot quirks + */ + +#define EXTIGY_FIRMWARE_SIZE_OLD 794 +#define EXTIGY_FIRMWARE_SIZE_NEW 483 + +static int snd_usb_boot_quirk(struct usb_device *dev, + struct usb_interface *intf, + const snd_usb_audio_quirk_t *quirk) +{ + struct usb_host_config *config = dev->actconfig; + + /* FIXME: we need to handle composite type quirks later.. */ + switch (quirk->type) { + case QUIRK_BOOT_EXTIGY: + snd_printdd(KERN_INFO "extigy_boot: boot length = %d\n", get_cfg_desc(config)->wTotalLength); + if (get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_OLD || + get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_NEW) { + /* Send message to force it to reconnect with full interface. */ + usb_control_msg(dev, usb_sndctrlpipe(dev,0), + 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ); + usb_get_device_descriptor(dev); + usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue); + return -ENODEV; /* quit this anyway */ + } + return 0; + } + return 0; +} + + +/* + * audio-interface quirks + */ static int snd_usb_create_quirk(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk) { + if (quirk->type & QUIRK_BOOT_MASK) + return 1; /* continue as the normal device */ + switch (quirk->type) { case QUIRK_MIDI_FIXED_ENDPOINT: case QUIRK_MIDI_YAMAHA: @@ -2417,7 +2456,7 @@ { struct usb_host_config *config = dev->actconfig; const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)usb_id->driver_info; - int i; + int i, err; snd_card_t *card; snd_usb_audio_t *chip; struct usb_host_interface *alts; @@ -2434,6 +2473,12 @@ goto __err_val; } + if (quirk) { + /* try to check the boot quirk */ + if (snd_usb_boot_quirk(dev, intf, quirk) < 0) + goto __err_val; + } + /* * found a config. now register to ALSA */ @@ -2478,8 +2523,15 @@ } } - if (!quirk) { - /* USB audio interface */ + err = 1; /* continue */ + if (quirk) { + /* need some special handlings */ + if ((err = snd_usb_create_quirk(chip, intf, quirk)) < 0) + goto __error; + } + + if (err > 0) { + /* create normal USB audio interfaces */ unsigned char *buffer; unsigned int index; int buflen; @@ -2494,10 +2546,6 @@ goto __error; } kfree(buffer); - } else { - /* USB midi interface */ - if (snd_usb_create_quirk(chip, intf, quirk) < 0) - goto __error; } /* we are allowed to call snd_card_register() many times */ diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h --- a/sound/usb/usbaudio.h Mon Feb 17 14:57:27 2003 +++ b/sound/usb/usbaudio.h Mon Feb 17 14:57:27 2003 @@ -154,6 +154,9 @@ #define QUIRK_COMPOSITE 3 #define QUIRK_AUDIO_FIXED_ENDPOINT 4 +#define QUIRK_BOOT_MASK 0x80 +#define QUIRK_BOOT_EXTIGY (QUIRK_BOOT_MASK | 0) + typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h --- a/sound/usb/usbquirks.h Mon Feb 17 14:57:27 2003 +++ b/sound/usb/usbquirks.h Mon Feb 17 14:57:27 2003 @@ -691,4 +691,20 @@ } }, +/* + * Boot-up quirks + */ +/* Extigy needs to send a vendor-specific control to boot up the + * correct interface + */ +{ + USB_DEVICE(0x041e, 0x3000), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "CreativeLabs", + .product_name = "Sound Blaster Extigy", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_BOOT_EXTIGY + } +}, + #undef USB_DEVICE_VENDOR_SPEC