From a6b9977667ca069f18ad85fab1c2445a0f2f4e78 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Fri, 24 Jan 2003 02:27:06 -0600 Subject: kbuild: Add CONFIG_MODVERSIONING and __kcrctab This patch adds the new config option CONFIG_MODVERSIONING which will be the new way of checking for ABI changes between kernel and module code. This and the following patches are in part based on an initial implementation by Rusty Russell and I believe some of the ideas go back to discussions on linux-kbuild, Keith Owens and Rusty. though I'm not sure I think credit for the basic idea of storing version info in sections goes to Keith Owens and Rusty. o Rename __gpl_ksymtab to __ksymtab_gpl since that looks more consistent and appending _gpl instead of putting it into the middle simplifies sharing code for EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() o Add CONFIG_MODVERSIONING o If CONFIG_MODVERSIONING is set, add a section __kcrctab{,_gpl}, which contains the ABI checksums for the exported symbols listed in __ksymtab{,_crc} Since we don't know the checksums yet at compilation time, just make them an unresolved symbol which gets filled in by the linker later. --- include/linux/module.h | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index 6dad1479105f..d017a67210c6 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -134,29 +134,40 @@ struct exception_table #ifdef CONFIG_MODULES + /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get(const char *symbol); void *__symbol_get_gpl(const char *symbol); #define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x))) +#ifdef CONFIG_MODVERSIONING +/* Mark the CRC weak since genksyms apparently decides not to + * generate a checksums for some symbols */ +#define __CRC_SYMBOL(sym, sec) \ + extern void *__crc_##sym __attribute__((weak)); \ + static const unsigned long __kcrctab_##sym \ + __attribute__((section("__kcrctab" sec))) \ + = (unsigned long) &__crc_##sym; +#else +#define __CRC_SYMBOL(sym, sec) +#endif + /* For every exported symbol, place a struct in the __ksymtab section */ -#define EXPORT_SYMBOL(sym) \ +#define __EXPORT_SYMBOL(sym, sec) \ + __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"))) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __ksymtab_##sym \ - __attribute__((section("__ksymtab"))) \ + __attribute__((section("__ksymtab" sec))) \ = { (unsigned long)&sym, __kstrtab_##sym } -#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") +#define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") -#define EXPORT_SYMBOL_GPL(sym) \ - static const char __kstrtab_##sym[] \ - __attribute__((section("__ksymtab_strings"))) \ - = MODULE_SYMBOL_PREFIX #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ - __attribute__((section("__gpl_ksymtab"))) \ - = { (unsigned long)&sym, __kstrtab_##sym } +/* We don't mangle the actual symbol anymore, so no need for + * special casing EXPORT_SYMBOL_NOVERS */ +#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym) struct module_ref { -- cgit v1.2.3 From 09369f635011eb6d520925f375f364f4273163e1 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Fri, 24 Jan 2003 09:45:27 -0600 Subject: kbuild: Generate versions for exported symbols Up to now, we had a way to store the checksums associated with the exported symbols, but they were not filled in yet. This is done with this patch, using the linker to actually do that for us. The comment added with this patch explains what magic exactly is going on. --- include/linux/module.h | 16 +++++++++++++-- scripts/Makefile.build | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index d017a67210c6..7475c1791529 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -140,6 +140,13 @@ void *__symbol_get(const char *symbol); void *__symbol_get_gpl(const char *symbol); #define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x))) +#ifdef __GENKSYMS__ + +/* genksyms doesn't handle GPL-only symbols yet */ +#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL + +#else + #ifdef CONFIG_MODVERSIONING /* Mark the CRC weak since genksyms apparently decides not to * generate a checksums for some symbols */ @@ -162,8 +169,13 @@ void *__symbol_get_gpl(const char *symbol); __attribute__((section("__ksymtab" sec))) \ = { (unsigned long)&sym, __kstrtab_##sym } -#define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") -#define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL(sym) \ + __EXPORT_SYMBOL(sym, "") + +#define EXPORT_SYMBOL_GPL(sym) \ + __EXPORT_SYMBOL(sym, "_gpl") + +#endif /* We don't mangle the actual symbol anymore, so no need for * special casing EXPORT_SYMBOL_NOVERS */ diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1fe8acad16fe..522c40663372 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -50,6 +50,55 @@ __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \ $(subdir-ym) $(build-targets) @: +# Module versioning +# --------------------------------------------------------------------------- + +ifdef CONFIG_MODVERSIONING + +# $(call if_changed_rule,vcc_o_c) does essentially the same as the +# normal $(call if_changed_dep,cc_o_c), i.e. compile an object file +# from a C file, keeping track of the command line and dependencies. +# +# However, actually it does: +# o compile a .tmp_.o from .c +# o if .tmp_.o doesn't contain a __ksymtab version, i.e. does +# not export symbols, we just rename .tmp_.o to .o and +# are done. +# o otherwise, we calculate symbol versions using the good old +# genksyms on the preprocessed source and postprocess them in a way +# that they are usable as a linker script +# o generate .o from .tmp_.o using the linker to +# replace the unresolved symbols __crc_exported_symbol with +# the actual value of the checksum generated by genksyms + +quiet_cmd_vcc_o_c = CC $(quiet_modtag) $@ +cmd_vcc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< + +define rule_vcc_o_c + $(if $($(quiet)cmd_vcc_o_c),echo ' $($(quiet)cmd_vcc_o_c)';) \ + $(cmd_vcc_o_c); \ + \ + if ! $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ + mv $(@D)/.tmp_$(@F) $@; \ + else \ + $(CPP) -D__GENKSYMS__ $(c_flags) $< \ + | $(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) \ + | grep __ver \ + | sed 's/\#define __ver_\([^ ]*\)[ ]*\([^ ]*\)/__crc_\1 = 0x\2 ;/g' \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + fi; + \ + scripts/fixdep $(depfile) $@ '$(cmd_vcc_o_c)' > $(@D)/.$(@F).tmp; \ + rm -f $(depfile); \ + mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd +endef + +endif + # Compile C sources (.c) # --------------------------------------------------------------------------- @@ -97,7 +146,11 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< %.o: %.c FORCE +ifdef CONFIG_MODVERSIONING + $(call if_changed_rule,vcc_o_c) +else $(call if_changed_dep,cc_o_c) +endif quiet_cmd_cc_lst_c = MKLST $@ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ -- cgit v1.2.3 From 1336f151165fd8a2da10a5d8e1a633e3b72e3fd7 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Fri, 24 Jan 2003 09:49:33 -0600 Subject: kbuild/modules: Track versions of exported symbols Store the information on the checksum alongside the rest of the information on exported symbols. To actually use them, we need something to check them against first, though ;) Also, fix some conditional debug code to actually compile. --- include/linux/module.h | 1 + kernel/module.c | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index 7475c1791529..af4272910b27 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -119,6 +119,7 @@ struct kernel_symbol_group unsigned int num_syms; const struct kernel_symbol *syms; + const unsigned long *crcs; }; /* Given an address, look for it in the exception tables */ diff --git a/kernel/module.c b/kernel/module.c index f54e6ada3d26..c9dc1996d136 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -916,7 +916,7 @@ static void layout_sections(struct module *mod, || strstr(secstrings + s->sh_name, ".init")) continue; s->sh_entsize = get_offset(&mod->core_size, s); - DEBUGP("\t%s\n", name); + DEBUGP("\t%s\n", secstrings + s->sh_name); } } @@ -932,7 +932,7 @@ static void layout_sections(struct module *mod, continue; s->sh_entsize = (get_offset(&mod->init_size, s) | INIT_OFFSET_MASK); - DEBUGP("\t%s\n", name); + DEBUGP("\t%s\n", secstrings + s->sh_name); } } } @@ -976,7 +976,8 @@ static struct module *load_module(void *umod, Elf_Shdr *sechdrs; char *secstrings, *args; unsigned int i, symindex, exportindex, strindex, setupindex, exindex, - modindex, obsparmindex, licenseindex, gplindex, vmagindex; + modindex, obsparmindex, licenseindex, gplindex, vmagindex, + crcindex, gplcrcindex; long arglen; struct module *mod; long err = 0; @@ -1012,7 +1013,8 @@ static struct module *load_module(void *umod, /* May not export symbols, or have setup params, so these may not exist */ - exportindex = setupindex = obsparmindex = gplindex = licenseindex = 0; + exportindex = setupindex = obsparmindex = gplindex = licenseindex + = crcindex = gplcrcindex = 0; /* And these should exist, but gcc whinges if we don't init them */ symindex = strindex = exindex = modindex = vmagindex = 0; @@ -1045,6 +1047,16 @@ static struct module *load_module(void *umod, /* Exported symbols. (GPL) */ DEBUGP("GPL symbols found in section %u\n", i); gplindex = i; + } else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab") + == 0) { + /* Exported symbols CRCs. */ + DEBUGP("CRC table in section %u\n", i); + crcindex = i; + } else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab_gpl") + == 0) { + /* Exported symbols CRCs. (GPL)*/ + DEBUGP("CRC table in section %u\n", i); + gplcrcindex = i; } else if (strcmp(secstrings+sechdrs[i].sh_name, "__param") == 0) { /* Setup parameter info */ @@ -1192,9 +1204,11 @@ static struct module *load_module(void *umod, mod->symbols.num_syms = (sechdrs[exportindex].sh_size / sizeof(*mod->symbols.syms)); mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr; + mod->symbols.crcs = (void *)sechdrs[crcindex].sh_addr; mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size / sizeof(*mod->symbols.syms)); mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr; + mod->gpl_symbols.crcs = (void *)sechdrs[gplcrcindex].sh_addr; /* Set up exception table */ if (exindex) { @@ -1497,6 +1511,10 @@ extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[]; extern const struct kernel_symbol __start___ksymtab_gpl[]; extern const struct kernel_symbol __stop___ksymtab_gpl[]; +extern const unsigned long __start___kcrctab[]; +extern const unsigned long __stop___kcrctab[]; +extern const unsigned long __start___kcrctab_gpl[]; +extern const unsigned long __stop___kcrctab_gpl[]; static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols; @@ -1505,12 +1523,14 @@ static int __init symbols_init(void) /* Add kernel symbols to symbol table */ kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); kernel_symbols.syms = __start___ksymtab; + kernel_symbols.crcs = __start___kcrctab; kernel_symbols.gplonly = 0; list_add(&kernel_symbols.list, &symbols); kernel_gpl_symbols.num_syms = (__stop___ksymtab_gpl - __start___ksymtab_gpl); kernel_gpl_symbols.syms = __start___ksymtab_gpl; + kernel_gpl_symbols.crcs = __start___kcrctab_gpl; kernel_gpl_symbols.gplonly = 1; list_add(&kernel_gpl_symbols.list, &symbols); -- cgit v1.2.3 From dcc38eae49e06d798497373771ae03f5508a2ec7 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Fri, 24 Jan 2003 09:54:04 -0600 Subject: kbuild/modules: Record versions for unresolved symbols In the case of CONFIG_MODVERSIONING, the build step will only generate preliminary .o objects, and an additional postprocessing step is necessary to record the versions of the unresolved symbols and add them into the final .ko The version information for unresolved symbols is again recorded into a special section, "__versions", which contains an array of symbol name strings and checksum (struct modversion_info). Size is here not an issue, since this section will not be stored permanently in kernel memory. Makefile.modver takes care of the following steps: o Collect the version information for all exported symbols from vmlinux and all modules which export symbols. o For each module, generate a C file which contains the modversion information for all unresolved symbols in that module. o For each module, compile that C file to an object file o Finally, link the .ko using the preliminary + the version information above. The first two steps are currently done by not very efficient scripting, so there's room for performance improvement using some helper C code. --- Makefile | 15 +++++++-- include/linux/module.h | 7 ++++ scripts/Makefile.modver | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/Makefile b/Makefile index 308673b8b2e5..3387d56da0b0 100644 --- a/Makefile +++ b/Makefile @@ -262,7 +262,7 @@ endif # When we're building modules with modversions, we need to consider # the built-in objects during the descend as well, in order to -# make sure the checksums are uptodate before we use them. +# make sure the checksums are uptodate before we record them. ifdef CONFIG_MODVERSIONING ifeq ($(KBUILD_MODULES),1) @@ -508,8 +508,16 @@ ifdef CONFIG_MODULES # Build modules -.PHONY: modules -modules: $(SUBDIRS) +.PHONY: modules __modversions +modules: $(SUBDIRS) __modversions + +ifdef CONFIG_MODVERSIONING + +__modversions: vmlinux $(SUBDIRS) + @echo ' Recording module symbol versions.'; + $(Q)$(MAKE) -rR -f scripts/Makefile.modver + +endif # Install modules @@ -690,6 +698,7 @@ MRPROPER_FILES += \ # Directories removed with 'make mrproper' MRPROPER_DIRS += \ + $(MODVERDIR) \ .tmp_export-objs \ include/config \ include/linux/modules diff --git a/include/linux/module.h b/include/linux/module.h index af4272910b27..e8726d9909d7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -33,12 +33,19 @@ #endif #define MODULE_NAME_LEN (64 - sizeof(unsigned long)) + struct kernel_symbol { unsigned long value; const char *name; }; +struct modversion_info +{ + unsigned long crc; + char name[MODULE_NAME_LEN]; +}; + /* These are either module local, or the kernel's dummy ones. */ extern int init_module(void); extern void cleanup_module(void); diff --git a/scripts/Makefile.modver b/scripts/Makefile.modver index 5405cbce2170..372d6aff5a32 100644 --- a/scripts/Makefile.modver +++ b/scripts/Makefile.modver @@ -2,3 +2,92 @@ # Module versions # =========================================================================== +.PHONY: __modversions +__modversions: + +include scripts/Makefile.lib + +# + +modules := $(patsubst ./%,%,$(shell cd $(MODVERDIR); find . -name \*.ko)) + +__modversions: $(modules) + @: + +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 $(MODVERDIR)/%.o init/vermagic.o FORCE + $(call if_changed,ld_ko_o) + +targets += $(modules) + + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(CFLAGS) -c -o $@ $< + +$(addprefix $(MODVERDIR)/,$(modules:.ko=.o)): %.o: %.c FORCE + $(call if_changed,cc_o_c) + +targets += $(addprefix $(MODVERDIR)/,$(modules:.ko=.o)) + +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 + +$(addprefix $(MODVERDIR)/,$(modules:.ko=.c)): \ +$(MODVERDIR)/%.c: %.o .tmp_all-versions FORCE + $(call if_changed_rule,mkver_o_c) + +targets += $(addprefix $(MODVERDIR)/,$(modules:.ko=.o.c)) + +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 -- cgit v1.2.3 From e9aff3178f09e5281ddc4bb1220a9acc64888421 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Sat, 25 Jan 2003 08:20:44 -0600 Subject: kbuild: gcc-3.3 warns about 2.5.59 EXPORT_SYMBOL When building linux-2.5.59 with gcc-3.3 (on s390, if that matters), I get a warning like "warning: `__ksymtab___foo' defined but not used" each time that EXPORT_SYMBOL is used. by Arnd Bergmann --- include/linux/module.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index e8726d9909d7..1be44624ec3a 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -99,7 +99,7 @@ extern const struct gtype##_id __mod_##gtype##_table \ */ #define MODULE_LICENSE(license) \ static const char __module_license[] \ - __attribute__((section(".init.license"))) = license + __attribute__((section(".init.license"), unused)) = license #else /* !MODULE */ @@ -161,7 +161,7 @@ void *__symbol_get_gpl(const char *symbol); #define __CRC_SYMBOL(sym, sec) \ extern void *__crc_##sym __attribute__((weak)); \ static const unsigned long __kcrctab_##sym \ - __attribute__((section("__kcrctab" sec))) \ + __attribute__((section("__kcrctab" sec), unused)) \ = (unsigned long) &__crc_##sym; #else #define __CRC_SYMBOL(sym, sec) @@ -174,7 +174,7 @@ void *__symbol_get_gpl(const char *symbol); __attribute__((section("__ksymtab_strings"))) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __ksymtab_##sym \ - __attribute__((section("__ksymtab" sec))) \ + __attribute__((section("__ksymtab" sec), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } #define EXPORT_SYMBOL(sym) \ -- cgit v1.2.3 From 31fd2ea0a3431613743ae6ea9d862796d3181e90 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 28 Jan 2003 21:12:19 +1100 Subject: [PATCH] USB: usbcore misc cleanup (notably for non-dma hcds) The support for non-dma HCDs is likely the most interesting bit here. - makes dma calls behave sensibly when used with host controllers that don't use dma (including sl811). usb_buffer_map() is a nop while scatterlist dma mappings fail (as they must). - make usb_sg_init() behave sensibly when used with non-dma hcs. the urbs are initted with transfer_buffer, not transfer_dma. this is the higher level analogue to usb_buffer_map(), so it needs to succeed unless there's a Real Error (tm). - moves two compatibility inlines from ehci.h into hcd.h so it'll be more practical to have the other hcds work in other environments (notably lk 2.4) too - remove URB_TIMEOUT_KILLED flag ... no device driver tests it; hcds don't really (uhci sets it, never reads it; sl811 doesn't enable the path that might set it), and it's not well defined. if any hcd needs such state, keep it in hc-private storage. - in usb_sg_wait(), use yield() instead of schedule() to let other activities free resources needed to continue. (This was noted recently by Oliver.) --- drivers/usb/core/hcd.c | 7 +++++-- drivers/usb/core/hcd.h | 14 ++++++++++++++ drivers/usb/core/message.c | 31 ++++++++++++++++++++++++------- drivers/usb/core/usb.c | 24 +++++++++++++++++------- drivers/usb/host/ehci.h | 10 ---------- drivers/usb/host/hc_simple.c | 3 +-- drivers/usb/host/uhci-hcd.c | 1 - include/linux/usb.h | 1 - 8 files changed, 61 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 4ce07f9a64b3..ef25a85a939a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1029,8 +1029,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) return status; } - /* lower level hcd code should use *_dma exclusively */ - if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { + /* lower level hcd code should use *_dma exclusively, + * unless it uses pio or talks to another transport. + */ + if (!(urb->transfer_flags & URB_NO_DMA_MAP) + && hcd->controller->dma_mask) { if (usb_pipecontrol (urb->pipe)) urb->setup_dma = dma_map_single ( hcd->controller, diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 8e8f58fb33d6..5a0dd57af6e1 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -111,6 +111,13 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ */ }; +/* 2.4 does this a bit differently ... */ +static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) +{ + return &hcd->self; +} + + struct hcd_dev { /* usb_device.hcpriv points to this */ struct list_head dev_list; /* on this hcd */ struct list_head urb_list; /* pending on this dev */ @@ -343,6 +350,13 @@ extern void usb_deregister_bus (struct usb_bus *); extern int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev); +/* for portability to 2.4, hcds should call this */ +static inline int hcd_register_root (struct usb_hcd *hcd) +{ + return usb_register_root_hub ( + hcd_to_bus (hcd)->root_hub, hcd->controller); +} + /*-------------------------------------------------------------------------*/ /* exported only within usbcore */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7b7689e38944..c0754419e7ea 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -206,7 +206,8 @@ static void sg_clean (struct usb_sg_request *io) kfree (io->urbs); io->urbs = 0; } - usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); + if (io->dev->dev.dma_mask != 0) + usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); io->dev = 0; } @@ -301,6 +302,7 @@ int usb_sg_init ( { int i; int urb_flags; + int dma; if (!io || !dev || !sg || usb_pipecontrol (pipe) @@ -314,8 +316,16 @@ int usb_sg_init ( io->sg = sg; io->nents = nents; + /* not all host controllers use DMA (like the mainstream pci ones); + * they can use PIO (sl811) or be software over another transport. + */ + dma = (dev->dev.dma_mask == 0); + if (dma) + io->entries = usb_buffer_map_sg (dev, pipe, sg, nents); + else + io->entries = nents; + /* initialize all the urbs we'll use */ - io->entries = usb_buffer_map_sg (dev, pipe, sg, nents); if (io->entries <= 0) return io->entries; @@ -347,8 +357,17 @@ int usb_sg_init ( io->urbs [i]->status = -EINPROGRESS; io->urbs [i]->actual_length = 0; - io->urbs [i]->transfer_dma = sg_dma_address (sg + i); - len = sg_dma_len (sg + i); + if (dma) { + /* hc may use _only_ transfer_dma */ + io->urbs [i]->transfer_dma = sg_dma_address (sg + i); + len = sg_dma_len (sg + i); + } else { + /* hc may use _only_ transfer_buffer */ + io->urbs [i]->transfer_buffer = + page_address (sg [i].page) + sg [i].offset; + len = sg [i].length; + } + if (length) { len = min_t (unsigned, len, length); length -= len; @@ -434,9 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io) retval = 0; i--; // FIXME: should it usb_sg_cancel() on INTERRUPT? - // how about imposing a backoff? - set_current_state (TASK_UNINTERRUPTIBLE); - schedule (); + yield (); break; /* no error? continue immediately. diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index bd06a32f88d6..f1643fff1d7b 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1224,7 +1224,8 @@ void usb_buffer_free ( * * Return value is either null (indicating no buffer could be mapped), or * the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the - * operation succeeds. + * operation succeeds. If the device is connected to this system through + * a non-DMA controller, this operation always succeeds. * * This call would normally be used for an urb which is reused, perhaps * as the target of a large periodic transfer, with usb_buffer_dmasync() @@ -1245,12 +1246,15 @@ struct urb *usb_buffer_map (struct urb *urb) || !(controller = bus->controller)) return 0; - urb->transfer_dma = dma_map_single (controller, + if (controller->dma_mask) { + urb->transfer_dma = dma_map_single (controller, urb->transfer_buffer, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); // FIXME generic api broken like pci, can't report errors // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; + } else + urb->transfer_dma = ~0; urb->transfer_flags |= URB_NO_DMA_MAP; return urb; } @@ -1271,7 +1275,8 @@ void usb_buffer_dmasync (struct urb *urb) || !(controller = bus->controller)) return; - dma_sync_single (controller, + if (controller->dma_mask) + dma_sync_single (controller, urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); @@ -1295,10 +1300,12 @@ void usb_buffer_unmap (struct urb *urb) || !(controller = bus->controller)) return; - dma_unmap_single (controller, + if (controller->dma_mask) + dma_unmap_single (controller, urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + urb->transfer_flags &= ~URB_NO_DMA_MAP; } /** @@ -1336,7 +1343,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, if (!dev || usb_pipecontrol (pipe) || !(bus = dev->bus) - || !(controller = bus->controller)) + || !(controller = bus->controller) + || !controller->dma_mask) return -1; // FIXME generic api broken like pci, can't report errors @@ -1362,7 +1370,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, if (!dev || !(bus = dev->bus) - || !(controller = bus->controller)) + || !(controller = bus->controller) + || !controller->dma_mask) return; dma_sync_sg (controller, sg, n_hw_ents, @@ -1386,7 +1395,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, if (!dev || !(bus = dev->bus) - || !(controller = bus->controller)) + || !(controller = bus->controller) + || !controller->dma_mask) return; dma_unmap_sg (controller, sg, n_hw_ents, diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 7b49ddf0648a..34522fe4b9bf 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -426,16 +426,6 @@ static inline int hcd_register_root (struct usb_hcd *hcd) #else /* LINUX_VERSION_CODE */ -// hcd_to_bus() eventually moves to hcd.h on 2.5 too -static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) - { return &hcd->self; } -// ... as does hcd_register_root() -static inline int hcd_register_root (struct usb_hcd *hcd) -{ - return usb_register_root_hub ( - hcd_to_bus (hcd)->root_hub, &hcd->pdev->dev); -} - #define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) #ifndef DEBUG diff --git a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c index d8b8039b8b0d..5d4cf5c02971 100644 --- a/drivers/usb/host/hc_simple.c +++ b/drivers/usb/host/hc_simple.c @@ -219,7 +219,7 @@ static int hci_unlink_urb (struct urb * urb) if (!list_empty (&urb->urb_list) && urb->status == -EINPROGRESS) { /* URB active? */ - if (urb->transfer_flags & (URB_ASYNC_UNLINK | URB_TIMEOUT_KILLED)) { + if (urb->transfer_flags & URB_ASYNC_UNLINK) { /* asynchronous with callback */ /* relink the urb to the del list */ list_move (&urb->urb_list, &hci->del_list); @@ -388,7 +388,6 @@ static void qu_urb_timeout (unsigned long lurb) struct urb *urb = (struct urb *) lurb; DBGFUNC ("enter qu_urb_timeout\n"); - urb->transfer_flags |= URB_TIMEOUT_KILLED; hci_unlink_urb (urb); } #endif diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index b3a8d06d6c19..c3c0a7505765 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -1747,7 +1747,6 @@ static void stall_callback(unsigned long ptr) tmp = tmp->next; - u->transfer_flags |= URB_TIMEOUT_KILLED; uhci_urb_dequeue(hcd, u); } diff --git a/include/linux/usb.h b/include/linux/usb.h index 9f465bfd8179..cb5c0db14aa1 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -554,7 +554,6 @@ extern int usb_disabled(void); #define URB_NO_FSBR 0x0020 /* UHCI-specific */ #define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */ #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */ -#define URB_TIMEOUT_KILLED 0x1000 /* only set by HCD! */ struct usb_iso_packet_descriptor { unsigned int offset; -- cgit v1.2.3 From 3957f2b34960d85b63e814262a8be7d5ad91444d Mon Sep 17 00:00:00 2001 From: James Morris Date: Sun, 2 Feb 2003 07:35:32 -0800 Subject: [CRYPTO]: in/out scatterlist support for ciphers. - Merge scatterwalk patch from Adam J. Richter API change: cipher methods now take in/out scatterlists and nbytes params. - Merge gss_krb5_crypto update from Adam J. Richter - Add KM_SOFTIRQn (instead of KM_CRYPTO_IN etc). - Add asm/kmap_types.h to crypto/internal.h - Update cipher.c credits. - Update cipher.c documentation. --- crypto/cipher.c | 296 ++++++++++++++++++++-------------- crypto/digest.c | 8 +- crypto/internal.h | 24 ++- crypto/tcrypt.c | 54 +++---- include/asm-alpha/kmap_types.h | 4 +- include/asm-i386/kmap_types.h | 4 +- include/asm-ia64/kmap_types.h | 4 +- include/asm-ppc/kmap_types.h | 4 +- include/asm-ppc64/kmap_types.h | 4 +- include/asm-s390/kmap_types.h | 4 +- include/asm-sparc/kmap_types.h | 4 +- include/asm-sparc64/kmap_types.h | 4 +- include/asm-x86_64/kmap_types.h | 4 +- include/linux/crypto.h | 22 ++- net/ipv4/esp.c | 4 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 4 +- 16 files changed, 256 insertions(+), 192 deletions(-) (limited to 'include/linux') diff --git a/crypto/cipher.c b/crypto/cipher.c index fb6292ad2aa1..1f2fab6eade9 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -4,6 +4,7 @@ * Cipher operations. * * Copyright (c) 2002 James Morris + * Generic scatterwalk code by Adam J. Richter . * * 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 @@ -16,12 +17,22 @@ #include #include #include +#include #include #include #include "internal.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); -typedef void (procfn_t)(struct crypto_tfm *, u8 *, cryptfn_t, int enc); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc); + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; static inline void xor_64(u8 *a, const u8 *b) { @@ -37,165 +48,191 @@ static inline void xor_128(u8 *a, const u8 *b) ((u32 *)a)[3] ^= ((u32 *)b)[3]; } -static inline unsigned int sglen(struct scatterlist *sg, unsigned int nsg) + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) { - unsigned int i, n; - - for (i = 0, n = 0; i < nsg; i++) - n += sg[i].length; - - return n; + return sg + 1; } -/* - * Do not call this unless the total length of all of the fragments - * has been verified as multiple of the block size. - */ -static unsigned int copy_chunks(struct crypto_tfm *tfm, u8 *buf, - struct scatterlist *sg, unsigned int sgidx, - unsigned int rlen, unsigned int *last, int in) +void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) { - unsigned int i, copied, coff, j, aligned; - unsigned int bsize = crypto_tfm_alg_blocksize(tfm); - - for (i = sgidx, j = copied = 0, aligned = 0 ; copied < bsize; i++) { - unsigned int len = sg[i].length; - unsigned int clen; - char *p; - - if (copied) { - coff = 0; - clen = min(len, bsize - copied); - - if (len == bsize - copied) - aligned = 1; /* last + right aligned */ - - } else { - coff = len - rlen; - clen = rlen; - } + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} - p = crypto_kmap(sg[i].page) + sg[i].offset + coff; - - if (in) - memcpy(&buf[copied], p, clen); +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +static void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatter_page_done(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virutual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } else - memcpy(p, &buf[copied], clen); - - crypto_kunmap(p); - *last = aligned ? 0 : clen; - copied += clen; + scatterwalk_start(walk, sg_next(walk->sg)); } - - return i - sgidx - 2 + aligned; } -static inline unsigned int gather_chunks(struct crypto_tfm *tfm, u8 *buf, - struct scatterlist *sg, - unsigned int sgidx, unsigned int rlen, - unsigned int *last) +static void scatter_done(struct scatter_walk *walk, int out, int more) { - return copy_chunks(tfm, buf, sg, sgidx, rlen, last, 1); + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatter_page_done(walk, out, more); } -static inline unsigned int scatter_chunks(struct crypto_tfm *tfm, u8 *buf, - struct scatterlist *sg, - unsigned int sgidx, unsigned int rlen, - unsigned int *last) +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +static int copy_chunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) { - return copy_chunks(tfm, buf, sg, sgidx, rlen, last, 0); + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatter_page_done(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; } /* - * Generic encrypt/decrypt wrapper for ciphers. - * - * If we find a a remnant at the end of a frag, we have to encrypt or - * decrypt across possibly multiple page boundaries via a temporary - * block, then continue processing with a chunk offset until the end - * of a frag is block aligned. - * - * The code is further complicated by having to remap a page after - * processing a block then yielding. The data will be offset from the - * start of page at the scatterlist offset, the chunking offset (coff) - * and the block offset (boff). + * Generic encrypt/decrypt wrapper for ciphers, handles operations across + * multiple page boundaries by using temporary blocks. In user context, + * the kernel is given a chance to schedule us once per block. */ -static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, - unsigned int nsg, cryptfn_t crfn, procfn_t prfn, int enc) +static int crypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc) { - unsigned int i, coff; - unsigned int bsize = crypto_tfm_alg_blocksize(tfm); - u8 tmp[bsize]; + struct scatter_walk walk_in, walk_out; + const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); + u8 tmp_src[nbytes > src->length ? bsize : 0]; + u8 tmp_dst[nbytes > dst->length ? bsize : 0]; - if (sglen(sg, nsg) % bsize) { + if (!nbytes) + return 0; + + if (nbytes % bsize) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; return -EINVAL; } - for (i = 0, coff = 0; i < nsg; i++) { - unsigned int n = 0, boff = 0; - unsigned int len = sg[i].length - coff; - char *p = crypto_kmap(sg[i].page) + sg[i].offset + coff; - - while (len) { - if (len < bsize) { - crypto_kunmap(p); - n = gather_chunks(tfm, tmp, sg, i, len, &coff); - prfn(tfm, tmp, crfn, enc); - scatter_chunks(tfm, tmp, sg, i, len, &coff); - crypto_yield(tfm); - goto unmapped; - } else { - prfn(tfm, p, crfn, enc); - crypto_kunmap(p); - crypto_yield(tfm); - - /* remap and point to recalculated offset */ - boff += bsize; - p = crypto_kmap(sg[i].page) - + sg[i].offset + coff + boff; - - len -= bsize; - - /* End of frag with no remnant? */ - if (coff && len == 0) - coff = 0; - } - } - crypto_kunmap(p); -unmapped: - i += n; + scatterwalk_start(&walk_in, src); + scatterwalk_start(&walk_out, dst); + + for(;;) { + u8 *src_p, *dst_p; + + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + src_p = which_buf(&walk_in, bsize, tmp_src); + dst_p = which_buf(&walk_out, bsize, tmp_dst); + + nbytes -= bsize; + copy_chunks(src_p, &walk_in, bsize, 0); + + prfn(tfm, dst_p, src_p, crfn, enc); + + scatter_done(&walk_in, 0, nbytes); + + copy_chunks(dst_p, &walk_out, bsize, 1); + scatter_done(&walk_out, 1, nbytes); + + if (!nbytes) + return 0; + + crypto_yield(tfm); } - return 0; } static void cbc_process(struct crypto_tfm *tfm, - u8 *block, cryptfn_t fn, int enc) + u8 *dst, u8 *src, cryptfn_t fn, int enc) { /* Null encryption */ if (!tfm->crt_cipher.cit_iv) return; if (enc) { - tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, block); - fn(tfm->crt_ctx, block, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, block, + tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); + fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); + memcpy(tfm->crt_cipher.cit_iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { - u8 buf[crypto_tfm_alg_blocksize(tfm)]; + const int need_stack = (src == dst); + u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = need_stack ? stack : dst; - fn(tfm->crt_ctx, buf, block); + fn(tfm->crt_ctx, buf, src); tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, block, + memcpy(tfm->crt_cipher.cit_iv, src, crypto_tfm_alg_blocksize(tfm)); - memcpy(block, buf, crypto_tfm_alg_blocksize(tfm)); + if (buf != dst) + memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); } } -static void ecb_process(struct crypto_tfm *tfm, u8 *block, +static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, cryptfn_t fn, int enc) { - fn(tfm->crt_ctx, block, block); + fn(tfm->crt_ctx, dst, src); } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -211,35 +248,44 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) } static int ecb_encrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) { - return crypt(tfm, sg, nsg, + return crypt(tfm, dst, src, nbytes, tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1); } static int ecb_decrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { - return crypt(tfm, sg, nsg, + return crypt(tfm, dst, src, nbytes, tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1); } static int cbc_encrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { - return crypt(tfm, sg, nsg, + return crypt(tfm, dst, src, nbytes, tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1); } static int cbc_decrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { - return crypt(tfm, sg, nsg, + return crypt(tfm, dst, src, nbytes, tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0); } static int nocrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { return -ENOSYS; } diff --git a/crypto/digest.c b/crypto/digest.c index 4db5f88ef38d..9e7c4bb417ab 100644 --- a/crypto/digest.c +++ b/crypto/digest.c @@ -28,10 +28,10 @@ static void update(struct crypto_tfm *tfm, unsigned int i; for (i = 0; i < nsg; i++) { - char *p = crypto_kmap(sg[i].page) + sg[i].offset; + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, p, sg[i].length); - crypto_kunmap(p); + crypto_kunmap(p, 0); crypto_yield(tfm); } } @@ -49,10 +49,10 @@ static void digest(struct crypto_tfm *tfm, tfm->crt_digest.dit_init(tfm); for (i = 0; i < nsg; i++) { - char *p = crypto_kmap(sg[i].page) + sg[i].offset; + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, p, sg[i].length); - crypto_kunmap(p); + crypto_kunmap(p, 0); crypto_yield(tfm); } crypto_digest_final(tfm, out); diff --git a/crypto/internal.h b/crypto/internal.h index eb4c92d3b47f..df34df2e6acc 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -16,17 +16,29 @@ #include #include #include +#include -static inline void *crypto_kmap(struct page *page) +static enum km_type km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +static inline enum km_type crypto_kmap_type(int out) +{ + return km_types[(in_softirq() ? 2 : 0) + out]; +} + + +static inline void *crypto_kmap(struct page *page, int out) { - return kmap_atomic(page, in_softirq() ? - KM_CRYPTO_SOFTIRQ : KM_CRYPTO_USER); + return kmap_atomic(page, crypto_kmap_type(out)); } -static inline void crypto_kunmap(void *vaddr) +static inline void crypto_kunmap(void *vaddr, int out) { - kunmap_atomic(vaddr, in_softirq() ? - KM_CRYPTO_SOFTIRQ : KM_CRYPTO_USER); + kunmap_atomic(vaddr, crypto_kmap_type(out)); } static inline void crypto_yield(struct crypto_tfm *tfm) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index bcce9065242a..a45e574528f7 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -703,7 +703,7 @@ test_des(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = len; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, len); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -746,7 +746,7 @@ test_des(void) sg[1].offset = ((long) p & ~PAGE_MASK); sg[1].length = 8; - ret = crypto_cipher_encrypt(tfm, sg, 2); + ret = crypto_cipher_encrypt(tfm, sg, sg, 16); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -814,7 +814,7 @@ test_des(void) sg[2].offset = ((long) p & ~PAGE_MASK); sg[2].length = 8; - ret = crypto_cipher_encrypt(tfm, sg, 3); + ret = crypto_cipher_encrypt(tfm, sg, sg, 32); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); @@ -890,7 +890,7 @@ test_des(void) sg[3].offset = ((long) p & ~PAGE_MASK); sg[3].length = 18; - ret = crypto_cipher_encrypt(tfm, sg, 4); + ret = crypto_cipher_encrypt(tfm, sg, sg, 24); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); @@ -979,7 +979,7 @@ test_des(void) sg[4].offset = ((long) p & ~PAGE_MASK); sg[4].length = 8; - ret = crypto_cipher_encrypt(tfm, sg, 5); + ret = crypto_cipher_encrypt(tfm, sg, sg, 16); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); @@ -1078,7 +1078,7 @@ test_des(void) sg[7].offset = ((long) p & ~PAGE_MASK); sg[7].length = 1; - ret = crypto_cipher_encrypt(tfm, sg, 8); + ret = crypto_cipher_encrypt(tfm, sg, sg, 8); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1120,7 +1120,7 @@ test_des(void) sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = len; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("des_decrypt() failed flags=%x\n", tfm->crt_flags); @@ -1163,7 +1163,7 @@ test_des(void) sg[1].offset = ((long) p & ~PAGE_MASK); sg[1].length = 8; - ret = crypto_cipher_decrypt(tfm, sg, 2); + ret = crypto_cipher_decrypt(tfm, sg, sg, 16); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1220,7 +1220,7 @@ test_des(void) sg[2].offset = ((long) p & ~PAGE_MASK); sg[2].length = 1; - ret = crypto_cipher_decrypt(tfm, sg, 3); + ret = crypto_cipher_decrypt(tfm, sg, sg, 16); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); @@ -1290,7 +1290,7 @@ test_des(void) crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, len); if (ret) { printk("des_cbc_encrypt() failed flags=%x\n", tfm->crt_flags); @@ -1349,7 +1349,7 @@ test_des(void) crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_encrypt(tfm, sg, 2); + ret = crypto_cipher_encrypt(tfm, sg, sg, 24); if (ret) { printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1398,7 +1398,7 @@ test_des(void) crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_blocksize(tfm)); - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, len); if (ret) { printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); @@ -1450,7 +1450,7 @@ test_des(void) crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_decrypt(tfm, sg, 2); + ret = crypto_cipher_decrypt(tfm, sg, sg, 8); if (ret) { printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1518,7 +1518,7 @@ test_des3_ede(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = len; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, len); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1561,7 +1561,7 @@ test_des3_ede(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = len; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, len); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1624,7 +1624,7 @@ test_blowfish(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = bf_tv[i].plen; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1666,7 +1666,7 @@ test_blowfish(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = bf_tv[i].plen; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1719,7 +1719,7 @@ test_blowfish(void) crypto_cipher_set_iv(tfm, bf_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("blowfish_cbc_encrypt() failed flags=%x\n", tfm->crt_flags); @@ -1764,7 +1764,7 @@ test_blowfish(void) crypto_cipher_set_iv(tfm, bf_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("blowfish_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); @@ -1829,7 +1829,7 @@ test_twofish(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = tf_tv[i].plen; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1871,7 +1871,7 @@ test_twofish(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = tf_tv[i].plen; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -1924,7 +1924,7 @@ test_twofish(void) crypto_cipher_set_iv(tfm, tf_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("blowfish_cbc_encrypt() failed flags=%x\n", tfm->crt_flags); @@ -1970,7 +1970,7 @@ test_twofish(void) crypto_cipher_set_iv(tfm, tf_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("blowfish_cbc_decrypt() failed flags=%x\n", tfm->crt_flags); @@ -2030,7 +2030,7 @@ test_serpent(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = sizeof(serp_tv[i].plaintext); - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -2070,7 +2070,7 @@ test_serpent(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = sizeof(serp_tv[i].plaintext); - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -2133,7 +2133,7 @@ test_aes(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = aes_tv[i].plen; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("encrypt() failed flags=%x\n", tfm->crt_flags); goto out; @@ -2175,7 +2175,7 @@ test_aes(void) sg[0].page = virt_to_page(p); sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].length = aes_tv[i].plen; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length); if (ret) { printk("decrypt() failed flags=%x\n", tfm->crt_flags); goto out; diff --git a/include/asm-alpha/kmap_types.h b/include/asm-alpha/kmap_types.h index 10061ab1c9ad..e7e1f7c8d148 100644 --- a/include/asm-alpha/kmap_types.h +++ b/include/asm-alpha/kmap_types.h @@ -23,8 +23,8 @@ D(7) KM_PTE0, D(8) KM_PTE1, D(9) KM_IRQ0, D(10) KM_IRQ1, -D(11) KM_CRYPTO_USER, -D(12) KM_CRYPTO_SOFTIRQ, +D(11) KM_SOFTIRQ0, +D(12) KM_SOFTIRQ1, D(13) KM_TYPE_NR }; diff --git a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h index 9ee55b1dea1f..dda910c4f1ba 100644 --- a/include/asm-i386/kmap_types.h +++ b/include/asm-i386/kmap_types.h @@ -22,8 +22,8 @@ D(8) KM_PTE1, D(9) KM_PTE2, D(10) KM_IRQ0, D(11) KM_IRQ1, -D(12) KM_CRYPTO_USER, -D(13) KM_CRYPTO_SOFTIRQ, +D(12) KM_SOFTIRQ0, +D(13) KM_SOFTIRQ1, D(14) KM_TYPE_NR }; diff --git a/include/asm-ia64/kmap_types.h b/include/asm-ia64/kmap_types.h index 77187f614170..d54e19055e6c 100644 --- a/include/asm-ia64/kmap_types.h +++ b/include/asm-ia64/kmap_types.h @@ -21,8 +21,8 @@ D(7) KM_PTE0, D(8) KM_PTE1, D(9) KM_IRQ0, D(10) KM_IRQ1, -D(11) KM_CRYPTO_USER, -D(12) KM_CRYPTO_SOFTIRQ, +D(11) KM_SOFTIRQ0, +D(12) KM_SOFTIRQ1, D(13) KM_TYPE_NR }; diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h index 1a4813527e74..5ffc886ddabb 100644 --- a/include/asm-ppc/kmap_types.h +++ b/include/asm-ppc/kmap_types.h @@ -14,8 +14,8 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/asm-ppc64/kmap_types.h b/include/asm-ppc64/kmap_types.h index f8422429758a..fd1574648223 100644 --- a/include/asm-ppc64/kmap_types.h +++ b/include/asm-ppc64/kmap_types.h @@ -14,8 +14,8 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/asm-s390/kmap_types.h b/include/asm-s390/kmap_types.h index f8422429758a..fd1574648223 100644 --- a/include/asm-s390/kmap_types.h +++ b/include/asm-s390/kmap_types.h @@ -14,8 +14,8 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/asm-sparc/kmap_types.h b/include/asm-sparc/kmap_types.h index 05eeec6d17f3..e215f7104974 100644 --- a/include/asm-sparc/kmap_types.h +++ b/include/asm-sparc/kmap_types.h @@ -13,8 +13,8 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/asm-sparc64/kmap_types.h b/include/asm-sparc64/kmap_types.h index 26c28fb7c8b7..34c1d3d9a3b0 100644 --- a/include/asm-sparc64/kmap_types.h +++ b/include/asm-sparc64/kmap_types.h @@ -17,8 +17,8 @@ enum km_type { KM_PTE1, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/asm-x86_64/kmap_types.h b/include/asm-x86_64/kmap_types.h index e87ef2e0f74d..7486338c6cea 100644 --- a/include/asm-x86_64/kmap_types.h +++ b/include/asm-x86_64/kmap_types.h @@ -11,8 +11,8 @@ enum km_type { KM_BIO_DST_IRQ, KM_IRQ0, KM_IRQ1, - KM_CRYPTO_USER, - KM_CRYPTO_SOFTIRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, KM_TYPE_NR }; diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 5c29e2b58011..5178882ec4d1 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -131,9 +131,13 @@ struct cipher_tfm { int (*cit_setkey)(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); int (*cit_encrypt)(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg); + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); int (*cit_decrypt)(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg); + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); void (*cit_xor_block)(u8 *dst, const u8 *src); }; @@ -274,19 +278,21 @@ static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, } static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, - unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); - return tfm->crt_cipher.cit_encrypt(tfm, sg, nsg); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); } static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, - struct scatterlist *sg, - unsigned int nsg) + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); - return tfm->crt_cipher.cit_decrypt(tfm, sg, nsg); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); } static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, diff --git a/net/ipv4/esp.c b/net/ipv4/esp.c index 5c4a1f3833da..09c8abd6aa8c 100644 --- a/net/ipv4/esp.c +++ b/net/ipv4/esp.c @@ -423,7 +423,7 @@ int esp_output(struct sk_buff *skb) goto error; } skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); - crypto_cipher_encrypt(tfm, sg, nfrags); + crypto_cipher_encrypt(tfm, sg, sg, clen); if (unlikely(sg != sgbuf)) kfree(sg); } while (0); @@ -520,7 +520,7 @@ int esp_input(struct xfrm_state *x, struct sk_buff *skb) goto out; } skb_to_sgvec(skb, sg, 8+esp->conf.ivlen, elen); - crypto_cipher_decrypt(esp->conf.tfm, sg, nfrags); + crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); if (unlikely(sg != sgbuf)) kfree(sg); diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 512a4d686e5f..84f879595cff 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -78,7 +78,7 @@ krb5_encrypt( sg[0].offset = ((long)out & ~PAGE_MASK); sg[0].length = length; - ret = crypto_cipher_encrypt(tfm, sg, 1); + ret = crypto_cipher_encrypt(tfm, sg, sg, length); out: dprintk("gss_k5encrypt returns %d\n",ret); @@ -117,7 +117,7 @@ krb5_decrypt( sg[0].offset = ((long)out & ~PAGE_MASK); sg[0].length = length; - ret = crypto_cipher_decrypt(tfm, sg, 1); + ret = crypto_cipher_decrypt(tfm, sg, sg, length); out: dprintk("gss_k5decrypt returns %d\n",ret); -- cgit v1.2.3 From de14887638ec6f54f12fe353da1e7663bea74b16 Mon Sep 17 00:00:00 2001 From: Kunihiro Ishiguro Date: Sun, 2 Feb 2003 08:14:44 -0800 Subject: [XFRM]: Add family member to xfrm_usersa_id. --- include/linux/xfrm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index bac8b2e3e666..7458d1f49472 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -163,6 +163,7 @@ struct xfrm_usersa_info { struct xfrm_usersa_id { xfrm_address_t saddr; __u32 spi; + __u16 family; __u8 proto; }; -- cgit v1.2.3 From d5ea3bb59fe2d4a5216e1daa1e5631f47825665e Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Mon, 3 Feb 2003 02:19:44 -0600 Subject: kbuild: Rename CONFIG_MODVERSIONING -> CONFIG_MODVERSIONS CONFIG_MODVERSIONING was a temporary name introduced to distinguish between the old and new module version implementation. Since the traces of the old implementation are now gone from the build system, we rename the config option back in order to not confuse users more than necessary in 2.6. Also, remove some historic modversions cruft throughout the tree. --- Makefile | 6 +++--- drivers/char/ftape/compressor/zftape-compress.c | 6 +----- drivers/char/ftape/lowlevel/ftape-init.c | 6 +----- drivers/char/ftape/zftape/zftape-init.c | 6 +----- drivers/scsi/aic7xxx/aic79xx_osm.c | 6 ------ drivers/scsi/aic7xxx/aic79xx_osm.h | 3 --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 6 ------ drivers/scsi/aic7xxx/aic7xxx_osm.h | 3 --- include/linux/module.h | 2 +- init/Kconfig | 3 +-- kernel/ksyms.c | 7 ------- kernel/module.c | 4 ++-- scripts/Makefile.build | 12 ++++++------ 13 files changed, 16 insertions(+), 54 deletions(-) (limited to 'include/linux') diff --git a/Makefile b/Makefile index f2904aa745d7..11b0d705a782 100644 --- a/Makefile +++ b/Makefile @@ -266,7 +266,7 @@ endif # the built-in objects during the descend as well, in order to # make sure the checksums are uptodate before we record them. -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS ifeq ($(KBUILD_MODULES),1) ifneq ($(KBUILD_BUILTIN),1) KBUILD_BUILTIN := 1 @@ -402,7 +402,7 @@ $(SUBDIRS): prepare .PHONY: prepare prepare: include/linux/version.h include/asm include/config/MARKER -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS ifdef KBUILD_MODULES ifeq ($(origin SUBDIRS),file) $(Q)rm -rf $(MODVERDIR) @@ -511,7 +511,7 @@ ifdef CONFIG_MODULES .PHONY: modules __modversions modules: $(SUBDIRS) __modversions -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS __modversions: vmlinux $(SUBDIRS) @echo ' Recording module symbol versions.'; diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c index 6f58ed077944..37c8fbaf247b 100644 --- a/drivers/char/ftape/compressor/zftape-compress.c +++ b/drivers/char/ftape/compressor/zftape-compress.c @@ -1196,11 +1196,7 @@ int zft_compressor_init(void) printk( KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n" -KERN_INFO "Compiled for kernel version %s" -#ifdef MODVERSIONS - " with versioned symbols" -#endif - "\n", UTS_RELEASE); +KERN_INFO "Compiled for kernel version %s\n", UTS_RELEASE); } #else /* !MODULE */ /* print a short no-nonsense boot message */ diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c index 70530a2bebd0..9ffe3de655c0 100644 --- a/drivers/char/ftape/lowlevel/ftape-init.c +++ b/drivers/char/ftape/lowlevel/ftape-init.c @@ -70,11 +70,7 @@ KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n" KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n" KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n" -KERN_INFO "Compiled for Linux version %s" -#ifdef MODVERSIONS - " with versioned symbols" -#endif - "\n", UTS_RELEASE); +KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE); } #else /* !MODULE */ /* print a short no-nonsense boot message */ diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c index 4e56739b6a32..b1c015254c6f 100644 --- a/drivers/char/ftape/zftape/zftape-init.c +++ b/drivers/char/ftape/zftape/zftape-init.c @@ -331,11 +331,7 @@ KERN_INFO KERN_INFO "and builtin compression (lzrw3 algorithm).\n" KERN_INFO -"Compiled for Linux version %s" -#ifdef MODVERSIONS - " with versioned symbols" -#endif - "\n", UTS_RELEASE); +"Compiled for Linux version %s\n", UTS_RELEASE); } #else /* !MODULE */ /* print a short no-nonsense boot message */ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 05edbed59319..0d15557c8383 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -42,12 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -/* - * This is the only file where module.h should - * embed module global version info. - */ -#define AHD_MODVERSION_FILE - #include "aic79xx_osm.h" #include "aic79xx_inline.h" #include diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index ecf6fdf9ef01..38da2b580d2d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -50,9 +50,6 @@ #include #include #include -#ifndef AHD_MODVERSION_FILE -#define __NO_VERSION__ -#endif #include #include diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 07087d348cd6..123ec0b80606 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -119,12 +119,6 @@ * */ -/* - * This is the only file where module.h should - * embed module global version info. - */ -#define AHC_MODVERSION_FILE - #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" #include diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index a76fa110ffdc..2c309f53022c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -67,9 +67,6 @@ #include #include #include -#ifndef AHC_MODVERSION_FILE -#define __NO_VERSION__ -#endif #include #include #include diff --git a/include/linux/module.h b/include/linux/module.h index 1be44624ec3a..1265b060475d 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -155,7 +155,7 @@ void *__symbol_get_gpl(const char *symbol); #else -#ifdef CONFIG_MODVERSIONING +#ifdef CONFIG_MODVERSIONS /* Mark the CRC weak since genksyms apparently decides not to * generate a checksums for some symbols */ #define __CRC_SYMBOL(sym, sec) \ diff --git a/init/Kconfig b/init/Kconfig index 5541908be8c0..887abc316ee2 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -144,11 +144,10 @@ config OBSOLETE_MODPARM have not been converted to the new module parameter system yet. If unsure, say Y. -config MODVERSIONING +config MODVERSIONS bool "Module versioning support (EXPERIMENTAL)" depends on MODULES && EXPERIMENTAL help - ---help--- Usually, you have to use modules compiled with your kernel. Saying Y here makes it sometimes possible to use modules compiled for different kernels, by adding enough information diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 574addf5af63..b65124149fc3 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -68,13 +68,6 @@ extern struct timezone sys_tz; extern int panic_timeout; -#ifdef CONFIG_MODVERSIONS -const struct module_symbol __export_Using_Versions -__attribute__((section("__ksymtab"))) = { - 1 /* Version version */, "Using_Versions" -}; -#endif - /* process memory management */ EXPORT_SYMBOL(do_mmap_pgoff); EXPORT_SYMBOL(do_munmap); diff --git a/kernel/module.c b/kernel/module.c index 64fb7e574927..72b3569404bf 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -725,7 +725,7 @@ static int obsolete_params(const char *name, } #endif /* CONFIG_OBSOLETE_MODPARM */ -#ifdef CONFIG_MODVERSIONING +#ifdef CONFIG_MODVERSIONS static int check_version(Elf_Shdr *sechdrs, unsigned int versindex, const char *symname, @@ -779,7 +779,7 @@ static inline int check_version(Elf_Shdr *sechdrs, { return 1; } -#endif /* CONFIG_MODVERSIONING */ +#endif /* CONFIG_MODVERSIONS */ /* Resolve a symbol for this module. I.e. if we find one, record usage. Must be holding module_mutex. */ diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1c2a3d057b40..554368dc80c8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -45,7 +45,7 @@ O_TARGET := $(obj)/built-in.o endif endif -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS modules := $(obj-m) touch-module = @mkdir -p $(MODVERDIR)/$(@D); touch $(MODVERDIR)/$(@:.o=.ko) else @@ -60,7 +60,7 @@ __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \ # Module versioning # --------------------------------------------------------------------------- -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS # $(call if_changed_rule,vcc_o_c) does essentially the same as the # normal $(call if_changed_dep,cc_o_c), i.e. compile an object file @@ -153,7 +153,7 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< %.o: %.c FORCE -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) else $(call if_changed_dep,cc_o_c) @@ -162,7 +162,7 @@ endif # For modversioning, we need to special case single-part modules # to mark them in $(MODVERDIR) -ifdef CONFIG_MODVERSIONING +ifdef CONFIG_MODVERSIONS $(single-used-m): %.o: %.c FORCE $(touch-module) $(call if_changed_rule,vcc_o_c) @@ -259,9 +259,9 @@ targets += $(multi-used-y) $(multi-used-m) # Rule to link modules ( .o -> .ko ) # -# With CONFIG_MODVERSIONING, generation of the final .ko is handled +# With CONFIG_MODVERSIONS, generation of the final .ko is handled # by scripts/Makefile.modver -ifndef CONFIG_MODVERSIONING +ifndef CONFIG_MODVERSIONS quiet_cmd_link_module = LD [M] $@ cmd_link_module = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o -- cgit v1.2.3 From fccbe3844c29beed4e665b1a5aafada44e133adc Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 16:59:04 -0800 Subject: [PATCH] implement posix_fadvise64() An implementation of posix_fadvise64(). It adds 368 bytes to my vmlinux and is worth it. I didn't bother doing posix_fadvise(), as userspace can implement that by calling fadvise64(). The main reason for wanting this syscall is to provide userspace with the ability to explicitly shoot down pagecache when streaming large files. This is what O_STEAMING does, only posix_fadvise() is standards-based, and harder to use. posix_fadvise() also subsumes sys_readahead(). POSIX_FADV_WILLNEED will generally provide asynchronous readahead semantics for small amounts of I/O. As long as things like indirect blocks are aready in core. POSIX_FADV_RANDOM gives unprivileged applications a way of disabling readahead on a per-fd basis, which may provide some benefit for super-seeky access patterns such as databases. The POSIX_FADV_* values are already implemented in glibc, and this patch ensures that they are in sync. A test app (fadvise.c) is available in ext3 CVS. See http://www.zip.com.au/~akpm/linux/ext3/ for CVS details. Ulrich has reviewed this patch (thanks). --- arch/i386/kernel/entry.S | 4 +-- include/asm-i386/unistd.h | 2 ++ include/linux/fadvise.h | 11 ++++++++ include/linux/fs.h | 2 ++ mm/Makefile | 2 +- mm/fadvise.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ mm/truncate.c | 21 ++++++++++---- 7 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 include/linux/fadvise.h create mode 100644 mm/fadvise.c (limited to 'include/linux') diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 09954f83b483..40bd0c4e42ca 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -792,8 +792,8 @@ ENTRY(sys_call_table) .long sys_io_getevents .long sys_io_submit .long sys_io_cancel - .long sys_ni_syscall /* 250 sys_alloc_hugepages - reuse this */ - .long sys_ni_syscall /* was sys_free_hugepages - reuse this */ + .long sys_fadvise64 /* 250 */ + .long sys_ni_syscall .long sys_exit_group .long sys_lookup_dcookie .long sys_epoll_create diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index fb5a97ec22f5..d21b3a8a4f4e 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -255,6 +255,8 @@ #define __NR_io_getevents 247 #define __NR_io_submit 248 #define __NR_io_cancel 249 +#define __NR_fadvise64 250 + #define __NR_exit_group 252 #define __NR_lookup_dcookie 253 #define __NR_epoll_create 254 diff --git a/include/linux/fadvise.h b/include/linux/fadvise.h new file mode 100644 index 000000000000..6fc656dfb93d --- /dev/null +++ b/include/linux/fadvise.h @@ -0,0 +1,11 @@ +#ifndef FADVISE_H_INCLUDED +#define FADVISE_H_INCLUDED + +#define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +#define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +#define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +#define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +#define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +#define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ + +#endif /* FADVISE_H_INCLUDED */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 76b32526394f..f4c994d02f5d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1102,6 +1102,8 @@ extern int full_check_disk_change(struct block_device *); extern int __check_disk_change(dev_t); extern int invalidate_inodes(struct super_block *); extern int invalidate_device(kdev_t, int); +extern void invalidate_mapping_pages(struct address_space *mapping, + pgoff_t start, pgoff_t end); extern void invalidate_inode_pages(struct address_space *mapping); extern void invalidate_inode_pages2(struct address_space *mapping); extern void write_inode_now(struct inode *, int); diff --git a/mm/Makefile b/mm/Makefile index a6dd1ab57fdf..a8de64ff3525 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -7,7 +7,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \ shmem.o vmalloc.o -obj-y := bootmem.o filemap.o mempool.o oom_kill.o \ +obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o readahead.o \ slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y) diff --git a/mm/fadvise.c b/mm/fadvise.c new file mode 100644 index 000000000000..9503b65076a1 --- /dev/null +++ b/mm/fadvise.c @@ -0,0 +1,72 @@ +/* + * mm/fadvise.c + * + * Copyright (C) 2002, Linus Torvalds + * + * 11Jan2003 akpm@digeo.com + * Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could + * deactivate the pages and clear PG_Referenced. + */ +int sys_fadvise64(int fd, loff_t offset, size_t len, int advice) +{ + struct file *file = fget(fd); + struct inode *inode; + struct address_space *mapping; + struct backing_dev_info *bdi; + int ret = 0; + + if (!file) + return -EBADF; + + inode = file->f_dentry->d_inode; + mapping = inode->i_mapping; + if (!mapping) + return -EINVAL; + + bdi = mapping->backing_dev_info; + + switch (advice) { + case POSIX_FADV_NORMAL: + file->f_ra.ra_pages = bdi->ra_pages; + break; + case POSIX_FADV_RANDOM: + file->f_ra.ra_pages = 0; + break; + case POSIX_FADV_SEQUENTIAL: + file->f_ra.ra_pages = bdi->ra_pages * 2; + break; + case POSIX_FADV_WILLNEED: + case POSIX_FADV_NOREUSE: + if (!mapping->a_ops->readpage) { + ret = -EINVAL; + break; + } + ret = do_page_cache_readahead(mapping, file, + offset >> PAGE_CACHE_SHIFT, + max_sane_readahead(len >> PAGE_CACHE_SHIFT)); + if (ret > 0) + ret = 0; + break; + case POSIX_FADV_DONTNEED: + invalidate_mapping_pages(mapping, offset >> PAGE_CACHE_SHIFT, + (len >> PAGE_CACHE_SHIFT) + 1); + break; + default: + ret = -EINVAL; + } + fput(file); + return ret; +} diff --git a/mm/truncate.c b/mm/truncate.c index b1782738666b..0c1dd53ae48f 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -177,24 +177,28 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) } /** - * invalidate_inode_pages - Invalidate all the unlocked pages of one inode - * @inode: the inode which pages we want to invalidate + * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode + * @inode: the address_space which holds the pages to invalidate + * @end: the index of the last page to invalidate (inclusive) + * @nr_pages: defines the pagecache span. Invalidate up to @start + @nr_pages * * This function only removes the unlocked pages, if you want to * remove all the pages of one inode, you must call truncate_inode_pages. * - * invalidate_inode_pages() will not block on IO activity. It will not + * invalidate_mapping_pages() will not block on IO activity. It will not * invalidate pages which are dirty, locked, under writeback or mapped into * pagetables. */ -void invalidate_inode_pages(struct address_space *mapping) +void invalidate_mapping_pages(struct address_space *mapping, + pgoff_t start, pgoff_t end) { struct pagevec pvec; - pgoff_t next = 0; + pgoff_t next = start; int i; pagevec_init(&pvec, 0); - while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { + while (next <= end && + pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; @@ -218,6 +222,11 @@ unlock: } } +void invalidate_inode_pages(struct address_space *mapping) +{ + invalidate_mapping_pages(mapping, 0, ~0UL); +} + /** * invalidate_inode_pages2 - remove all unmapped pages from an address_space * @mapping - the address_space -- cgit v1.2.3 From b29422e31ced8c0b37b23eff2eda8ec2cbfc3f3a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 16:59:17 -0800 Subject: [PATCH] add stats for page reclaim via inode freeing pagecache can be reclaimed via the page LRU and via prune_icache. We currently don't know how much reclaim is happening via each. The patch adds instrumentation to display the number of pages which were freed via prune_icache. This is displayed in /proc/vmstat:pginodesteal and /proc/vmstat:kswapd_inodesteal. Turns out that under some workloads (well, dbench at least), fully half of page reclaim is via the unused inode list. Which seems quite OK to me. --- fs/inode.c | 8 +++++++- include/linux/fs.h | 4 ++-- include/linux/page-flags.h | 5 +++++ mm/page_alloc.c | 5 +++++ mm/truncate.c | 27 +++++++++++++++------------ 5 files changed, 34 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/inode.c b/fs/inode.c index 257f33f98e05..4179e6a45075 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -392,6 +393,7 @@ static void prune_icache(int nr_to_scan) LIST_HEAD(freeable); int nr_pruned = 0; int nr_scanned; + unsigned long reap = 0; spin_lock(&inode_lock); for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) { @@ -410,7 +412,7 @@ static void prune_icache(int nr_to_scan) __iget(inode); spin_unlock(&inode_lock); if (remove_inode_buffers(inode)) - invalidate_inode_pages(&inode->i_data); + reap += invalidate_inode_pages(&inode->i_data); iput(inode); spin_lock(&inode_lock); @@ -428,6 +430,10 @@ static void prune_icache(int nr_to_scan) inodes_stat.nr_unused -= nr_pruned; spin_unlock(&inode_lock); dispose_list(&freeable); + if (current_is_kswapd) + mod_page_state(kswapd_inodesteal, reap); + else + mod_page_state(pginodesteal, reap); } /* diff --git a/include/linux/fs.h b/include/linux/fs.h index f4c994d02f5d..9a17c9819ae9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1102,9 +1102,9 @@ extern int full_check_disk_change(struct block_device *); extern int __check_disk_change(dev_t); extern int invalidate_inodes(struct super_block *); extern int invalidate_device(kdev_t, int); -extern void invalidate_mapping_pages(struct address_space *mapping, +unsigned long invalidate_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t end); -extern void invalidate_inode_pages(struct address_space *mapping); +unsigned long invalidate_inode_pages(struct address_space *mapping); extern void invalidate_inode_pages2(struct address_space *mapping); extern void write_inode_now(struct inode *, int); extern int filemap_fdatawrite(struct address_space *); diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index a50e09ff79ea..0327a8421c9d 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -97,15 +97,20 @@ struct page_state { unsigned long pswpin; /* swap reads */ unsigned long pswpout; /* swap writes */ unsigned long pgalloc; /* page allocations */ + unsigned long pgfree; /* page freeings */ unsigned long pgactivate; /* pages moved inactive->active */ unsigned long pgdeactivate; /* pages moved active->inactive */ unsigned long pgfault; /* faults (major+minor) */ unsigned long pgmajfault; /* faults (major only) */ + unsigned long pgscan; /* pages scanned by page reclaim */ unsigned long pgrefill; /* inspected in refill_inactive_zone */ unsigned long pgsteal; /* total pages reclaimed */ + unsigned long pginodesteal; /* pages reclaimed via inode freeing */ unsigned long kswapd_steal; /* pages reclaimed by kswapd */ + + unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */ unsigned long pageoutrun; /* kswapd's calls to page reclaim */ unsigned long allocstall; /* direct reclaim calls */ unsigned long pgrotated; /* pages rotated to tail of the LRU */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3969ad493b35..0112d0eb63cf 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1379,15 +1379,20 @@ static char *vmstat_text[] = { "pswpin", "pswpout", "pgalloc", + "pgfree", "pgactivate", "pgdeactivate", "pgfault", "pgmajfault", + "pgscan", "pgrefill", "pgsteal", + "pginodesteal", "kswapd_steal", + + "kswapd_inodesteal", "pageoutrun", "allocstall", "pgrotated", diff --git a/mm/truncate.c b/mm/truncate.c index 0c1dd53ae48f..56bdd03b1576 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -64,24 +64,25 @@ truncate_complete_page(struct address_space *mapping, struct page *page) * ->page_lock. That provides exclusion against the __set_page_dirty * functions. */ -static void +static int invalidate_complete_page(struct address_space *mapping, struct page *page) { if (page->mapping != mapping) - return; + return 0; if (PagePrivate(page) && !try_to_release_page(page, 0)) - return; + return 0; write_lock(&mapping->page_lock); if (PageDirty(page)) { write_unlock(&mapping->page_lock); - } else { - __remove_from_page_cache(page); - write_unlock(&mapping->page_lock); - ClearPageUptodate(page); - page_cache_release(page); /* pagecache ref */ + return 0; } + __remove_from_page_cache(page); + write_unlock(&mapping->page_lock); + ClearPageUptodate(page); + page_cache_release(page); /* pagecache ref */ + return 1; } /** @@ -189,11 +190,12 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) * invalidate pages which are dirty, locked, under writeback or mapped into * pagetables. */ -void invalidate_mapping_pages(struct address_space *mapping, +unsigned long invalidate_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t end) { struct pagevec pvec; pgoff_t next = start; + unsigned long ret = 0; int i; pagevec_init(&pvec, 0); @@ -213,18 +215,19 @@ void invalidate_mapping_pages(struct address_space *mapping, goto unlock; if (page_mapped(page)) goto unlock; - invalidate_complete_page(mapping, page); + ret += invalidate_complete_page(mapping, page); unlock: unlock_page(page); } pagevec_release(&pvec); cond_resched(); } + return ret; } -void invalidate_inode_pages(struct address_space *mapping) +unsigned long invalidate_inode_pages(struct address_space *mapping) { - invalidate_mapping_pages(mapping, 0, ~0UL); + return invalidate_mapping_pages(mapping, 0, ~0UL); } /** -- cgit v1.2.3 From cecee7397a165fb2c952b0738ec008768a4d6081 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 16:59:30 -0800 Subject: [PATCH] mm/mmap.c whitespace cleanups - Don't require a 160-col xterm - Coding style consistency --- include/linux/mm.h | 7 ++-- mm/mmap.c | 95 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 36 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 50eb18eb0488..d2b99c852301 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -491,7 +491,9 @@ extern int do_munmap(struct mm_struct *, unsigned long, size_t); extern unsigned long do_brk(unsigned long, unsigned long); -static inline void __vma_unlink(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct * prev) +static inline void +__vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, + struct vm_area_struct *prev) { prev->vm_next = vma->vm_next; rb_erase(&vma->vm_rb, &mm->mm_rb); @@ -499,7 +501,8 @@ static inline void __vma_unlink(struct mm_struct * mm, struct vm_area_struct * v mm->mmap_cache = prev; } -static inline int can_vma_merge(struct vm_area_struct * vma, unsigned long vm_flags) +static inline int +can_vma_merge(struct vm_area_struct *vma, unsigned long vm_flags) { if (!vma->vm_file && vma->vm_flags == vm_flags) return 1; diff --git a/mm/mmap.c b/mm/mmap.c index b8f425646511..61d0dc32646a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -205,7 +205,8 @@ out: * internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits * into "VM_xxx". */ -static inline unsigned long calc_vm_flags(unsigned long prot, unsigned long flags) +static inline unsigned long +calc_vm_flags(unsigned long prot, unsigned long flags) { #define _trans(x,bit1,bit2) \ ((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) @@ -254,10 +255,10 @@ static void validate_mm(struct mm_struct * mm) { #define validate_mm(mm) do { } while (0) #endif -static struct vm_area_struct * find_vma_prepare(struct mm_struct * mm, unsigned long addr, - struct vm_area_struct ** pprev, - struct rb_node *** rb_link, - struct rb_node ** rb_parent) +static struct vm_area_struct * +find_vma_prepare(struct mm_struct *mm, unsigned long addr, + struct vm_area_struct **pprev, struct rb_node ***rb_link, + struct rb_node ** rb_parent) { struct vm_area_struct * vma; struct rb_node ** __rb_link, * __rb_parent, * rb_prev; @@ -291,8 +292,9 @@ static struct vm_area_struct * find_vma_prepare(struct mm_struct * mm, unsigned return vma; } -static inline void __vma_link_list(struct mm_struct * mm, struct vm_area_struct * vma, - struct vm_area_struct * prev, struct rb_node * rb_parent) +static inline void +__vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, + struct vm_area_struct *prev, struct rb_node *rb_parent) { if (prev) { vma->vm_next = prev->vm_next; @@ -300,20 +302,21 @@ static inline void __vma_link_list(struct mm_struct * mm, struct vm_area_struct } else { mm->mmap = vma; if (rb_parent) - vma->vm_next = rb_entry(rb_parent, struct vm_area_struct, vm_rb); + vma->vm_next = rb_entry(rb_parent, + struct vm_area_struct, vm_rb); else vma->vm_next = NULL; } } -static void __vma_link_rb(struct mm_struct * mm, struct vm_area_struct * vma, - struct rb_node ** rb_link, struct rb_node * rb_parent) +static void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, + struct rb_node **rb_link, struct rb_node *rb_parent) { rb_link_node(&vma->vm_rb, rb_parent, rb_link); rb_insert_color(&vma->vm_rb, &mm->mm_rb); } -static inline void __vma_link_file(struct vm_area_struct * vma) +static inline void __vma_link_file(struct vm_area_struct *vma) { struct file * file; @@ -332,8 +335,10 @@ static inline void __vma_link_file(struct vm_area_struct * vma) } } -static void __vma_link(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct * prev, - struct rb_node ** rb_link, struct rb_node * rb_parent) +static void +__vma_link(struct mm_struct *mm, struct vm_area_struct *vma, + struct vm_area_struct *prev, struct rb_node **rb_link, + struct rb_node *rb_parent) { __vma_link_list(mm, vma, prev, rb_parent); __vma_link_rb(mm, vma, rb_link, rb_parent); @@ -529,7 +534,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, * to. we assume access permissions have been handled by the open * of the memory object, so we don't do any here. */ - vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; if (flags & MAP_LOCKED) { if (!capable(CAP_IPC_LOCK)) @@ -549,14 +555,19 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, if (file) { switch (flags & MAP_TYPE) { case MAP_SHARED: - if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE)) + if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) return -EACCES; - /* Make sure we don't allow writing to an append-only file.. */ + /* + * Make sure we don't allow writing to an append-only + * file.. + */ if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE)) return -EACCES; - /* make sure there are no mandatory locks on the file. */ + /* + * Make sure there are no mandatory locks on the file. + */ if (locks_verify_locked(inode)) return -EAGAIN; @@ -610,7 +621,9 @@ munmap_back: /* Check memory availability in shmem_file_setup? */ vm_flags |= VM_ACCOUNT; } else if (vm_flags & VM_WRITE) { - /* Private writable mapping: check memory availability */ + /* + * Private writable mapping: check memory availability + */ charged = len >> PAGE_SHIFT; if (!vm_enough_memory(charged)) return -ENOMEM; @@ -620,10 +633,12 @@ munmap_back: /* Can we just expand an old anonymous mapping? */ if (!file && !(vm_flags & VM_SHARED) && rb_parent) - if (vma_merge(mm, prev, rb_parent, addr, addr + len, vm_flags, NULL, 0)) + if (vma_merge(mm, prev, rb_parent, addr, addr + len, + vm_flags, NULL, 0)) goto out; - /* Determine the object being mapped and call the appropriate + /* + * Determine the object being mapped and call the appropriate * specific mapper. the address has already been validated, but * not unmapped, but the maps are removed from the list. */ @@ -734,7 +749,9 @@ unacct_error: * This function "knows" that -ENOMEM has the bits set. */ #ifndef HAVE_ARCH_UNMAPPED_AREA -static inline unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) +static inline unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; @@ -769,10 +786,14 @@ static inline unsigned long arch_get_unmapped_area(struct file *filp, unsigned l } } #else -extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); +extern unsigned long +arch_get_unmapped_area(struct file *, unsigned long, unsigned long, + unsigned long, unsigned long); #endif -unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) +unsigned long +get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) { if (flags & MAP_FIXED) { if (addr > TASK_SIZE - len) @@ -783,7 +804,8 @@ unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned } if (file && file->f_op && file->f_op->get_unmapped_area) - return file->f_op->get_unmapped_area(file, addr, len, pgoff, flags); + return file->f_op->get_unmapped_area(file, addr, len, + pgoff, flags); return arch_get_unmapped_area(file, addr, len, pgoff, flags); } @@ -806,7 +828,8 @@ struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) while (rb_node) { struct vm_area_struct * vma_tmp; - vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); + vma_tmp = rb_entry(rb_node, + struct vm_area_struct, vm_rb); if (vma_tmp->vm_end > addr) { vma = vma_tmp; @@ -824,8 +847,9 @@ struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) } /* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ -struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, - struct vm_area_struct **pprev) +struct vm_area_struct * +find_vma_prev(struct mm_struct *mm, unsigned long addr, + struct vm_area_struct **pprev) { struct vm_area_struct *vma = NULL, *prev = NULL; struct rb_node * rb_node; @@ -852,7 +876,7 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, } } - out: +out: *pprev = prev; return prev ? prev->vm_next : vma; } @@ -899,7 +923,8 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) return 0; } -struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) +struct vm_area_struct * +find_extend_vma(struct mm_struct *mm, unsigned long addr) { struct vm_area_struct *vma, *prev; @@ -918,7 +943,7 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add /* * vma is the first one with address < vma->vm_start. Have to extend vma. */ -int expand_stack(struct vm_area_struct * vma, unsigned long address) +int expand_stack(struct vm_area_struct *vma, unsigned long address) { unsigned long grow; @@ -953,7 +978,8 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) return 0; } -struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) +struct vm_area_struct * +find_extend_vma(struct mm_struct * mm, unsigned long addr) { struct vm_area_struct * vma; unsigned long start; @@ -1023,7 +1049,7 @@ static void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev, break; } no_mmaps: - if (last < first) /* needed for arches with discontiguous pgd indices */ + if (last < first) /* for arches with discontiguous pgd indices */ return; /* * If the PGD bits are not consecutive in the virtual address, the @@ -1298,7 +1324,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len) flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; /* Can we just expand an old anonymous mapping? */ - if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, flags, NULL, 0)) + if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, + flags, NULL, 0)) goto out; /* @@ -1408,7 +1435,7 @@ void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) struct vm_area_struct * __vma, * prev; struct rb_node ** rb_link, * rb_parent; - __vma = find_vma_prepare(mm, vma->vm_start, &prev, &rb_link, &rb_parent); + __vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent); if (__vma && __vma->vm_start < vma->vm_end) BUG(); vma_link(mm, vma, prev, rb_link, rb_parent); -- cgit v1.2.3 From 3ac8c84597560f3c8a950d36d0e7a95cbe43f9d1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 16:59:43 -0800 Subject: [PATCH] remove __GFP_HIGHIO Patch From: Hugh Dickins Recently noticed that __GFP_HIGHIO has played no real part since bounce buffering was converted to mempool in 2.5.12: so this patch (over 2.5.58-mm1) removes it and GFP_NOHIGHIO and SLAB_NOHIGHIO. Also removes GFP_KSWAPD, in 2.5 same as GFP_KERNEL; leaves GFP_USER, which can be a useful comment, even though in 2.5 same as GFP_KERNEL. One anomaly needs comment: strictly, if there's no __GFP_HIGHIO, then GFP_NOHIGHIO translates to GFP_NOFS; but GFP_NOFS looks wrong in the block layer, and if you follow them down, you find that GFP_NOFS and GFP_NOIO behave the same way in mempool_alloc - so I've used the less surprising GFP_NOIO to replace GFP_NOHIGHIO. --- drivers/block/ll_rw_blk.c | 2 +- include/linux/blkdev.h | 2 +- include/linux/gfp.h | 23 ++++++++++------------- include/linux/slab.h | 3 +-- mm/highmem.c | 13 ++++--------- mm/vmscan.c | 4 ++-- 6 files changed, 19 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 36436a7aa57f..f8a4e7a81f4b 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -274,7 +274,7 @@ void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) init_emergency_isa_pool(); q->bounce_gfp = GFP_NOIO | GFP_DMA; } else - q->bounce_gfp = GFP_NOHIGHIO; + q->bounce_gfp = GFP_NOIO; /* * keep this for debugging for now... diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 90171e65e989..c599ea36233b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -292,7 +292,7 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn; #define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD) extern int init_emergency_isa_pool(void); -inline void blk_queue_bounce(request_queue_t *q, struct bio **bio); +extern void blk_queue_bounce(request_queue_t *q, struct bio **bio); #define rq_for_each_bio(bio, rq) \ if ((rq->bio)) \ diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 54bf03eaf3e7..c9fb5039e753 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -14,20 +14,17 @@ /* Action modifiers - doesn't change the zoning */ #define __GFP_WAIT 0x10 /* Can wait and reschedule? */ #define __GFP_HIGH 0x20 /* Should access emergency pools? */ -#define __GFP_IO 0x40 /* Can start low memory physical IO? */ -#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ -#define __GFP_FS 0x100 /* Can call down to low-level FS? */ -#define __GFP_COLD 0x200 /* Cache-cold page required */ -#define __GFP_NOWARN 0x400 /* Suppress page allocation failure warning */ - -#define GFP_NOHIGHIO ( __GFP_WAIT | __GFP_IO) -#define GFP_NOIO ( __GFP_WAIT) -#define GFP_NOFS ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO) +#define __GFP_IO 0x40 /* Can start physical IO? */ +#define __GFP_FS 0x80 /* Can call down to low-level FS? */ +#define __GFP_COLD 0x100 /* Cache-cold page required */ +#define __GFP_NOWARN 0x200 /* Suppress page allocation failure warning */ + #define GFP_ATOMIC (__GFP_HIGH) -#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) -#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM) -#define GFP_KERNEL ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) -#define GFP_KSWAPD ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_NOIO (__GFP_WAIT) +#define GFP_NOFS (__GFP_WAIT | __GFP_IO) +#define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff --git a/include/linux/slab.h b/include/linux/slab.h index 997bc710bfb0..220a672af798 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -17,13 +17,12 @@ typedef struct kmem_cache_s kmem_cache_t; /* flags for kmem_cache_alloc() */ #define SLAB_NOFS GFP_NOFS #define SLAB_NOIO GFP_NOIO -#define SLAB_NOHIGHIO GFP_NOHIGHIO #define SLAB_ATOMIC GFP_ATOMIC #define SLAB_USER GFP_USER #define SLAB_KERNEL GFP_KERNEL #define SLAB_DMA GFP_DMA -#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_HIGHIO|__GFP_FS|__GFP_COLD|__GFP_NOWARN) +#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|__GFP_COLD|__GFP_NOWARN) #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */ /* flags to pass to kmem_cache_create(). diff --git a/mm/highmem.c b/mm/highmem.c index ee5e622dcbfe..33adcf242697 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -366,7 +366,7 @@ static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int return 0; } -void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, int bio_gfp, +static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, mempool_t *pool) { struct page *page; @@ -387,7 +387,7 @@ void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, int bio_gfp, * irk, bounce it */ if (!bio) - bio = bio_alloc(bio_gfp, (*bio_orig)->bi_vcnt); + bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt); to = bio->bi_io_vec + i; @@ -447,10 +447,9 @@ void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, int bio_gfp, *bio_orig = bio; } -inline void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) +void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) { mempool_t *pool; - int bio_gfp; /* * for non-isa bounce case, just check if the bounce pfn is equal @@ -460,20 +459,16 @@ inline void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) if (!(q->bounce_gfp & GFP_DMA)) { if (q->bounce_pfn >= blk_max_pfn) return; - - bio_gfp = GFP_NOHIGHIO; pool = page_pool; } else { BUG_ON(!isa_page_pool); - - bio_gfp = GFP_NOIO; pool = isa_page_pool; } /* * slow path */ - __blk_queue_bounce(q, bio_orig, bio_gfp, pool); + __blk_queue_bounce(q, bio_orig, pool); } #if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_HIGHMEM) diff --git a/mm/vmscan.c b/mm/vmscan.c index a8b9d2c450c4..60c534dc4129 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -894,9 +894,9 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps) max_scan = to_reclaim * 2; if (max_scan < SWAP_CLUSTER_MAX) max_scan = SWAP_CLUSTER_MAX; - to_free -= shrink_zone(zone, max_scan, GFP_KSWAPD, + to_free -= shrink_zone(zone, max_scan, GFP_KERNEL, to_reclaim, &nr_mapped, ps, priority); - shrink_slab(max_scan + nr_mapped, GFP_KSWAPD); + shrink_slab(max_scan + nr_mapped, GFP_KERNEL); if (zone->all_unreclaimable) continue; if (zone->pages_scanned > zone->present_pages * 2) -- cgit v1.2.3 From 8c4ea5db4be446f8dac64dddae306646734ab1e0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 17:00:57 -0800 Subject: [PATCH] Remove __ from topology macros Patch from Matthew Dobson When I originally wrote the patches implementing the in-kernel topology macros, they were meant to be called as a second layer of functions, sans underbars. This additional layer was deemed unnecessary and summarily dropped. As such, carrying around (and typing!) all these extra underbars is quite pointless. Here's a patch to nip this in the (sorta) bud. The macros only appear in 16 files so far, most of them being the definitions themselves. --- drivers/base/cpu.c | 2 +- drivers/base/memblk.c | 2 +- drivers/base/node.c | 2 +- include/asm-alpha/topology.h | 10 +++++----- include/asm-generic/topology.h | 24 ++++++++++++------------ include/asm-i386/cpu.h | 2 +- include/asm-i386/memblk.h | 2 +- include/asm-i386/node.h | 2 +- include/asm-i386/topology.h | 14 +++++++------- include/asm-ia64/topology.h | 18 +++++++++--------- include/asm-mips64/topology.h | 2 +- include/asm-ppc64/topology.h | 13 ++++--------- include/linux/mmzone.h | 2 +- kernel/sched.c | 10 +++++----- mm/page_alloc.c | 2 +- mm/vmscan.c | 2 +- 16 files changed, 52 insertions(+), 57 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 84a85241ce8a..1c729154c10c 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -35,7 +35,7 @@ struct device_driver cpu_driver = { */ int __init register_cpu(struct cpu *cpu, int num, struct node *root) { - cpu->node_id = __cpu_to_node(num); + cpu->node_id = cpu_to_node(num); cpu->sysdev.name = "cpu"; cpu->sysdev.id = num; if (root) diff --git a/drivers/base/memblk.c b/drivers/base/memblk.c index bac6fb235086..a8f27d612fc4 100644 --- a/drivers/base/memblk.c +++ b/drivers/base/memblk.c @@ -36,7 +36,7 @@ struct device_driver memblk_driver = { */ int __init register_memblk(struct memblk *memblk, int num, struct node *root) { - memblk->node_id = __memblk_to_node(num); + memblk->node_id = memblk_to_node(num); memblk->sysdev.name = "memblk"; memblk->sysdev.id = num; if (root) diff --git a/drivers/base/node.c b/drivers/base/node.c index 6ec8e58b888c..261bf881da60 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -72,7 +72,7 @@ int __init register_node(struct node *node, int num, struct node *parent) { int error; - node->cpumap = __node_to_cpu_mask(num); + node->cpumap = node_to_cpumask(num); node->sysroot.id = num; if (parent) node->sysroot.dev.parent = &parent->sysroot.sysdev; diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h index 074daa9353ae..fe77fb5b4105 100644 --- a/include/asm-alpha/topology.h +++ b/include/asm-alpha/topology.h @@ -6,7 +6,7 @@ #include #ifdef CONFIG_NUMA -static inline int __cpu_to_node(int cpu) +static inline int cpu_to_node(int cpu) { int node; @@ -23,13 +23,13 @@ static inline int __cpu_to_node(int cpu) return node; } -static inline int __node_to_cpu_mask(int node) +static inline int node_to_cpumask(int node) { unsigned long node_cpu_mask = 0; int cpu; for(cpu = 0; cpu < NR_CPUS; cpu++) { - if (cpu_online(cpu) && (__cpu_to_node(cpu) == node)) + if (cpu_online(cpu) && (cpu_to_node(cpu) == node)) node_cpu_mask |= 1UL << cpu; } @@ -40,8 +40,8 @@ static inline int __node_to_cpu_mask(int node) return node_cpu_mask; } -# define __node_to_memblk(node) (node) -# define __memblk_to_node(memblk) (memblk) +# define node_to_memblk(node) (node) +# define memblk_to_node(memblk) (memblk) #else /* CONFIG_NUMA */ # include diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h index 990654bc86ec..955763b04857 100644 --- a/include/asm-generic/topology.h +++ b/include/asm-generic/topology.h @@ -29,23 +29,23 @@ /* Other architectures wishing to use this simple topology API should fill in the below functions as appropriate in their own file. */ -#ifndef __cpu_to_node -#define __cpu_to_node(cpu) (0) +#ifndef cpu_to_node +#define cpu_to_node(cpu) (0) #endif -#ifndef __memblk_to_node -#define __memblk_to_node(memblk) (0) +#ifndef memblk_to_node +#define memblk_to_node(memblk) (0) #endif -#ifndef __parent_node -#define __parent_node(node) (0) +#ifndef parent_node +#define parent_node(node) (0) #endif -#ifndef __node_to_first_cpu -#define __node_to_first_cpu(node) (0) +#ifndef node_to_cpumask +#define node_to_cpumask(node) (cpu_online_map) #endif -#ifndef __node_to_cpu_mask -#define __node_to_cpu_mask(node) (cpu_online_map) +#ifndef node_to_first_cpu +#define node_to_first_cpu(node) (0) #endif -#ifndef __node_to_memblk -#define __node_to_memblk(node) (0) +#ifndef node_to_memblk +#define node_to_memblk(node) (0) #endif /* Cross-node load balancing interval. */ diff --git a/include/asm-i386/cpu.h b/include/asm-i386/cpu.h index 50b1d4439a44..b2b79ebda49b 100644 --- a/include/asm-i386/cpu.h +++ b/include/asm-i386/cpu.h @@ -17,7 +17,7 @@ static inline int arch_register_cpu(int num){ struct node *parent = NULL; #ifdef CONFIG_NUMA - parent = &node_devices[__cpu_to_node(num)].node; + parent = &node_devices[cpu_to_node(num)].node; #endif /* CONFIG_NUMA */ return register_cpu(&cpu_devices[num].cpu, num, parent); diff --git a/include/asm-i386/memblk.h b/include/asm-i386/memblk.h index a3a23052a93a..bd8187e358bb 100644 --- a/include/asm-i386/memblk.h +++ b/include/asm-i386/memblk.h @@ -14,7 +14,7 @@ struct i386_memblk { extern struct i386_memblk memblk_devices[MAX_NR_MEMBLKS]; static inline int arch_register_memblk(int num){ - int p_node = __memblk_to_node(num); + int p_node = memblk_to_node(num); return register_memblk(&memblk_devices[num].memblk, num, &node_devices[p_node].node); diff --git a/include/asm-i386/node.h b/include/asm-i386/node.h index 26836eb7be10..104f10b2bbf7 100644 --- a/include/asm-i386/node.h +++ b/include/asm-i386/node.h @@ -13,7 +13,7 @@ struct i386_node { extern struct i386_node node_devices[MAX_NUMNODES]; static inline int arch_register_node(int num){ - int p_node = __parent_node(num); + int p_node = parent_node(num); struct node *parent = NULL; if (p_node != num) diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index 53d8a01ef8a7..be697216b1e3 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h @@ -34,32 +34,32 @@ extern volatile unsigned long node_2_cpu_mask[]; extern volatile int cpu_2_node[]; /* Returns the number of the node containing CPU 'cpu' */ -static inline int __cpu_to_node(int cpu) +static inline int cpu_to_node(int cpu) { return cpu_2_node[cpu]; } /* Returns the number of the node containing MemBlk 'memblk' */ -#define __memblk_to_node(memblk) (memblk) +#define memblk_to_node(memblk) (memblk) /* Returns the number of the node containing Node 'node'. This architecture is flat, so it is a pretty simple function! */ -#define __parent_node(node) (node) +#define parent_node(node) (node) /* Returns a bitmask of CPUs on Node 'node'. */ -static inline unsigned long __node_to_cpu_mask(int node) +static inline unsigned long node_to_cpumask(int node) { return node_2_cpu_mask[node]; } /* Returns the number of the first CPU on Node 'node'. */ -static inline int __node_to_first_cpu(int node) +static inline int node_to_first_cpu(int node) { - return __ffs(__node_to_cpu_mask(node)); + return __ffs(node_to_cpumask(node)); } /* Returns the number of the first MemBlk on Node 'node' */ -#define __node_to_memblk(node) (node) +#define node_to_memblk(node) (node) /* Cross-node load balancing interval. */ #define NODE_BALANCE_RATE 100 diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index 22a5aaca8d21..b154e116980e 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -21,25 +21,25 @@ /* * Returns the number of the node containing CPU 'cpu' */ -#define __cpu_to_node(cpu) (int)(cpu_to_node_map[cpu]) +#define cpu_to_node(cpu) (int)(cpu_to_node_map[cpu]) /* * Returns a bitmask of CPUs on Node 'node'. */ -#define __node_to_cpu_mask(node) (node_to_cpu_mask[node]) +#define node_to_cpumask(node) (node_to_cpumask[node]) #else -#define __cpu_to_node(cpu) (0) -#define __node_to_cpu_mask(node) (phys_cpu_present_map) +#define cpu_to_node(cpu) (0) +#define node_to_cpumask(node) (phys_cpu_present_map) #endif /* * Returns the number of the node containing MemBlk 'memblk' */ #ifdef CONFIG_ACPI_NUMA -#define __memblk_to_node(memblk) (node_memblk[memblk].nid) +#define memblk_to_node(memblk) (node_memblk[memblk].nid) #else -#define __memblk_to_node(memblk) (memblk) +#define memblk_to_node(memblk) (memblk) #endif /* @@ -47,18 +47,18 @@ * Not implemented here. Multi-level hierarchies detected with * the help of node_distance(). */ -#define __parent_node(nid) (nid) +#define parent_node(nid) (nid) /* * Returns the number of the first CPU on Node 'node'. */ -#define __node_to_first_cpu(node) (__ffs(__node_to_cpu_mask(node))) +#define node_to_first_cpu(node) (__ffs(node_to_cpumask(node))) /* * Returns the number of the first MemBlk on Node 'node' * Should be fixed when IA64 discontigmem goes in. */ -#define __node_to_memblk(node) (node) +#define node_to_memblk(node) (node) /* Cross-node load balancing interval. */ #define NODE_BALANCE_RATE 10 diff --git a/include/asm-mips64/topology.h b/include/asm-mips64/topology.h index fe5988686b1d..04b0168e8736 100644 --- a/include/asm-mips64/topology.h +++ b/include/asm-mips64/topology.h @@ -3,6 +3,6 @@ #include -#define __cpu_to_node(cpu) (cputocnode(cpu)) +#define cpu_to_node(cpu) (cputocnode(cpu)) #endif /* _ASM_MIPS64_TOPOLOGY_H */ diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h index c3b4266c2ebf..ecc6cab2895e 100644 --- a/include/asm-ppc64/topology.h +++ b/include/asm-ppc64/topology.h @@ -5,7 +5,7 @@ #ifdef CONFIG_NUMA -static inline int __cpu_to_node(int cpu) +static inline int cpu_to_node(int cpu) { int node; @@ -19,7 +19,7 @@ static inline int __cpu_to_node(int cpu) return node; } -static inline int __node_to_first_cpu(int node) +static inline int node_to_first_cpu(int node) { int cpu; @@ -31,7 +31,7 @@ static inline int __node_to_first_cpu(int node) return -1; } -static inline unsigned long __node_to_cpu_mask(int node) +static inline unsigned long node_to_cpumask(int node) { int cpu; unsigned long mask = 0UL; @@ -51,12 +51,7 @@ static inline unsigned long __node_to_cpu_mask(int node) #else /* !CONFIG_NUMA */ -#define __cpu_to_node(cpu) (0) -#define __memblk_to_node(memblk) (0) -#define __parent_node(nid) (0) -#define __node_to_first_cpu(node) (0) -#define __node_to_cpu_mask(node) (cpu_online_map) -#define __node_to_memblk(node) (0) +#include #endif /* CONFIG_NUMA */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index bcb57ed21a8d..8db7ca4df8f2 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -257,7 +257,7 @@ static inline struct zone *next_zone(struct zone *zone) #include /* Returns the number of the current Node. */ -#define numa_node_id() (__cpu_to_node(smp_processor_id())) +#define numa_node_id() (cpu_to_node(smp_processor_id())) #ifndef CONFIG_DISCONTIGMEM extern struct pglist_data contig_page_data; diff --git a/kernel/sched.c b/kernel/sched.c index d2318d53b087..3e072580a244 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -213,7 +213,7 @@ __init void node_nr_running_init(void) int i; for (i = 0; i < NR_CPUS; i++) - cpu_rq(i)->node_nr_running = &node_nr_running[__cpu_to_node(i)]; + cpu_rq(i)->node_nr_running = &node_nr_running[cpu_to_node(i)]; } #else /* !CONFIG_NUMA */ @@ -715,7 +715,7 @@ static int sched_best_cpu(struct task_struct *p) } minload = 10000000; - cpumask = __node_to_cpu_mask(node); + cpumask = node_to_cpumask(node); for (i = 0; i < NR_CPUS; ++i) { if (!(cpumask & (1UL << i))) continue; @@ -767,7 +767,7 @@ static int find_busiest_node(int this_node) static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq) { - int this_node = __cpu_to_node(this_cpu); + int this_node = cpu_to_node(this_cpu); /* * Avoid rebalancing between nodes too often. * We rebalance globally once every NODE_BALANCE_RATE load balances. @@ -776,9 +776,9 @@ static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq) int node = find_busiest_node(this_node); this_rq->nr_balanced = 0; if (node >= 0) - return (__node_to_cpu_mask(node) | (1UL << this_cpu)); + return (node_to_cpumask(node) | (1UL << this_cpu)); } - return __node_to_cpu_mask(this_node); + return node_to_cpumask(this_node); } #else /* !CONFIG_NUMA */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0112d0eb63cf..ef7d20c61e46 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1269,7 +1269,7 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat, pgdat->node_mem_map = node_mem_map; free_area_init_core(pgdat, zones_size, zholes_size); - memblk_set_online(__node_to_memblk(nid)); + memblk_set_online(node_to_memblk(nid)); calculate_zone_bitmap(pgdat, zones_size); } diff --git a/mm/vmscan.c b/mm/vmscan.c index 60c534dc4129..0fc00047b27c 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -929,7 +929,7 @@ int kswapd(void *p) DEFINE_WAIT(wait); daemonize(); - set_cpus_allowed(tsk, __node_to_cpu_mask(pgdat->node_id)); + set_cpus_allowed(tsk, node_to_cpumask(pgdat->node_id)); sprintf(tsk->comm, "kswapd%d", pgdat->node_id); sigfillset(&tsk->blocked); -- cgit v1.2.3 From b312379d0d8e5ed6647c8a48de05aad2c205b8e6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 3 Feb 2003 17:01:37 -0800 Subject: [PATCH] misc fixes - Fix dead comment in load_elf_interp() (Dave Airlie) - Add some (hard-won) commentary around the early SET_PERSONALITY() in load_elf_binary(). - Remove dead hugetlb prototype. - Fix some silliness in hugetlbpage.c --- arch/i386/mm/hugetlbpage.c | 4 ++-- fs/binfmt_elf.c | 21 +++++++++++++++++++-- include/linux/hugetlb.h | 1 - 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index 1663e7730a18..2dc1534f420d 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -283,8 +283,8 @@ int try_to_free_low(int count) break; } page = list_entry(p, struct page, list); - if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem - map = page; + if (!PageHighMem(page)) + map = page; } if (map) { list_del(&map->list); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 962094391026..0d214c4a54fd 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -362,8 +362,6 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, } } - /* Now use mmap to map the library into memory. */ - /* * Now fill out the bss section. First pad the last page up * to the page boundary, and then perform a mmap to make sure @@ -536,6 +534,25 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; + /* + * The early SET_PERSONALITY here is so that the lookup + * for the interpreter happens in the namespace of the + * to-be-execed image. SET_PERSONALITY can select an + * alternate root. + * + * However, SET_PERSONALITY is NOT allowed to switch + * this task into the new images's memory mapping + * policy - that is, TASK_SIZE must still evaluate to + * that which is appropriate to the execing application. + * This is because exit_mmap() needs to have TASK_SIZE + * evaluate to the size of the old image. + * + * So if (say) a 64-bit application is execing a 32-bit + * application it is the architecture's responsibility + * to defer changing the value of TASK_SIZE until the + * switch really is going to happen - do this in + * flush_thread(). - akpm + */ SET_PERSONALITY(elf_ex, ibcs2_interpreter); interpreter = open_exec(elf_interpreter); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 3bf94e2205bd..325d91ba012a 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -18,7 +18,6 @@ void zap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); int hugetlb_prefault(struct address_space *, struct vm_area_struct *); void huge_page_release(struct page *); -void hugetlb_release_key(struct hugetlb_key *); int hugetlb_report_meminfo(char *); int is_hugepage_mem_enough(size_t); -- cgit v1.2.3 From 81c0cfccff334bf6e9c35233fb53341ff1b47f9a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 3 Feb 2003 18:02:57 -0800 Subject: [PATCH] PA-RISC updates for 2.5.59 - conversion of remaining drivers to generic device model - more of sfr's compat stuff - eliminate some bogus syscalls - update for MUX driver - beginnings of new module code - tell the keyboard driver about CONFIG_PARISC --- arch/parisc/Makefile | 6 +- arch/parisc/kernel/irq.c | 6 +- arch/parisc/kernel/module.c | 432 +++++++++++++++++++++++++++++++++----- arch/parisc/kernel/parisc_ksyms.c | 4 - arch/parisc/kernel/signal32.c | 53 ----- arch/parisc/kernel/sys_parisc32.c | 68 ------ arch/parisc/kernel/syscall.S | 41 ++-- arch/parisc/kernel/traps.c | 6 +- drivers/char/keyboard.c | 2 +- drivers/net/lasi_82596.c | 63 +++--- drivers/parisc/ccio-dma.c | 32 --- drivers/parisc/sba_iommu.c | 6 +- drivers/parport/parport_gsc.c | 1 + drivers/serial/8250_gsc.c | 20 +- drivers/serial/mux.c | 170 +++++++++------ fs/binfmt_som.c | 2 +- include/asm-parisc/bitops.h | 9 +- include/asm-parisc/compat.h | 20 ++ include/asm-parisc/dma-mapping.h | 2 - include/asm-parisc/module.h | 8 + include/asm-parisc/smp.h | 3 +- include/linux/elf.h | 168 +++++++++++++++ include/linux/pci_ids.h | 6 +- 23 files changed, 761 insertions(+), 367 deletions(-) (limited to 'include/linux') diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 0ddc46b05151..973d26aeabd9 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -33,10 +33,10 @@ FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align OBJCOPY_FLAGS =-O binary -R .note -R .comment -S -cflags-y := -D__linux__ -pipe -fno-strength-reduce +cflags-y := -pipe -# These should be on for older toolchains or SOM toolchains that don't -# enable them by default. +# These flags should be implied by an hppa-linux configuration, but they +# are not in gcc 3.2. cflags-y += -mno-space-regs -mfast-indirect-calls # No fixed-point multiply diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index f09a9419796a..4abe55cdd129 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -243,7 +243,7 @@ int show_interrupts(struct seq_file *p, void *v) for (i = 0; i <= MAX_CPU_IRQ; i++) { struct irqaction *action = ®ion->action[i]; unsigned int irq_no = IRQ_FROM_REGION(regnr) + i; - int j=0; + int j = 0; if (!action->handler) continue; @@ -251,7 +251,7 @@ int show_interrupts(struct seq_file *p, void *v) #ifdef CONFIG_SMP for (; j < NR_CPUS; j++) #endif - seq_printf(p, "%10u ", kstat_cpu(j).irqs[regnr][irq_no]); + seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq_no]); seq_printf(p, " %14s", region->data.name ? region->data.name : "N/A"); @@ -388,7 +388,7 @@ void do_irq(struct irqaction *action, int irq, struct pt_regs * regs) int cpu = smp_processor_id(); irq_enter(); - ++kstat_cpu(cpu).irqs[IRQ_REGION(irq)][IRQ_OFFSET(irq)]; + ++kstat_cpu(cpu).irqs[irq]; DBG_IRQ(irq, ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq))); diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index c995e0329558..b8e33137ccff 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -13,6 +13,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + (c) 2003 Randolph Chung + + The best reference for this stuff is probably the Processor- + Specific ELF Supplement for PA-RISC: + http://ftp.parisc-linux.org/docs/elf-pa-hp.pdf */ #include #include @@ -21,19 +27,92 @@ #include #include -#if 0 +#if 1 #define DEBUGP printk #else #define DEBUGP(fmt...) #endif -enum parisc_fsel { - e_fsel, - e_lsel, - e_rsel, - e_lrsel, - e_rrsel + +#ifndef __LP64__ +struct got_entry { + Elf32_Addr addr; +}; + +struct fdesc_entry { + Elf32_Addr gp; + Elf32_Addr addr; +}; + +struct stub_entry { + Elf32_Word insns[2]; /* each stub entry has two insns */ +}; +#else +struct got_entry { + Elf64_Addr addr; +}; + +struct fdesc_entry { + Elf64_Addr dummy[2]; + Elf64_Addr gp; + Elf64_Addr addr; +}; + +struct stub_entry { + Elf64_Word insns[4]; /* each stub entry has four insns */ }; +#endif + +/* Field selection types defined by hppa */ +#define rnd(x) (((x)+0x1000)&~0x1fff) +/* fsel: full 32 bits */ +#define fsel(v,a) ((v)+(a)) +/* lsel: select left 21 bits */ +#define lsel(v,a) (((v)+(a))>>11) +/* rsel: select right 11 bits */ +#define rsel(v,a) (((v)+(a))&0x7ff) +/* lrsel with rounding of addend to nearest 8k */ +#define lrsel(v,a) (((v)+rnd(a))>>11) +/* rrsel with rounding of addend to nearest 8k */ +#define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a))) + +#define mask(x,sz) ((x) & ~((1<<(sz))-1)) + + +/* The reassemble_* functions prepare an immediate value for + insertion into an opcode. pa-risc uses all sorts of weird bitfields + in the instruction to hold the value. */ +static inline int reassemble_14(int as14) +{ + return (((as14 & 0x1fff) << 1) | + ((as14 & 0x2000) >> 13)); +} + +static inline int reassemble_17(int as17) +{ + return (((as17 & 0x10000) >> 16) | + ((as17 & 0x0f800) << 5) | + ((as17 & 0x00400) >> 8) | + ((as17 & 0x003ff) << 3)); +} + +static inline int reassemble_21(int as21) +{ + return (((as21 & 0x100000) >> 20) | + ((as21 & 0x0ffe00) >> 8) | + ((as21 & 0x000180) << 7) | + ((as21 & 0x00007c) << 14) | + ((as21 & 0x000003) << 12)); +} + +static inline int reassemble_22(int as22) +{ + return (((as22 & 0x200000) >> 21) | + ((as22 & 0x1f0000) << 5) | + ((as22 & 0x00f800) << 5) | + ((as22 & 0x000400) >> 8) | + ((as22 & 0x0003ff) << 3)); +} void *module_alloc(unsigned long size) { @@ -42,6 +121,81 @@ void *module_alloc(unsigned long size) return vmalloc(size); } +#ifndef __LP64__ +static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) +{ + return 0; +} + +static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) +{ + return 0; +} + +static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) +{ + unsigned long cnt = 0; + + for (; n > 0; n--, rela++) + { + switch (ELF32_R_TYPE(rela->r_info)) { + case R_PARISC_PCREL17F: + case R_PARISC_PCREL22F: + cnt++; + } + } + + return cnt; +} +#else +static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) +{ + unsigned long cnt = 0; + + for (; n > 0; n--, rela++) + { + switch (ELF64_R_TYPE(rela->r_info)) { + case R_PARISC_LTOFF21L: + case R_PARISC_LTOFF14R: + case R_PARISC_PCREL22F: + cnt++; + } + } + + return cnt; +} + +static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) +{ + unsigned long cnt = 3; /* 3 for finalize */ + + for (; n > 0; n--, rela++) + { + switch (ELF64_R_TYPE(rela->r_info)) { + case R_PARISC_FPTR64: + cnt++; + } + } + + return cnt; +} + +static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) +{ + unsigned long cnt = 0; + + for (; n > 0; n--, rela++) + { + switch (ELF64_R_TYPE(rela->r_info)) { + case R_PARISC_PCREL22F: + cnt++; + } + } + + return cnt; +} +#endif + /* Free memory returned from module_alloc */ void module_free(struct module *mod, void *module_region) @@ -51,35 +205,145 @@ void module_free(struct module *mod, void *module_region) table entries. */ } -/* We don't need anything special. */ -long module_core_size(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, - struct module *module) +#define CONST +int module_frob_arch_sections(CONST Elf_Ehdr *hdr, + CONST Elf_Shdr *sechdrs, + CONST char *secstrings, + struct module *me) { - return module->core_size; + unsigned long gots = 0, fdescs = 0, stubs = 0; + unsigned int i; + + for (i = 1; i < hdr->e_shnum; i++) { + const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; + unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); + + if (sechdrs[i].sh_type != SHT_RELA) + continue; + + /* some of these are not relevant for 32-bit/64-bit + * we leave them here to make the code common. the + * compiler will do its thing and optimize out the + * stuff we don't need + */ + gots += count_gots(rels, nrels); + fdescs += count_fdescs(rels, nrels); + stubs += count_stubs(rels, nrels); + } + + /* align things a bit */ + me->core_size = ALIGN(me->core_size, 16); + me->arch.got_offset = me->core_size; + me->core_size += gots * sizeof(struct got_entry); + + me->core_size = ALIGN(me->core_size, 16); + me->arch.fdesc_offset = me->core_size; + me->core_size += stubs * sizeof(struct fdesc_entry); + + me->core_size = ALIGN(me->core_size, 16); + me->arch.stub_offset = me->core_size; + me->core_size += stubs * sizeof(struct stub_entry); + + return 0; } -long module_init_size(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - const char *secstrings, - struct module *module) +static Elf_Addr get_got(struct module *me, unsigned long value, long addend) { - return module->init_size; + unsigned int i; + struct got_entry *got; + + value += addend; + + BUG_ON(value == 0); + + got = me->module_core + me->arch.got_offset; + for (i = 0; got[i].addr; i++) + if (got[i].addr == value) + return i * sizeof(struct got_entry); + + got[i].addr = value; + return i * sizeof(struct got_entry); } -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) +static Elf_Addr get_fdesc(struct module *me, unsigned long value) { - /* parisc should not need this ... */ - printk(KERN_ERR "module %s: %s not yet implemented.\n", - mod->name, __FUNCTION__); - return 0; + struct fdesc_entry *fdesc = me->module_core + me->arch.fdesc_offset; + + if (!value) { + printk(KERN_ERR "%s: zero OPD requested!\n", me->name); + return 0; + } + + /* Look for existing fdesc entry. */ + while (fdesc->addr) { + if (fdesc->addr == value) + return (Elf_Addr)fdesc; + fdesc++; + } + + /* Create new one */ + fdesc->addr = value; + fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; + return (Elf_Addr)fdesc; } +static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, + int millicode) +{ + unsigned long i; + struct stub_entry *stub; + + i = me->arch.stub_count++; + stub = me->module_core + me->arch.stub_offset + + i * sizeof(struct stub_entry); + +#ifndef __LP64__ +/* for 32-bit the stub looks like this: + * ldil L'XXX,%r1 + * be,n R'XXX(%sr4,%r1) + */ + stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */ + stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */ + + stub->insns[0] |= reassemble_21(lrsel(value, addend)); + stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); +#else +/* for 64-bit we have two kinds of stubs: + * for normal function calls: + * ldd 0(%dp),%dp + * ldd 10(%dp), %r1 + * bve (%r1) + * ldd 18(%dp), %dp + * + * for millicode: + * ldil 0, %r1 + * ldo 0(%r1), %r1 + * ldd 10(%r1), %r1 + * bve,n (%r1) + */ + if (!millicode) + { + stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ + stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ + stub->insns[2] = 0xe820d000; /* bve (%r1) */ + stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ + stub->insns[0] |= reassemble_21(get_got(me, value, addend)); + } + else + { + stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ + stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ + stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ + stub->insns[3] = 0xe820d002; /* bve,n (%r1) */ + + stub->insns[0] |= reassemble_21(lrsel(value, addend)); + stub->insns[1] |= reassemble_14(rrsel(value, addend)); + } +#endif + + return (Elf_Addr)stub; +} int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, @@ -104,7 +368,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; Elf32_Sym *sym; Elf32_Word *loc; - Elf32_Addr value; + Elf32_Addr val; + Elf32_Sword addend; + Elf32_Addr dot; + register unsigned long dp asm ("r27"); DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); @@ -120,59 +387,81 @@ int apply_relocate_add(Elf_Shdr *sechdrs, me->name, strtab + sym->st_name); return -ENOENT; } + dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; - value = sym->st_value + rel[i].r_addend; + val = sym->st_value; + addend = rel[i].r_addend; - DEBUGP("Symbol %s loc 0x%lx value 0x%lx: ", +#if 0 +#define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t : + DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", strtab + sym->st_name, - (uint32_t)loc, value); + (uint32_t)loc, val, addend, + r(R_PARISC_PLABEL32) + r(R_PARISC_DIR32) + r(R_PARISC_DIR21L) + r(R_PARISC_DIR14R) + r(R_PARISC_SEGREL32) + r(R_PARISC_DPREL21L) + r(R_PARISC_DPREL14R) + r(R_PARISC_PCREL17F) + r(R_PARISC_PCREL22F) + "UNKNOWN"); +#undef r +#endif switch (ELF32_R_TYPE(rel[i].r_info)) { case R_PARISC_PLABEL32: /* 32-bit function address */ - DEBUGP("R_PARISC_PLABEL32\n"); + /* no function descriptors... */ + *loc = fsel(val, addend); break; case R_PARISC_DIR32: /* direct 32-bit ref */ - DEBUGP("R_PARISC_DIR32\n"); + *loc = fsel(val, addend); break; case R_PARISC_DIR21L: /* left 21 bits of effective address */ - DEBUGP("R_PARISC_DIR21L\n"); + *loc = mask(*loc, 21) | reassemble_21(lrsel(val, addend)); break; case R_PARISC_DIR14R: /* right 14 bits of effective address */ - DEBUGP("R_PARISC_DIR14R\n"); + *loc = mask(*loc, 14) | reassemble_14(rrsel(val, addend)); break; case R_PARISC_SEGREL32: /* 32-bit segment relative address */ - DEBUGP("R_PARISC_SEGREL32\n"); + val -= (uint32_t)me->module_core; + *loc = fsel(val, addend); break; case R_PARISC_DPREL21L: /* left 21 bit of relative address */ - DEBUGP("R_PARISC_DPREL21L\n"); + val -= dp; + *loc = mask(*loc, 21) | reassemble_21(lrsel(val, addend) - dp); break; case R_PARISC_DPREL14R: /* right 14 bit of relative address */ - DEBUGP("R_PARISC_DPREL14R\n"); + val -= dp; + *loc = mask(*loc, 14) | reassemble_14(rrsel(val, addend) - dp); break; case R_PARISC_PCREL17F: /* 17-bit PC relative address */ - DEBUGP("R_PARISC_PCREL17F\n"); + val = get_stub(me, val, addend, 0) - dot - 8; + *loc = (*loc&0x1f1ffd) | reassemble_17(val); break; case R_PARISC_PCREL22F: - /* 22-bit PC relative address */ - DEBUGP("R_PARISC_PCREL22F\n"); + /* 22-bit PC relative address; only defined for pa20 */ + val = get_stub(me, val, addend, 0) - dot - 8; + *loc = (*loc&0x3ff1ffd) | reassemble_22(val); break; default: - printk(KERN_ERR "module %s: Unknown relocation: %Lu\n", + printk(KERN_ERR "module %s: Unknown relocation: %u\n", me->name, ELF32_R_TYPE(rel[i].r_info)); return -ENOEXEC; } } - return -ENOEXEC; + return 0; } #else @@ -186,7 +475,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; Elf64_Sym *sym; Elf64_Word *loc; - Elf64_Addr value; + Elf64_Addr val; + Elf64_Sxword addend; + Elf64_Addr dot; DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); @@ -202,38 +493,56 @@ int apply_relocate_add(Elf_Shdr *sechdrs, me->name, strtab + sym->st_name); return -ENOENT; } + dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; - value = sym->st_value + rel[i].r_addend; + val = sym->st_value; + addend = rel[i].r_addend; - DEBUGP("Symbol %s loc 0x%Lx value 0x%Lx: ", +#if 1 +#define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t : + DEBUGP("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n", strtab + sym->st_name, - (uint64_t)loc, value); + loc, val, addend, + r(R_PARISC_LTOFF14R) + r(R_PARISC_LTOFF21L) + r(R_PARISC_PCREL22F) + r(R_PARISC_DIR64) + r(R_PARISC_SEGREL32) + r(R_PARISC_FPTR64) + "UNKNOWN"); +#undef r +#endif switch (ELF64_R_TYPE(rel[i].r_info)) { - case R_PARISC_LTOFF14R: - /* LT-relative; right 14 bits */ - DEBUGP("R_PARISC_LTOFF14R\n"); - break; case R_PARISC_LTOFF21L: /* LT-relative; left 21 bits */ - DEBUGP("R_PARISC_LTOFF21L\n"); + *loc = mask(*loc, 21) | reassemble_21(get_got(me, val, addend)); + break; + case R_PARISC_LTOFF14R: + /* L(ltoff(val+addend)) */ + /* LT-relative; right 14 bits */ + *loc = mask(*loc, 14) | reassemble_14(get_got(me, val, addend)); break; case R_PARISC_PCREL22F: /* PC-relative; 22 bits */ - DEBUGP("R_PARISC_PCREL22F\n"); + if (strncmp(strtab + sym->st_name, "$$", 2) == 0) + val = get_stub(me, val, addend, 1) - dot - 8; + else + val = get_stub(me, val, addend, 0) - dot - 8; + *loc = (*loc&0x3ff1ffd) | reassemble_22(val); break; case R_PARISC_DIR64: /* 64-bit effective address */ - DEBUGP("R_PARISC_DIR64\n"); - *loc = value; + *loc = fsel(val, addend); break; case R_PARISC_SEGREL32: /* 32-bit segment relative address */ - DEBUGP("R_PARISC_SEGREL32\n"); + val -= (uint64_t)me->module_core; + *loc = fsel(val, addend); break; case R_PARISC_FPTR64: /* 64-bit function address */ - DEBUGP("R_PARISC_FPTR64\n"); + *loc = get_fdesc(me, val+addend); break; default: @@ -242,7 +551,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, return -ENOEXEC; } } - return -ENOEXEC; + return 0; } #endif @@ -250,5 +559,14 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { +#ifdef __LP64__ + me->init = (void *)get_fdesc(me, (Elf_Addr)me->init); +#ifdef CONFIG_MODULE_UNLOAD + if (me->cleanup) + me->cleanup = (void *)get_fdesc(me, (Elf_Addr)me->cleanup); + if (me->destroy) + me->destroy = (void *)get_fdesc(me, (Elf_Addr)me->destroy); +#endif +#endif return 0; } diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 63e7d7b5ff13..9813d4678790 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -31,10 +31,6 @@ EXPORT_SYMBOL(hppa_dma_ops); EXPORT_SYMBOL(get_pci_node_path); #endif -#ifdef CONFIG_IOMMU_CCIO -EXPORT_SYMBOL(ccio_get_fake); -#endif - #include #include EXPORT_SYMBOL(enable_irq); diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 0bb353f0733f..c1af9ab751c2 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -17,59 +17,6 @@ struct k_sigaction32 { struct sigaction32 sa; }; -typedef unsigned int old_sigset_t32; - -static int -put_old_sigset32(old_sigset_t32 *up, old_sigset_t *set) -{ - old_sigset_t32 set32 = *set; - return put_user(set32, up); -} - -static int -get_old_segset32(old_sigset_t32 *up, old_sigset_t *set) -{ - old_sigset_t32 set32; - int r; - - if ((r = get_user(set32, up)) == 0) - *set = set32; - - return r; -} - -long -sys32_sigpending(old_sigset_t32 *set) -{ - extern long sys_sigpending(old_sigset_t *set); - old_sigset_t pending; - int ret; - - KERNEL_SYSCALL(ret, sys_sigpending, &pending); - - /* can't put_user an old_sigset_t -- it is too big */ - if (put_old_sigset32(set, &pending)) - return -EFAULT; - - return ret; -} - -int sys32_sigprocmask(int how, old_sigset_t32 *set, - old_sigset_t32 *oset) -{ - extern int sys_sigprocmask(int how, old_sigset_t *set, - old_sigset_t *oset); - old_sigset_t s; - int ret; - - if (set && get_old_segset32 (set, &s)) - return -EFAULT; - KERNEL_SYSCALL(ret, sys_sigprocmask, how, set ? &s : NULL, oset ? &s : NULL); - if (!ret && oset && put_old_sigset32(oset, &s)) - return -EFAULT; - return ret; -} - static inline void sigset_32to64(sigset_t *s64, sigset_t32 *s32) { diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 7d14a688e518..de994c1e6d1f 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -314,74 +314,6 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, return -ENOSYS; } -/* 32-bit user apps use struct statfs which uses 'long's */ -struct statfs32 { - __s32 f_type; - __s32 f_bsize; - __s32 f_blocks; - __s32 f_bfree; - __s32 f_bavail; - __s32 f_files; - __s32 f_ffree; - __kernel_fsid_t f_fsid; - __s32 f_namelen; - __s32 f_spare[6]; -}; - -/* convert statfs struct to statfs32 struct and copy result to user */ -static unsigned long statfs32_to_user(struct statfs32 *ust32, struct statfs *st) -{ - struct statfs32 st32; -#undef CP -#define CP(a) st32.a = st->a - CP(f_type); - CP(f_bsize); - CP(f_blocks); - CP(f_bfree); - CP(f_bavail); - CP(f_files); - CP(f_ffree); - CP(f_fsid); - CP(f_namelen); - return copy_to_user(ust32, &st32, sizeof st32); -} - -/* The following statfs calls are copies of code from linux/fs/open.c and - * should be checked against those from time to time */ -asmlinkage long sys32_statfs(const char * path, struct statfs32 * buf) -{ - struct nameidata nd; - int error; - - error = user_path_walk(path, &nd); - if (!error) { - struct statfs tmp; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); - if (!error && statfs32_to_user(buf, &tmp)) - error = -EFAULT; - path_release(&nd); - } - return error; -} - -asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 * buf) -{ - struct file * file; - struct statfs tmp; - int error; - - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); - if (!error && statfs32_to_user(buf, &tmp)) - error = -EFAULT; - fput(file); -out: - return error; -} - extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 02f676ee84e6..acde743c0fb0 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -425,30 +425,27 @@ sys_call_table: /* I don't like this */ ENTRY_UHOH(sgetmask) ENTRY_UHOH(ssetmask) - ENTRY_SAME(setreuid) /* 70 */ + ENTRY_SAME(setreuid) /* 70 */ ENTRY_SAME(setregid) ENTRY_SAME(mincore) - ENTRY_DIFF(sigpending) + ENTRY_COMP(sigpending) ENTRY_SAME(sethostname) /* Following 3 have linux-common-code structs containing longs -( */ - ENTRY_DIFF(setrlimit) /* 75 */ + ENTRY_DIFF(setrlimit) /* 75 */ ENTRY_DIFF(getrlimit) ENTRY_DIFF(getrusage) /* struct timeval and timezone are maybe?? consistent wide and narrow */ ENTRY_DIFF(gettimeofday) ENTRY_DIFF(settimeofday) - ENTRY_SAME(getgroups) /* 80 */ + ENTRY_SAME(getgroups) /* 80 */ ENTRY_SAME(setgroups) /* struct socketaddr... */ ENTRY_SAME(sendto) ENTRY_SAME(symlink) /* see stat comment */ ENTRY_COMP(newlstat) - ENTRY_SAME(readlink) /* 85 */ - /* suspect we'll need some work for narrow shlibs on wide kernel */ - /* NOTE this doesn't get used when I boot 32-bit userspace */ - /* containing working shlib apps -- can this be nuked? */ - ENTRY_UHOH(uselib) + ENTRY_SAME(readlink) /* 85 */ + ENTRY_SAME(ni_syscall) /* was uselib */ ENTRY_SAME(swapon) ENTRY_SAME(reboot) ENTRY_SAME(mmap2) @@ -461,17 +458,15 @@ sys_call_table: ENTRY_SAME(getpriority) ENTRY_SAME(setpriority) ENTRY_SAME(recv) - ENTRY_DIFF(statfs) - ENTRY_DIFF(fstatfs) /* 100 */ + ENTRY_COMP(statfs) + ENTRY_COMP(fstatfs) /* 100 */ ENTRY_SAME(stat64) - /* don't think hppa glibc even provides an entry pt for this - * so disable for now */ - ENTRY_UHOH(socketcall) + ENTRY_SAME(ni_syscall) /* was socketcall */ ENTRY_SAME(syslog) /* even though manpage says struct timeval contains longs, ours has * time_t and suseconds_t -- both of which are safe wide/narrow */ ENTRY_COMP(setitimer) - ENTRY_COMP(getitimer) /* 105 */ + ENTRY_COMP(getitimer) /* 105 */ ENTRY_SAME(capget) ENTRY_SAME(capset) ENTRY_OURS(pread64) @@ -494,10 +489,10 @@ sys_call_table: ENTRY_SAME(recvfrom) /* struct timex contains longs */ ENTRY_DIFF(adjtimex) - ENTRY_SAME(mprotect) /* 125 */ + ENTRY_SAME(mprotect) /* 125 */ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */ - ENTRY_DIFF(sigprocmask) - ENTRY_SAME(ni_syscall) /* create_module */ + ENTRY_COMP(sigprocmask) + ENTRY_SAME(ni_syscall) /* create_module */ ENTRY_SAME(init_module) ENTRY_SAME(delete_module) ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */ @@ -547,13 +542,13 @@ sys_call_table: ENTRY_COMP(nanosleep) ENTRY_SAME(mremap) ENTRY_SAME(setresuid) - ENTRY_SAME(getresuid) /* 165 */ + ENTRY_SAME(getresuid) /* 165 */ ENTRY_DIFF(sigaltstack_wrapper) ENTRY_SAME(ni_syscall) /* query_module */ ENTRY_SAME(poll) /* structs contain pointers and an in_addr... */ ENTRY_DIFF(nfsservctl) - ENTRY_SAME(setresgid) /* 170 */ + ENTRY_SAME(setresgid) /* 170 */ ENTRY_SAME(getresgid) ENTRY_SAME(prctl) /* signals need a careful review */ @@ -594,15 +589,9 @@ sys_call_table: ENTRY_OURS(ftruncate64) /* 200 */ ENTRY_SAME(getdents64) ENTRY_DIFF(fcntl64) -#ifdef CONFIG_XFS_FS - ENTRY_SAME(attrctl) - ENTRY_SAME(acl_get) - ENTRY_SAME(acl_set) /* 205 */ -#else ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) /* 205 */ -#endif ENTRY_SAME(gettid) ENTRY_SAME(readahead) ENTRY_SAME(ni_syscall) /* tkill */ diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 1ea93d50efcc..e04f3ed3810d 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -123,7 +123,11 @@ void dump_stack(void) } -static int kstack_depth_to_print = 48; +#ifndef __LP64__ +static int kstack_depth_to_print = 64 * 4; +#else +static int kstack_depth_to_print = 128 * 4; +#endif void show_stack(unsigned long *sp) { diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index bc1dfea7021d..8d59b8a25d21 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -918,7 +918,7 @@ static void kbd_bh(unsigned long dummy) DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); -#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) static unsigned short x86_keycodes[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index a2b744f10623..888eb07e1050 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -91,6 +91,7 @@ #include #include #include +#include static char version[] __devinitdata = "82596.c $Revision: 1.29 $\n"; @@ -121,13 +122,13 @@ static char version[] __devinitdata = #define CHECK_WBACK(addr,len) \ - do { if (!dma_consistent) dma_cache_wback((unsigned long)addr,len); } while (0) + do { dma_cache_sync((void *)addr, len, DMA_TO_DEVICE); } while (0) #define CHECK_INV(addr,len) \ - do { if (!dma_consistent) dma_cache_inv((unsigned long)addr,len); } while(0) + do { dma_cache_sync((void *)addr,len, DMA_FROM_DEVICE); } while(0) #define CHECK_WBACK_INV(addr,len) \ - do { if (!dma_consistent) dma_cache_wback_inv((unsigned long)addr,len); } while (0) + do { dma_cache_sync((void *)addr,len, DMA_BIDIRECTIONAL); } while (0) #define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ @@ -383,6 +384,7 @@ struct i596_private { int options; spinlock_t lock; dma_addr_t dma_addr; + struct device *dev; }; static char init_setup[] = @@ -402,10 +404,6 @@ static char init_setup[] = 0x00, 0x7f /* *multi IA */ }; -static struct pci_dev *fake_pci_dev; /* The fake pci_dev needed for - pci_* functions under ccio. */ -static int dma_consistent = 1; /* Zero if pci_alloc_consistent() fails */ - static int i596_open(struct net_device *dev); static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev); static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -558,8 +556,8 @@ static inline void init_rx_bufs(struct net_device *dev) if (skb == NULL) panic("82596: alloc_skb() failed"); skb_reserve(skb, 2); - dma_addr = pci_map_single(fake_pci_dev, skb->tail,PKT_BUF_SZ, - PCI_DMA_FROMDEVICE); + dma_addr = dma_map_single(lp->dev, skb->tail,PKT_BUF_SZ, + DMA_FROM_DEVICE); skb->dev = dev; rbd->v_next = rbd+1; rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1)); @@ -605,9 +603,9 @@ static inline void remove_rx_bufs(struct net_device *dev) for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { if (rbd->skb == NULL) break; - pci_unmap_single(fake_pci_dev, + dma_unmap_single(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), - PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + PKT_BUF_SZ, DMA_FROM_DEVICE); dev_kfree_skb(rbd->skb); } } @@ -774,7 +772,7 @@ static inline int i596_rx(struct net_device *dev) struct sk_buff *newskb; dma_addr_t dma_addr; - pci_unmap_single(fake_pci_dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); /* Get fresh skbuff to replace filled one. */ newskb = dev_alloc_skb(PKT_BUF_SZ + 4); if (newskb == NULL) { @@ -788,7 +786,7 @@ static inline int i596_rx(struct net_device *dev) rx_in_place = 1; rbd->skb = newskb; newskb->dev = dev; - dma_addr = pci_map_single(fake_pci_dev, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + dma_addr = dma_map_single(lp->dev, newskb->tail, PKT_BUF_SZ, DMA_FROM_DEVICE); rbd->v_data = newskb->tail; rbd->b_data = WSWAPchar(dma_addr); CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); @@ -805,7 +803,7 @@ memory_squeeze: skb->dev = dev; if (!rx_in_place) { /* 16 byte align the data fields */ - pci_dma_sync_single(fake_pci_dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + dma_sync_single(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); skb_reserve(skb, 2); memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len); } @@ -886,7 +884,7 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private { struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; struct sk_buff *skb = tx_cmd->skb; - pci_unmap_single(fake_pci_dev, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb(skb); @@ -1118,8 +1116,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) tbd->pad = 0; tbd->size = EOF | length; - tx_cmd->dma_addr = pci_map_single(fake_pci_dev, skb->data, skb->len, - PCI_DMA_TODEVICE); + tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len, + DMA_TO_DEVICE); tbd->data = WSWAPchar(tx_cmd->dma_addr); DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); @@ -1156,6 +1154,8 @@ static int __devinit i82596_probe(struct net_device *dev) { int i; struct i596_private *lp; + /* we're going to overwrite dev->priv, so pull the device out */ + struct device *gen_dev = dev->priv; char eth_addr[6]; dma_addr_t dma_addr; @@ -1198,17 +1198,11 @@ static int __devinit i82596_probe(struct net_device *dev) printk("82596.c: MAC of HP700 LAN read from EEPROM\n"); } - dev->mem_start = (unsigned long) pci_alloc_consistent(fake_pci_dev, - sizeof(struct i596_private), &dma_addr); + dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev, + sizeof(struct i596_private), &dma_addr, GFP_KERNEL); if (!dev->mem_start) { - printk("%s: Couldn't get consistent shared memory\n", dev->name); - dma_consistent = 0; - dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0); - if (!dev->mem_start) { - printk("%s: Couldn't get shared memory\n", dev->name); - return -ENOMEM; - } - dma_addr = virt_to_bus(dev->mem_start); + printk("%s: Couldn't get shared memory\n", dev->name); + return -ENOMEM; } ether_setup(dev); @@ -1243,6 +1237,7 @@ static int __devinit i82596_probe(struct net_device *dev) lp->scb.rfd = I596_NULL; lp->lock = SPIN_LOCK_UNLOCKED; lp->dma_addr = dma_addr; + lp->dev = gen_dev; CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private)); @@ -1320,7 +1315,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) if ((ptr->status) & 0x1000) lp->stats.tx_aborted_errors++; } - pci_unmap_single(fake_pci_dev, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_irq(skb); tx_cmd->cmd.command = 0; /* Mark free */ @@ -1530,8 +1525,6 @@ lan_init_chip(struct parisc_device *dev) return -ENODEV; } - fake_pci_dev = ccio_get_fake(dev); - if (!dev->irq) { printk(KERN_ERR __FILE__ ": IRQ not found for i82596 at 0x%lx\n", dev->hpa); return -ENODEV; @@ -1546,6 +1539,7 @@ lan_init_chip(struct parisc_device *dev) netdevice->base_addr = dev->hpa; netdevice->irq = dev->irq; netdevice->init = i82596_probe; + netdevice->priv = &dev->dev; retval = register_netdev(netdevice); if (retval) { @@ -1601,13 +1595,8 @@ static void __exit lasi_82596_exit(void) unregister_netdev(netdevice); lp = (struct i596_private *) netdevice->priv; - if (dma_consistent) - pci_free_consistent(fake_pci_dev, - sizeof(struct i596_private), - (void *)netdevice->mem_start, lp->dma_addr); - else - free_page(netdevice->mem_start); - + dma_free_noncoherent(lp->dev, sizeof(struct i596_private), + (void *)netdevice->mem_start, lp->dma_addr); netdevice->priv = NULL; } diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 9c5af58ecab4..20505f6997a9 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1555,38 +1555,6 @@ static int ccio_probe(struct parisc_device *dev) return 0; } -struct pci_dev * ccio_get_fake(const struct parisc_device *dev) -{ - struct ioc *ioc; - - dev = find_pa_parent_type(dev, HPHW_IOA); - if(!dev) - return NULL; - - ioc = ccio_find_ioc(dev->hw_path); - if(!ioc) - return NULL; - - if(ioc->fake_pci_dev) - return ioc->fake_pci_dev; - - ioc->fake_pci_dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); - if(ioc->fake_pci_dev == NULL) { - printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); - return NULL; - } - memset(ioc->fake_pci_dev, 0, sizeof(struct pci_dev)); - - ioc->fake_pci_dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL); - if(ioc->fake_pci_dev->dev.platform_data == NULL) { - printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); - return NULL; - } - - HBA_DATA(ioc->fake_pci_dev->dev.platform_data)->iommu = ioc; - return ioc->fake_pci_dev; -} - /* We *can't* support JAVA (T600). Venture there at your own risk. */ static struct parisc_device_id ccio_tbl[] = { { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 41d2f167aa9a..a66bb850a312 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -974,8 +974,8 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, * * See Documentation/DMA-mapping.txt */ -static void * -sba_alloc_consistent(struct device *hwdev, size_t size, dma_addr_t *dma_handle) +static void *sba_alloc_consistent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, int gfp) { void *ret; @@ -985,7 +985,7 @@ sba_alloc_consistent(struct device *hwdev, size_t size, dma_addr_t *dma_handle) return 0; } - ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); + ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret) { memset(ret, 0, size); diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index 34fb645ff8fe..d00cfb4c862a 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -40,6 +40,7 @@ #include #include +#include #include #include diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index a5bb58e9fd55..97482bed7f31 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -32,6 +33,7 @@ static void setup_parisc_serial(struct serial_struct *serial, serial->type = PORT_16550A; serial->line = line; + serial->iomap_base = address; serial->iomem_base = ioremap(address, 0x8); serial->irq = irq; @@ -91,11 +93,13 @@ static struct parisc_device_id serial_tbl[] = { { 0 } }; -/* Hack. Dino's serial port will get listed first on some machines. - * So we register this driver first which knows about Lasi's serial port. - * This needs to get fixed properly somehow. +/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1 + * attached to Dino. Unfortunately, Dino appears before Lasi in the device + * tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one + * which only knows about Lasi and then a second which will find all the + * other serial ports. HPUX ignores this problem. */ -static struct parisc_device_id serial1_tbl[] = { +static struct parisc_device_id lasi_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ @@ -111,9 +115,9 @@ static struct parisc_device_id serial1_tbl[] = { MODULE_DEVICE_TABLE(parisc, serial_tbl); -static struct parisc_driver serial1_driver = { - .name = "Serial RS232", - .id_table = serial1_tbl, +static struct parisc_driver lasi_driver = { + .name = "Lasi RS232", + .id_table = lasi_tbl, .probe = serial_init_chip, }; @@ -125,7 +129,7 @@ static struct parisc_driver serial_driver = { int __init probe_serial_gsc(void) { - register_parisc_driver(&serial1_driver); + register_parisc_driver(&lasi_driver); register_parisc_driver(&serial_driver); return 0; } diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 3ef15146632e..26d884a3189d 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #ifdef CONFIG_MAGIC_SYSRQ #include @@ -32,34 +34,35 @@ #include -#define MUX_NR 1 - #define MUX_OFFSET 0x800 #define MUX_LINE_OFFSET 0x80 #define MUX_FIFO_SIZE 255 -#define MUX_MIN_FREE_SIZE 32 - -#define MUX_FIFO_DRAIN_DELAY 1 -#define MUX_POLL_DELAY (30 * HZ / 1000) +#define MUX_POLL_DELAY (30 * HZ / 1000) -#define IO_COMMAND_REG_OFFSET 0x30 -#define IO_STATUS_REG_OFFSET 0x34 #define IO_DATA_REG_OFFSET 0x3c #define IO_DCOUNT_REG_OFFSET 0x40 -#define IO_UCOUNT_REG_OFFSET 0x44 -#define IO_FIFOS_REG_OFFSET 0x48 #define MUX_EOFIFO(status) ((status & 0xF000) == 0xF000) #define MUX_STATUS(status) ((status & 0xF000) == 0x8000) #define MUX_BREAK(status) ((status & 0xF000) == 0x2000) +#define UART_NR 8 +struct mux_card { + struct uart_port ports[UART_NR]; + struct uart_driver drv; + struct mux_card *next; +}; + +static struct mux_card mux_card_head = { + .next = NULL, +}; -static struct uart_port mux_ports[MUX_NR]; static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET) #define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET) +#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 /** * mux_tx_empty - Check if the transmitter fifo is empty. @@ -205,8 +208,8 @@ static void mux_write(struct uart_port *port) static void mux_read(struct uart_port *port) { int data; - __u32 start_count = port->icount.rx; struct tty_struct *tty = port->info->tty; + __u32 start_count = port->icount.rx; while(1) { data = __raw_readl((unsigned long)port->membase @@ -294,7 +297,7 @@ static const char *mux_type(struct uart_port *port) } /** - * release_port - Release memory and IO regions. + * mux_release_port - Release memory and IO regions. * @port: Ptr to the uart_port. * * Release any memory and IO region resources currently in use by @@ -350,17 +353,26 @@ static int mux_verify_port(struct uart_port *port, struct serial_struct *ser) } /** - * mux_drv_poll - Mux poll function. + * mux_drv_poll - Mux poll function. * @unused: Unused variable * * This function periodically polls the Serial MUX to check for new data. */ static void mux_poll(unsigned long unused) { - struct uart_port *port = &mux_ports[0]; + int i; + struct mux_card *card = &mux_card_head; + + while(card) { + for(i = 0; i < UART_NR; ++i) { + if(!card->ports[i].info) + continue; - mux_read(port); - mux_write(port); + mux_read(&card->ports[i]); + mux_write(&card->ports[i]); + } + card = card->next; + } mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); } @@ -395,20 +407,6 @@ static struct uart_ops mux_pops = { .verify_port = mux_verify_port, }; -static struct uart_driver mux_reg = { - .owner = THIS_MODULE, - .driver_name = "ttyB", -#ifdef CONFIG_DEVFS_FS - .dev_name = "ttyB%d", -#else - .dev_name = "ttyB%d", -#endif - .major = MUX_MAJOR, - .minor = 0, - .nr = MUX_NR, - .cons = MUX_CONSOLE, -}; - /** * mux_probe - Determine if the Serial Mux should claim this device. * @dev: The parisc device. @@ -418,36 +416,77 @@ static struct uart_driver mux_reg = { */ static int __init mux_probe(struct parisc_device *dev) { - int i, ret; - struct uart_port *port = &mux_ports[0]; - - init_timer(&mux_timer); - mux_timer.function = mux_poll; - - printk(KERN_INFO "Serial mux driver Revision: 0.1\n"); - - ret = uart_register_driver(&mux_reg); - if (ret) - return ret; - - for (i = 0; i < MUX_NR; i++) { - port = &mux_ports[i]; - - port->iobase = 0; - port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET); - port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); - port->iotype = SERIAL_IO_MEM; - port->type = PORT_MUX; - port->irq = SERIAL_IRQ_NONE; - port->uartclk = 0; - port->fifosize = MUX_FIFO_SIZE; - port->ops = &mux_pops; - port->flags = UPF_BOOT_AUTOCONF; - port->line = 0; - - uart_add_one_port(&mux_reg, port); + int i, j, ret, ports, port_cnt = 0; + u8 iodc_data[8]; + unsigned long bytecnt; + struct uart_port *port; + struct mux_card *card = &mux_card_head; + + ret = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 8); + if(ret != PDC_OK) { + printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); + return 1; + } + + ports = GET_MUX_PORTS(iodc_data); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.2\n", + ports); + + if(!card->drv.nr) { + init_timer(&mux_timer); + mux_timer.function = mux_poll; + } else { + port_cnt += UART_NR; + while(card->next) { + card = card->next; + port_cnt += UART_NR; + } } + for(i = 0; i < ports / UART_NR; ++i) { + if(card->drv.nr) { + card->next = kmalloc(sizeof(struct mux_card), GFP_KERNEL); + if(!card->next) { + printk(KERN_ERR "Serial mux: Unable to allocate memory.\n"); + return 1; + } + memset(card->next, '\0', sizeof(struct mux_card)); + card = card->next; + } + + card->drv.owner = THIS_MODULE; + card->drv.driver_name = "ttyB"; + card->drv.dev_name = "ttyB%d"; + card->drv.major = MUX_MAJOR; + card->drv.minor = port_cnt; + card->drv.nr = UART_NR; + card->drv.cons = MUX_CONSOLE; + + ret = uart_register_driver(&card->drv); + if(ret) { + printk(KERN_ERR "Serial mux: Unable to register driver.\n"); + return 1; + } + + for(j = 0; j < UART_NR; ++j) { + port = &card->ports[j]; + + port->iobase = 0; + port->mapbase = dev->hpa + MUX_OFFSET + (j * MUX_LINE_OFFSET); + port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); + port->iotype = SERIAL_IO_MEM; + port->type = PORT_MUX; + port->irq = SERIAL_IRQ_NONE; + port->uartclk = 0; + port->fifosize = MUX_FIFO_SIZE; + port->ops = &mux_pops; + port->flags = UPF_BOOT_AUTOCONF; + port->line = j; + ret = uart_add_one_port(&card->drv, port); + BUG_ON(ret); + } + port_cnt += UART_NR; + } return 0; } @@ -459,9 +498,9 @@ static struct parisc_device_id mux_tbl[] = { MODULE_DEVICE_TABLE(parisc, mux_tbl); static struct parisc_driver mux_driver = { - .name = "Serial MUX driver", - .id_table = mux_tbl, - .probe = mux_probe, + .name = "Serial MUX", + .id_table = mux_tbl, + .probe = mux_probe, }; /** @@ -482,12 +521,13 @@ static int __init mux_init(void) static void __exit mux_exit(void) { int i; + struct mux_card *card = &mux_card_head; - for (i = 0; i < MUX_NR; i++) { - uart_remove_one_port(&mux_reg, &mux_ports[i]); + for (i = 0; i < UART_NR; i++) { + uart_remove_one_port(&card->drv, &card->ports[i]); } - uart_unregister_driver(&mux_reg); + uart_unregister_driver(&card->drv); } module_init(mux_init); diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index 1f1165436d91..3c9e596596ea 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c @@ -56,7 +56,7 @@ static int som_core_dump(long signr, struct pt_regs * regs); static struct linux_binfmt som_format = { .module = THIS_MODULE, .load_binary = load_som_binary, - .load_library = load_som_library, + .load_shlib = load_som_library, .core_dump = som_core_dump, .min_coredump = SOM_PAGESIZE }; diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h index 99e163032f14..c2eed7aa218b 100644 --- a/include/asm-parisc/bitops.h +++ b/include/asm-parisc/bitops.h @@ -257,7 +257,14 @@ static __inline__ int ffs(int x) * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ - +#define hweight64(x) \ +({ \ + unsigned long __x = (x); \ + unsigned int __w; \ + __w = generic_hweight32((unsigned int) __x); \ + __w += generic_hweight32((unsigned int) (__x>>32)); \ + __w; \ +}) #define hweight32(x) generic_hweight32(x) #define hweight16(x) generic_hweight16(x) #define hweight8(x) generic_hweight8(x) diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h index 6b146922ea10..4cbe08f1b22e 100644 --- a/include/asm-parisc/compat.h +++ b/include/asm-parisc/compat.h @@ -72,4 +72,24 @@ struct compat_flock { compat_pid_t l_pid; }; +struct compat_statfs { + s32 f_type; + s32 f_bsize; + s32 f_blocks; + s32 f_bfree; + s32 f_bavail; + s32 f_files; + s32 f_ffree; + __kernel_fsid_t f_fsid; + s32 f_namelen; + s32 f_spare[6]; +}; + +typedef u32 compat_old_sigset_t; /* at least 32 bits */ + +#define _COMPAT_NSIG 64 +#define _COMPAT_NSIG_BPW BITS_PER_LONG + +typedef u32 compat_sigset_word; + #endif /* _ASM_PARISC_COMPAT_H */ diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h index 2428762027b3..a4c2bf437b61 100644 --- a/include/asm-parisc/dma-mapping.h +++ b/include/asm-parisc/dma-mapping.h @@ -203,7 +203,6 @@ parisc_walk_tree(struct device *dev) struct parisc_device; struct ioc; void * ccio_get_iommu(const struct parisc_device *dev); -struct pci_dev * ccio_get_fake(const struct parisc_device *dev); int ccio_request_resource(const struct parisc_device *dev, struct resource *res); int ccio_allocate_resource(const struct parisc_device *dev, @@ -213,7 +212,6 @@ int ccio_allocate_resource(const struct parisc_device *dev, void *alignf_data); #else /* !CONFIG_IOMMU_CCIO */ #define ccio_get_iommu(dev) NULL -#define ccio_get_fake(dev) NULL #define ccio_request_resource(dev, res) request_resource(&iomem_resource, res) #define ccio_allocate_resource(dev, res, size, min, max, align, alignf, data) \ allocate_resource(&iomem_resource, res, size, min, max, \ diff --git a/include/asm-parisc/module.h b/include/asm-parisc/module.h index f6c2466621f4..acf6770cd5d3 100644 --- a/include/asm-parisc/module.h +++ b/include/asm-parisc/module.h @@ -7,10 +7,14 @@ #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym #define Elf_Ehdr Elf64_Ehdr +#define Elf_Addr Elf64_Addr +#define Elf_Rela Elf64_Rela #else #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Ehdr Elf32_Ehdr +#define Elf_Addr Elf32_Addr +#define Elf_Rela Elf32_Rela #endif #define module_map(x) vmalloc(x) @@ -20,6 +24,10 @@ struct mod_arch_specific { + unsigned long got_offset; + unsigned long fdesc_offset, fdesc_count; + unsigned long stub_offset; + unsigned long stub_count; }; #endif /* _ASM_PARISC_MODULE_H */ diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h index b43525324dc1..cda89e45e05f 100644 --- a/include/asm-parisc/smp.h +++ b/include/asm-parisc/smp.h @@ -12,6 +12,7 @@ #define PDC_OS_BOOT_RENDEZVOUS_HI 0x28 #ifndef ASSEMBLY +#include #include /* for NR_CPUS */ typedef unsigned long address_t; @@ -53,7 +54,7 @@ extern unsigned long cpu_present_mask; #define cpu_online(cpu) (cpu_online_map & (1<<(cpu))) #define cpu_possible(cpu) (cpu_present_mask & (1<<(cpu))) - + extern inline unsigned int num_online_cpus(void) { return hweight32(cpu_online_map); diff --git a/include/linux/elf.h b/include/linux/elf.h index bef237b527bd..1330ef61c75c 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -519,6 +519,174 @@ typedef struct { #define EF_ALPHA_32BIT 1 /* All addresses are below 2GB */ +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + typedef struct elf32_rel { Elf32_Addr r_offset; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 94f9d488c2f7..86016d76a3a1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -582,7 +582,10 @@ #define PCI_DEVICE_ID_SI_7016 0x7016 #define PCI_VENDOR_ID_HP 0x103c -#define PCI_DEVICE_ID_HP_DONNER_GFX 0x1008 +#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a #define PCI_DEVICE_ID_HP_TACHYON 0x1028 #define PCI_DEVICE_ID_HP_TACHLITE 0x1029 #define PCI_DEVICE_ID_HP_J2585A 0x1030 @@ -591,6 +594,7 @@ #define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A #define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b #define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 #define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 #define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 -- cgit v1.2.3 From 3da2fe139367719839cf44325ba44eae3d37f38f Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Mon, 3 Feb 2003 18:19:44 -0800 Subject: [PATCH] use 64 bit jiffies: infrastructure Provide a sane way to avoid unneccessary locking on 64 bit platforms, and a 64 bit analogous to "jiffies_to_clock_t()". --- include/linux/jiffies.h | 22 +++++++++++++++++++++- include/linux/times.h | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 7367127511b3..c81b51bab1e3 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -2,15 +2,35 @@ #define _LINUX_JIFFIES_H #include +#include +#include #include /* for HZ */ /* * The 64-bit value is not volatile - you MUST NOT read it - * without holding read_lock_irq(&xtime_lock) + * without holding read_lock_irq(&xtime_lock). + * get_jiffies_64() will do this for you as appropriate. */ extern u64 jiffies_64; extern unsigned long volatile jiffies; +static inline u64 get_jiffies_64(void) +{ +#if BITS_PER_LONG < 64 + extern rwlock_t xtime_lock; + unsigned long flags; + u64 tmp; + + read_lock_irqsave(&xtime_lock, flags); + tmp = jiffies_64; + read_unlock_irqrestore(&xtime_lock, flags); + return tmp; +#else + return (u64)jiffies; +#endif +} + + /* * These inlines deal with timer wrapping correctly. You are * strongly encouraged to use them diff --git a/include/linux/times.h b/include/linux/times.h index 1174e9f88ea2..9895fd31bd5f 100644 --- a/include/linux/times.h +++ b/include/linux/times.h @@ -2,7 +2,30 @@ #define _LINUX_TIMES_H #ifdef __KERNEL__ +#include +#include + +#if (HZ % USER_HZ)==0 # define jiffies_to_clock_t(x) ((x) / (HZ / USER_HZ)) +#else +# define jiffies_to_clock_t(x) ((clock_t) jiffies_64_to_clock_t((u64) x)) +#endif + +static inline u64 jiffies_64_to_clock_t(u64 x) +{ +#if (HZ % USER_HZ)==0 + do_div(x, HZ / USER_HZ); +#else + /* + * There are better ways that don't overflow early, + * but even this doesn't overflow in hundreds of years + * in 64 bits, so.. + */ + x *= USER_HZ; + do_div(x, HZ); +#endif + return x; +} #endif struct tms { -- cgit v1.2.3 From 5ad0c9427d97547b6adbde4244f9732de6ba4248 Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Mon, 3 Feb 2003 18:19:59 -0800 Subject: [PATCH] use 64 bit jiffies: 64-bit process start time This prevents reporting processes as having started in the future, after 32 bit jiffies wrap. --- fs/proc/array.c | 4 ++-- include/linux/sched.h | 2 +- kernel/acct.c | 11 ++++++++--- kernel/fork.c | 3 ++- mm/oom_kill.c | 6 +++--- 5 files changed, 16 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/fs/proc/array.c b/fs/proc/array.c index 29b41941d83e..e135ac5a1080 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -301,7 +301,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) ppid = task->pid ? task->real_parent->pid : 0; read_unlock(&tasklist_lock); res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ -%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \ +%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu \ %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n", task->pid, task->comm, @@ -324,7 +324,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) nice, 0UL /* removed */, jiffies_to_clock_t(task->it_real_value), - jiffies_to_clock_t(task->start_time), + (unsigned long long) jiffies_64_to_clock_t(task->start_time), vsize, mm ? mm->rss : 0, /* you might want to shift this left 3 */ task->rlim[RLIMIT_RSS].rlim_cur, diff --git a/include/linux/sched.h b/include/linux/sched.h index 15a951d2d27e..3a1367bacd1c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -343,7 +343,7 @@ struct task_struct { unsigned long it_real_incr, it_prof_incr, it_virt_incr; struct timer_list real_timer; unsigned long utime, stime, cutime, cstime; - unsigned long start_time; + u64 start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; /* process credentials */ diff --git a/kernel/acct.c b/kernel/acct.c index 8c51231fc0b2..47736b0fb8e5 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -51,7 +51,9 @@ #include #include #include +#include #include +#include /* * These constants control the amount of freespace that suspend and @@ -306,6 +308,7 @@ static void do_acct_process(long exitcode, struct file *file) mm_segment_t fs; unsigned long vsize; unsigned long flim; + u64 elapsed; /* * First check to see if there is enough free_space to continue @@ -323,9 +326,11 @@ static void do_acct_process(long exitcode, struct file *file) strncpy(ac.ac_comm, current->comm, ACCT_COMM); ac.ac_comm[ACCT_COMM - 1] = '\0'; - ac.ac_btime = CT_TO_SECS(current->start_time) + - (xtime.tv_sec - (jiffies / HZ)); - ac.ac_etime = encode_comp_t(jiffies - current->start_time); + elapsed = get_jiffies_64() - current->start_time; + ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ? + (unsigned long) elapsed : (unsigned long) -1l); + do_div(elapsed, HZ); + ac.ac_btime = xtime.tv_sec - elapsed; ac.ac_utime = encode_comp_t(current->utime); ac.ac_stime = encode_comp_t(current->stime); ac.ac_uid = current->uid; diff --git a/kernel/fork.c b/kernel/fork.c index 0ba9e64b5821..4fc3fcd5dacb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -814,7 +815,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->cutime = p->cstime = 0; p->array = NULL; p->lock_depth = -1; /* -1 = no lock */ - p->start_time = jiffies; + p->start_time = get_jiffies_64(); p->security = NULL; retval = -ENOMEM; diff --git a/mm/oom_kill.c b/mm/oom_kill.c index fd6788f8fca4..073e24ed7709 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -19,6 +19,7 @@ #include #include #include +#include /* #define DEBUG */ @@ -68,11 +69,10 @@ static int badness(struct task_struct *p) /* * CPU time is in seconds and run time is in minutes. There is no * particular reason for this other than that it turned out to work - * very well in practice. This is not safe against jiffie wraps - * but we don't care _that_ much... + * very well in practice. */ cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3); - run_time = (jiffies - p->start_time) >> (SHIFT_HZ + 10); + run_time = (get_jiffies_64() - p->start_time) >> (SHIFT_HZ + 10); points /= int_sqrt(cpu_time); points /= int_sqrt(int_sqrt(run_time)); -- cgit v1.2.3