diff options
256 files changed, 2866 insertions, 2060 deletions
diff --git a/.gitignore b/.gitignore index 22fb8fa9bc3..8d14531846b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.s *.ko *.so +*.so.dbg *.mod.c *.i *.lst diff --git a/Documentation/device-mapper/dm-uevent.txt b/Documentation/device-mapper/dm-uevent.txt new file mode 100644 index 00000000000..07edbd85c71 --- /dev/null +++ b/Documentation/device-mapper/dm-uevent.txt @@ -0,0 +1,97 @@ +The device-mapper uevent code adds the capability to device-mapper to create +and send kobject uevents (uevents). Previously device-mapper events were only +available through the ioctl interface. The advantage of the uevents interface +is the event contains environment attributes providing increased context for +the event avoiding the need to query the state of the device-mapper device after +the event is received. + +There are two functions currently for device-mapper events. The first function +listed creates the event and the second function sends the event(s). + +void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti, + const char *path, unsigned nr_valid_paths) + +void dm_send_uevents(struct list_head *events, struct kobject *kobj) + + +The variables added to the uevent environment are: + +Variable Name: DM_TARGET +Uevent Action(s): KOBJ_CHANGE +Type: string +Description: +Value: Name of device-mapper target that generated the event. + +Variable Name: DM_ACTION +Uevent Action(s): KOBJ_CHANGE +Type: string +Description: +Value: Device-mapper specific action that caused the uevent action. + PATH_FAILED - A path has failed. + PATH_REINSTATED - A path has been reinstated. + +Variable Name: DM_SEQNUM +Uevent Action(s): KOBJ_CHANGE +Type: unsigned integer +Description: A sequence number for this specific device-mapper device. +Value: Valid unsigned integer range. + +Variable Name: DM_PATH +Uevent Action(s): KOBJ_CHANGE +Type: string +Description: Major and minor number of the path device pertaining to this +event. +Value: Path name in the form of "Major:Minor" + +Variable Name: DM_NR_VALID_PATHS +Uevent Action(s): KOBJ_CHANGE +Type: unsigned integer +Description: +Value: Valid unsigned integer range. + +Variable Name: DM_NAME +Uevent Action(s): KOBJ_CHANGE +Type: string +Description: Name of the device-mapper device. +Value: Name + +Variable Name: DM_UUID +Uevent Action(s): KOBJ_CHANGE +Type: string +Description: UUID of the device-mapper device. +Value: UUID. (Empty string if there isn't one.) + +An example of the uevents generated as captured by udevmonitor is shown +below. + +1.) Path failure. +UEVENT[1192521009.711215] change@/block/dm-3 +ACTION=change +DEVPATH=/block/dm-3 +SUBSYSTEM=block +DM_TARGET=multipath +DM_ACTION=PATH_FAILED +DM_SEQNUM=1 +DM_PATH=8:32 +DM_NR_VALID_PATHS=0 +DM_NAME=mpath2 +DM_UUID=mpath-35333333000002328 +MINOR=3 +MAJOR=253 +SEQNUM=1130 + +2.) Path reinstate. +UEVENT[1192521132.989927] change@/block/dm-3 +ACTION=change +DEVPATH=/block/dm-3 +SUBSYSTEM=block +DM_TARGET=multipath +DM_ACTION=PATH_REINSTATED +DM_SEQNUM=2 +DM_PATH=8:32 +DM_NR_VALID_PATHS=1 +DM_NAME=mpath2 +DM_UUID=mpath-35333333000002328 +MINOR=3 +MAJOR=253 +SEQNUM=1131 diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt index fe8b0c4892c..616043a6da9 100644 --- a/Documentation/kbuild/kconfig-language.txt +++ b/Documentation/kbuild/kconfig-language.txt @@ -77,7 +77,12 @@ applicable everywhere (see syntax). Optionally, dependencies only for this default value can be added with "if". -- dependencies: "depends on"/"requires" <expr> +- type definition + default value: + "def_bool"/"def_tristate" <expr> ["if" <expr>] + This is a shorthand notation for a type definition plus a value. + Optionally dependencies for this default value can be added with "if". + +- dependencies: "depends on" <expr> This defines a dependency for this menu entry. If multiple dependencies are defined, they are connected with '&&'. Dependencies are applied to all other options within this menu entry (which also @@ -289,3 +294,10 @@ source: "source" <prompt> This reads the specified configuration file. This file is always parsed. + +mainmenu: + + "mainmenu" <prompt> + +This sets the config program's title bar if the config program chooses +to use it. diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index f099b814d38..6166e2d7da7 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -518,6 +518,28 @@ more details, with real examples. In this example for a specific GCC version the build will error out explaining to the user why it stops. + cc-cross-prefix + cc-cross-prefix is used to check if there exist a $(CC) in path with + one of the listed prefixes. The first prefix where there exist a + prefix$(CC) in the PATH is returned - and if no prefix$(CC) is found + then nothing is returned. + Additional prefixes are separated by a single space in the + call of cc-cross-prefix. + This functionality is usefull for architecture Makefile that try + to set CROSS_COMPILE to well know values but may have several + values to select between. + It is recommended only to try to set CROSS_COMPILE is it is a cross + build (host arch is different from target arch). And is CROSS_COMPILE + is already set then leave it with the old value. + + Example: + #arch/m68k/Makefile + ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-) + endif + endif + === 4 Host Program support Kbuild supports building executables on the host for use during the diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 929734386fd..6accd360da7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -419,8 +419,10 @@ and is between 256 and 4096 characters. It is defined in the file over the 8254 in addition to over the IO-APIC. The kernel tries to set a sensible default. - hpet= [X86-32,HPET] option to disable HPET and use PIT. - Format: disable + hpet= [X86-32,HPET] option to control HPET usage + Format: { enable (default) | disable | force } + disable: disable HPET and use PIT instead + force: allow force enabled of undocumented chips (ICH4, VIA) com20020= [HW,NET] ARCnet - COM20020 chipset Format: diff --git a/MAINTAINERS b/MAINTAINERS index 2534dc4aa95..4ed41394e49 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2178,7 +2178,7 @@ S: Maintained KCONFIG P: Roman Zippel M: zippel@linux-m68k.org -L: kbuild-devel@lists.sourceforge.net +L: linux-kbuild@vger.kernel.org S: Maintained KDUMP @@ -2207,6 +2207,7 @@ KERNEL BUILD (kbuild: Makefile, scripts/Makefile.*) P: Sam Ravnborg M: sam@ravnborg.org T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git +L: linux-kbuild@vger.kernel.org S: Maintained KERNEL JANITORS @@ -887,10 +887,7 @@ prepare2: prepare3 outputmakefile prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \ include/asm include/config/auto.conf -ifneq ($(KBUILD_MODULES),) - $(Q)mkdir -p $(MODVERDIR) - $(Q)rm -f $(MODVERDIR)/* -endif + $(cmd_crmodverdir) archprepare: prepare1 scripts_basic @@ -906,14 +903,24 @@ prepare: prepare0 export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) -# FIXME: The asm symlink changes when $(ARCH) changes. That's -# hard to detect, but I suppose "make mrproper" is a good idea -# before switching between archs anyway. - -include/asm: - @echo ' SYMLINK $@ -> include/asm-$(SRCARCH)' - $(Q)if [ ! -d include ]; then mkdir -p include; fi; - @ln -fsn asm-$(SRCARCH) $@ +# The asm symlink changes when $(ARCH) changes. +# Detect this and ask user to run make mrproper + +include/asm: FORCE + $(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`; \ + if [ -L include/asm ]; then \ + if [ "$$asmlink" != "$(SRCARCH)" ]; then \ + echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \ + echo " set ARCH or save .config and run 'make mrproper' to fix it"; \ + exit 1; \ + fi; \ + else \ + echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \ + if [ ! -d include ]; then \ + mkdir -p include; \ + fi; \ + ln -fsn asm-$(SRCARCH) $@; \ + fi # Generate some files # --------------------------------------------------------------------------- @@ -1023,19 +1030,12 @@ _modinst_: fi $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst -# If System.map exists, run depmod. This deliberately does not have a -# dependency on System.map since that would run the dependency tree on -# vmlinux. This depmod is only for convenience to give the initial +# This depmod is only for convenience to give the initial # boot a modules.dep even before / is mounted read-write. However the # boot script depmod is the master version. -ifeq "$(strip $(INSTALL_MOD_PATH))" "" -depmod_opts := -else -depmod_opts := -b $(INSTALL_MOD_PATH) -r -endif PHONY += _modinst_post _modinst_post: _modinst_ - if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi + $(call cmd,depmod) else # CONFIG_MODULES @@ -1223,8 +1223,7 @@ else # KBUILD_EXTMOD KBUILD_MODULES := 1 PHONY += crmodverdir crmodverdir: - $(Q)mkdir -p $(MODVERDIR) - $(Q)rm -f $(MODVERDIR)/* + $(cmd_crmodverdir) PHONY += $(objtree)/Module.symvers $(objtree)/Module.symvers: @@ -1252,15 +1251,6 @@ _emodinst_: $(Q)mkdir -p $(MODLIB)/$(install-dir) $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst -# Run depmod only is we have System.map and depmod is executable -quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) - cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \ - $(DEPMOD) -ae -F System.map \ - $(if $(strip $(INSTALL_MOD_PATH)), \ - -b $(INSTALL_MOD_PATH) -r) \ - $(KERNELRELEASE); \ - fi - PHONY += _emodinst_post _emodinst_post: _emodinst_ $(call cmd,depmod) @@ -1344,7 +1334,7 @@ define find-sources find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \ -name $1 -print; \ find $(__srctree) $(RCS_FIND_IGNORE) \ - \( -name include -o -name arch \) -prune -o \ + \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \ -name $1 -print; \ ) endef @@ -1493,9 +1483,11 @@ endif # Modules / %/: prepare scripts FORCE + $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) %.ko: prepare scripts FORCE + $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) $(@:.ko=.o) $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost @@ -1509,6 +1501,19 @@ quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs))) quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) cmd_rmfiles = rm -f $(rm-files) +# Run depmod only is we have System.map and depmod is executable +# and we build for the host arch +quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) + cmd_depmod = \ + if [ -r System.map -a -x $(DEPMOD) -a "$(SUBARCH)" == "$(ARCH)" ]; then \ + $(DEPMOD) -ae -F System.map \ + $(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) -r) \ + $(KERNELRELEASE); \ + fi + +# Create temporary dir for module support files +cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR); rm -f $(MODVERDIR)/* + a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \ $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \ diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 7627e9bd8b4..f6e44fc5283 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -1080,7 +1080,7 @@ config APM_REAL_MODE_POWER_OFF endif # APM -source "arch/x86/kernel/cpu/cpufreq/Kconfig" +source "arch/x86/kernel/cpu/cpufreq/Kconfig_32" source "drivers/cpuidle/Kconfig" diff --git a/arch/i386/Makefile b/arch/i386/Makefile index f036d2dee3d..b88e47ca303 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -102,7 +102,7 @@ core-$(CONFIG_XEN) += arch/x86/xen/ # default subarch .h files mflags-y += -Iinclude/asm-x86/mach-default -head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task_32.o +head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task.o libs-y += arch/x86/lib/ core-y += arch/x86/kernel/ \ @@ -131,9 +131,9 @@ all: bzImage zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage zImage bzImage: vmlinux - $(Q)mkdir -p $(objtree)/arch/i386/boot - $(Q)ln -fsn $(objtree)/arch/x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE) + $(Q)mkdir -p $(objtree)/arch/i386/boot + $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage compressed: zImage diff --git a/arch/x86/ia32/ia32_binfmt.c b/arch/x86/ia32/ia32_binfmt.c index 5027650eb27..55822d2cf05 100644 --- a/arch/x86/ia32/ia32_binfmt.c +++ b/arch/x86/ia32/ia32_binfmt.c @@ -5,10 +5,6 @@ * This tricks binfmt_elf.c into loading 32bit binaries using lots * of ugly preprocessor tricks. Talk about very very poor man's inheritance. */ -#define __ASM_X86_64_ELF_H 1 - -#undef ELF_CLASS -#define ELF_CLASS ELFCLASS32 #include <linux/types.h> #include <linux/stddef.h> @@ -19,6 +15,7 @@ #include <linux/binfmts.h> #include <linux/mm.h> #include <linux/security.h> +#include <linux/elfcore-compat.h> #include <asm/segment.h> #include <asm/ptrace.h> @@ -31,6 +28,20 @@ #include <asm/ia32.h> #include <asm/vsyscall32.h> +#undef ELF_ARCH +#undef ELF_CLASS +#define ELF_CLASS ELFCLASS32 +#define ELF_ARCH EM_386 + +#undef elfhdr +#undef elf_phdr +#undef elf_note +#undef elf_addr_t +#define elfhdr elf32_hdr +#define elf_phdr elf32_phdr +#define elf_note elf32_note +#define elf_addr_t Elf32_Off + #define ELF_NAME "elf/i386" #define AT_SYSINFO 32 @@ -48,74 +59,20 @@ int sysctl_vsyscall32 = 1; } while(0) struct file; -struct elf_phdr; #define IA32_EMULATOR 1 -#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) - -#undef ELF_ARCH -#define ELF_ARCH EM_386 - -#define ELF_DATA ELFDATA2LSB +#undef ELF_ET_DYN_BASE -#define USE_ELF_CORE_DUMP 1 - -/* Override elfcore.h */ -#define _LINUX_ELFCORE_H 1 -typedef unsigned int elf_greg_t; - -#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -struct elf_siginfo -{ - int si_signo; /* signal number */ - int si_code; /* extra code */ - int si_errno; /* errno */ -}; +#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) #define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0) -struct elf_prstatus -{ - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned int pr_sigpend; /* Set of pending signals */ - unsigned int pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime; /* Cumulative user time */ - struct compat_timeval pr_cstime; /* Cumulative system time */ - elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* True if math co-processor being used. */ -}; - -#define ELF_PRARGSZ (80) /* Number of chars for args */ - -struct elf_prpsinfo -{ - char pr_state; /* numeric process state */ - char pr_sname; /* char for pr_state */ - char pr_zomb; /* zombie */ - char pr_nice; /* nice val */ - unsigned int pr_flag; /* flags */ - __u16 pr_uid; - __u16 pr_gid; - pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* filename of executable */ - char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ -}; - #define _GET_SEG(x) \ ({ __u32 seg; asm("movl %%" __stringify(x) ",%0" : "=r"(seg)); seg; }) /* Assumes current==process to be dumped */ +#undef ELF_CORE_COPY_REGS #define ELF_CORE_COPY_REGS(pr_reg, regs) \ pr_reg[0] = regs->rbx; \ pr_reg[1] = regs->rcx; \ @@ -135,36 +92,41 @@ struct elf_prpsinfo pr_reg[15] = regs->rsp; \ pr_reg[16] = regs->ss; -#define user user32 + +#define elf_prstatus compat_elf_prstatus +#define elf_prpsinfo compat_elf_prpsinfo +#define elf_fpregset_t struct user_i387_ia32_struct +#define elf_fpxregset_t struct user32_fxsr_struct +#define user user32 #undef elf_read_implies_exec #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) -//#include <asm/ia32.h> -#include <linux/elf.h> - -typedef struct user_i387_ia32_struct elf_fpregset_t; -typedef struct user32_fxsr_struct elf_fpxregset_t; - -static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs) +#define elf_core_copy_regs elf32_core_copy_regs +static inline void elf32_core_copy_regs(compat_elf_gregset_t *elfregs, + struct pt_regs *regs) { - ELF_CORE_COPY_REGS((*elfregs), regs) + ELF_CORE_COPY_REGS((&elfregs->ebx), regs) } -static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) +#define elf_core_copy_task_regs elf32_core_copy_task_regs +static inline int elf32_core_copy_task_regs(struct task_struct *t, + compat_elf_gregset_t* elfregs) { struct pt_regs *pp = task_pt_regs(t); - ELF_CORE_COPY_REGS((*elfregs), pp); + ELF_CORE_COPY_REGS((&elfregs->ebx), pp); /* fix wrong segments */ - (*elfregs)[7] = t->thread.ds; - (*elfregs)[9] = t->thread.fsindex; - (*elfregs)[10] = t->thread.gsindex; - (*elfregs)[8] = t->thread.es; + elfregs->ds = t->thread.ds; + elfregs->fs = t->thread.fsindex; + elfregs->gs = t->thread.gsindex; + elfregs->es = t->thread.es; return 1; } +#define elf_core_copy_task_fpregs elf32_core_copy_task_fpregs static inline int -elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu) +elf32_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, + elf_fpregset_t *fpu) { struct _fpstate_ia32 *fpstate = (void*)fpu; mm_segment_t oldfs = get_fs(); @@ -186,8 +148,9 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr #define ELF_CORE_COPY_XFPREGS 1 #define ELF_CORE_XFPREG_TYPE NT_PRXFPREG +#define elf_core_copy_task_xfpregs elf32_core_copy_task_xfpregs static inline int -elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) +elf32_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) { struct pt_regs *regs = task_pt_regs(t); if (!tsk_used_math(t)) @@ -206,6 +169,10 @@ elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) extern int force_personality32; +#undef ELF_EXEC_PAGESIZE +#undef ELF_HWCAP +#undef ELF_PLATFORM +#undef SET_PERSONALITY #define ELF_EXEC_PAGESIZE PAGE_SIZE #define ELF_HWCAP (boot_cpu_data.x86_capability[0]) #define ELF_PLATFORM ("i686") @@ -231,6 +198,7 @@ do { \ #define load_elf_binary load_elf32_binary +#undef ELF_PLAT_INIT #define ELF_PLAT_INIT(r, load_addr) elf32_init(r) #undef start_thread diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index a3fa11f8f46..ccea590bbb9 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -extra-y := head_32.o init_task_32.o vmlinux.lds +extra-y := head_32.o init_task.o vmlinux.lds obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ @@ -17,6 +17,7 @@ obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_PCI) += early-quirks.o obj-$(CONFIG_APM) += apm_32.o obj-$(CONFIG_X86_SMP) += smp_32.o smpboot_32.o tsc_sync.o obj-$(CONFIG_SMP) += smpcommon_32.o diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 43da66213a4..dec06e76928 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -extra-y := head_64.o head64.o init_task_64.o vmlinux.lds +extra-y := head_64.o head64.o init_task.o vmlinux.lds EXTRA_AFLAGS := -traditional obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ @@ -39,7 +39,7 @@ obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_AUDIT) += audit_64.o obj-$(CONFIG_MODULES) += module_64.o -obj-$(CONFIG_PCI) += early-quirks_64.o +obj-$(CONFIG_PCI) += early-quirks.o obj-y += topology.o obj-y += intel_cacheinfo.o diff --git a/arch/x86/kernel/acpi/Makefile_32 b/arch/x86/kernel/acpi/Makefile_32 index a4852a2e919..045dd54b33e 100644 --- a/arch/x86/kernel/acpi/Makefile_32 +++ b/arch/x86/kernel/acpi/Makefile_32 @@ -1,7 +1,4 @@ obj-$(CONFIG_ACPI) += boot.o -ifneq ($(CONFIG_PCI),) -obj-$(CONFIG_X86_IO_APIC) += earlyquirk_32.o -endif obj-$(CONFIG_ACPI_SLEEP) += sleep_32.o wakeup_32.o ifneq ($(CONFIG_ACPI_PROCESSOR),) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 25337f2b739..289247d974c 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -555,7 +555,7 @@ EXPORT_SYMBOL(acpi_map_lsapic); int acpi_unmap_lsapic(int cpu) { - x86_cpu_to_apicid[cpu] = -1; + per_cpu(x86_cpu_to_apicid, cpu) = -1; cpu_clear(cpu, cpu_present_map); num_processors--; diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index 2d39f55d29a..10b67170b13 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -29,7 +29,7 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu) { - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); flags->bm_check = 0; if (num_online_cpus() == 1) @@ -72,7 +72,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, struct acpi_processor_cx *cx, struct acpi_power_register *reg) { struct cstate_entry *percpu_entry; - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); cpumask_t saved_mask; int retval; diff --git a/arch/x86/kernel/acpi/earlyquirk_32.c b/arch/x86/kernel/acpi/earlyquirk_32.c deleted file mode 100644 index 23f78efc577..00000000000 --- a/arch/x86/kernel/acpi/earlyquirk_32.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Do early PCI probing for bug detection when the main PCI subsystem is - * not up yet. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/acpi.h> - -#include <asm/pci-direct.h> -#include <asm/acpi.h> -#include <asm/apic.h> - -#ifdef CONFIG_ACPI - -static int __init nvidia_hpet_check(struct acpi_table_header *header) -{ - return 0; -} -#endif - -static int __init check_bridge(int vendor, int device) -{ -#ifdef CONFIG_ACPI - static int warned; - /* According to Nvidia all timer overrides are bogus unless HPET - is enabled. */ - if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { - if (!warned && acpi_table_parse(ACPI_SIG_HPET, - nvidia_hpet_check)) { - warned = 1; - acpi_skip_timer_override = 1; - printk(KERN_INFO "Nvidia board " - "detected. Ignoring ACPI " - "timer override.\n"); - printk(KERN_INFO "If you got timer trouble " - "try acpi_use_timer_override\n"); - - } - } -#endif - if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) { - timer_over_8254 = 0; - printk(KERN_INFO "ATI board detected. Disabling timer routing " - "over 8254.\n"); - } - return 0; -} - -void __init check_acpi_pci(void) -{ - int num, slot, func; - - /* Assume the machine supports type 1. If not it will - always read ffffffff and should not have any side effect. - Actually a few buggy systems can machine check. Allow the user - to disable it by command line option at least -AK */ - if (!early_pci_allowed()) - return; - - /* Poor man's PCI discovery */ - for (num = 0; num < 32; num++) { - for (slot = 0; slot < 32; slot++) { - for (func = 0; func < 8; func++) { - u32 class; - u32 vendor; - class = read_pci_config(num, slot, func, - PCI_CLASS_REVISION); - if (class == 0xffffffff) - break; - - if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) - continue; - - vendor = read_pci_config(num, slot, func, - PCI_VENDOR_ID); - - if (check_bridge(vendor & 0xffff, vendor >> 16)) - return; - } - - } - } -} diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index b54fded4983..2ed0a4ce62f 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -63,7 +63,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) void arch_acpi_processor_init_pdc(struct acpi_processor *pr) { unsigned int cpu = pr->id; - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); pr->pdc = NULL; if (c->x86_vendor == X86_VENDOR_INTEL) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 3bd2688bd44..d6405e0842b 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -357,14 +357,14 @@ void alternatives_smp_switch(int smp) if (smp) { printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + clear_bit(X86_FEATURE_UP, cpu_data(0).x86_capability); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_lock(mod->locks, mod->locks_end, mod->text, mod->text_end); } else { printk(KERN_INFO "SMP alternatives: switching to UP code\n"); set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability); list_for_each_entry(mod, &smp_alt_modules, next) alternatives_smp_unlock(mod->locks, mod->locks_end, mod->text, mod->text_end); @@ -432,7 +432,7 @@ void __init alternative_instructions(void) if (1 == num_possible_cpus()) { printk(KERN_INFO "SMP alternatives: switching to UP code\n"); set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability); alternatives_smp_unlock(__smp_locks, __smp_locks_end, _text, _etext); } diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig_32 index d8c6f132dc7..d8c6f132dc7 100644 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig_32 diff --git a/arch/x86/kernel/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig_64 index a3fd51926cb..9c9699fdcf5 100644 --- a/arch/x86/kernel/cpufreq/Kconfig +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig_64 @@ -19,7 +19,7 @@ config X86_POWERNOW_K8 To compile this driver as a module, choose M here: the module will be called powernow-k8. - For details, take a look at <file:Documentation/cpu-freq/>. + For details, take a look at <file:Documentation/cpu-freq/>. If in doubt, say N. diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 2ca43ba32bc..fea0af0476b 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -77,7 +77,7 @@ static unsigned int acpi_pstate_strict; static int check_est_cpu(unsigned int cpuid) { - struct cpuinfo_x86 *cpu = &cpu_data[cpuid]; + struct cpuinfo_x86 *cpu = &cpu_data(cpuid); if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) @@ -560,7 +560,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) unsigned int cpu = policy->cpu; struct acpi_cpufreq_data *data; unsigned int result = 0; - struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; + struct cpuinfo_x86 *c = &cpu_data(policy->cpu); struct acpi_processor_performance *perf; dprintk("acpi_cpufreq_cpu_init\n"); diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c index c11baaf9f2b..326a4c81f68 100644 --- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c +++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c @@ -305,7 +305,7 @@ static struct cpufreq_driver eps_driver = { static int __init eps_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); /* This driver will work only on Centaur C7 processors with * Enhanced SpeedStep/PowerSaver registers */ diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index 1e7ae7dafcf..94619c22f56 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c @@ -199,7 +199,7 @@ static int elanfreq_target (struct cpufreq_policy *policy, static int elanfreq_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); unsigned int i; int result; @@ -280,7 +280,7 @@ static struct cpufreq_driver elanfreq_driver = { static int __init elanfreq_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); /* Test if we have the right hardware */ if ((c->x86_vendor != X86_VENDOR_AMD) || diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c index 5045f5d583c..749d00cb2eb 100644 --- a/arch/x86/kernel/cpu/cpufreq/longhaul.c +++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c @@ -780,7 +780,7 @@ static int longhaul_setup_southbridge(void) static int __init longhaul_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); char *cpuname=NULL; int ret; u32 lo, hi; @@ -959,7 +959,7 @@ static struct cpufreq_driver longhaul_driver = { static int __init longhaul_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) return -ENODEV; diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c index b2689514295..af4a867a097 100644 --- a/arch/x86/kernel/cpu/cpufreq/longrun.c +++ b/arch/x86/kernel/cpu/cpufreq/longrun.c @@ -172,7 +172,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, u32 save_lo, save_hi; u32 eax, ebx, ecx, edx; u32 try_hi; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); if (!low_freq || !high_freq) return -EINVAL; @@ -298,7 +298,7 @@ static struct cpufreq_driver longrun_driver = { */ static int __init longrun_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); if (c->x86_vendor != X86_VENDOR_TRANSMETA || !cpu_has(c, X86_FEATURE_LONGRUN)) diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 793eae854f4..14791ec55cf 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; + struct cpuinfo_x86 *c = &cpu_data(policy->cpu); int cpuid = 0; unsigned int i; @@ -279,7 +279,7 @@ static struct cpufreq_driver p4clockmod_driver = { static int __init cpufreq_p4_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); int ret; /* diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index a07f6d84033..eb9b62b0830 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c @@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6_driver = { */ static int __init powernow_k6_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || ((c->x86_model != 12) && (c->x86_model != 13))) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c index f3686a5f230..b5a9863d6cd 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c @@ -114,7 +114,7 @@ static int check_fsb(unsigned int fsbspeed) static int check_powernow(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); unsigned int maxei, eax, ebx, ecx, edx; if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) { diff --git a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c index d9f3e90a7ae..42da9bd677d 100644 --- a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c +++ b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c @@ -102,7 +102,7 @@ static int sc520_freq_target (struct cpufreq_policy *policy, static int sc520_freq_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); int result; /* capability check */ @@ -151,7 +151,7 @@ static struct cpufreq_driver sc520_freq_driver = { static int __init sc520_freq_init(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); int err; /* Test if we have the right hardware */ diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 811d4743854..3031f119619 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c @@ -230,7 +230,7 @@ static struct cpu_model models[] = static int centrino_cpu_init_table(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; + struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu); struct cpu_model *model; for(model = models; model->cpu_id != NULL; model++) @@ -340,7 +340,7 @@ static unsigned int get_cur_freq(unsigned int cpu) static int centrino_cpu_init(struct cpufreq_policy *policy) { - struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; + struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu); unsigned freq; unsigned l, h; int ret; @@ -612,7 +612,7 @@ static struct cpufreq_driver centrino_driver = { */ static int __init centrino_init(void) { - struct cpuinfo_x86 *cpu = cpu_data; + struct cpuinfo_x86 *cpu = &cpu_data(0); if (!cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c index b1acc8ce316..76c3ab0da46 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c @@ -228,7 +228,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency); unsigned int speedstep_detect_processor (void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); u32 ebx, msr_lo, msr_hi; dprintk("x86: %x, model: %x\n", c->x86, c->x86_model); diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 297a2411694..9921b01fe19 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -295,7 +295,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb; #ifdef CONFIG_X86_HT - unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data); + unsigned int cpu = c->cpu_index; #endif if (c->cpuid_level > 3) { @@ -417,14 +417,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) if (new_l2) { l2 = new_l2; #ifdef CONFIG_X86_HT - cpu_llc_id[cpu] = l2_id; + per_cpu(cpu_llc_id, cpu) = l2_id; #endif } if (new_l3) { l3 = new_l3; #ifdef CONFIG_X86_HT - cpu_llc_id[cpu] = l3_id; + per_cpu(cpu_llc_id, cpu) = l3_id; #endif } @@ -459,7 +459,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) struct _cpuid4_info *this_leaf, *sibling_leaf; unsigned long num_threads_sharing; int index_msb, i; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(cpu); this_leaf = CPUID4_INFO_IDX(cpu, index); num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; @@ -470,8 +470,8 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) index_msb = get_count_order(num_threads_sharing); for_each_online_cpu(i) { - if (c[i].apicid >> index_msb == - c[cpu].apicid >> index_msb) { + if (cpu_data(i).apicid >> index_msb == + c->apicid >> index_msb) { cpu_set(i, this_leaf->shared_cpu_map); if (i != cpu && cpuid4_info[i]) { sibling_leaf = CPUID4_INFO_IDX(i, index); diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 54cdbf1a40f..c02541e6e65 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -120,7 +120,9 @@ int reserve_perfctr_nmi(unsigned int msr) unsigned int counter; counter = nmi_perfctr_msr_to_bit(msr); - BUG_ON(counter > NMI_MAX_COUNTER_BITS); + /* register not managed by the allocator? */ + if (counter > NMI_MAX_COUNTER_BITS) + return 1; if (!test_and_set_bit(counter, perfctr_nmi_owner)) return 1; @@ -132,7 +134,9 @@ void release_perfctr_nmi(unsigned int msr) unsigned int counter; counter = nmi_perfctr_msr_to_bit(msr); - BUG_ON(counter > NMI_MAX_COUNTER_BITS); + /* register not managed by the allocator? */ + if (counter > NMI_MAX_COUNTER_BITS) + return; clear_bit(counter, perfctr_nmi_owner); } @@ -142,7 +146,9 @@ int reserve_evntsel_nmi(unsigned int msr) unsigned int counter; counter = nmi_evntsel_msr_to_bit(msr); - BUG_ON(counter > NMI_MAX_COUNTER_BITS); + /* register not managed by the allocator? */ + if (counter > NMI_MAX_COUNTER_BITS) + return 1; if (!test_and_set_bit(counter, evntsel_nmi_owner)) return 1; @@ -154,7 +160,9 @@ void release_evntsel_nmi(unsigned int msr) unsigned int counter; counter = nmi_evntsel_msr_to_bit(msr); - BUG_ON(counter > NMI_MAX_COUNTER_BITS); + /* register not managed by the allocator? */ + if (counter > NMI_MAX_COUNTER_BITS) + return; clear_bit(counter, evntsel_nmi_owner); } diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 879a0f789b1..2d42b414b77 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -85,12 +85,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* nothing */ }; struct cpuinfo_x86 *c = v; - int i, n = c - cpu_data; + int i, n = 0; int fpu_exception; #ifdef CONFIG_SMP if (!cpu_online(n)) return 0; + n = c->cpu_index; #endif seq_printf(m, "processor\t: %d\n" "vendor_id\t: %s\n" @@ -175,11 +176,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { - return *pos < NR_CPUS ? cpu_data + *pos : NULL; + if (*pos == 0) /* just in case, cpu 0 is not the first */ + *pos = first_cpu(cpu_possible_map); + if ((*pos) < NR_CPUS && cpu_possible(*pos)) + return &cpu_data(*pos); + return NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - ++*pos; + *pos = next_cpu(*pos, cpu_possible_map); return c_start(m, pos); } static void c_stop(struct seq_file *m, void *v) diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 70dcf912d9f..05c9936a16c 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -114,7 +114,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, static int cpuid_open(struct inode *inode, struct file *file) { unsigned int cpu = iminor(file->f_path.dentry->d_inode); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + struct cpuinfo_x86 *c = &cpu_data(cpu); if (cpu >= NR_CPUS || !cpu_online(cpu)) return -ENXIO; /* No such CPU */ @@ -134,15 +134,18 @@ static const struct file_operations cpuid_fops = { .open = cpuid_open, }; -static int __cpuinit cpuid_device_create(int i) +static __cpuinit int cpuid_device_create(int cpu) { - int err = 0; struct device *dev; - dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i); - if (IS_ERR(dev)) - err = PTR_ERR(dev); - return err; + dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), + "cpu%d", cpu); + return IS_ERR(dev) ? PTR_ERR(dev) : 0; +} + +static void cpuid_device_destroy(int cpu) +{ + device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); } static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb, @@ -150,18 +153,21 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; + int err = 0; switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - cpuid_device_create(cpu); + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + err = cpuid_device_create(cpu); break; + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); + cpuid_device_destroy(cpu); break; } - return NOTIFY_OK; + return err ? NOTIFY_BAD : NOTIFY_OK; } static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier = @@ -198,7 +204,7 @@ static int __init cpuid_init(void) out_class: i = 0; for_each_online_cpu(i) { - device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i)); + cpuid_device_destroy(i); } class_destroy(cpuid_class); out_chrdev: @@ -212,7 +218,7 @@ static void __exit cpuid_exit(void) int cpu = 0; for_each_online_cpu(cpu) - device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); + cpuid_device_destroy(cpu); class_destroy(cpuid_class); unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); diff --git a/arch/x86/kernel/early-quirks_64.c b/arch/x86/kernel/early-quirks.c index 13aa4fd728f..dc34acbd54a 100644 --- a/arch/x86/kernel/early-quirks_64.c +++ b/arch/x86/kernel/early-quirks.c @@ -13,9 +13,13 @@ #include <linux/acpi.h> #include <linux/pci_ids.h> #include <asm/pci-direct.h> -#include <asm/proto.h> -#include <asm/iommu.h> #include <asm/dma.h> +#include <asm/io_apic.h> +#include <asm/apic.h> + +#ifdef CONFIG_IOMMU +#include <asm/iommu.h> +#endif static void __init via_bugs(void) { @@ -23,7 +27,8 @@ static void __init via_bugs(void) if ((end_pfn > MAX_DMA32_PFN || force_iommu) && !iommu_aperture_allowed) { printk(KERN_INFO - "Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n"); + "Looks like a VIA chipset. Disabling IOMMU." + " Override with iommu=allowed\n"); iommu_aperture_disabled = 1; } #endif @@ -40,6 +45,7 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header) static void __init nvidia_bugs(void) { #ifdef CONFIG_ACPI +#ifdef CONFIG_X86_IO_APIC /* * All timer overrides on Nvidia are * wrong unless HPET is enabled. @@ -59,17 +65,20 @@ static void __init nvidia_bugs(void) "try acpi_use_timer_override\n"); } #endif +#endif /* RED-PEN skip them on mptables too? */ } static void __init ati_bugs(void) { +#ifdef CONFIG_X86_IO_APIC if (timer_over_8254 == 1) { timer_over_8254 = 0; printk(KERN_INFO - "ATI board detected. Disabling timer routing over 8254.\n"); + "ATI board detected. Disabling timer routing over 8254.\n"); } +#endif } struct chipset { @@ -104,7 +113,7 @@ void __init early_quirks(void) if (class == 0xffffffff) break; - if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) + if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) continue; vendor = read_pci_config(num, slot, func, diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 4ae03e3e829..ce703e21c91 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -24,10 +24,19 @@ #include <acpi/acpi_bus.h> #endif -/* which logical CPU number maps to which CPU (physical APIC ID) */ -u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly +/* + * which logical CPU number maps to which CPU (physical APIC ID) + * + * The following static array is used during kernel startup + * and the x86_cpu_to_apicid_ptr contains the address of the + * array during this time. Is it zeroed when the per_cpu + * data area is removed. + */ +u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata = { [0 ... NR_CPUS-1] = BAD_APICID }; -EXPORT_SYMBOL(x86_cpu_to_apicid); +void *x86_cpu_to_apicid_ptr; +DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID; +EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid); struct genapic __read_mostly *genapic = &apic_flat; diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 91c7526768e..07352b74bda 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -172,7 +172,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask) */ cpu = first_cpu(cpumask); if ((unsigned)cpu < NR_CPUS) - return x86_cpu_to_apicid[cpu]; + return per_cpu(x86_cpu_to_apicid, cpu); else return BAD_APICID; } diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index a7eee0a4751..6b3469311e4 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -58,7 +58,7 @@ void __init x86_64_start_kernel(char * real_mode_data) for (i = 0; i < IDT_ENTRIES; i++) set_intr_gate(i, early_idt_handler); - asm volatile("lidt %0" :: "m" (idt_descr)); + load_idt((const struct desc_ptr *)&idt_descr); early_printk("Kernel alive\n"); diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 772afab8f19..53303f2e547 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -69,12 +69,15 @@ static inline void hpet_clear_mapping(void) * HPET command line enable / disable */ static int boot_hpet_disable; +int hpet_force_user; static int __init hpet_setup(char* str) { if (str) { if (!strncmp("disable", str, 7)) boot_hpet_disable = 1; + if (!strncmp("force", str, 5)) + hpet_force_user = 1; } return 1; } diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c index d34a10cc13a..f634fc715c9 100644 --- a/arch/x86/kernel/i8259_32.c +++ b/arch/x86/kernel/i8259_32.c @@ -403,7 +403,8 @@ void __init native_init_IRQ(void) int vector = FIRST_EXTERNAL_VECTOR + i; if (i >= NR_IRQS) break; - if (vector != SYSCALL_VECTOR) + /* SYSCALL_VECTOR was reserved in trap_init. */ + if (!test_bit(vector, used_vectors)) set_intr_gate(vector, interrupt[i]); } diff --git a/arch/x86/kernel/init_task_32.c b/arch/x86/kernel/init_task.c index d26fc063a76..468c9c43784 100644 --- a/arch/x86/kernel/init_task_32.c +++ b/arch/x86/kernel/init_task.c @@ -15,7 +15,6 @@ static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); - EXPORT_SYMBOL(init_mm); /* @@ -25,7 +24,7 @@ EXPORT_SYMBOL(init_mm); * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union thread_union init_thread_union +union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; @@ -35,12 +34,14 @@ union thread_union init_thread_union * All other task structs will be allocated on slabs in fork.c */ struct task_struct init_task = INIT_TASK(init_task); - EXPORT_SYMBOL(init_task); /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, - * no more per-task TSS's. - */ + * no more per-task TSS's. The TSS size is kept cacheline-aligned + * so they are allowed to end up in the .data.cacheline_aligned + * section. Since TSS's are completely CPU-local, we want them + * on exact cacheline boundaries, to eliminate cacheline ping-pong. + */ DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; diff --git a/arch/x86/kernel/init_task_64.c b/arch/x86/kernel/init_task_64.c deleted file mode 100644 index 4ff33d4f855..00000000000 --- a/arch/x86/kernel/init_task_64.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/init_task.h> -#include <linux/fs.h> -#include <linux/mqueue.h> - -#include <asm/uaccess.h> -#include <asm/pgtable.h> -#include <asm/desc.h> - -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - -/* - * Initial task structure. - * - * We need to make sure that this is 8192-byte aligned due to the - * way process stacks are handled. This is done by having a special - * "init_task" linker map entry.. - */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); -/* - * per-CPU TSS segments. Threads are completely 'soft' on Linux, - * no more per-task TSS's. The TSS size is kept cacheline-aligned - * so they are allowed to end up in the .data.cacheline_aligned - * section. Since TSS's are completely CPU-local, we want them - * on exact cacheline boundaries, to eliminate cacheline ping-pong. - */ -DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; - -/* Copies of the original ist values from the tss are only accessed during - * debugging, no special alignment required. - */ -DEFINE_PER_CPU(struct orig_ist, orig_ist); - -#define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 03e88fc00e5..f35c6eb33da 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -1198,7 +1198,7 @@ static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 } static int __assign_irq_vector(int irq) { static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; - int vector, offset, i; + int vector, offset; BUG_ON((unsigned)irq >= NR_IRQ_VECTORS); @@ -1215,11 +1215,8 @@ next: } if (vector == current_vector) return -ENOSPC; - if (vector == SYSCALL_VECTOR) + if (test_and_set_bit(vector, used_vectors)) goto next; - for (i = 0; i < NR_IRQ_VECTORS; i++) - if (irq_vector[i] == vector) - goto next; current_vector = vector; current_offset = offset; @@ -2295,6 +2292,12 @@ static inline void __init check_timer(void) void __init setup_IO_APIC(void) { + int i; + + /* Reserve all the system vectors. */ + for (i = FIRST_SYSTEM_VECTOR; i < NR_VECTORS; i++) + set_bit(i, used_vectors); + enable_IO_APIC(); if (acpi_ioapic) diff --git a/arch/x86/kernel/mce_64.c b/arch/x86/kernel/mce_64.c index 82c85bdff3a..07bbfe7aa7f 100644 --- a/arch/x86/kernel/mce_64.c +++ b/arch/x86/kernel/mce_64.c @@ -799,7 +799,8 @@ static __cpuinit int mce_create_device(unsigned int cpu) { int err; int i; - if (!mce_available(&cpu_data[cpu])) + + if (!mce_available(&cpu_data(cpu))) return -EIO; memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject)); diff --git a/arch/x86/kernel/mce_amd_64.c b/arch/x86/kernel/mce_amd_64.c index 0d2afd96aca..752fb16a817 100644 --- a/arch/x86/kernel/mce_amd_64.c +++ b/arch/x86/kernel/mce_amd_64.c @@ -472,11 +472,11 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) sprintf(name, "threshold_bank%i", bank); #ifdef CONFIG_SMP - if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) { /* symlink */ + if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ i = first_cpu(per_cpu(cpu_core_map, cpu)); /* first core not up yet */ - if (cpu_data[i].cpu_core_id) + if (cpu_data(i).cpu_core_id) goto out; /* already linked */ diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index 09cf7811035..09c315214a5 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode.c @@ -132,7 +132,7 @@ static struct ucode_cpu_info { static void collect_cpu_info(int cpu_num) { - struct cpuinfo_x86 *c = cpu_data + cpu_num; + struct cpuinfo_x86 *c = &cpu_data(cpu_num); struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; unsigned int val[2]; @@ -522,7 +522,7 @@ static struct platform_device *microcode_pdev; static int cpu_request_microcode(int cpu) { char name[30]; - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); const struct firmware *firmware; void *buf; unsigned long size; @@ -570,7 +570,7 @@ static int cpu_request_microcode(int cpu) static int apply_microcode_check_cpu(int cpu) { - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; cpumask_t old; unsigned int val[2]; diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c index 8bf0ca03ac8..ef4aab12358 100644 --- a/arch/x86/kernel/mpparse_64.c +++ b/arch/x86/kernel/mpparse_64.c @@ -57,6 +57,8 @@ unsigned long mp_lapic_addr = 0; /* Processor that is doing the boot up */ unsigned int boot_cpu_id = -1U; +EXPORT_SYMBOL(boot_cpu_id); + /* Internal processor count */ unsigned int num_processors __cpuinitdata = 0; @@ -86,7 +88,7 @@ static int __init mpf_checksum(unsigned char *mp, int len) return sum & 0xFF; } -static void __cpuinit MP_processor_info (struct mpc_config_processor *m) +static void __cpuinit MP_processor_info(struct mpc_config_processor *m) { int cpu; cpumask_t tmp_map; @@ -123,7 +125,18 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m) cpu = 0; } bios_cpu_apicid[cpu] = m->mpc_apicid; - x86_cpu_to_apicid[cpu] = m->mpc_apicid; + /* + * We get called early in the the start_kernel initialization + * process when the per_cpu data area is not yet setup, so we + * use a static array that is removed after the per_cpu data + * area is created. + */ + if (x86_cpu_to_apicid_ptr) { + u8 *x86_cpu_to_apicid = (u8 *)x86_cpu_to_apicid_ptr; + x86_cpu_to_apicid[cpu] = m->mpc_apicid; + } else { + per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid; + } cpu_set(cpu, cpu_possible_map); cpu_set(cpu, cpu_present_map); diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index e18e516cf54..ee6eba4ecfe 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -112,7 +112,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf, static int msr_open(struct inode *inode, struct file *file) { unsigned int cpu = iminor(file->f_path.dentry->d_inode); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + struct cpuinfo_x86 *c = &cpu_data(cpu); if (cpu >= NR_CPUS || !cpu_online(cpu)) return -ENXIO; /* No such CPU */ diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index b2b42bdb0a1..afaf9f12c03 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -11,7 +11,7 @@ #include <asm/iommu.h> #include <asm/calgary.h> -int iommu_merge __read_mostly = 0; +int iommu_merge __read_mostly = 1; EXPORT_SYMBOL(iommu_merge); dma_addr_t bad_dma_address __read_mostly; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 044a47745a5..7b899584d29 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -295,34 +295,52 @@ static int __init idle_setup(char *str) } early_param("idle", idle_setup); -void show_regs(struct pt_regs * regs) +void __show_registers(struct pt_regs *regs, int all) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; unsigned long d0, d1, d2, d3, d6, d7; + unsigned long esp; + unsigned short ss, gs; + + if (user_mode_vm(regs)) { + esp = regs->esp; + ss = regs->xss & 0xffff; + savesegment(gs, gs); + } else { + esp = (unsigned long) (®s->esp); + savesegment(ss, ss); + savesegment(gs, gs); + } printk("\n"); - printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); - printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id()); + printk("Pid: %d, comm: %s %s (%s %.*s)\n", + task_pid_nr(current), current->comm, + print_tainted(), init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); + + printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", + 0xffff & regs->xcs, regs->eip, regs->eflags, + smp_processor_id()); print_symbol("EIP is at %s\n", regs->eip); - if (user_mode_vm(regs)) - printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); - printk(" EFLAGS: %08lx %s (%s %.*s)\n", - regs->eflags, print_tainted(), init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", - regs->eax,regs->ebx,regs->ecx,regs->edx); - printk("ESI: %08lx EDI: %08lx EBP: %08lx", - regs->esi, regs->edi, regs->ebp); - printk(" DS: %04x ES: %04x FS: %04x\n", - 0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs); + regs->eax, regs->ebx, regs->ecx, regs->edx); + printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n", + regs->esi, regs->edi, regs->ebp, esp); + printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", + regs->xds & 0xffff, regs->xes & 0xffff, + regs->xfs & 0xffff, gs, ss); + + if (!all) + return; cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); cr4 = read_cr4_safe(); - printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); + printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", + cr0, cr2, cr3, cr4); get_debugreg(d0, 0); get_debugreg(d1, 1); @@ -330,10 +348,16 @@ void show_regs(struct pt_regs * regs) get_debugreg(d3, 3); printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", d0, d1, d2, d3); + get_debugreg(d6, 6); get_debugreg(d7, 7); - printk("DR6: %08lx DR7: %08lx\n", d6, d7); + printk("DR6: %08lx DR7: %08lx\n", + d6, d7); +} +void show_regs(struct pt_regs *regs) +{ + __show_registers(regs, 1); show_trace(NULL, regs, ®s->esp); } diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d769e204f94..a4ce1911efd 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -45,9 +45,12 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) if (!(config & 0x2)) pci_write_config_byte(dev, 0xf4, config); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, + quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, + quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, + quirk_intel_irqbalance); #endif #if defined(CONFIG_HPET_TIMER) @@ -56,7 +59,8 @@ unsigned long force_hpet_address; static enum { NONE_FORCE_HPET_RESUME, OLD_ICH_FORCE_HPET_RESUME, - ICH_FORCE_HPET_RESUME + ICH_FORCE_HPET_RESUME, + VT8237_FORCE_HPET_RESUME } force_hpet_resume_type; static void __iomem *rcba_base; @@ -146,17 +150,17 @@ static void ich_force_enable_hpet(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, - ich_force_enable_hpet); + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, - ich_force_enable_hpet); + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, - ich_force_enable_hpet); + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, - ich_force_enable_hpet); + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, - ich_force_enable_hpet); + ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, - ich_force_enable_hpet); + ich_force_enable_hpet); static struct pci_dev *cached_dev; @@ -232,10 +236,91 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev) printk(KERN_DEBUG "Failed to force enable HPET\n"); } +/* + * Undocumented chipset features. Make sure that the user enforced + * this. + */ +static void old_ich_force_enable_hpet_user(struct pci_dev *dev) +{ + if (hpet_force_user) + old_ich_force_enable_hpet(dev); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, + old_ich_force_enable_hpet_user); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, + old_ich_force_enable_hpet_user); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, + old_ich_force_enable_hpet_user); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, + old_ich_force_enable_hpet_user); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, - old_ich_force_enable_hpet); + old_ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, - old_ich_force_enable_hpet); + old_ich_force_enable_hpet); + + +static void vt8237_force_hpet_resume(void) +{ + u32 val; + + if (!force_hpet_address || !cached_dev) + return; + + val = 0xfed00000 | 0x80; + pci_write_config_dword(cached_dev, 0x68, val); + + pci_read_config_dword(cached_dev, 0x68, &val); + if (val & 0x80) + printk(KERN_DEBUG "Force enabled HPET at resume\n"); + else + BUG(); +} + +static void vt8237_force_enable_hpet(struct pci_dev *dev) +{ + u32 uninitialized_var(val); + + if (!hpet_force_user || hpet_address || force_hpet_address) + return; + + pci_read_config_dword(dev, 0x68, &val); + /* + * Bit 7 is HPET enable bit. + * Bit 31:10 is HPET base address (contrary to what datasheet claims) + */ + if (val & 0x80) { + force_hpet_address = (val & ~0x3ff); + printk(KERN_DEBUG "HPET at base address 0x%lx\n", + force_hpet_address); + return; + } + + /* + * HPET is disabled. Trying enabling at FED00000 and check + * whether it sticks + */ + val = 0xfed00000 | 0x80; + pci_write_config_dword(dev, 0x68, val); + + pci_read_config_dword(dev, 0x68, &val); + if (val & 0x80) { + force_hpet_address = (val & ~0x3ff); + printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", + force_hpet_address); + cached_dev = dev; + force_hpet_resume_type = VT8237_FORCE_HPET_RESUME; + return; + } + + printk(KERN_DEBUG "Failed to force enable HPET\n"); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, + vt8237_force_enable_hpet); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, + vt8237_force_enable_hpet); + void force_hpet_resume(void) { @@ -246,6 +331,9 @@ void force_hpet_resume(void) case OLD_ICH_FORCE_HPET_RESUME: return old_ich_force_hpet_resume(); + case VT8237_FORCE_HPET_RESUME: + return vt8237_force_hpet_resume(); + default: break; } diff --git a/arch/x86/kernel/reboot_64.c b/arch/x86/kernel/reboot_64.c index 368db2b9c5a..776eb06b651 100644 --- a/arch/x86/kernel/reboot_64.c +++ b/arch/x86/kernel/reboot_64.c @@ -11,6 +11,7 @@ #include <linux/sched.h> #include <asm/io.h> #include <asm/delay.h> +#include <asm/desc.h> #include <asm/hw_irq.h> #include <asm/system.h> #include <asm/pgtable.h> @@ -136,7 +137,7 @@ void machine_emergency_restart(void) } case BOOT_TRIPLE: - __asm__ __volatile__("lidt (%0)": :"r" (&no_idt)); + load_idt((const struct desc_ptr *)&no_idt); __asm__ __volatile__("int3"); reboot_type = BOOT_KBD; diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 8b30b26ad06..1a07bbea7be 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c @@ -12,6 +12,7 @@ #include <linux/interrupt.h> #include <asm/reboot_fixups.h> #include <asm/msr.h> +#include <asm/geode.h> static void cs5530a_warm_reset(struct pci_dev *dev) { @@ -24,11 +25,8 @@ static void cs5530a_warm_reset(struct pci_dev *dev) static void cs5536_warm_reset(struct pci_dev *dev) { - /* - * 6.6.2.12 Soft Reset (DIVIL_SOFT_RESET) - * writing 1 to the LSB of this MSR causes a hard reset. - */ - wrmsrl(0x51400017, 1ULL); + /* writing 1 to the LSB of this MSR causes a hard reset */ + wrmsrl(MSR_DIVIL_SOFT_RESET, 1ULL); udelay(50); /* shouldn't get here but be safe and spin a while */ } diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c index ba918823505..3558ac78c92 100644 --- a/arch/x86/kernel/setup64.c +++ b/arch/x86/kernel/setup64.c @@ -185,6 +185,12 @@ void __cpuinit check_efer(void) unsigned long kernel_eflags; /* + * Copies of the original ist values from the tss are only accessed during + * debugging, no special alignment required. + */ +DEFINE_PER_CPU(struct orig_ist, orig_ist); + +/* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT * and IDT. We reload them nevertheless, this function acts as a @@ -224,8 +230,8 @@ void __cpuinit cpu_init (void) memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE); cpu_gdt_descr[cpu].size = GDT_SIZE; - asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu])); - asm volatile("lidt %0" :: "m" (idt_descr)); + load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]); + load_idt((const struct desc_ptr *)&idt_descr); memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); syscall_init(); diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 18e6eaf138c..ba2e165a8a0 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -661,9 +661,7 @@ void __init setup_arch(char **cmdline_p) #endif #ifdef CONFIG_PCI -#ifdef CONFIG_X86_IO_APIC - check_acpi_pci(); /* Checks more than just ACPI actually */ -#endif + early_quirks(); #endif #ifdef CONFIG_ACPI diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index cdcba697522..31322d42eaa 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -302,6 +302,11 @@ void __init setup_arch(char **cmdline_p) dmi_scan_machine(); +#ifdef CONFIG_SMP + /* setup to use the static apicid table during kernel startup */ + x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init; +#endif + #ifdef CONFIG_ACPI /* * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). @@ -554,7 +559,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) but in the same order as the HT nodeids. If that doesn't result in a usable node fall back to the path for the previous case. */ - int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits); + int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits); if (ht_nodeid >= 0 && apicid_to_node[ht_nodeid] != NUMA_NO_NODE) node = apicid_to_node[ht_nodeid]; @@ -878,6 +883,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; + c->cpu_index = 0; #endif } @@ -984,6 +990,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) static int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_x86 *c = v; + int cpu = 0; /* * These flag bits must match the definitions in <asm/cpufeature.h>. @@ -1062,8 +1069,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_SMP - if (!cpu_online(c-cpu_data)) + if (!cpu_online(c->cpu_index)) return 0; + cpu = c->cpu_index; #endif seq_printf(m,"processor\t: %u\n" @@ -1071,7 +1079,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "cpu family\t: %d\n" "model\t\t: %d\n" "model name\t: %s\n", - (unsigned)(c-cpu_data), + (unsigned)cpu, c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", c->x86, (int)c->x86_model, @@ -1083,7 +1091,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if (cpu_has(c,X86_FEATURE_TSC)) { - unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data)); + unsigned int freq = cpufreq_quick_get((unsigned)cpu); if (!freq) freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", @@ -1096,7 +1104,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_SMP if (smp_num_siblings * c->x86_max_cores > 1) { - int cpu = c - cpu_data; seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", cpus_weight(per_cpu(cpu_core_map, cpu))); @@ -1154,12 +1161,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { - return *pos < NR_CPUS ? cpu_data + *pos : NULL; + if (*pos == 0) /* just in case, cpu 0 is not the first */ + *pos = first_cpu(cpu_possible_map); + if ((*pos) < NR_CPUS && cpu_possible(*pos)) + return &cpu_data(*pos); + return NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - ++*pos; + *pos = next_cpu(*pos, cpu_possible_map); return c_start(m, pos); } diff --git a/arch/x86/kernel/smp_32.c b/arch/x86/kernel/smp_32.c index 9ced828d555..f3211530839 100644 --- a/arch/x86/kernel/smp_32.c +++ b/arch/x86/kernel/smp_32.c @@ -610,7 +610,7 @@ static void stop_this_cpu (void * dummy) */ cpu_clear(smp_processor_id(), cpu_online_map); disable_local_APIC(); - if (cpu_data[smp_processor_id()].hlt_works_ok) + if (cpu_data(smp_processor_id()).hlt_works_ok) for(;;) halt(); for (;;); } @@ -676,7 +676,7 @@ static int convert_apicid_to_cpu(int apic_id) int i; for (i = 0; i < NR_CPUS; i++) { - if (x86_cpu_to_apicid[i] == apic_id) + if (per_cpu(x86_cpu_to_apicid, i) == apic_id) return i; } return -1; diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c index 5c2964727d1..03fa6ed559c 100644 --- a/arch/x86/kernel/smp_64.c +++ b/arch/x86/kernel/smp_64.c @@ -322,17 +322,27 @@ void unlock_ipi_call_lock(void) } /* - * this function sends a 'generic call function' IPI to one other CPU - * in the system. - * - * cpu is a standard Linux logical CPU number. + * this function sends a 'generic call function' IPI to all other CPU + * of the system defined in the mask. */ -static void -__smp_call_function_single(int cpu, void (*func) (void *info), void *info, - int nonatomic, int wait) + +static int +__smp_call_function_mask(cpumask_t mask, + void (*func)(void *), void *info, + int wait) { struct call_data_struct data; - int cpus = 1; + cpumask_t allbutself; + int cpus; + + allbutself = cpu_online_map; + cpu_clear(smp_processor_id(), allbutself); + + cpus_and(mask, mask, allbutself); + cpus = cpus_weight(mask); + + if (!cpus) + return 0; data.func = func; data.info = info; @@ -343,19 +353,55 @@ __smp_call_function_single(int cpu, void (*func) (void *info), void *info, call_data = &data; wmb(); - /* Send a message to all other CPUs and wait for them to respond */ - send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR); + + /* Send a message to other CPUs */ + if (cpus_equal(mask, allbutself)) + send_IPI_allbutself(CALL_FUNCTION_VECTOR); + else + send_IPI_mask(mask, CALL_FUNCTION_VECTOR); /* Wait for response */ while (atomic_read(&data.started) != cpus) cpu_relax(); if (!wait) - return; + return 0; while (atomic_read(&data.finished) != cpus) cpu_relax(); + + return 0; +} +/** + * smp_call_function_mask(): Run a function on a set of other CPUs. + * @mask: The set of cpus to run on. Must not include the current cpu. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @wait: If true, wait (atomically) until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + */ +int smp_call_function_mask(cpumask_t mask, + void (*func)(void *), void *info, + int wait) +{ + int ret; + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + + spin_lock(&call_lock); + ret = __smp_call_function_mask(mask, func, info, wait); + spin_unlock(&call_lock); + return ret; } +EXPORT_SYMBOL(smp_call_function_mask); /* * smp_call_function_single - Run a function on a specific CPU @@ -374,6 +420,7 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { /* prevent preemption and reschedule on another processor */ + int ret; int me = get_cpu(); /* Can deadlock when called with interrupts disabled */ @@ -387,51 +434,14 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, return 0; } - spin_lock(&call_lock); - __smp_call_function_single(cpu, func, info, nonatomic, wait); - spin_unlock(&call_lock); + ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); + put_cpu(); - return 0; + return ret; } EXPORT_SYMBOL(smp_call_function_single); /* - * this function sends a 'generic call function' IPI to all other CPUs - * in the system. - */ -static void __smp_call_function (void (*func) (void *info), void *info, - int nonatomic, int wait) -{ - struct call_data_struct data; - int cpus = num_online_cpus()-1; - - if (!cpus) - return; - - data.func = func; - data.info = info; - atomic_set(&data.started, 0); - data.wait = wait; - if (wait) - atomic_set(&data.finished, 0); - - call_data = &data; - wmb(); - /* Send a message to all other CPUs and wait for them to respond */ - send_IPI_allbutself(CALL_FUNCTION_VECTOR); - - /* Wait for response */ - while (atomic_read(&data.started) != cpus) - cpu_relax(); - - if (!wait) - return; - - while (atomic_read(&data.finished) != cpus) - cpu_relax(); -} - -/* * smp_call_function - run a function on all other CPUs. * @func: The function to run. This must be fast and non-blocking. * @info: An arbitrary pointer to pass to the function. @@ -449,10 +459,7 @@ static void __smp_call_function (void (*func) (void *info), void *info, int smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait) { - spin_lock(&call_lock); - __smp_call_function(func,info,nonatomic,wait); - spin_unlock(&call_lock); - return 0; + return smp_call_function_mask(cpu_online_map, func, info, wait); } EXPORT_SYMBOL(smp_call_function); @@ -479,7 +486,7 @@ void smp_send_stop(void) /* Don't deadlock on the call lock in panic */ nolock = !spin_trylock(&call_lock); local_irq_save(flags); - __smp_call_function(stop_this_cpu, NULL, 0, 0); + __smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0); if (!nolock) spin_unlock(&call_lock); disable_local_APIC(); diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c index 1b9ee68c98a..ef0f34ede1a 100644 --- a/arch/x86/kernel/smpboot_32.c +++ b/arch/x86/kernel/smpboot_32.c @@ -67,7 +67,7 @@ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); /* Last level cache ID of each logical CPU */ -int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; +DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID; /* representing HT siblings of each logical CPU */ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); @@ -89,12 +89,20 @@ EXPORT_SYMBOL(cpu_possible_map); static cpumask_t smp_commenced_mask; /* Per CPU bogomips and other parameters */ -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; -EXPORT_SYMBOL(cpu_data); +DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); +EXPORT_PER_CPU_SYMBOL(cpu_info); -u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = - { [0 ... NR_CPUS-1] = 0xff }; -EXPORT_SYMBOL(x86_cpu_to_apicid); +/* + * The following static array is used during kernel startup + * and the x86_cpu_to_apicid_ptr contains the address of the + * array during this time. Is it zeroed when the per_cpu + * data area is removed. + */ +u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata = + { [0 ... NR_CPUS-1] = BAD_APICID }; +void *x86_cpu_to_apicid_ptr; +DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID; +EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid); u8 apicid_2_node[MAX_APICID]; @@ -150,9 +158,10 @@ void __init smp_alloc_memory(void) void __cpuinit smp_store_cpu_info(int id) { - struct cpuinfo_x86 *c = cpu_data + id; + struct cpuinfo_x86 *c = &cpu_data(id); *c = boot_cpu_data; + c->cpu_index = id; if (id!=0) identify_secondary_cpu(c); /* @@ -294,7 +303,7 @@ static int cpucount; /* maps the cpu to the sched domain representing multi-core */ cpumask_t cpu_coregroup_map(int cpu) { - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); /* * For perf, we return last level cache shared map. * And for power savings, we return cpu_core_map @@ -311,41 +320,41 @@ static cpumask_t cpu_sibling_setup_map; void __cpuinit set_cpu_sibling_map(int cpu) { int i; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(cpu); cpu_set(cpu, cpu_sibling_setup_map); if (smp_num_siblings > 1) { for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (c[cpu].phys_proc_id == c[i].phys_proc_id && - c[cpu].cpu_core_id == c[i].cpu_core_id) { + if (c->phys_proc_id == cpu_data(i).phys_proc_id && + c->cpu_core_id == cpu_data(i).cpu_core_id) { cpu_set(i, per_cpu(cpu_sibling_map, cpu)); cpu_set(cpu, per_cpu(cpu_sibling_map, i)); cpu_set(i, per_cpu(cpu_core_map, cpu)); cpu_set(cpu, per_cpu(cpu_core_map, i)); - cpu_set(i, c[cpu].llc_shared_map); - cpu_set(cpu, c[i].llc_shared_map); + cpu_set(i, c->llc_shared_map); + cpu_set(cpu, cpu_data(i).llc_shared_map); } } } else { cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); } - cpu_set(cpu, c[cpu].llc_shared_map); + cpu_set(cpu, c->llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); - c[cpu].booted_cores = 1; + c->booted_cores = 1; return; } for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (cpu_llc_id[cpu] != BAD_APICID && - cpu_llc_id[cpu] == cpu_llc_id[i]) { - cpu_set(i, c[cpu].llc_shared_map); - cpu_set(cpu, c[i].llc_shared_map); + if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && + per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { + cpu_set(i, c->llc_shared_map); + cpu_set(cpu, cpu_data(i).llc_shared_map); } - if (c[cpu].phys_proc_id == c[i].phys_proc_id) { + if (c->phys_proc_id == cpu_data(i).phys_proc_id) { cpu_set(i, per_cpu(cpu_core_map, cpu)); cpu_set(cpu, per_cpu(cpu_core_map, i)); /* @@ -357,15 +366,15 @@ void __cpuinit set_cpu_sibling_map(int cpu) * the booted_cores for this new cpu */ if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) - c[cpu].booted_cores++; + c->booted_cores++; /* * increment the core count for all * the other cpus in this package */ if (i != cpu) - c[i].booted_cores++; - } else if (i != cpu && !c[cpu].booted_cores) - c[cpu].booted_cores = c[i].booted_cores; + cpu_data(i).booted_cores++; + } else if (i != cpu && !c->booted_cores) + c->booted_cores = cpu_data(i).booted_cores; } } } @@ -804,7 +813,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) irq_ctx_init(cpu); - x86_cpu_to_apicid[cpu] = apicid; + per_cpu(x86_cpu_to_apicid, cpu) = apicid; /* * This grunge runs the startup process for * the targeted processor. @@ -844,7 +853,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); printk("CPU%d: ", cpu); - print_cpu_info(&cpu_data[cpu]); + print_cpu_info(&cpu_data(cpu)); Dprintk("CPU has booted.\n"); } else { boot_error= 1; @@ -866,7 +875,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ cpucount--; } else { - x86_cpu_to_apicid[cpu] = apicid; + per_cpu(x86_cpu_to_apicid, cpu) = apicid; cpu_set(cpu, cpu_present_map); } @@ -915,7 +924,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu) struct warm_boot_cpu_info info; int apicid, ret; - apicid = x86_cpu_to_apicid[cpu]; + apicid = per_cpu(x86_cpu_to_apicid, cpu); if (apicid == BAD_APICID) { ret = -ENODEV; goto exit; @@ -961,11 +970,11 @@ static void __init smp_boot_cpus(unsigned int max_cpus) */ smp_store_cpu_info(0); /* Final full version of the data */ printk("CPU%d: ", 0); - print_cpu_info(&cpu_data[0]); + print_cpu_info(&cpu_data(0)); boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); - x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; + per_cpu(x86_cpu_to_apicid, 0) = boot_cpu_physical_apicid; current_thread_info()->cpu = 0; @@ -1008,6 +1017,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); + map_cpu_to_logical_apicid(); cpu_set(0, per_cpu(cpu_sibling_map, 0)); cpu_set(0, per_cpu(cpu_core_map, 0)); return; @@ -1029,6 +1039,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) } smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); + map_cpu_to_logical_apicid(); cpu_set(0, per_cpu(cpu_sibling_map, 0)); cpu_set(0, per_cpu(cpu_core_map, 0)); return; @@ -1082,7 +1093,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) Dprintk("Before bogomips.\n"); for (cpu = 0; cpu < NR_CPUS; cpu++) if (cpu_isset(cpu, cpu_callout_map)) - bogosum += cpu_data[cpu].loops_per_jiffy; + bogosum += cpu_data(cpu).loops_per_jiffy; printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", cpucount+1, @@ -1152,7 +1163,7 @@ void __init native_smp_prepare_boot_cpu(void) void remove_siblinginfo(int cpu) { int sibling; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(cpu); for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); @@ -1160,15 +1171,15 @@ void remove_siblinginfo(int cpu) * last thread sibling in this cpu core going down */ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) - c[sibling].booted_cores--; + cpu_data(sibling).booted_cores--; } for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); cpus_clear(per_cpu(cpu_sibling_map, cpu)); cpus_clear(per_cpu(cpu_core_map, cpu)); - c[cpu].phys_proc_id = 0; - c[cpu].cpu_core_id = 0; + c->phys_proc_id = 0; + c->cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); } diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index d4c33aba3ff..b7e768dd87c 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c @@ -65,7 +65,7 @@ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); /* Last level cache ID of each logical CPU */ -u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; +DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID; /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map __read_mostly; @@ -84,8 +84,8 @@ cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); /* Per CPU bogomips and other parameters */ -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; -EXPORT_SYMBOL(cpu_data); +DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); +EXPORT_PER_CPU_SYMBOL(cpu_info); /* Set when the idlers are all forked */ int smp_threads_ready; @@ -138,9 +138,10 @@ static unsigned long __cpuinit setup_trampoline(void) static void __cpuinit smp_store_cpu_info(int id) { - struct cpuinfo_x86 *c = cpu_data + id; + struct cpuinfo_x86 *c = &cpu_data(id); *c = boot_cpu_data; + c->cpu_index = id; identify_cpu(c); print_cpu_info(c); } @@ -237,7 +238,7 @@ void __cpuinit smp_callin(void) /* maps the cpu to the sched domain representing multi-core */ cpumask_t cpu_coregroup_map(int cpu) { - struct cpuinfo_x86 *c = cpu_data + cpu; + struct cpuinfo_x86 *c = &cpu_data(cpu); /* * For perf, we return last level cache shared map. * And for power savings, we return cpu_core_map @@ -254,41 +255,41 @@ static cpumask_t cpu_sibling_setup_map; static inline void set_cpu_sibling_map(int cpu) { int i; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(cpu); cpu_set(cpu, cpu_sibling_setup_map); if (smp_num_siblings > 1) { for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (c[cpu].phys_proc_id == c[i].phys_proc_id && - c[cpu].cpu_core_id == c[i].cpu_core_id) { + if (c->phys_proc_id == cpu_data(i).phys_proc_id && + c->cpu_core_id == cpu_data(i).cpu_core_id) { cpu_set(i, per_cpu(cpu_sibling_map, cpu)); cpu_set(cpu, per_cpu(cpu_sibling_map, i)); cpu_set(i, per_cpu(cpu_core_map, cpu)); cpu_set(cpu, per_cpu(cpu_core_map, i)); - cpu_set(i, c[cpu].llc_shared_map); - cpu_set(cpu, c[i].llc_shared_map); + cpu_set(i, c->llc_shared_map); + cpu_set(cpu, cpu_data(i).llc_shared_map); } } } else { cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); } - cpu_set(cpu, c[cpu].llc_shared_map); + cpu_set(cpu, c->llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); - c[cpu].booted_cores = 1; + c->booted_cores = 1; return; } for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (cpu_llc_id[cpu] != BAD_APICID && - cpu_llc_id[cpu] == cpu_llc_id[i]) { - cpu_set(i, c[cpu].llc_shared_map); - cpu_set(cpu, c[i].llc_shared_map); + if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && + per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { + cpu_set(i, c->llc_shared_map); + cpu_set(cpu, cpu_data(i).llc_shared_map); } - if (c[cpu].phys_proc_id == c[i].phys_proc_id) { + if (c->phys_proc_id == cpu_data(i).phys_proc_id) { cpu_set(i, per_cpu(cpu_core_map, cpu)); cpu_set(cpu, per_cpu(cpu_core_map, i)); /* @@ -300,15 +301,15 @@ static inline void set_cpu_sibling_map(int cpu) * the booted_cores for this new cpu */ if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) - c[cpu].booted_cores++; + c->booted_cores++; /* * increment the core count for all * the other cpus in this package */ if (i != cpu) - c[i].booted_cores++; - } else if (i != cpu && !c[cpu].booted_cores) - c[cpu].booted_cores = c[i].booted_cores; + cpu_data(i).booted_cores++; + } else if (i != cpu && !c->booted_cores) + c->booted_cores = cpu_data(i).booted_cores; } } } @@ -694,7 +695,7 @@ do_rest: clear_node_cpumask(cpu); /* was set by numa_add_cpu */ cpu_clear(cpu, cpu_present_map); cpu_clear(cpu, cpu_possible_map); - x86_cpu_to_apicid[cpu] = BAD_APICID; + per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID; return -EIO; } @@ -841,6 +842,26 @@ static int __init smp_sanity_check(unsigned max_cpus) } /* + * Copy apicid's found by MP_processor_info from initial array to the per cpu + * data area. The x86_cpu_to_apicid_init array is then expendable and the + * x86_cpu_to_apicid_ptr is zeroed indicating that the static array is no + * longer available. + */ +void __init smp_set_apicids(void) +{ + int cpu; + + for_each_cpu_mask(cpu, cpu_possible_map) { + if (per_cpu_offset(cpu)) + per_cpu(x86_cpu_to_apicid, cpu) = + x86_cpu_to_apicid_init[cpu]; + } + + /* indicate the static array will be going away soon */ + x86_cpu_to_apicid_ptr = NULL; +} + +/* * Prepare for SMP bootup. The MP table or ACPI has been read * earlier. Just do some sanity checking here and enable APIC mode. */ @@ -849,6 +870,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) nmi_watchdog_default(); current_cpu_data = boot_cpu_data; current_thread_info()->cpu = 0; /* needed? */ + smp_set_apicids(); set_cpu_sibling_map(0); if (smp_sanity_check(max_cpus) < 0) { @@ -968,7 +990,7 @@ void __init smp_cpus_done(unsigned int max_cpus) static void remove_siblinginfo(int cpu) { int sibling; - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(cpu); for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); @@ -976,15 +998,15 @@ static void remove_siblinginfo(int cpu) * last thread sibling in this cpu core going down */ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) - c[sibling].booted_cores--; + cpu_data(sibling).booted_cores--; } for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); cpus_clear(per_cpu(cpu_sibling_map, cpu)); cpus_clear(per_cpu(cpu_core_map, cpu)); - c[cpu].phys_proc_id = 0; - c[cpu].cpu_core_id = 0; + c->phys_proc_id = 0; + c->cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); } diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c index 76274eeae9a..bc9f59c246f 100644 --- a/arch/x86/kernel/suspend_64.c +++ b/arch/x86/kernel/suspend_64.c @@ -32,9 +32,9 @@ void __save_processor_state(struct saved_context *ctxt) /* * descriptor tables */ - asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit)); - asm volatile ("sidt %0" : "=m" (ctxt->idt_limit)); - asm volatile ("str %0" : "=m" (ctxt->tr)); + store_gdt((struct desc_ptr *)&ctxt->gdt_limit); + store_idt((struct desc_ptr *)&ctxt->idt_limit); + store_tr(ctxt->tr); /* XMM0..XMM15 should be handled by kernel_fpu_begin(). */ /* @@ -91,8 +91,9 @@ void __restore_processor_state(struct saved_context *ctxt) * now restore the descriptor tables to their proper values * ltr is done i fix_processor_context(). */ - asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit)); - asm volatile ("lidt %0" :: "m" (ctxt->idt_limit)); + load_gdt((const struct desc_ptr *)&ctxt->gdt_limit); + load_idt((const struct desc_ptr *)&ctxt->idt_limit); + /* * segment registers diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 1e9d57256eb..cc9acace7e2 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -63,6 +63,9 @@ int panic_on_unrecovered_nmi; +DECLARE_BITMAP(used_vectors, NR_VECTORS); +EXPORT_SYMBOL_GPL(used_vectors); + asmlinkage int system_call(void); /* Do we ignore FPU interrupts ? */ @@ -288,33 +291,9 @@ EXPORT_SYMBOL(dump_stack); void show_registers(struct pt_regs *regs) { int i; - int in_kernel = 1; - unsigned long esp; - unsigned short ss, gs; - - esp = (unsigned long) (®s->esp); - savesegment(ss, ss); - savesegment(gs, gs); - if (user_mode_vm(regs)) { - in_kernel = 0; - esp = regs->esp; - ss = regs->xss & 0xffff; - } + print_modules(); - printk(KERN_EMERG "CPU: %d\n" - KERN_EMERG "EIP: %04x:[<%08lx>] %s VLI\n" - KERN_EMERG "EFLAGS: %08lx (%s %.*s)\n", - smp_processor_id(), 0xffff & regs->xcs, regs->eip, - print_tainted(), regs->eflags, init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip); - printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", - regs->eax, regs->ebx, regs->ecx, regs->edx); - printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", - regs->esi, regs->edi, regs->ebp, esp); - printk(KERN_EMERG "ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", - regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss); + __show_registers(regs, 0); printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", TASK_COMM_LEN, current->comm, task_pid_nr(current), current_thread_info(), current, task_thread_info(current)); @@ -322,14 +301,14 @@ void show_registers(struct pt_regs *regs) * When in-kernel, we also print out the stack and code at the * time of the fault.. */ - if (in_kernel) { + if (!user_mode_vm(regs)) { u8 *eip; unsigned int code_prologue = code_bytes * 43 / 64; unsigned int code_len = code_bytes; unsigned char c; printk("\n" KERN_EMERG "Stack: "); - show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); + show_stack_log_lvl(NULL, regs, ®s->esp, KERN_EMERG); printk(KERN_EMERG "Code: "); @@ -374,11 +353,11 @@ int is_valid_bugaddr(unsigned long eip) void die(const char * str, struct pt_regs * regs, long err) { static struct { - spinlock_t lock; + raw_spinlock_t lock; u32 lock_owner; int lock_owner_depth; } die = { - .lock = __SPIN_LOCK_UNLOCKED(die.lock), + .lock = __RAW_SPIN_LOCK_UNLOCKED, .lock_owner = -1, .lock_owner_depth = 0 }; @@ -389,13 +368,14 @@ void die(const char * str, struct pt_regs * regs, long err) if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); - spin_lock_irqsave(&die.lock, flags); + __raw_spin_lock(&die.lock); + raw_local_save_flags(flags); die.lock_owner = smp_processor_id(); die.lock_owner_depth = 0; bust_spinlocks(1); } else - local_save_flags(flags); + raw_local_save_flags(flags); if (++die.lock_owner_depth < 3) { unsigned long esp; @@ -439,7 +419,8 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(0); die.lock_owner = -1; add_taint(TAINT_DIE); - spin_unlock_irqrestore(&die.lock, flags); + __raw_spin_unlock(&die.lock); + raw_local_irq_restore(flags); if (!regs) return; @@ -1142,6 +1123,8 @@ static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) void __init trap_init(void) { + int i; + #ifdef CONFIG_EISA void __iomem *p = ioremap(0x0FFFD9, 4); if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) { @@ -1201,6 +1184,11 @@ void __init trap_init(void) set_system_gate(SYSCALL_VECTOR,&system_call); + /* Reserve all the builtin and the syscall vector. */ + for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) + set_bit(i, used_vectors); + set_bit(SYSCALL_VECTOR, used_vectors); + /* * Should be a barrier for any external CPU state. */ diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index b4c887341a2..d0c2bc7ab2e 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -462,7 +462,7 @@ void out_of_line_bug(void) EXPORT_SYMBOL(out_of_line_bug); #endif -static DEFINE_SPINLOCK(die_lock); +static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; static int die_owner = -1; static unsigned int die_nest_count; @@ -474,13 +474,13 @@ unsigned __kprobes long oops_begin(void) oops_enter(); /* racy, but better than risking deadlock. */ - local_irq_save(flags); + raw_local_irq_save(flags); cpu = smp_processor_id(); - if (!spin_trylock(&die_lock)) { + if (!__raw_spin_trylock(&die_lock)) { if (cpu == die_owner) /* nested oops. should stop eventually */; else - spin_lock(&die_lock); + __raw_spin_lock(&die_lock); } die_nest_count++; die_owner = cpu; @@ -494,12 +494,10 @@ void __kprobes oops_end(unsigned long flags) die_owner = -1; bust_spinlocks(0); die_nest_count--; - if (die_nest_count) - /* We still own the lock */ - local_irq_restore(flags); - else + if (!die_nest_count) /* Nest count reaches zero, release the lock. */ - spin_unlock_irqrestore(&die_lock, flags); + __raw_spin_unlock(&die_lock); + raw_local_irq_restore(flags); if (panic_on_oops) panic("Fatal exception"); oops_exit(); diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index 9683f1d3560..d78444c788a 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c @@ -181,8 +181,8 @@ int recalibrate_cpu_khz(void) if (cpu_has_tsc) { cpu_khz = calculate_cpu_khz(); tsc_khz = cpu_khz; - cpu_data[0].loops_per_jiffy = - cpufreq_scale(cpu_data[0].loops_per_jiffy, + cpu_data(0).loops_per_jiffy = + cpufreq_scale(cpu_data(0).loops_per_jiffy, cpu_khz_old, cpu_khz); return 0; } else @@ -215,7 +215,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) return 0; } ref_freq = freq->old; - loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; + loops_per_jiffy_ref = cpu_data(freq->cpu).loops_per_jiffy; cpu_khz_ref = cpu_khz; } @@ -223,7 +223,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || (val == CPUFREQ_RESUMECHANGE)) { if (!(freq->flags & CPUFREQ_CONST_LOOPS)) - cpu_data[freq->cpu].loops_per_jiffy = + cpu_data(freq->cpu).loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 9f22e542c37..9c70af45b42 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -73,13 +73,13 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, struct cpufreq_freqs *freq = data; unsigned long *lpj, dummy; - if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC)) + if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC)) return 0; lpj = &dummy; if (!(freq->flags & CPUFREQ_CONST_LOOPS)) #ifdef CONFIG_SMP - lpj = &cpu_data[freq->cpu].loops_per_jiffy; + lpj = &cpu_data(freq->cpu).loops_per_jiffy; #else lpj = &boot_cpu_data.loops_per_jiffy; #endif diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index e14cb3f5386..ad4005c6d4a 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -48,7 +48,7 @@ ({unsigned long v; \ extern char __vsyscall_0; \ asm("" : "=r" (v) : "0" (x)); \ - ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); }) + ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); }) /* * vsyscall_gtod_data contains data that is : @@ -291,7 +291,7 @@ static void __cpuinit vsyscall_set_cpu(int cpu) #ifdef CONFIG_NUMA node = cpu_to_node(cpu); #endif - if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) + if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP)) write_rdtscp_aux((node << 12) | cpu); /* Store cpu number in limit so that it can be loaded quickly diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c index f6edb11364d..952e7a89c2a 100644 --- a/arch/x86/lib/delay_32.c +++ b/arch/x86/lib/delay_32.c @@ -82,7 +82,7 @@ inline void __const_udelay(unsigned long xloops) __asm__("mull %0" :"=d" (xloops), "=&a" (d0) :"1" (xloops), "0" - (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))); + (cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4))); __delay(++xloops); } diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c index 2dbebd30834..0ebbfb9e7c7 100644 --- a/arch/x86/lib/delay_64.c +++ b/arch/x86/lib/delay_64.c @@ -40,7 +40,8 @@ EXPORT_SYMBOL(__delay); inline void __const_udelay(unsigned long xloops) { - __delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1); + __delay(((xloops * HZ * + cpu_data(raw_smp_processor_id()).loops_per_jiffy) >> 32) + 1); } EXPORT_SYMBOL(__const_udelay); diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index c5f2692273e..361ac5107b3 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -36,8 +36,8 @@ static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned = { [0 ... NR /* per CPU data structure (for /proc/cpuinfo et al), visible externally * indexed physically */ -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; -EXPORT_SYMBOL(cpu_data); +DEFINE_PER_CPU(cpuinfo_x86, cpu_info) __cacheline_aligned; +EXPORT_PER_CPU_SYMBOL(cpu_info); /* physical ID of the CPU used to boot the system */ unsigned char boot_cpu_id; @@ -430,7 +430,7 @@ find_smp_config(void) void __init smp_store_cpu_info(int id) { - struct cpuinfo_x86 *c=&cpu_data[id]; + struct cpuinfo_x86 *c = &cpu_data(id); *c = boot_cpu_data; @@ -634,7 +634,7 @@ do_boot_cpu(__u8 cpu) cpu, smp_processor_id())); printk("CPU%d: ", cpu); - print_cpu_info(&cpu_data[cpu]); + print_cpu_info(&cpu_data(cpu)); wmb(); cpu_set(cpu, cpu_callout_map); cpu_set(cpu, cpu_present_map); @@ -683,7 +683,7 @@ smp_boot_cpus(void) */ smp_store_cpu_info(boot_cpu_id); printk("CPU%d: ", boot_cpu_id); - print_cpu_info(&cpu_data[boot_cpu_id]); + print_cpu_info(&cpu_data(boot_cpu_id)); if(is_cpu_quad()) { /* booting on a Quad CPU */ @@ -714,7 +714,7 @@ smp_boot_cpus(void) unsigned long bogosum = 0; for (i = 0; i < NR_CPUS; i++) if (cpu_isset(i, cpu_online_map)) - bogosum += cpu_data[i].loops_per_jiffy; + bogosum += cpu_data(i).loops_per_jiffy; printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", cpucount+1, bogosum/(500000/HZ), diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index d6181597a0a..503dfc05111 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c @@ -564,7 +564,8 @@ no_context: * it's allocated already. */ if ((page >> PAGE_SHIFT) < max_low_pfn - && (page & _PAGE_PRESENT)) { + && (page & _PAGE_PRESENT) + && !(page & _PAGE_PSE)) { page &= PAGE_MASK; page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)]; diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 7c560843ded..644b4f7ece1 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c @@ -169,7 +169,7 @@ void dump_pagetable(unsigned long address) pmd = pmd_offset(pud, address); if (bad_address(pmd)) goto bad; printk("PMD %lx ", pmd_val(*pmd)); - if (!pmd_present(*pmd)) goto ret; + if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret; pte = pte_offset_kernel(pmd, address); if (bad_address(pte)) goto bad; @@ -285,7 +285,6 @@ static int vmalloc_fault(unsigned long address) return 0; } -static int page_fault_trace; int show_unhandled_signals = 1; /* @@ -354,10 +353,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, if (likely(regs->eflags & X86_EFLAGS_IF)) local_irq_enable(); - if (unlikely(page_fault_trace)) - printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n", - regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code); - if (unlikely(error_code & PF_RSVD)) pgtable_bad(address, regs, error_code); @@ -488,7 +483,7 @@ bad_area_nosemaphore: if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && printk_ratelimit()) { printk( - "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", + "%s%s[%d]: segfault at %lx rip %lx rsp %lx error %lx\n", tsk->pid > 1 ? KERN_INFO : KERN_EMERG, tsk->comm, tsk->pid, address, regs->rip, regs->rsp, error_code); @@ -621,10 +616,3 @@ void vmalloc_sync_all(void) BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == (__START_KERNEL & PGDIR_MASK))); } - -static int __init enable_pagefaulttrace(char *str) -{ - page_fault_trace = 1; - return 1; -} -__setup("pagefaulttrace", enable_pagefaulttrace); diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 5eec5e56d07..3d6926ba899 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -612,7 +612,7 @@ void __init init_cpu_to_node(void) { int i; for (i = 0; i < NR_CPUS; i++) { - u8 apicid = x86_cpu_to_apicid[i]; + u8 apicid = x86_cpu_to_apicid_init[i]; if (apicid == BAD_APICID) continue; if (apicid_to_node[apicid] == NUMA_NO_NODE) diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index c049ce414f0..0ed046a187f 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c @@ -13,25 +13,45 @@ #include <linux/mm.h> #include <asm/ptrace.h> #include <asm/uaccess.h> +#include <asm/stacktrace.h> -struct frame_head { - struct frame_head * ebp; - unsigned long ret; -} __attribute__((packed)); +static void backtrace_warning_symbol(void *data, char *msg, + unsigned long symbol) +{ + /* Ignore warnings */ +} -static struct frame_head * -dump_kernel_backtrace(struct frame_head * head) +static void backtrace_warning(void *data, char *msg) { - oprofile_add_trace(head->ret); + /* Ignore warnings */ +} - /* frame pointers should strictly progress back up the stack - * (towards higher addresses) */ - if (head >= head->ebp) - return NULL; +static int backtrace_stack(void *data, char *name) +{ + /* Yes, we want all stacks */ + return 0; +} + +static void backtrace_address(void *data, unsigned long addr) +{ + unsigned int *depth = data; - return head->ebp; + if ((*depth)--) + oprofile_add_trace(addr); } +static struct stacktrace_ops backtrace_ops = { + .warning = backtrace_warning, + .warning_symbol = backtrace_warning_symbol, + .stack = backtrace_stack, + .address = backtrace_address, +}; + +struct frame_head { + struct frame_head *ebp; + unsigned long ret; +} __attribute__((packed)); + static struct frame_head * dump_user_backtrace(struct frame_head * head) { @@ -53,72 +73,16 @@ dump_user_backtrace(struct frame_head * head) return bufhead[0].ebp; } -/* - * | | /\ Higher addresses - * | | - * --------------- stack base (address of current_thread_info) - * | thread info | - * . . - * | stack | - * --------------- saved regs->ebp value if valid (frame_head address) - * . . - * --------------- saved regs->rsp value if x86_64 - * | | - * --------------- struct pt_regs * stored on stack if 32-bit - * | | - * . . - * | | - * --------------- %esp - * | | - * | | \/ Lower addresses - * - * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the - * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other - * exceptions use special stacks, maintained by the interrupt stack table - * (IST). These stacks are set up in trap_init() in - * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point - * to the kernel stack; instead, it points to some location on the NMI - * stack. On the other hand, regs->rsp is the stack pointer saved when the - * NMI occurred. (2) For 32-bit, regs->esp is not valid because the - * processor does not save %esp on the kernel stack when interrupts occur - * in the kernel mode. - */ -#ifdef CONFIG_FRAME_POINTER -static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs) -{ - unsigned long headaddr = (unsigned long)head; -#ifdef CONFIG_X86_64 - unsigned long stack = (unsigned long)regs->rsp; -#else - unsigned long stack = (unsigned long)regs; -#endif - unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE; - - return headaddr > stack && headaddr < stack_base; -} -#else -/* without fp, it's just junk */ -static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs) -{ - return 0; -} -#endif - - void x86_backtrace(struct pt_regs * const regs, unsigned int depth) { - struct frame_head *head; - -#ifdef CONFIG_X86_64 - head = (struct frame_head *)regs->rbp; -#else - head = (struct frame_head *)regs->ebp; -#endif + struct frame_head *head = (struct frame_head *)frame_pointer(regs); + unsigned long stack = stack_pointer(regs); if (!user_mode_vm(regs)) { - while (depth-- && valid_kernel_stack(head, regs)) - head = dump_kernel_backtrace(head); + if (depth) + dump_trace(NULL, regs, (unsigned long *)stack, + &backtrace_ops, &depth); return; } diff --git a/arch/x86_64/.gitignore b/arch/x86_64/.gitignore new file mode 100644 index 00000000000..36ef4c374d2 --- /dev/null +++ b/arch/x86_64/.gitignore @@ -0,0 +1 @@ +boot diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 25785b23df8..aab25f3ba3c 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -723,7 +723,7 @@ config ARCH_HIBERNATION_HEADER source "drivers/acpi/Kconfig" -source "arch/x86/kernel/cpufreq/Kconfig" +source "arch/x86/kernel/cpu/cpufreq/Kconfig_64" source "drivers/cpuidle/Kconfig" @@ -768,9 +768,9 @@ source "fs/Kconfig.binfmt" config IA32_EMULATION bool "IA32 Emulation" help - Include code to run 32-bit programs under a 64-bit kernel. You should likely - turn this on, unless you're 100% sure that you don't have any 32-bit programs - left. + Include code to run 32-bit programs under a 64-bit kernel. You should + likely turn this on, unless you're 100% sure that you don't have any + 32-bit programs left. config IA32_AOUT tristate "IA32 a.out support" diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 03e1ede27b8..6d89ab762ff 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -74,7 +74,7 @@ KBUILD_CFLAGS += $(cflags-y) CFLAGS_KERNEL += $(cflags-kernel-y) KBUILD_AFLAGS += -m64 -head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task_64.o +head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task.o libs-y += arch/x86/lib/ core-y += arch/x86/kernel/ \ @@ -97,9 +97,9 @@ BOOTIMAGE := arch/x86/boot/bzImage KBUILD_IMAGE := $(BOOTIMAGE) bzImage: vmlinux - $(Q)mkdir -p $(objtree)/arch/x86_64/boot - $(Q)ln -fsn $(objtree)/arch/x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) + $(Q)mkdir -p $(objtree)/arch/x86_64/boot + $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage bzlilo: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a7351084f2f..235a51e328c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -422,12 +422,6 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, return 0; } -#ifdef CONFIG_IA64 -#define arch_cpu_to_apicid ia64_cpu_to_sapicid -#else -#define arch_cpu_to_apicid x86_cpu_to_apicid -#endif - static int map_madt_entry(u32 acpi_id) { unsigned long madt_end, entry; @@ -501,7 +495,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) return apic_id; for (i = 0; i < NR_CPUS; ++i) { - if (arch_cpu_to_apicid[i] == apic_id) + if (cpu_physical_id(i) == apic_id) return i; } return -1; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bbaa545ea99..629eadbd0ec 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1392,7 +1392,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc) * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command * @dma_dir: Data tranfer direction of the command - * @sg: sg list for the data buffer of the command + * @sgl: sg list for the data buffer of the command * @n_elem: Number of sg entries * @timeout: Timeout in msecs (0 for default) * diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 53070f6b1fc..d753e568588 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -40,7 +40,7 @@ #include <asm/msr.h> #define DRV_NAME "pata_cs5536" -#define DRV_VERSION "0.0.5" +#define DRV_VERSION "0.0.6" enum { CFG = 0, @@ -214,7 +214,7 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) cs5536_read(pdev, DTC, &dtc); dtc &= ~(IDE_DRV_MASK << dshift); - dtc |= mwdma_timings[mode] << dshift; + dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift; cs5536_write(pdev, DTC, dtc); } diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 8d98a9fb0a4..f147dc7bf46 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -92,7 +92,7 @@ static struct scsi_host_template sis_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -166,11 +166,11 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) return addr; } -static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) +static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg, u32 *val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); - u32 val, val2 = 0; + u32 val2 = 0; u8 pmr; if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ @@ -178,13 +178,16 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) pci_read_config_byte(pdev, SIS_PMR, &pmr); - pci_read_config_dword(pdev, cfg_addr, &val); + pci_read_config_dword(pdev, cfg_addr, val); if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED)) pci_read_config_dword(pdev, cfg_addr+0x10, &val2); - return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */ + *val |= val2; + *val &= 0xfffffffb; /* avoid problems with powerdowned ports */ + + return 0; } static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val) @@ -214,7 +217,7 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return -EINVAL; if (ap->flags & SIS_FLAG_CFGSCR) - return sis_scr_cfg_read(ap, sc_reg); + return sis_scr_cfg_read(ap, sc_reg, val); pci_read_config_byte(pdev, SIS_PMR, &pmr); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 6f66551d9e5..5c82ec7f8bb 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -150,7 +150,7 @@ static struct coretemp_data *coretemp_update_device(struct device *dev) static int __devinit coretemp_probe(struct platform_device *pdev) { struct coretemp_data *data; - struct cpuinfo_x86 *c = &(cpu_data)[pdev->id]; + struct cpuinfo_x86 *c = &cpu_data(pdev->id); int err; u32 eax, edx; @@ -359,7 +359,7 @@ static int __init coretemp_init(void) struct pdev_entry *p, *n; /* quick check if we run Intel */ - if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL) + if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) goto exit; err = platform_driver_register(&coretemp_driver); @@ -367,7 +367,7 @@ static int __init coretemp_init(void) goto exit; for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &(cpu_data)[i]; + struct cpuinfo_x86 *c = &cpu_data(i); /* check if family 6, models e, f, 16 */ if ((c->cpuid_level < 0) || (c->x86 != 0x6) || diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index f17e771e42f..3330667280b 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -200,7 +200,7 @@ static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor) u8 vid_which_vrm(void) { - struct cpuinfo_x86 *c = cpu_data; + struct cpuinfo_x86 *c = &cpu_data(0); u32 eax; u8 eff_family, eff_model, eff_stepping, vrm_ret; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 6d9fd92763f..6eaece96524 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1056,6 +1056,9 @@ endif config BLK_DEV_IDEDMA def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA +config IDE_ARCH_OBSOLETE_INIT + def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC + endif config BLK_DEV_HD_ONLY diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index f7449d04114..48db6167bb9 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -45,7 +45,7 @@ bastide_register(unsigned int base, unsigned int aux, int irq, hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); hw.irq = irq; - ide_register_hw(&hw, 0, hwif); + ide_register_hw(&hw, NULL, 0, hwif); return 0; } diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 3af33fbf1f8..410a0d13e35 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -316,27 +316,29 @@ static int icside_dma_end(ide_drive_t *drive) drive->waiting_for_dma = 0; - disable_dma(hwif->hw.dma); + disable_dma(state->dev->dma); /* Teardown mappings after DMA has completed. */ dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); - return get_dma_residue(hwif->hw.dma) != 0; + return get_dma_residue(state->dev->dma) != 0; } static void icside_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct icside_state *state = hwif->hwif_data; /* We can not enable DMA on both channels simultaneously. */ - BUG_ON(dma_channel_active(hwif->hw.dma)); - enable_dma(hwif->hw.dma); + BUG_ON(dma_channel_active(state->dev->dma)); + enable_dma(state->dev->dma); } static int icside_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct icside_state *state = hwif->hwif_data; struct request *rq = hwif->hwgroup->rq; unsigned int dma_mode; @@ -348,7 +350,7 @@ static int icside_dma_setup(ide_drive_t *drive) /* * We can not enable DMA on both channels. */ - BUG_ON(dma_channel_active(hwif->hw.dma)); + BUG_ON(dma_channel_active(state->dev->dma)); icside_build_sglist(drive, rq); @@ -365,14 +367,14 @@ static int icside_dma_setup(ide_drive_t *drive) /* * Select the correct timing for this drive. */ - set_dma_speed(hwif->hw.dma, drive->drive_data); + set_dma_speed(state->dev->dma, drive->drive_data); /* * Tell the DMA engine about the SG table and * data direction. */ - set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents); - set_dma_mode(hwif->hw.dma, dma_mode); + set_dma_sg(state->dev->dma, hwif->sg_table, hwif->sg_nents); + set_dma_mode(state->dev->dma, dma_mode); drive->waiting_for_dma = 1; @@ -438,40 +440,16 @@ static void icside_dma_init(ide_hwif_t *hwif) #define icside_dma_init(hwif) (0) #endif -static ide_hwif_t *icside_find_hwif(unsigned long dataport) -{ - ide_hwif_t *hwif; - int index; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->io_ports[IDE_DATA_OFFSET] == dataport) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (!hwif->io_ports[IDE_DATA_OFFSET]) - goto found; - } - - hwif = NULL; -found: - return hwif; -} - static ide_hwif_t * icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = (unsigned long)base + info->dataoffset; ide_hwif_t *hwif; - hwif = icside_find_hwif(port); + hwif = ide_find_port(port); if (hwif) { int i; - memset(&hwif->hw, 0, sizeof(hw_regs_t)); - /* * Ensure we're using MMIO */ @@ -479,13 +457,10 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e hwif->mmio = 1; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->hw.io_ports[i] = port; hwif->io_ports[i] = port; port += 1 << info->stepping; } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset; hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset; - hwif->hw.irq = ec->irq; hwif->irq = ec->irq; hwif->noprobe = 0; hwif->chipset = ide_acorn; @@ -500,6 +475,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) { ide_hwif_t *hwif; void __iomem *base; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); if (!base) @@ -523,9 +499,9 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) state->hwif[0] = hwif; - probe_hwif_init(hwif); + idx[0] = hwif->index; - ide_proc_register_port(hwif); + ide_device_add(idx); return 0; } @@ -537,6 +513,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) void __iomem *ioc_base, *easi_base; unsigned int sel = 0; int ret; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); if (!ioc_base) { @@ -592,7 +569,6 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) hwif->serialized = 1; hwif->config_data = (unsigned long)ioc_base; hwif->select_data = sel; - hwif->hw.dma = ec->dma; mate->maskproc = icside_maskproc; mate->channel = 1; @@ -601,18 +577,16 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) mate->serialized = 1; mate->config_data = (unsigned long)ioc_base; mate->select_data = sel | 1; - mate->hw.dma = ec->dma; if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { icside_dma_init(hwif); icside_dma_init(mate); } - probe_hwif_init(hwif); - probe_hwif_init(mate); + idx[0] = hwif->index; + idx[1] = mate->index; - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + ide_device_add(idx); return 0; diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index bce2bec8141..8957cbadf5c 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -31,5 +31,5 @@ void __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, 1, NULL); + ide_register_hw(&hw, NULL, 1, NULL); } diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 83811af1161..0775a3afef4 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -13,42 +13,25 @@ #include <asm/ecard.h> -/* - * Something like this really should be in generic code, but isn't. - */ static ide_hwif_t * rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) { unsigned long port = (unsigned long)base; - ide_hwif_t *hwif; - int index, i; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == port) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0) - goto found; - } + ide_hwif_t *hwif = ide_find_port(port); + int i; - return NULL; + if (hwif == NULL) + goto out; - found: for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->hw.io_ports[i] = port; hwif->io_ports[i] = port; port += sz; } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - hwif->hw.irq = hwif->irq = irq; + hwif->irq = irq; hwif->mmio = 1; default_hwif_mmiops(hwif); - +out: return hwif; } @@ -58,6 +41,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) ide_hwif_t *hwif; void __iomem *base; int ret; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; ret = ecard_request_resources(ec); if (ret) @@ -74,8 +58,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) hwif->hwif_data = base; hwif->gendev.parent = &ec->dev; hwif->noprobe = 0; - probe_hwif_init(hwif); - ide_proc_register_port(hwif); + + idx[0] = hwif->index; + + ide_device_add(idx); + ecard_set_drvdata(ec, hwif); goto out; } diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index 9a96a10ba9d..ff20377b4c8 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -782,7 +782,7 @@ init_e100_ide (void) ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); - ide_register_hw(&hw, 1, &hwif); + ide_register_hw(&hw, NULL, 1, &hwif); hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->set_pio_mode = &cris_set_pio_mode; diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index 6d26ad7360d..4a49b5c59ac 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -68,7 +68,6 @@ static inline void hw_setup(hw_regs_t *hw) hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT; hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; - hw->dma = NO_DMA; hw->chipset = ide_generic; } @@ -101,7 +100,7 @@ void __init h8300_ide_init(void) hw_setup(&hw); /* register if */ - idx = ide_register_hw(&hw, 1, &hwif); + idx = ide_register_hw(&hw, NULL, 1, &hwif); if (idx == -1) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); return; diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 1d5f6823101..89df48fdc69 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -350,7 +350,7 @@ static int taskfile_load_raw(ide_drive_t *drive, memset(&args, 0, sizeof(ide_task_t)); args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.data_phase = TASKFILE_IN; + args.data_phase = TASKFILE_NO_DATA; args.handler = &task_no_data_intr; /* convert gtf to IDE Taskfile */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 2722d9165b6..00123d99527 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -593,28 +593,12 @@ static int smart_enable(ide_drive_t *drive) return ide_raw_taskfile(drive, &args, NULL); } -static int get_smart_values(ide_drive_t *drive, u8 *buf) +static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_VALUES; - args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; - args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; - args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; - args.command_type = IDE_DRIVE_TASK_IN; - args.data_phase = TASKFILE_IN; - args.handler = &task_in_intr; - (void) smart_enable(drive); - return ide_raw_taskfile(drive, &args, buf); -} - -static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) -{ - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_THRESHOLDS; + args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd; args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; @@ -656,7 +640,7 @@ static int proc_idedisk_read_smart_thresholds ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (!get_smart_thresholds(drive, page)) { + if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; @@ -675,7 +659,7 @@ static int proc_idedisk_read_smart_values ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (!get_smart_values(drive, page)) { + if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 80b4f17f394..428f7a8a00b 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -901,10 +901,7 @@ void ide_dma_timeout (ide_drive_t *drive) EXPORT_SYMBOL(ide_dma_timeout); -/* - * Needed for allowing full modular support of ide-driver - */ -static int ide_release_dma_engine(ide_hwif_t *hwif) +static void ide_release_dma_engine(ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { pci_free_consistent(hwif->pci_dev, @@ -913,7 +910,6 @@ static int ide_release_dma_engine(ide_hwif_t *hwif) hwif->dmatable_dma); hwif->dmatable_cpu = NULL; } - return 1; } static int ide_release_iomio_dma(ide_hwif_t *hwif) @@ -956,12 +952,6 @@ static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned in { printk(KERN_INFO " %s: MMIO-DMA ", hwif->name); - hwif->dma_base = base; - - if(hwif->mate) - hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; - else - hwif->dma_master = base; return 0; } @@ -975,8 +965,6 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port return 1; } - hwif->dma_base = base; - if (hwif->cds->extra) { hwif->extra_base = base + (hwif->channel ? 8 : 16); @@ -991,10 +979,6 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port } } - if(hwif->mate) - hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base:base; - else - hwif->dma_master = base; return 0; } @@ -1006,12 +990,9 @@ static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int por return ide_iomio_dma(hwif, base, ports); } -/* - * This can be called for a dynamically installed interface. Don't __init it - */ -void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) +void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports) { - if (ide_dma_iobase(hwif, dma_base, num_ports)) + if (ide_dma_iobase(hwif, base, num_ports)) return; if (ide_allocate_dma_engine(hwif)) { @@ -1019,6 +1000,13 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p return; } + hwif->dma_base = base; + + if (hwif->mate) + hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base; + else + hwif->dma_master = base; + if (!(hwif->dma_command)) hwif->dma_command = hwif->dma_base; if (!(hwif->dma_vendor1)) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 32eaa3f8051..c89f0d3058e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -55,7 +55,7 @@ #include <asm/io.h> static int __ide_end_request(ide_drive_t *drive, struct request *rq, - int uptodate, unsigned int nr_bytes) + int uptodate, unsigned int nr_bytes, int dequeue) { int ret = 1; @@ -80,9 +80,11 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, if (!end_that_request_chunk(rq, uptodate, nr_bytes)) { add_disk_randomness(rq->rq_disk); - if (!list_empty(&rq->queuelist)) - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; + if (dequeue) { + if (!list_empty(&rq->queuelist)) + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + } end_that_request_last(rq, uptodate); ret = 0; } @@ -122,7 +124,7 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) nr_bytes = rq->hard_cur_sectors << 9; } - ret = __ide_end_request(drive, rq, uptodate, nr_bytes); + ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1); spin_unlock_irqrestore(&ide_lock, flags); return ret; @@ -255,39 +257,13 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors) { unsigned long flags; - int ret = 1; + int ret; spin_lock_irqsave(&ide_lock, flags); - BUG_ON(!blk_rq_started(rq)); - - /* - * if failfast is set on a request, override number of sectors and - * complete the whole request right now - */ - if (blk_noretry_request(rq) && end_io_error(uptodate)) - nr_sectors = rq->hard_nr_sectors; - - if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) - rq->errors = -EIO; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - HWGROUP(drive)->hwif->ide_dma_on(drive); - } - - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - if (blk_rq_tagged(rq)) - blk_queue_end_tag(drive->queue, rq); - end_that_request_last(rq, uptodate); - ret = 0; - } + ret = __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0); spin_unlock_irqrestore(&ide_lock, flags); + return ret; } EXPORT_SYMBOL_GPL(ide_end_dequeued_request); @@ -800,7 +776,20 @@ static ide_startstop_t do_special (ide_drive_t *drive) s->b.set_tune = 0; if (set_pio_mode_abuse(drive->hwif, req_pio)) { - if (hwif->set_pio_mode) + + if (hwif->set_pio_mode == NULL) + return ide_stopped; + + /* + * take ide_lock for drive->[no_]unmask/[no_]io_32bit + */ + if (req_pio == 8 || req_pio == 9) { + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + hwif->set_pio_mode(drive, req_pio); + spin_unlock_irqrestore(&ide_lock, flags); + } else hwif->set_pio_mode(drive, req_pio); } else { int keep_dma = drive->using_dma; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index d4d790f91f9..95168833d06 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -693,35 +693,16 @@ static u8 ide_auto_reduce_xfer (ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) +int ide_driveid_update(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; struct hd_driveid *id; -#if 0 - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) - return 0; - - taskfile_lib_get_identify(drive, (char *)&id); + unsigned long timeout, flags; - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - } - return 1; -#else /* * Re-read drive->id for possible DMA mode * change (copied from ide-probe.c) */ - unsigned long timeout, flags; SELECT_MASK(drive, 1); if (IDE_CONTROL_REG) @@ -763,7 +744,6 @@ int ide_driveid_update (ide_drive_t *drive) } return 1; -#endif } int ide_config_drive_speed(ide_drive_t *drive, u8 speed) diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index 2b8009c50e9..e245521af7b 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -40,9 +40,8 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id ide_std_init_ports(&hw, pnp_port_start(dev, 0), pnp_port_start(dev, 1)); hw.irq = pnp_irq(dev, 0); - hw.dma = NO_DMA; - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); if (index != -1) { printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e294c7415c2..d5146c57e5b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -717,7 +717,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave); * This routine only knows how to look for drive units 0 and 1 * on an interface, so any setting of MAX_DRIVES > 2 won't work here. */ -static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) +static void probe_hwif(ide_hwif_t *hwif) { unsigned long flags; unsigned int irqd; @@ -819,8 +819,8 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) return; } - if (fixup) - fixup(hwif); + if (hwif->fixup) + hwif->fixup(hwif); for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; @@ -859,10 +859,11 @@ static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) } static int hwif_init(ide_hwif_t *hwif); +static void hwif_register_devices(ide_hwif_t *hwif); -int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) +static int probe_hwif_init(ide_hwif_t *hwif) { - probe_hwif(hwif, fixup); + probe_hwif(hwif); if (!hwif_init(hwif)) { printk(KERN_INFO "%s: failed to initialize IDE interface\n", @@ -870,34 +871,12 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif) return -1; } - if (hwif->present) { - u16 unit = 0; - int ret; + if (hwif->present) + hwif_register_devices(hwif); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - /* For now don't attach absent drives, we may - want them on default or a new "empty" class - for hotplug reprobing ? */ - if (drive->present) { - ret = device_register(&drive->gendev); - if (ret < 0) - printk(KERN_WARNING "IDE: %s: " - "device_register error: %d\n", - __FUNCTION__, ret); - } - } - } return 0; } -int probe_hwif_init(ide_hwif_t *hwif) -{ - return probe_hwif_init_with_fixup(hwif, NULL); -} - -EXPORT_SYMBOL(probe_hwif_init); - #if MAX_HWIFS > 1 /* * save_match() is used to simplify logic in init_irq() below. @@ -1379,6 +1358,24 @@ out: return 0; } +static void hwif_register_devices(ide_hwif_t *hwif) +{ + unsigned int i; + + for (i = 0; i < MAX_DRIVES; i++) { + ide_drive_t *drive = &hwif->drives[i]; + + if (drive->present) { + int ret = device_register(&drive->gendev); + + if (ret < 0) + printk(KERN_WARNING "IDE: %s: " + "device_register error: %d\n", + __FUNCTION__, ret); + } + } +} + int ideprobe_init (void) { unsigned int index; @@ -1390,27 +1387,18 @@ int ideprobe_init (void) for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) - probe_hwif(&ide_hwifs[index], NULL); + probe_hwif(&ide_hwifs[index]); for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) hwif_init(&ide_hwifs[index]); for (index = 0; index < MAX_HWIFS; ++index) { if (probe[index]) { ide_hwif_t *hwif = &ide_hwifs[index]; - int unit; if (!hwif->present) continue; if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) hwif->chipset = ide_generic; - for (unit = 0; unit < MAX_DRIVES; ++unit) - if (hwif->drives[unit].present) { - int ret = device_register( - &hwif->drives[unit].gendev); - if (ret < 0) - printk(KERN_WARNING "IDE: %s: " - "device_register error: %d\n", - __FUNCTION__, ret); - } + hwif_register_devices(hwif); } } for (index = 0; index < MAX_HWIFS; ++index) @@ -1420,3 +1408,22 @@ int ideprobe_init (void) } EXPORT_SYMBOL_GPL(ideprobe_init); + +int ide_device_add(u8 idx[4]) +{ + int i, rc = 0; + + for (i = 0; i < 4; i++) { + if (idx[i] != 0xff) + rc |= probe_hwif_init(&ide_hwifs[idx[i]]); + } + + for (i = 0; i < 4; i++) { + if (idx[i] != 0xff) + ide_proc_register_port(&ide_hwifs[idx[i]]); + } + + return rc; +} + +EXPORT_SYMBOL_GPL(ide_device_add); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index fc1d8ae6a80..a4007d30da5 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -804,8 +804,6 @@ void ide_proc_register_port(ide_hwif_t *hwif) create_proc_ide_drives(hwif); } -EXPORT_SYMBOL_GPL(ide_proc_register_port); - #ifdef CONFIG_BLK_DEV_IDEPCI void ide_pci_create_host_proc(const char *name, get_info_t *get_info) { diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b463cef2de6..7b9181b5469 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -621,7 +621,6 @@ typedef struct os_dat_s { */ #define USE_IOTRACE 0 #if USE_IOTRACE -#include <linux/io_trace.h> #define IO_IDETAPE_FIFO 500 #endif diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 2a3c8d49834..73ef6bf5fbc 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -8,23 +8,6 @@ * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz * * The big the bad and the ugly. - * - * Problems to be fixed because of BH interface or the lack therefore. - * - * Fill me in stupid !!! - * - * HOST: - * General refers to the Controller and Driver "pair". - * DATA HANDLER: - * Under the context of Linux it generally refers to an interrupt handler. - * However, it correctly describes the 'HOST' - * DATA BLOCK: - * The amount of data needed to be transfered as predefined in the - * setup of the device. - * STORAGE ATOMIC: - * The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as - * small as a single sector or as large as the entire command block - * request. */ #include <linux/module.h> @@ -695,9 +678,6 @@ int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, return ide_do_drive_cmd(drive, &rq, ide_wait); } -/* - * FIXME : this needs to map into at taskfile. <andre@linux-ide.org> - */ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { int err = 0; @@ -761,9 +741,6 @@ static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf) return ide_do_drive_cmd(drive, &rq, ide_wait); } -/* - * FIXME : this needs to map into at taskfile. <andre@linux-ide.org> - */ int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { void __user *p = (void __user *)arg; @@ -860,9 +837,14 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_OUT_DMA: case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: - hwif->dma_setup(drive); - hwif->dma_exec_cmd(drive, taskfile->command); - hwif->dma_start(drive); + if (!drive->using_dma) + break; + + if (!hwif->dma_setup(drive)) { + hwif->dma_exec_cmd(drive, taskfile->command); + hwif->dma_start(drive); + return ide_started; + } break; default: @@ -876,7 +858,8 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) return task->prehandler(drive, task->rq); } ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); + return ide_started; } - return ide_started; + return ide_stopped; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 961e6c89728..674a65c1a13 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -168,7 +168,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); - memcpy(&hwif->hw, &hw, sizeof(hw)); memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; @@ -214,7 +213,7 @@ static void __init init_ide_data (void) init_hwif_data(hwif, index); init_hwif_default(hwif, index); #if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI) - hwif->irq = hwif->hw.irq = + hwif->irq = ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); #endif } @@ -265,6 +264,30 @@ static int ide_system_bus_speed(void) return system_bus_speed; } +ide_hwif_t * ide_find_port(unsigned long base) +{ + ide_hwif_t *hwif; + int i; + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->io_ports[IDE_DATA_OFFSET] == base) + goto found; + } + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->io_ports[IDE_DATA_OFFSET] == 0) + goto found; + } + + hwif = NULL; +found: + return hwif; +} + +EXPORT_SYMBOL_GPL(ide_find_port); + static struct resource* hwif_request_region(ide_hwif_t *hwif, unsigned long addr, int num) { @@ -391,6 +414,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->cds = tmp_hwif->cds; #endif + hwif->fixup = tmp_hwif->fixup; + hwif->set_pio_mode = tmp_hwif->set_pio_mode; hwif->set_dma_mode = tmp_hwif->set_dma_mode; hwif->mdma_filter = tmp_hwif->mdma_filter; @@ -652,7 +677,6 @@ void ide_setup_ports ( hw_regs_t *hw, } } hw->irq = irq; - hw->dma = NO_DMA; hw->ack_intr = ack_intr; /* * hw->iops = iops; @@ -660,11 +684,11 @@ void ide_setup_ports ( hw_regs_t *hw, } /** - * ide_register_hw_with_fixup - register IDE interface + * ide_register_hw - register IDE interface * @hw: hardware registers + * @fixup: fixup function * @initializing: set while initializing built-in drivers * @hwifp: pointer to returned hwif - * @fixup: fixup function * * Register an IDE interface, specifying exactly the registers etc. * Set init=1 iff calling before probes have taken place. @@ -672,9 +696,8 @@ void ide_setup_ports ( hw_regs_t *hw, * Returns -1 on error. */ -int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, - ide_hwif_t **hwifp, - void(*fixup)(ide_hwif_t *hwif)) +int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *), + int initializing, ide_hwif_t **hwifp) { int index, retry = 1; ide_hwif_t *hwif; @@ -682,7 +705,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, do { for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; - if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) + if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) goto found; } for (index = 0; index < MAX_HWIFS; ++index) { @@ -690,7 +713,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, if (hwif->hold) continue; if ((!hwif->present && !hwif->mate && !initializing) || - (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) + (!hwif->io_ports[IDE_DATA_OFFSET] && initializing)) goto found; } for (index = 0; index < MAX_HWIFS; index++) @@ -706,16 +729,18 @@ found: } if (hwif->present) return -1; - memcpy(&hwif->hw, hw, sizeof(*hw)); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); + memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); hwif->irq = hw->irq; hwif->noprobe = 0; + hwif->fixup = fixup; hwif->chipset = hw->chipset; hwif->gendev.parent = hw->dev; + hwif->ack_intr = hw->ack_intr; + + if (initializing == 0) { + u8 idx[4] = { index, 0xff, 0xff, 0xff }; - if (!initializing) { - probe_hwif_init_with_fixup(hwif, fixup); - ide_proc_register_port(hwif); + ide_device_add(idx); } if (hwifp) @@ -724,13 +749,6 @@ found: return (initializing || hwif->present) ? index : -1; } -EXPORT_SYMBOL(ide_register_hw_with_fixup); - -int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp) -{ - return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL); -} - EXPORT_SYMBOL(ide_register_hw); /* @@ -1046,7 +1064,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_init_hwif_ports(&hw, (unsigned long) args[0], (unsigned long) args[1], NULL); hw.irq = args[2]; - if (ide_register_hw(&hw, 0, NULL) == -1) + if (ide_register_hw(&hw, NULL, 0, NULL) == -1) return -EIO; return 0; } @@ -1397,6 +1415,9 @@ static int __init ide_setup(char *s) "reset", "minus6", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; + + hw_regs_t hwregs; + hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -1506,9 +1527,9 @@ static int __init ide_setup(char *s) case 2: /* base,ctl */ vals[2] = 0; /* default irq = probe for it */ case 3: /* base,ctl,irq */ - hwif->hw.irq = vals[2]; - ide_init_hwif_ports(&hwif->hw, (unsigned long) vals[0], (unsigned long) vals[1], &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + memset(&hwregs, 0, sizeof(hwregs)); + ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq); + memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports)); hwif->irq = vals[2]; hwif->noprobe = 0; hwif->chipset = ide_forced; diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 2f0ef9b4403..10311ecc674 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -102,6 +102,8 @@ static void outReg (u8 data, u8 reg) outb_p(data, dataPort); } +static DEFINE_SPINLOCK(ali14xx_lock); + /* * Set PIO mode for the specified drive. * This function computes timing parameters @@ -129,14 +131,14 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio) /* stuff timing parameters into controller registers */ driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&ali14xx_lock, flags); outb_p(regOn, basePort); outReg(param1, regTab[driveNum].reg1); outReg(param2, regTab[driveNum].reg2); outReg(param3, regTab[driveNum].reg3); outReg(param4, regTab[driveNum].reg4); outb_p(regOff, basePort); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&ali14xx_lock, flags); } /* @@ -193,6 +195,7 @@ static int __init initRegisters (void) { static int __init ali14xx_probe(void) { ide_hwif_t *hwif, *mate; + static u8 idx[4] = { 0, 1, 0xff, 0xff }; printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n", basePort, regOn); @@ -217,11 +220,7 @@ static int __init ali14xx_probe(void) mate->mate = hwif; mate->channel = 1; - probe_hwif_init(hwif); - probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + ide_device_add(idx); return 0; } diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index 101aee1711c..4a0be251a05 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -212,8 +212,8 @@ fail_base2: // xsurf_iops, IRQ_AMIGA_PORTS); } - - index = ide_register_hw(&hw, 1, &hwif); + + index = ide_register_hw(&hw, NULL, 1, &hwif); if (index != -1) { hwif->mmio = 1; printk("ide%d: ", index); diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index f1652125486..24a845d45bd 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -67,20 +67,24 @@ static void sub22 (char b, char c) } } +static DEFINE_SPINLOCK(dtc2278_lock); + static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) { unsigned long flags; if (pio >= 3) { - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&dtc2278_lock, flags); /* * This enables PIO mode4 (3?) on the first interface */ sub22(1,0xc3); sub22(0,0xa0); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&dtc2278_lock, flags); } else { /* we don't know how to set it back again.. */ + /* Actually we do - there is a data sheet available for the + Winbond but does anyone actually care */ } /* @@ -94,6 +98,7 @@ static int __init dtc2278_probe(void) { unsigned long flags; ide_hwif_t *hwif, *mate; + static u8 idx[4] = { 0, 1, 0xff, 0xff }; hwif = &ide_hwifs[0]; mate = &ide_hwifs[1]; @@ -129,16 +134,13 @@ static int __init dtc2278_probe(void) mate->serialized = 1; mate->chipset = ide_dtc2278; + mate->pio_mask = ATA_PIO4; mate->drives[0].no_unmask = 1; mate->drives[1].no_unmask = 1; mate->mate = hwif; mate->channel = 1; - probe_hwif_init(hwif); - probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + ide_device_add(idx); return 0; } diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index f0829b83e97..7d7936f1b90 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -72,7 +72,7 @@ void __init falconide_init(void) 0, 0, NULL, // falconide_iops, IRQ_MFP_IDE); - index = ide_register_hw(&hw, 1, NULL); + index = ide_register_hw(&hw, NULL, 1, NULL); if (index != -1) printk("ide%d: Falcon IDE interface\n", index); diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index 0830a021bbb..53331ee1e95 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -165,7 +165,7 @@ found: // &gayle_iops, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); if (index != -1) { hwif->mmio = 1; switch (i) { diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 2e5a9cc5c0f..a4245d13f11 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -247,6 +247,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio) } } +static DEFINE_SPINLOCK(ht6560b_lock); + /* * Enable/Disable so called prefetch mode */ @@ -254,9 +256,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state) { unsigned long flags; int t = HT_PREFETCH_MODE << 8; - - spin_lock_irqsave(&ide_lock, flags); - + + spin_lock_irqsave(&ht6560b_lock, flags); + /* * Prefetch mode and unmask irq seems to conflict */ @@ -268,9 +270,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state) drive->drive_data &= ~t; /* disable prefetch mode */ drive->no_unmask = 0; } - - spin_unlock_irqrestore(&ide_lock, flags); - + + spin_unlock_irqrestore(&ht6560b_lock, flags); + #ifdef DEBUG printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); #endif @@ -287,16 +289,14 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio) ht_set_prefetch(drive, pio & 1); return; } - + timing = ht_pio2timings(drive, pio); - - spin_lock_irqsave(&ide_lock, flags); - + + spin_lock_irqsave(&ht6560b_lock, flags); drive->drive_data &= 0xff00; drive->drive_data |= timing; - - spin_unlock_irqrestore(&ide_lock, flags); - + spin_unlock_irqrestore(&ht6560b_lock, flags); + #ifdef DEBUG printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); #endif @@ -311,6 +311,7 @@ MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); int __init ht6560b_init(void) { ide_hwif_t *hwif, *mate; + static u8 idx[4] = { 0, 1, 0xff, 0xff }; int t; if (probe_ht6560b == 0) @@ -359,11 +360,7 @@ int __init ht6560b_init(void) mate->drives[0].drive_data = t; mate->drives[1].drive_data = t; - probe_hwif_init(hwif); - probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + ide_device_add(idx); return 0; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index e8e360c2619..03715c05866 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -153,7 +153,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave); + return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL); } /*====================================================================== diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c index b992b2b91fe..7bb79f53dac 100644 --- a/drivers/ide/legacy/ide_platform.c +++ b/drivers/ide/legacy/ide_platform.c @@ -33,39 +33,24 @@ static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base, int mmio) { unsigned long port = (unsigned long)base; - ide_hwif_t *hwif; - int index, i; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == port) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0) - goto found; - } + ide_hwif_t *hwif = ide_find_port(port); + int i; - return NULL; - -found: + if (hwif == NULL) + goto out; - hwif->hw.io_ports[IDE_DATA_OFFSET] = port; + hwif->io_ports[IDE_DATA_OFFSET] = port; port += (1 << pdata->ioport_shift); for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++, port += (1 << pdata->ioport_shift)) - hwif->hw.io_ports[i] = port; + hwif->io_ports[i] = port; - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); - hwif->hw.irq = hwif->irq = irq; + hwif->irq = irq; - hwif->hw.dma = NO_DMA; - hwif->chipset = hwif->hw.chipset = ide_generic; + hwif->chipset = ide_generic; if (mmio) { hwif->mmio = 1; @@ -73,8 +58,8 @@ found: } hwif_prop.hwif = hwif; - hwif_prop.index = index; - + hwif_prop.index = hwif->index; +out: return hwif; } @@ -83,6 +68,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) struct resource *res_base, *res_alt, *res_irq; ide_hwif_t *hwif; struct pata_platform_info *pdata; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; int ret = 0; int mmio = 0; @@ -130,10 +116,11 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) hwif->gendev.parent = &pdev->dev; hwif->noprobe = 0; - probe_hwif_init(hwif); + idx[0] = hwif->index; + + ide_device_add(idx); platform_set_drvdata(pdev, hwif); - ide_proc_register_port(hwif); return 0; diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index b557c45a5a9..e87cd2f1643 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -93,21 +93,21 @@ void macide_init(void) 0, 0, macide_ack_intr, // quadra_ide_iops, IRQ_NUBUS_F); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); break; case MAC_IDE_PB: ide_setup_ports(&hw, IDE_BASE, macide_offsets, 0, 0, macide_ack_intr, // macide_pb_iops, IRQ_NUBUS_C); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); break; case MAC_IDE_BABOON: ide_setup_ports(&hw, BABOON_BASE, macide_offsets, 0, 0, NULL, // macide_baboon_iops, IRQ_BABOON_1); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); if (index == -1) break; if (macintosh_config->ident == MAC_MODEL_PB190) { diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 16ba70b4609..a73db1bd482 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -89,9 +89,8 @@ void q40_ide_setup_ports ( hw_regs_t *hw, else hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]); } - + hw->irq = irq; - hw->dma = NO_DMA; hw->ack_intr = ack_intr; /* * hw->iops = iops; @@ -142,7 +141,7 @@ void q40ide_init(void) 0, NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, NULL, 1, &hwif); // **FIXME** if (index != -1) hwif->mmio = 1; diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 0c81d2d0b94..912e73853fa 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -89,26 +89,6 @@ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ -static void qd_write_reg (u8 content, unsigned long reg) -{ - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); - outb(content,reg); - spin_unlock_irqrestore(&ide_lock, flags); -} - -static u8 __init qd_read_reg (unsigned long reg) -{ - unsigned long flags; - u8 read; - - spin_lock_irqsave(&ide_lock, flags); - read = inb(reg); - spin_unlock_irqrestore(&ide_lock, flags); - return read; -} - /* * qd_select: * @@ -121,7 +101,7 @@ static void qd_select (ide_drive_t *drive) (QD_TIMREG(drive) & 0x02); if (timings[index] != QD_TIMING(drive)) - qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); + outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); } /* @@ -284,7 +264,7 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio) } if (!HWIF(drive)->channel && drive->media != ide_disk) { - qd_write_reg(0x5f, QD_CONTROL_PORT); + outb(0x5f, QD_CONTROL_PORT); printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO " "and post-write buffer on %s.\n", drive->name, HWIF(drive)->name); @@ -301,16 +281,15 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio) static int __init qd_testreg(int port) { - u8 savereg; - u8 readreg; unsigned long flags; + u8 savereg, readreg; - spin_lock_irqsave(&ide_lock, flags); + local_irq_save(flags); savereg = inb_p(port); outb_p(QD_TESTVAL, port); /* safe value */ readreg = inb_p(port); outb(savereg, port); - spin_unlock_irqrestore(&ide_lock, flags); + local_irq_restore(flags); if (savereg == QD_TESTVAL) { printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); @@ -364,13 +343,13 @@ static void __exit qd_unsetup(ide_hwif_t *hwif) if (set_pio_mode == (void *)qd6500_set_pio_mode) { // will do it for both - qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0])); } else if (set_pio_mode == (void *)qd6580_set_pio_mode) { if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { - qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); - qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); + outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1])); } else { - qd_write_reg(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); + outb(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0])); } } else { printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n"); @@ -389,10 +368,11 @@ static void __exit qd_unsetup(ide_hwif_t *hwif) static int __init qd_probe(int base) { ide_hwif_t *hwif; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; u8 config; u8 unit; - config = qd_read_reg(QD_CONFIG_PORT); + config = inb(QD_CONFIG_PORT); if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; @@ -419,9 +399,9 @@ static int __init qd_probe(int base) hwif->set_pio_mode = &qd6500_set_pio_mode; - probe_hwif_init(hwif); + idx[0] = unit; - ide_proc_register_port(hwif); + ide_device_add(idx); return 1; } @@ -436,7 +416,7 @@ static int __init qd_probe(int base) /* qd6580 found */ - control = qd_read_reg(QD_CONTROL_PORT); + control = inb(QD_CONTROL_PORT); printk(KERN_NOTICE "qd6580 at %#x\n", base); printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", @@ -453,11 +433,11 @@ static int __init qd_probe(int base) hwif->set_pio_mode = &qd6580_set_pio_mode; - probe_hwif_init(hwif); + idx[0] = unit; - qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + ide_device_add(idx); - ide_proc_register_port(hwif); + outb(QD_DEF_CONTR, QD_CONTROL_PORT); return 1; } else { @@ -474,19 +454,17 @@ static int __init qd_probe(int base) hwif->set_pio_mode = &qd6580_set_pio_mode; - probe_hwif_init(hwif); - qd_setup(mate, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2); mate->set_pio_mode = &qd6580_set_pio_mode; - probe_hwif_init(mate); + idx[0] = 0; + idx[1] = 1; - qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + ide_device_add(idx); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + outb(QD_DEF_CONTR, QD_CONTROL_PORT); return 0; /* no other qd65xx possible */ } diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 1151c92dd53..79577b91687 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -124,8 +124,9 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) static int __init umc8672_probe(void) { - unsigned long flags; ide_hwif_t *hwif, *mate; + unsigned long flags; + static u8 idx[4] = { 0, 1, 0xff, 0xff }; if (!request_region(0x108, 2, "umc8672")) { printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); @@ -158,11 +159,7 @@ static int __init umc8672_probe(void) mate->mate = hwif; mate->channel = 1; - probe_hwif_init(hwif); - probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + ide_device_add(idx); return 0; } diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 2f322d7e881..1de58566e5b 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -601,8 +601,9 @@ static int au_ide_probe(struct device *dev) _auide_hwif *ahwif = &auide_hwif; ide_hwif_t *hwif; struct resource *res; - hw_regs_t *hw; int ret = 0; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) char *mode = "MWDMA2"; @@ -644,12 +645,12 @@ static int au_ide_probe(struct device *dev) /* FIXME: This might possibly break PCMCIA IDE devices */ hwif = &ide_hwifs[pdev->id]; - hw = &hwif->hw; - hwif->irq = hw->irq = ahwif->irq; + hwif->irq = ahwif->irq; hwif->chipset = ide_au1xxx; - auide_setup_ports(hw, ahwif); - memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); + memset(&hw, 0, sizeof(hw)); + auide_setup_ports(&hw, ahwif); + memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA @@ -706,8 +707,10 @@ static int au_ide_probe(struct device *dev) hwif->config_data = 0; /* no chipset-specific code */ hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ + hwif->drives[1].autotune = 1; #endif - hwif->drives[0].no_io_32bit = 1; + hwif->drives[0].no_io_32bit = 1; + hwif->drives[1].no_io_32bit = 1; auide_hwif.hwif = hwif; hwif->hwif_data = &auide_hwif; @@ -717,9 +720,9 @@ static int au_ide_probe(struct device *dev) dbdma_init_done = 1; #endif - probe_hwif_init(hwif); + idx[0] = hwif->index; - ide_proc_register_port(hwif); + ide_device_add(idx); dev_set_drvdata(dev, hwif); diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index c2e29571b00..521edd41b57 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -71,6 +71,7 @@ static int __devinit swarm_ide_probe(struct device *dev) u8 __iomem *base; phys_t offset, size; int i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; if (!SIBYTE_HAVE_IDE) return -ENODEV; @@ -119,18 +120,15 @@ static int __devinit swarm_ide_probe(struct device *dev) hwif->noprobe = 0; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - hwif->hw.io_ports[i] = + hwif->io_ports[i] = (unsigned long)(base + ((0x1f0 + i) << 5)); - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = + hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)(base + (0x3f6 << 5)); - hwif->hw.irq = K_INT_GB_IDE; + hwif->irq = K_INT_GB_IDE; - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->irq = hwif->hw.irq; + idx[0] = hwif->index; - probe_hwif_init(hwif); - - ide_proc_register_port(hwif); + ide_device_add(idx); dev_set_drvdata(dev, hwif); diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index b3dc12a70d5..19ec421f7b9 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/aec62xx.c Version 0.26 Sep 1, 2007 + * linux/drivers/ide/pci/aec62xx.c Version 0.27 Sep 16, 2007 * * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> @@ -141,19 +141,6 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0); } -static void aec62xx_dma_lost_irq (ide_drive_t *drive) -{ - switch (HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - case PCI_DEVICE_ID_ARTOP_ATP865: - case PCI_DEVICE_ID_ARTOP_ATP865R: - printk(" AEC62XX time out "); - default: - break; - } -} - static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name) { int bus_speed = system_bus_clock(); @@ -195,8 +182,6 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) if (hwif->dma_base == 0) return; - hwif->dma_lost_irq = &aec62xx_dma_lost_irq; - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) return; @@ -209,7 +194,7 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) } } -static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { +static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { { /* 0 */ .name = "AEC6210", .init_chipset = init_chipset_aec62xx, @@ -268,12 +253,12 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { * finds a device matching our IDE device tables. * * NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R] - * chips, pass a local copy of 'struct pci_device_id' down the call chain. + * chips, pass a local copy of 'struct ide_port_info' down the call chain. */ - + static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t d; + struct ide_port_info d; u8 idx = id->driver_data; d = aec62xx_chipsets[idx]; diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 8ee2b48d105..a607dd31a64 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/alim15x3.c Version 0.27 Aug 27 2007 + * linux/drivers/ide/pci/alim15x3.c Version 0.29 Sep 16 2007 * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer @@ -492,6 +492,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + /* + * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 + */ + if (m5229_revision >= 0x20 && isa_dev) { + pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); + chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; + } goto out; } @@ -537,7 +544,30 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } } + out: + /* + * CD_ROM DMA on (m5229, 0x53, bit0) + * Enable this bit even if we want to use PIO. + * PIO FIFO off (m5229, 0x53, bit1) + * The hardware will use 0x54h and 0x55h to control PIO FIFO. + * (Not on later devices it seems) + * + * 0x53 changes meaning on later revs - we must no touch + * bit 1 on them. Need to check if 0x20 is the right break. + */ + if (m5229_revision >= 0x20) { + pci_read_config_byte(dev, 0x53, &tmpbyte); + + if (m5229_revision <= 0x20) + tmpbyte = (tmpbyte & (~0x02)) | 0x01; + else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) + tmpbyte |= 0x03; + else + tmpbyte |= 0x01; + + pci_write_config_byte(dev, 0x53, tmpbyte); + } pci_dev_put(north); pci_dev_put(isa_dev); local_irq_restore(flags); @@ -616,36 +646,8 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) if ((tmpbyte & (1 << hwif->channel)) == 0) cbl = ATA_CBL_PATA80; } - } else { - /* - * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 - */ - pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); - chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; } - /* - * CD_ROM DMA on (m5229, 0x53, bit0) - * Enable this bit even if we want to use PIO - * PIO FIFO off (m5229, 0x53, bit1) - * The hardware will use 0x54h and 0x55h to control PIO FIFO - * (Not on later devices it seems) - * - * 0x53 changes meaning on later revs - we must no touch - * bit 1 on them. Need to check if 0x20 is the right break - */ - - pci_read_config_byte(dev, 0x53, &tmpbyte); - - if(m5229_revision <= 0x20) - tmpbyte = (tmpbyte & (~0x02)) | 0x01; - else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) - tmpbyte |= 0x03; - else - tmpbyte |= 0x01; - - pci_write_config_byte(dev, 0x53, tmpbyte); - local_irq_restore(flags); return cbl; @@ -664,31 +666,9 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->set_dma_mode = &ali_set_dma_mode; hwif->udma_filter = &ali_udma_filter; - /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ - if (m5229_revision <= 0xC4) - hwif->host_flags |= IDE_HFLAG_NO_LBA48_DMA; - if (hwif->dma_base == 0) return; - /* - * check in ->init_dma guarantees m5229_revision >= 0x20 here - */ - - if (m5229_revision == 0x20) - hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; - - if (m5229_revision <= 0x20) - hwif->ultra_mask = 0x00; /* no udma */ - else if (m5229_revision < 0xC2) - hwif->ultra_mask = ATA_UDMA2; - else if (m5229_revision == 0xC2 || m5229_revision == 0xC3) - hwif->ultra_mask = ATA_UDMA4; - else if (m5229_revision == 0xC4) - hwif->ultra_mask = ATA_UDMA5; - else - hwif->ultra_mask = ATA_UDMA6; - hwif->dma_setup = &ali15x3_dma_setup; if (hwif->cbl != ATA_CBL_PATA40_SHORT) @@ -766,7 +746,7 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) ide_setup_dma(hwif, dmabase, 8); } -static ide_pci_device_t ali15x3_chipset __devinitdata = { +static const struct ide_port_info ali15x3_chipset __devinitdata = { .name = "ALI15X3", .init_chipset = init_chipset_ali15x3, .init_hwif = init_hwif_ali15x3, @@ -792,15 +772,34 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev { }, }; - ide_pci_device_t *d = &ali15x3_chipset; + struct ide_port_info d = ali15x3_chipset; + u8 rev = dev->revision; if (pci_dev_present(ati_rs100)) printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n"); + /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ + if (rev <= 0xC4) + d.host_flags |= IDE_HFLAG_NO_LBA48_DMA; + + if (rev >= 0x20) { + if (rev == 0x20) + d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + + if (rev < 0xC2) + d.udma_mask = ATA_UDMA2; + else if (rev == 0xC2 || rev == 0xC3) + d.udma_mask = ATA_UDMA4; + else if (rev == 0xC4) + d.udma_mask = ATA_UDMA5; + else + d.udma_mask = ATA_UDMA6; + } + #if defined(CONFIG_SPARC64) - d->init_hwif = init_hwif_common_ali15x3; + d.init_hwif = init_hwif_common_ali15x3; #endif /* CONFIG_SPARC64 */ - return ide_setup_pci_device(dev, d); + return ide_setup_pci_device(dev, &d); } diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 7cafefbf6c1..8d4125ec252 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -77,7 +77,7 @@ static struct amd_ide_chip { }; static struct amd_ide_chip *amd_config; -static ide_pci_device_t *amd_chipset; +static const struct ide_port_info *amd_chipset; static unsigned int amd_80w; static unsigned int amd_clock; @@ -242,19 +242,12 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) { - int i; - if (hwif->irq == 0) /* 0 is bogus but will do for now */ hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel); hwif->set_pio_mode = &amd_set_pio_mode; hwif->set_dma_mode = &amd_set_drive; - for (i = 0; i < 2; i++) { - hwif->drives[i].io_32bit = 1; - hwif->drives[i].unmask = 1; - } - if (!hwif->dma_base) return; @@ -270,16 +263,21 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) } } +#define IDE_HFLAGS_AMD \ + (IDE_HFLAG_PIO_NO_BLACKLIST | \ + IDE_HFLAG_PIO_NO_DOWNGRADE | \ + IDE_HFLAG_POST_SET_MODE | \ + IDE_HFLAG_IO_32BIT | \ + IDE_HFLAG_UNMASK_IRQS | \ + IDE_HFLAG_BOOTABLE) + #define DECLARE_AMD_DEV(name_str) \ { \ .name = name_str, \ .init_chipset = init_chipset_amd74xx, \ .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \ - .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | \ - IDE_HFLAG_PIO_NO_DOWNGRADE | \ - IDE_HFLAG_POST_SET_MODE | \ - IDE_HFLAG_BOOTABLE, \ + .host_flags = IDE_HFLAGS_AMD, \ .pio_mask = ATA_PIO5, \ .swdma_mask = ATA_SWDMA2, \ .mwdma_mask = ATA_MWDMA2, \ @@ -291,16 +289,13 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) .init_chipset = init_chipset_amd74xx, \ .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \ - .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | \ - IDE_HFLAG_PIO_NO_DOWNGRADE | \ - IDE_HFLAG_POST_SET_MODE | \ - IDE_HFLAG_BOOTABLE, \ + .host_flags = IDE_HFLAGS_AMD, \ .pio_mask = ATA_PIO5, \ .swdma_mask = ATA_SWDMA2, \ .mwdma_mask = ATA_MWDMA2, \ } -static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { +static const struct ide_port_info amd74xx_chipsets[] __devinitdata = { /* 0 */ DECLARE_AMD_DEV("AMD7401"), /* 1 */ DECLARE_AMD_DEV("AMD7409"), /* 2 */ DECLARE_AMD_DEV("AMD7411"), diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 30784305307..ef8e0164ef7 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -189,8 +189,7 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) hwif->dma_host_off = &atiixp_dma_host_off; } - -static ide_pci_device_t atiixp_pci_info[] __devinitdata = { +static const struct ide_port_info atiixp_pci_info[] __devinitdata = { { /* 0 */ .name = "ATIIXP", .init_hwif = init_hwif_atiixp, diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index f369645e4d1..4aa48104e0c 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -185,6 +185,8 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ +static DEFINE_SPINLOCK(cmd640_lock); + /* * These are initialized to point at the devices we control */ @@ -258,12 +260,12 @@ static u8 get_cmd640_reg_vlb (u16 reg) static u8 get_cmd640_reg(u16 reg) { - u8 b; unsigned long flags; + u8 b; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); b = __get_cmd640_reg(reg); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return b; } @@ -271,9 +273,9 @@ static void put_cmd640_reg(u16 reg, u8 val) { unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); __put_cmd640_reg(reg,val); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } static int __init match_pci_cmd640_device (void) @@ -351,7 +353,7 @@ static int __init secondary_port_responding (void) { unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ udelay(100); @@ -359,11 +361,11 @@ static int __init secondary_port_responding (void) outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ udelay(100); if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 0; /* nothing responded */ } } - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 1; /* success */ } @@ -440,11 +442,11 @@ static void __init setup_device_ptrs (void) static void set_prefetch_mode (unsigned int index, int mode) { ide_drive_t *drive = cmd_drives[index]; + unsigned long flags; int reg = prefetch_regs[index]; u8 b; - unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); b = __get_cmd640_reg(reg); if (mode) { /* want prefetch on? */ #if CMD640_PREFETCH_MASKS @@ -460,7 +462,7 @@ static void set_prefetch_mode (unsigned int index, int mode) b |= prefetch_masks[index]; /* disable prefetch */ } __put_cmd640_reg(reg, b); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } /* @@ -561,7 +563,7 @@ static void program_drive_counts (unsigned int index) /* * Now that everything is ready, program the new timings */ - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -570,7 +572,7 @@ static void program_drive_counts (unsigned int index) setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; __put_cmd640_reg(arttim_regs[index], setup_count); __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } /* @@ -670,20 +672,20 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) static int pci_conf1(void) { - u32 tmp; unsigned long flags; + u32 tmp; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); outb(0x01, 0xCFB); tmp = inl(0xCF8); outl(0x80000000, 0xCF8); if (inl(0xCF8) == 0x80000000) { outl(tmp, 0xCF8); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 1; } outl(tmp, 0xCF8); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 0; } @@ -691,15 +693,15 @@ static int pci_conf2(void) { unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&cmd640_lock, flags); outb(0x00, 0xCFB); outb(0x00, 0xCF8); outb(0x00, 0xCFA); if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 1; } - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 0; } diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index adee2ef6fd7..ea0143ef5fe 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -535,7 +535,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq; break; case PCI_DEVICE_ID_CMD_646: - hwif->chipset = ide_cmd646; if (dev->revision == 0x01) { hwif->ide_dma_end = &cmd646_1_ide_dma_end; break; @@ -549,7 +548,7 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) } } -static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { +static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { { /* 0 */ .name = "CMD643", .init_chipset = init_chipset_cmd64x, @@ -573,6 +572,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, + .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, @@ -591,7 +591,7 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t d; + struct ide_port_info d; u8 idx = id->driver_data; d = cmd64x_chipsets[idx]; diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index aa98e817d38..0466462fd21 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -141,7 +141,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) .pio_mask = ATA_PIO4, \ } -static ide_pci_device_t cyrix_chipsets[] __devinitdata = { +static const struct ide_port_info cyrix_chipsets[] __devinitdata = { /* 0 */ DECLARE_CS_DEV("Cyrix 5510"), /* 1 */ DECLARE_CS_DEV("Cyrix 5520") }; @@ -154,9 +154,8 @@ static ide_pci_device_t cyrix_chipsets[] __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_hwif_t *hwif = NULL, *mate = NULL; - ata_index_t index; - ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; + const struct ide_port_info *d = &cyrix_chipsets[id->driver_data]; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; ide_setup_pci_noise(dev, d); @@ -172,29 +171,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic return -ENODEV; } - index.all = 0xf0f0; - /* * Now the chipset is configured we can let the core * do all the device setup for us */ - ide_pci_setup_ports(dev, d, 14, &index); - - if ((index.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index.b.low]; - if ((index.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index.b.high]; - - if (hwif) - probe_hwif_init(hwif); - if (mate) - probe_hwif_init(mate); + ide_pci_setup_ports(dev, d, 14, &idx[0]); - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); + ide_device_add(idx); return 0; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index ba0c6eba024..599408952bd 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cs5530.c Version 0.76 Aug 3 2007 + * linux/drivers/ide/pci/cs5530.c Version 0.77 Sep 24 2007 * * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2000 Mark Lord <mlord@pobox.com> @@ -146,7 +146,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; - unsigned long flags; if (pci_resource_start(dev, 4) == 0) return -EFAULT; @@ -171,9 +170,6 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch goto out; } - spin_lock_irqsave(&ide_lock, flags); - /* all CPUs (there should only be one CPU with this chipset) */ - /* * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 @@ -224,8 +220,6 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch pci_write_config_byte(master_0, 0x42, 0x00); pci_write_config_byte(master_0, 0x43, 0xc1); - spin_unlock_irqrestore(&ide_lock, flags); - out: pci_dev_put(master_0); pci_dev_put(cs5530_0); @@ -261,7 +255,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) hwif->udma_filter = cs5530_udma_filter; } -static ide_pci_device_t cs5530_chipset __devinitdata = { +static const struct ide_port_info cs5530_chipset __devinitdata = { .name = "CS5530", .init_chipset = init_chipset_cs5530, .init_hwif = init_hwif_cs5530, diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index 5ac82ffa5c0..9094916e378 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -186,7 +186,7 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif) hwif->cbl = cs5535_cable_detect(hwif->pci_dev); } -static ide_pci_device_t cs5535_chipset __devinitdata = { +static const struct ide_port_info cs5535_chipset __devinitdata = { .name = "CS5535", .init_hwif = init_hwif_cs5535, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE | diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index efc20bd97fd..3ef4fc10fe2 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -428,7 +428,6 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c */ static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) { - hwif->chipset = ide_cy82c693; hwif->set_pio_mode = &cy82c693_set_pio_mode; if (hwif->dma_base == 0) @@ -449,11 +448,12 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) } } -static ide_pci_device_t cy82c693_chipset __devinitdata = { +static const struct ide_port_info cy82c693_chipset __devinitdata = { .name = "CY82C693", .init_chipset = init_chipset_cy82c693, .init_iops = init_iops_cy82c693, .init_hwif = init_hwif_cy82c693, + .chipset = ide_cy82c693, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO4, diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index 46f4a888c03..83829081640 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -80,7 +80,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_register_hw_with_fixup(&hw, 0, &hwif, ide_undecoded_slave); + rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif); if (rc < 0) { printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); pci_disable_device(dev); diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 51165832e7f..f44d70852c3 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -54,37 +54,24 @@ __setup("all-generic-ide", ide_generic_all_on); module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); -static void __devinit init_hwif_generic (ide_hwif_t *hwif) -{ - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_UMC_UM8673F: - case PCI_DEVICE_ID_UMC_UM8886A: - case PCI_DEVICE_ID_UMC_UM8886BF: - hwif->irq = hwif->channel ? 15 : 14; - break; - default: - break; - } -} +#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) -#define DECLARE_GENERIC_PCI_DEV(name_str, dma_setting) \ +#define DECLARE_GENERIC_PCI_DEV(name_str, extra_flags) \ { \ .name = name_str, \ - .init_hwif = init_hwif_generic, \ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \ - dma_setting | \ + extra_flags | \ IDE_HFLAG_BOOTABLE, \ .swdma_mask = ATA_SWDMA2, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = ATA_UDMA6, \ } -static ide_pci_device_t generic_chipsets[] __devinitdata = { +static const struct ide_port_info generic_chipsets[] __devinitdata = { /* 0 */ DECLARE_GENERIC_PCI_DEV("Unknown", 0), { /* 1 */ .name = "NS87410", - .init_hwif = init_hwif_generic, .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_BOOTABLE, @@ -95,16 +82,15 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { /* 2 */ DECLARE_GENERIC_PCI_DEV("SAMURAI", 0), /* 3 */ DECLARE_GENERIC_PCI_DEV("HT6565", 0), - /* 4 */ DECLARE_GENERIC_PCI_DEV("UM8673F", IDE_HFLAG_NO_DMA), - /* 5 */ DECLARE_GENERIC_PCI_DEV("UM8886A", IDE_HFLAG_NO_DMA), - /* 6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF", IDE_HFLAG_NO_DMA), + /* 4 */ DECLARE_GENERIC_PCI_DEV("UM8673F", IDE_HFLAGS_UMC), + /* 5 */ DECLARE_GENERIC_PCI_DEV("UM8886A", IDE_HFLAGS_UMC), + /* 6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF", IDE_HFLAGS_UMC), /* 7 */ DECLARE_GENERIC_PCI_DEV("HINT_IDE", 0), /* 8 */ DECLARE_GENERIC_PCI_DEV("VIA_IDE", IDE_HFLAG_NO_AUTODMA), /* 9 */ DECLARE_GENERIC_PCI_DEV("OPTI621V", IDE_HFLAG_NO_AUTODMA), { /* 10 */ .name = "VIA8237SATA", - .init_hwif = init_hwif_generic, .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_OFF_BOARD, .swdma_mask = ATA_SWDMA2, @@ -118,7 +104,6 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { { /* 14 */ .name = "Revolution", - .init_hwif = init_hwif_generic, .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | IDE_HFLAG_OFF_BOARD, .swdma_mask = ATA_SWDMA2, @@ -138,7 +123,7 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &generic_chipsets[id->driver_data]; + const struct ide_port_info *d = &generic_chipsets[id->driver_data]; int ret = -ENODEV; /* Don't use the generic entry unless instructed to do so */ diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 67af1a7dde3..ae6307fae4f 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -129,7 +129,7 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) hwif->set_dma_mode = &hpt34x_set_mode; } -static ide_pci_device_t hpt34x_chipsets[] __devinitdata = { +static const struct ide_port_info hpt34x_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT343", .init_chipset = init_chipset_hpt34x, @@ -158,7 +158,7 @@ static ide_pci_device_t hpt34x_chipsets[] __devinitdata = { static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d; + const struct ide_port_info *d; u16 pcicmd = 0; pci_read_config_word(dev, PCI_COMMAND, &pcicmd); diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 18f5b7ddaee..612b795241b 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1425,7 +1425,7 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) return 0; } -static ide_pci_device_t hpt366_chipsets[] __devinitdata = { +static const struct ide_port_info hpt366_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT36x", .init_chipset = init_chipset_hpt366, @@ -1510,7 +1510,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic { struct hpt_info *info = NULL; struct pci_dev *dev2 = NULL; - ide_pci_device_t d; + struct ide_port_info d; u8 idx = id->driver_data; u8 rev = dev->revision; diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index dfbe605120c..90b52ed37bf 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -193,7 +193,7 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) .udma_mask = ATA_UDMA6, \ } -static ide_pci_device_t it8213_chipsets[] __devinitdata = { +static const struct ide_port_info it8213_chipsets[] __devinitdata = { /* 0 */ DECLARE_ITE_DEV("IT8213"), }; diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 08e820e89ae..5c997543531 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -638,7 +638,7 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha .pio_mask = ATA_PIO4, \ } -static ide_pci_device_t it821x_chipsets[] __devinitdata = { +static const struct ide_port_info it821x_chipsets[] __devinitdata = { /* 0 */ DECLARE_ITE_DEV("IT8212"), }; diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index 2eeff670d9a..bdf64d99770 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -118,7 +118,7 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif) hwif->cbl = ata66_jmicron(hwif); } -static ide_pci_device_t jmicron_chipset __devinitdata = { +static const struct ide_port_info jmicron_chipset __devinitdata = { .name = "JMB", .init_hwif = init_hwif_jmicron, .host_flags = IDE_HFLAG_BOOTABLE, diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index d21b5892382..d4df4642dbb 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -260,7 +260,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) hwif->ide_dma_end = &ns87415_ide_dma_end; } -static ide_pci_device_t ns87415_chipset __devinitdata = { +static const struct ide_port_info ns87415_chipset __devinitdata = { .name = "NS87415", #ifdef CONFIG_SUPERIO .init_iops = init_iops_ns87415, diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 3573ffeaaa3..8953d9c3926 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/opti621.c Version 0.8 Aug 27, 2007 + * linux/drivers/ide/pci/opti621.c Version 0.9 Sep 24, 2007 * * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) */ @@ -133,6 +133,8 @@ static int reg_base; #define PIO_NOT_EXIST 254 #define PIO_DONT_KNOW 255 +static DEFINE_SPINLOCK(opti621_lock); + /* there are stored pio numbers from other calls of opti621_set_pio_mode */ static void compute_pios(ide_drive_t *drive, const u8 pio) /* Store values into drive->drive_data @@ -278,7 +280,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) second.recovery_time, drdy); #endif - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&opti621_lock, flags); reg_base = hwif->io_ports[IDE_DATA_OFFSET]; @@ -317,7 +319,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) /* and read prefetch for both drives */ write_reg(misc, MISC_REG); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&opti621_lock, flags); } /* @@ -331,7 +333,7 @@ static void __devinit init_hwif_opti621 (ide_hwif_t *hwif) hwif->set_pio_mode = &opti621_set_pio_mode; } -static ide_pci_device_t opti621_chipsets[] __devinitdata = { +static const struct ide_port_info opti621_chipsets[] __devinitdata = { { /* 0 */ .name = "OPTI621", .init_hwif = init_hwif_opti621, diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index d1e7823454f..4234efeba60 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -513,7 +513,7 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) .udma_mask = udma, \ } -static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { +static const struct ide_port_info pdcnew_chipsets[] __devinitdata = { /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5), /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6), /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5), @@ -534,7 +534,7 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d; + const struct ide_port_info *d; struct pci_dev *bridge = dev->bus->self; u8 idx = id->driver_data; diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 29306121dc4..e09742e2ba5 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -302,13 +302,6 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - - /* PDC20265 has problems with large LBA48 requests */ - if ((dev->device == PCI_DEVICE_ID_PROMISE_20267) || - (dev->device == PCI_DEVICE_ID_PROMISE_20265)) - hwif->rqsize = 256; - hwif->set_pio_mode = &pdc202xx_set_pio_mode; hwif->set_dma_mode = &pdc202xx_set_mode; @@ -382,7 +375,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, } } -#define DECLARE_PDC2026X_DEV(name_str, udma) \ +#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \ { \ .name = name_str, \ .init_chipset = init_chipset_pdc202xx, \ @@ -390,13 +383,14 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, .init_dma = init_dma_pdc202xx, \ .extra = 48, \ .host_flags = IDE_HFLAG_ERROR_STOPS_FIFO | \ + extra_flags | \ IDE_HFLAG_OFF_BOARD, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = udma, \ } -static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { +static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { { /* 0 */ .name = "PDC20246", .init_chipset = init_chipset_pdc202xx, @@ -410,10 +404,10 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .udma_mask = ATA_UDMA2, }, - /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4), - /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4), - /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5), - /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5), + /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4, 0), + /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4, 0), + /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5, IDE_HFLAG_RQSIZE_256), + /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5, IDE_HFLAG_RQSIZE_256), }; /** @@ -427,7 +421,7 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d; + const struct ide_port_info *d; u8 idx = id->driver_data; d = &pdc202xx_chipsets[idx]; diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index ec0c6e96a21..9329d4a810e 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -396,7 +396,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif) .udma_mask = udma, \ } -static ide_pci_device_t piix_pci_info[] __devinitdata = { +static const struct ide_port_info piix_pci_info[] __devinitdata = { /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */ /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */ @@ -449,9 +449,7 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &piix_pci_info[id->driver_data]; - - return ide_setup_pci_device(dev, d); + return ide_setup_pci_device(dev, &piix_pci_info[id->driver_data]); } /** diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index dd2583ef1ad..6b10ae260fa 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -35,13 +35,13 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) u16 reg; struct pci_dev *dev = hwif->pci_dev; - hwif->chipset = ide_rz1000; if (!pci_read_config_word (dev, 0x40, ®) && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { printk(KERN_INFO "%s: disabled chipset read-ahead " "(buggy RZ1000/RZ1001)\n", hwif->name); } else { - hwif->serialized = 1; + if (hwif->mate) + hwif->mate->serialized = hwif->serialized = 1; hwif->drives[0].no_unmask = 1; hwif->drives[1].no_unmask = 1; printk(KERN_INFO "%s: serialized, disabled unmasking " @@ -49,9 +49,10 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) } } -static ide_pci_device_t rz1000_chipset __devinitdata = { +static const struct ide_port_info rz1000_chipset __devinitdata = { .name = "RZ100x", .init_hwif = init_hwif_rz1000, + .chipset = ide_rz1000, .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE, }; diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index b2423e03bf3..d2c8b5524f2 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -372,7 +372,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) hwif->ide_dma_end = &sc1200_ide_dma_end; } -static ide_pci_device_t sc1200_chipset __devinitdata = { +static const struct ide_port_info sc1200_chipset __devinitdata = { .name = "SC1200", .init_hwif = init_hwif_sc1200, .host_flags = IDE_HFLAG_SERIALIZE | diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index ae9b50331d2..ebb7132b9b8 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -538,12 +538,13 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) /** * init_setup_scc - set up an SCC PATA Controller * @dev: PCI device - * @d: IDE PCI device + * @d: IDE port info * * Perform the initial set up for this device. */ -static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *d) +static int __devinit init_setup_scc(struct pci_dev *dev, + const struct ide_port_info *d) { unsigned long ctl_base; unsigned long dma_base; @@ -702,7 +703,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) .pio_mask = ATA_PIO4, \ } -static ide_pci_device_t scc_chipsets[] __devinitdata = { +static const struct ide_port_info scc_chipsets[] __devinitdata = { /* 0 */ DECLARE_SCC_DEV("sccIDE"), }; @@ -717,9 +718,7 @@ static ide_pci_device_t scc_chipsets[] __devinitdata = { static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &scc_chipsets[id->driver_data]; - - return init_setup_scc(dev, d); + return init_setup_scc(dev, &scc_chipsets[id->driver_data]); } /** diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index a3d880e21d0..a7280311357 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -158,13 +158,6 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0; - /* If we are about to put a disk into UDMA mode we screwed up. - Our code assumes we never _ever_ do this on an OSB4 */ - - if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 && - drive->media == ide_disk && speed >= XFER_UDMA_0) - BUG(); - pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); pci_read_config_byte(dev, 0x54, &ultra_enable); @@ -373,7 +366,7 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) } } -static ide_pci_device_t serverworks_chipsets[] __devinitdata = { +static const struct ide_port_info serverworks_chipsets[] __devinitdata = { { /* 0 */ .name = "SvrWks OSB4", .init_chipset = init_chipset_svwks, @@ -430,7 +423,7 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = { static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t d; + struct ide_port_info d; u8 idx = id->driver_data; d = serverworks_chipsets[idx]; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 5af74ea1d46..de820aa58cd 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -614,6 +614,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) void __iomem *virt_base; ide_hwif_t *hwif; int h; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; /* * Find an empty HWIF; if none available, return -ENOMEM. @@ -654,10 +655,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) } if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) { + hw_regs_t hw; + /* Initialize the IO registers */ - sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport); - memcpy(hwif->io_ports, hwif->hw.io_ports, - sizeof (hwif->io_ports)); + memset(&hw, 0, sizeof(hw)); + sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); + memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; } @@ -679,11 +682,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) ide_init_sgiioc4(hwif); - if (probe_hwif_init(hwif)) - return -EIO; + idx[0] = hwif->index; - /* Create /proc/ide entries */ - ide_proc_register_port(hwif); + if (ide_device_add(idx)) + return -EIO; return 0; } diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 1353afb10a4..6d99441c605 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.17 Oct 18 2007 + * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007 * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> @@ -57,8 +57,8 @@ static int pdev_is_sata(struct pci_dev *pdev) { - switch(pdev->device) - { +#ifdef CONFIG_BLK_DEV_IDE_SATA + switch(pdev->device) { case PCI_DEVICE_ID_SII_3112: case PCI_DEVICE_ID_SII_1210SA: return 1; @@ -66,9 +66,10 @@ static int pdev_is_sata(struct pci_dev *pdev) return 0; } BUG(); +#endif return 0; } - + /** * is_sata - check if hwif is SATA * @hwif: interface to check @@ -136,7 +137,7 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) * SI3112 SATA controller life is a bit simpler. */ -static u8 sil_udma_filter(ide_drive_t *drive) +static u8 sil_pata_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; unsigned long base = (unsigned long) hwif->hwif_data; @@ -147,23 +148,23 @@ static u8 sil_udma_filter(ide_drive_t *drive) else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if (is_sata(hwif)) { - mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f; - goto out; - } - if ((scsc & 0x30) == 0x10) /* 133 */ - mask = 0x7f; + mask = ATA_UDMA6; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ - mask = 0x7f; + mask = ATA_UDMA6; else if ((scsc & 0x30) == 0x00) /* 100 */ - mask = 0x3f; + mask = ATA_UDMA5; else /* Disabled ? */ BUG(); -out: + return mask; } +static u8 sil_sata_udma_filter(ide_drive_t *drive) +{ + return strstr(drive->id->model, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6; +} + /** * sil_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -340,10 +341,11 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - unsigned long base = (unsigned long)hwif->hwif_data; unsigned long addr = siimage_selreg(hwif, 0x1); if (SATA_ERROR_REG) { + unsigned long base = (unsigned long)hwif->hwif_data; + u32 ext_stat = readl((void __iomem *)(base + 0x10)); u8 watchdog = 0; if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { @@ -376,7 +378,7 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) } /** - * siimage_busproc - bus isolation ioctl + * sil_sata_busproc - bus isolation IOCTL * @drive: drive to isolate/restore * @state: bus state to set * @@ -384,8 +386,8 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) * SATA controller the work required is quite limited, we * just have to clean up the statistics */ - -static int siimage_busproc (ide_drive_t * drive, int state) + +static int sil_sata_busproc(ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); u32 stat_config = 0; @@ -417,14 +419,14 @@ static int siimage_busproc (ide_drive_t * drive, int state) } /** - * siimage_reset_poll - wait for sata reset + * sil_sata_reset_poll - wait for SATA reset * @drive: drive we are resetting * * Poll the SATA phy and see whether it has come back from the dead * yet. */ - -static int siimage_reset_poll (ide_drive_t *drive) + +static int sil_sata_reset_poll(ide_drive_t *drive) { if (SATA_STATUS_REG) { ide_hwif_t *hwif = HWIF(drive); @@ -436,27 +438,22 @@ static int siimage_reset_poll (ide_drive_t *drive) HWGROUP(drive)->polling = 0; return ide_started; } - return 0; - } else { - return 0; } + + return 0; } /** - * siimage_pre_reset - reset hook + * sil_sata_pre_reset - reset hook * @drive: IDE device being reset * * For the SATA devices we need to handle recalibration/geometry * differently */ - -static void siimage_pre_reset (ide_drive_t *drive) -{ - if (drive->media != ide_disk) - return; - if (is_sata(HWIF(drive))) - { +static void sil_sata_pre_reset(ide_drive_t *drive) +{ + if (drive->media == ide_disk) { drive->special.b.set_geometry = 0; drive->special.b.recalibrate = 0; } @@ -502,7 +499,6 @@ static void siimage_reset (ide_drive_t *drive) drive->failures++; } } - } /** @@ -758,16 +754,11 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) hwif->sata_misc[SATA_IEN_OFFSET] = base + 0x148; } - hw.irq = hwif->pci_dev->irq; + memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); - memcpy(&hwif->hw, &hw, sizeof(hw)); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); + hwif->irq = dev->irq; - hwif->irq = hw.irq; - - base = (unsigned long) addr; - - hwif->dma_base = base + (ch ? 0x08 : 0x00); + hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00); hwif->mmio = 1; } @@ -864,28 +855,31 @@ static u8 __devinit ata66_siimage(ide_hwif_t *hwif) static void __devinit init_hwif_siimage(ide_hwif_t *hwif) { + u8 sata = is_sata(hwif); + hwif->resetproc = &siimage_reset; hwif->set_pio_mode = &sil_set_pio_mode; hwif->set_dma_mode = &sil_set_dma_mode; - hwif->reset_poll = &siimage_reset_poll; - hwif->pre_reset = &siimage_pre_reset; - hwif->udma_filter = &sil_udma_filter; - if(is_sata(hwif)) { + if (sata) { static int first = 1; - hwif->busproc = &siimage_busproc; + hwif->busproc = &sil_sata_busproc; + hwif->reset_poll = &sil_sata_reset_poll; + hwif->pre_reset = &sil_sata_pre_reset; + hwif->udma_filter = &sil_sata_udma_filter; if (first) { printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n"); first = 0; } - } + } else + hwif->udma_filter = &sil_pata_udma_filter; if (hwif->dma_base == 0) return; - if (is_sata(hwif)) + if (sata) hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; if (hwif->cbl != ATA_CBL_PATA40_SHORT) @@ -911,7 +905,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) .udma_mask = ATA_UDMA6, \ } -static ide_pci_device_t siimage_chipsets[] __devinitdata = { +static const struct ide_port_info siimage_chipsets[] __devinitdata = { /* 0 */ DECLARE_SII_DEV("SiI680"), /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"), /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA") diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index c1d280b0639..6b7bb53acef 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -264,7 +264,7 @@ static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) if (mode >= XFER_MW_DMA_0) { t1 &= ~0x04; /* disable UDMA */ idx = mode - XFER_MW_DMA_0 + 5; - } + } else idx = mode - XFER_PIO_0; t1 |= ini_time_value[clk][idx] << 12; t1 |= act_time_value[clk][idx] << 16; @@ -579,7 +579,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) hwif->cbl = ata66_sis5513(hwif); } -static ide_pci_device_t sis5513_chipset __devinitdata = { +static const struct ide_port_info sis5513_chipset __devinitdata = { .name = "SIS5513", .init_chipset = init_chipset_sis5513, .init_hwif = init_hwif_sis5513, diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 0dce459b126..147d783f752 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -361,13 +361,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) hwif->selectproc = &sl82c105_selectproc; hwif->resetproc = &sl82c105_resetproc; - /* - * We support 32-bit I/O on this interface, and - * it doesn't have problems with interrupts. - */ - hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1; - hwif->drives[0].unmask = hwif->drives[1].unmask = 1; - if (!hwif->dma_base) return; @@ -394,12 +387,15 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) hwif->serialized = hwif->mate->serialized = 1; } -static ide_pci_device_t sl82c105_chipset __devinitdata = { +static const struct ide_port_info sl82c105_chipset __devinitdata = { .name = "W82C105", .init_chipset = init_chipset_sl82c105, .init_hwif = init_hwif_sl82c105, .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, - .host_flags = IDE_HFLAG_NO_AUTODMA | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAG_IO_32BIT | + IDE_HFLAG_UNMASK_IRQS | + IDE_HFLAG_NO_AUTODMA | + IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, }; diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 4f22dffdf8e..eb4445b229e 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.18 Aug 9, 2007 + * linux/drivers/ide/pci/slc90e66.c Version 0.19 Sep 24, 2007 * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> @@ -21,6 +21,8 @@ #include <asm/io.h> +static DEFINE_SPINLOCK(slc90e66_lock); + static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) { ide_hwif_t *hwif = HWIF(drive); @@ -40,7 +42,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) { 2, 1 }, { 2, 3 }, }; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&slc90e66_lock, flags); pci_read_config_word(dev, master_port, &master_data); if (pio > 1) @@ -71,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) pci_write_config_word(dev, master_port, master_data); if (is_slave) pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&slc90e66_lock, flags); } static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) @@ -146,7 +148,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } -static ide_pci_device_t slc90e66_chipset __devinitdata = { +static const struct ide_port_info slc90e66_chipset __devinitdata = { .name = "SLC90E66", .init_hwif = init_hwif_slc90e66, .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 631506e9b5d..a66ebd14664 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -218,7 +218,7 @@ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, return err; } -static ide_pci_device_t tc86c001_chipset __devinitdata = { +static const struct ide_port_info tc86c001_chipset __devinitdata = { .name = "TC86C001", .init_chipset = init_chipset_tc86c001, .init_hwif = init_hwif_tc86c001, diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index 30b52f62699..a227c41d23a 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -102,7 +102,7 @@ static void __devinit init_hwif_triflex(ide_hwif_t *hwif) hwif->set_dma_mode = &triflex_set_mode; } -static ide_pci_device_t triflex_device __devinitdata = { +static const struct ide_port_info triflex_device __devinitdata = { .name = "TRIFLEX", .init_hwif = init_hwif_triflex, .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 140d486f623..5011ba22e36 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -250,7 +250,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) u8 reg = 0; struct pci_dev *dev = hwif->pci_dev; - hwif->chipset = ide_trm290; cfgbase = pci_resource_start(dev, 4); if ((dev->class & 5) && cfgbase) { hwif->config_data = cfgbase; @@ -320,9 +319,10 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) #endif } -static ide_pci_device_t trm290_chipset __devinitdata = { +static const struct ide_port_info trm290_chipset __devinitdata = { .name = "TRM290", .init_hwif = init_hwif_trm290, + .chipset = ide_trm290, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | #if 0 /* play it safe for now */ IDE_HFLAG_TRUST_BIOS_FOR_DMA | diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index c8022a92a0e..a0d3c16b68e 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -1,6 +1,6 @@ /* * - * Version 3.49 + * Version 3.50 * * VIA IDE driver for Linux. Supported southbridges: * @@ -422,65 +422,40 @@ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif) static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) { - struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); - int i; - hwif->set_pio_mode = &via_set_pio_mode; hwif->set_dma_mode = &via_set_drive; -#ifdef CONFIG_PPC_CHRP - if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { - hwif->irq = hwif->channel ? 15 : 14; - } -#endif - - for (i = 0; i < 2; i++) { - hwif->drives[i].io_32bit = 1; - hwif->drives[i].unmask = (vdev->via_config->flags & VIA_NO_UNMASK) ? 0 : 1; - } - if (!hwif->dma_base) return; - hwif->ultra_mask = vdev->via_config->udma_mask; - if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = via82cxxx_cable_detect(hwif); } -static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { - { /* 0 */ - .name = "VP_IDE", - .init_chipset = init_chipset_via82cxxx, - .init_hwif = init_hwif_via82cxxx, - .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, - .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | - IDE_HFLAG_PIO_NO_DOWNGRADE | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_BOOTABLE, - .pio_mask = ATA_PIO5, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - },{ /* 1 */ - .name = "VP_IDE", - .init_chipset = init_chipset_via82cxxx, - .init_hwif = init_hwif_via82cxxx, - .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, - .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | - IDE_HFLAG_PIO_NO_DOWNGRADE | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_BOOTABLE, - .pio_mask = ATA_PIO5, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - } +static const struct ide_port_info via82cxxx_chipset __devinitdata = { + .name = "VP_IDE", + .init_chipset = init_chipset_via82cxxx, + .init_hwif = init_hwif_via82cxxx, + .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, + .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | + IDE_HFLAG_PIO_NO_DOWNGRADE | + IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_IO_32BIT | + IDE_HFLAG_BOOTABLE, + .pio_mask = ATA_PIO5, + .swdma_mask = ATA_SWDMA2, + .mwdma_mask = ATA_MWDMA2, }; static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) { struct pci_dev *isa = NULL; struct via_isa_bridge *via_config; + u8 idx = id->driver_data; + struct ide_port_info d; + + d = via82cxxx_chipset; + /* * Find the ISA bridge and check we know what it is. */ @@ -490,7 +465,23 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n"); return -ENODEV; } - return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]); + + if (idx == 0) + d.host_flags |= IDE_HFLAG_NO_AUTODMA; + else + d.enablebits[1].reg = d.enablebits[0].reg = 0; + + if ((via_config->flags & VIA_NO_UNMASK) == 0) + d.host_flags |= IDE_HFLAG_UNMASK_IRQS; + +#ifdef CONFIG_PPC_CHRP + if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) + d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; +#endif + + d.udma_mask = via_config->udma_mask; + + return ide_setup_pci_device(dev, &d); } static const struct pci_device_id via_pci_tbl[] = { diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index df2e92034f5..5f0da35ab5a 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -316,8 +316,8 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, ide_hwifs[data_port].pio_mask = ATA_PIO4; ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode; + ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; - hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; /* Enable Harddisk Interrupt, * and make it edge sensitive */ @@ -402,8 +402,8 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, ide_hwifs[data_port].pio_mask = ATA_PIO4; ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode; + ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; - hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack; /* Enable Harddisk Interrupt, * and make it edge sensitive */ diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index c5547935676..816b5311dad 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1039,6 +1039,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) { struct device_node *np = pmif->node; const int *bidp; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; @@ -1124,8 +1126,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* Tell common code _not_ to mess with resources */ hwif->mmio = 1; hwif->hwif_data = pmif; - pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + memset(&hw, 0, sizeof(hw)); + pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq); + memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); hwif->chipset = ide_pmac; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay; hwif->hold = pmif->mediabay; @@ -1163,10 +1166,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) pmac_ide_setup_dma(pmif, hwif); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - /* We probe the hwif now */ - probe_hwif_init(hwif); + idx[0] = hwif->index; - ide_proc_register_port(hwif); + ide_device_add(idx); return 0; } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index fff567bcedb..02d14bf85ab 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -147,15 +147,15 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) #ifdef CONFIG_BLK_DEV_IDEDMA_PCI /** * ide_get_or_set_dma_base - setup BMIBA - * @d: IDE pci device data - * @hwif: Interface + * @d: IDE port info + * @hwif: IDE interface * * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. * Where a device has a partner that is already in DMA mode we check * and enforce IDE simplex rules. */ -static unsigned long ide_get_or_set_dma_base(ide_pci_device_t *d, ide_hwif_t *hwif) +static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif) { unsigned long dma_base = 0; struct pci_dev *dev = hwif->pci_dev; @@ -225,10 +225,11 @@ static unsigned long ide_get_or_set_dma_base(ide_pci_device_t *d, ide_hwif_t *hw } #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ -void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) +void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) { - printk(KERN_INFO "%s: IDE controller at PCI slot %s\n", - d->name, pci_name(dev)); + printk(KERN_INFO "%s: IDE controller (0x%04x:0x%04x rev 0x%02x) at " + " PCI slot %s\n", d->name, dev->vendor, dev->device, + dev->revision, pci_name(dev)); } EXPORT_SYMBOL_GPL(ide_setup_pci_noise); @@ -237,15 +238,15 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); /** * ide_pci_enable - do PCI enables * @dev: PCI device - * @d: IDE pci device data + * @d: IDE port info * * Enable the IDE PCI device. We attempt to enable the device in full * but if that fails then we only need BAR4 so we will enable that. * * Returns zero on success or an error code */ - -static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d) + +static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) { int ret; @@ -260,9 +261,9 @@ static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d) } /* - * assume all devices can do 32-bit dma for now. we can add a - * dma mask field to the ide_pci_device_t if we need it (or let - * lower level driver set the dma mask) + * assume all devices can do 32-bit DMA for now, we can add + * a DMA mask field to the struct ide_port_info if we need it + * (or let lower level driver set the DMA mask) */ ret = pci_set_dma_mask(dev, DMA_32BIT_MASK); if (ret < 0) { @@ -284,13 +285,13 @@ out: /** * ide_pci_configure - configure an unconfigured device * @dev: PCI device - * @d: IDE pci device data + * @d: IDE port info * * Enable and configure the PCI device we have been passed. * Returns zero on success or an error code. */ - -static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d) + +static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d) { u16 pcicmd = 0; /* @@ -318,15 +319,15 @@ static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d) /** * ide_pci_check_iomem - check a register is I/O - * @dev: pci device - * @d: ide_pci_device - * @bar: bar number + * @dev: PCI device + * @d: IDE port info + * @bar: BAR number * * Checks if a BAR is configured and points to MMIO space. If so * print an error and return an error code. Otherwise return 0 */ - -static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar) + +static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar) { ulong flags = pci_resource_flags(dev, bar); @@ -348,7 +349,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar /** * ide_hwif_configure - configure an IDE interface * @dev: PCI device holding interface - * @d: IDE pci data + * @d: IDE port info * @mate: Paired interface if any * * Perform the initial set up for the hardware interface structure. This @@ -357,8 +358,8 @@ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar * * Returns the new hardware interface structure, or NULL on a failure */ - -static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *mate, int port, int irq) + +static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq) { unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; @@ -387,19 +388,20 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, return NULL; /* no room in ide_hwifs[] */ if (hwif->io_ports[IDE_DATA_OFFSET] != base || hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) { - memset(&hwif->hw, 0, sizeof(hwif->hw)); -#ifndef IDE_ARCH_OBSOLETE_INIT - ide_std_init_ports(&hwif->hw, base, (ctl | 2)); - hwif->hw.io_ports[IDE_IRQ_OFFSET] = 0; + hw_regs_t hw; + + memset(&hw, 0, sizeof(hw)); +#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT + ide_std_init_ports(&hw, base, ctl | 2); #else - ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); + ide_init_hwif_ports(&hw, base, ctl | 2, NULL); #endif - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; } - hwif->chipset = ide_pci; + hwif->chipset = d->chipset ? d->chipset : ide_pci; hwif->pci_dev = dev; - hwif->cds = (struct ide_pci_device_s *) d; + hwif->cds = d; hwif->channel = port; if (!hwif->irq) @@ -414,21 +416,17 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, /** * ide_hwif_setup_dma - configure DMA interface * @dev: PCI device - * @d: IDE pci data - * @hwif: Hardware interface we are configuring + * @d: IDE port info + * @hwif: IDE interface * * Set up the DMA base for the interface. Enable the master bits as * necessary and attempt to bring the device DMA into a ready to use * state */ - -#ifndef CONFIG_BLK_DEV_IDEDMA_PCI -static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif) -{ -} -#else -static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif) + +static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif) { +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI u16 pcicmd; pci_read_config_word(dev, PCI_COMMAND, &pcicmd); @@ -460,13 +458,13 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi "(BIOS)\n", hwif->name, d->name); } } -} #endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/ +} /** * ide_setup_pci_controller - set up IDE PCI * @dev: PCI device - * @d: IDE PCI data + * @d: IDE port info * @noisy: verbose flag * @config: returned as 1 if we configured the hardware * @@ -474,8 +472,8 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi * up the PCI side of the device, checks that the device is enabled * and enables it if need be */ - -static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, int noisy, int *config) + +static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_info *d, int noisy, int *config) { int ret; u16 pcicmd; @@ -500,9 +498,6 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in printk(KERN_INFO "%s: device enabled (Linux)\n", d->name); } - if (noisy) - printk(KERN_INFO "%s: chipset revision %d\n", - d->name, dev->revision); out: return ret; } @@ -510,9 +505,9 @@ out: /** * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device - * @d: IDE pci device info + * @d: IDE port info * @pciirq: IRQ line - * @index: ata index to update + * @idx: ATA index table to update * * Scan the interfaces attached to this device and do any * necessary per port setup. Attach the devices and ask the @@ -522,26 +517,25 @@ out: * but is also used directly as a helper function by some controllers * where the chipset setup is not the default PCI IDE one. */ - -void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, ata_index_t *index) + +void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; - int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; u8 tmp; - index->all = 0xf0f0; - /* * Set up the IDE ports */ - + for (port = 0; port < channels; ++port) { - ide_pci_enablebit_t *e = &(d->enablebits[port]); - + const ide_pci_enablebit_t *e = &(d->enablebits[port]); + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || - (tmp & e->mask) != e->val)) + (tmp & e->mask) != e->val)) { + printk(KERN_INFO "%s: IDE port disabled\n", d->name); continue; /* port not enabled */ + } if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) continue; @@ -549,11 +543,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a /* setup proper ancestral information */ hwif->gendev.parent = &dev->dev; - if (hwif->channel) { - index->b.high = hwif->index; - } else { - index->b.low = hwif->index; - } + *(idx + port) = hwif->index; if (d->init_iops) @@ -562,15 +552,28 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) ide_hwif_setup_dma(dev, d, hwif); - if ((d->host_flags & IDE_HFLAG_LEGACY_IRQS) && hwif->irq == 0) + if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) hwif->irq = port ? 15 : 14; + hwif->fixup = d->fixup; + hwif->host_flags = d->host_flags; hwif->pio_mask = d->pio_mask; if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate) hwif->mate->serialized = hwif->serialized = 1; + if (d->host_flags & IDE_HFLAG_IO_32BIT) { + hwif->drives[0].io_32bit = 1; + hwif->drives[1].io_32bit = 1; + } + + if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) { + hwif->drives[0].unmask = 1; + hwif->drives[1].unmask = 1; + } + if (hwif->dma_base) { hwif->swdma_mask = d->swdma_mask; hwif->mwdma_mask = d->mwdma_mask; @@ -580,6 +583,9 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; + if (d->host_flags & IDE_HFLAG_RQSIZE_256) + hwif->rqsize = 256; + if (d->init_hwif) /* Call chipset-specific routine * for each enabled hwif @@ -587,10 +593,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a d->init_hwif(hwif); mate = hwif; - at_least_one_hwif_enabled = 1; } - if (!at_least_one_hwif_enabled) - printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name); } EXPORT_SYMBOL_GPL(ide_pci_setup_ports); @@ -602,13 +605,13 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports); * * One thing that is not standardized is the location of the * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; + * we "know" about, this information is in the struct ide_port_info; * for all other chipsets, we just assume both interfaces are enabled. */ -static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, - ata_index_t *index, u8 noisy) +static int do_ide_setup_pci_device(struct pci_dev *dev, + const struct ide_port_info *d, + u8 *idx, u8 noisy) { - static ata_index_t ata_index = { .b = { .low = 0xff, .high = 0xff } }; int tried_config = 0; int pciirq, ret; @@ -658,51 +661,35 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, /* FIXME: silent failure can happen */ - *index = ata_index; - ide_pci_setup_ports(dev, d, pciirq, index); + ide_pci_setup_ports(dev, d, pciirq, idx); out: return ret; } -int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) +int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) { - ide_hwif_t *hwif = NULL, *mate = NULL; - ata_index_t index_list; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; int ret; - ret = do_ide_setup_pci_device(dev, d, &index_list, 1); - if (ret < 0) - goto out; + ret = do_ide_setup_pci_device(dev, d, &idx[0], 1); - if ((index_list.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index_list.b.low]; - if ((index_list.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index_list.b.high]; + if (ret >= 0) + ide_device_add(idx); - if (hwif) - probe_hwif_init_with_fixup(hwif, d->fixup); - if (mate) - probe_hwif_init_with_fixup(mate, d->fixup); - - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); -out: return ret; } EXPORT_SYMBOL_GPL(ide_setup_pci_device); int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, - ide_pci_device_t *d) + const struct ide_port_info *d) { struct pci_dev *pdev[] = { dev1, dev2 }; - ata_index_t index_list[2]; int ret, i; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; for (i = 0; i < 2; i++) { - ret = do_ide_setup_pci_device(pdev[i], d, index_list + i, !i); + ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i); /* * FIXME: Mom, mom, they stole me the helper function to undo * do_ide_setup_pci_device() on the first device! @@ -711,25 +698,7 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, goto out; } - for (i = 0; i < 2; i++) { - u8 idx[2] = { index_list[i].b.low, index_list[i].b.high }; - int j; - - for (j = 0; j < 2; j++) { - if ((idx[j] & 0xf0) != 0xf0) - probe_hwif_init(ide_hwifs + idx[j]); - } - } - - for (i = 0; i < 2; i++) { - u8 idx[2] = { index_list[i].b.low, index_list[i].b.high }; - int j; - - for (j = 0; j < 2; j++) { - if ((idx[j] & 0xf0) != 0xf0) - ide_proc_register_port(ide_hwifs + idx[j]); - } - } + ide_device_add(idx); out: return ret; } @@ -754,9 +723,6 @@ static LIST_HEAD(ide_pci_drivers); * hands the controllers off to the core PCI code to do the rest of * the work. * - * The driver_data of the driver table must point to an ide_pci_device_t - * describing the interface. - * * Returns are the same as for pci_register_driver */ diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index ec1b6cfefcd..bfc6061f155 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -136,7 +136,8 @@ static int gameport_measure_speed(struct gameport *gameport) } gameport_close(gameport); - return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); + return (cpu_data(raw_smp_processor_id()).loops_per_jiffy * + (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); #else diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index c803d2bba65..48d647abea4 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -563,7 +563,7 @@ static void media_bay_step(int i) ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); hw.irq = bay->cd_irq; hw.chipset = ide_pmac; - bay->cd_index = ide_register_hw(&hw, 0, NULL); + bay->cd_index = ide_register_hw(&hw, NULL, 0, NULL); pmu_resume(); } if (bay->cd_index == -1) { diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 34a8c60a254..9b6fbf044fd 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -267,6 +267,12 @@ config DM_MULTIPATH_RDAC ---help--- Multipath support for LSI/Engenio RDAC. +config DM_MULTIPATH_HP + tristate "HP MSA multipath support (EXPERIMENTAL)" + depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL + ---help--- + Multipath support for HP MSA (Active/Passive) series hardware. + config DM_DELAY tristate "I/O delaying target (EXPERIMENTAL)" depends on BLK_DEV_DM && EXPERIMENTAL @@ -276,4 +282,10 @@ config DM_DELAY If unsure, say N. +config DM_UEVENT + bool "DM uevents (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + Generate udev events for DM events. + endif # MD diff --git a/drivers/md/Makefile b/drivers/md/Makefile index c49366cdc05..d9aa7edb878 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -8,6 +8,7 @@ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-mirror-objs := dm-log.o dm-raid1.o dm-rdac-objs := dm-mpath-rdac.o +dm-hp-sw-objs := dm-mpath-hp-sw.o md-mod-objs := md.o bitmap.o raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \ @@ -35,6 +36,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o obj-$(CONFIG_DM_DELAY) += dm-delay.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o +obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o @@ -48,6 +50,10 @@ ifeq ($(CONFIG_ALTIVEC),y) altivec_flags := -maltivec -mabi=altivec endif +ifeq ($(CONFIG_DM_UEVENT),y) +dm-mod-objs += dm-uevent.o +endif + targets += raid6int1.c $(obj)/raid6int1.c: UNROLL := 1 $(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h index 3f7b827649e..d4509be0fe6 100644 --- a/drivers/md/dm-bio-list.h +++ b/drivers/md/dm-bio-list.h @@ -21,11 +21,6 @@ static inline int bio_list_empty(const struct bio_list *bl) return bl->head == NULL; } -#define BIO_LIST_INIT { .head = NULL, .tail = NULL } - -#define BIO_LIST(bl) \ - struct bio_list bl = BIO_LIST_INIT - static inline void bio_list_init(struct bio_list *bl) { bl->head = bl->tail = NULL; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 4a5849b5519..0eb5416798b 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -36,7 +36,6 @@ struct dm_crypt_io { struct work_struct work; atomic_t pending; int error; - int post_process; }; /* @@ -57,7 +56,7 @@ struct crypt_config; struct crypt_iv_operations { int (*ctr)(struct crypt_config *cc, struct dm_target *ti, - const char *opts); + const char *opts); void (*dtr)(struct crypt_config *cc); const char *(*status)(struct crypt_config *cc); int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); @@ -80,6 +79,8 @@ struct crypt_config { mempool_t *page_pool; struct bio_set *bs; + struct workqueue_struct *io_queue; + struct workqueue_struct *crypt_queue; /* * crypto related data */ @@ -137,7 +138,7 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) } static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, - const char *opts) + const char *opts) { struct crypto_cipher *essiv_tfm; struct crypto_hash *hash_tfm; @@ -175,6 +176,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, if (err) { ti->error = "Error calculating hash in ESSIV"; + kfree(salt); return err; } @@ -188,7 +190,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, if (crypto_cipher_blocksize(essiv_tfm) != crypto_blkcipher_ivsize(cc->tfm)) { ti->error = "Block size of ESSIV cipher does " - "not match IV size of block cipher"; + "not match IV size of block cipher"; crypto_free_cipher(essiv_tfm); kfree(salt); return -EINVAL; @@ -319,10 +321,10 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, return r; } -static void -crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, - struct bio *bio_out, struct bio *bio_in, - sector_t sector, int write) +static void crypt_convert_init(struct crypt_config *cc, + struct convert_context *ctx, + struct bio *bio_out, struct bio *bio_in, + sector_t sector, int write) { ctx->bio_in = bio_in; ctx->bio_out = bio_out; @@ -338,7 +340,7 @@ crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, * Encrypt / decrypt data from one bio to another one (can be the same one) */ static int crypt_convert(struct crypt_config *cc, - struct convert_context *ctx) + struct convert_context *ctx) { int r = 0; @@ -370,7 +372,7 @@ static int crypt_convert(struct crypt_config *cc, } r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length, - ctx->write, ctx->sector); + ctx->write, ctx->sector); if (r < 0) break; @@ -380,13 +382,13 @@ static int crypt_convert(struct crypt_config *cc, return r; } - static void dm_crypt_bio_destructor(struct bio *bio) - { +static void dm_crypt_bio_destructor(struct bio *bio) +{ struct dm_crypt_io *io = bio->bi_private; struct crypt_config *cc = io->target->private; bio_free(bio, cc->bs); - } +} /* * Generate a new unfragmented bio with the given size @@ -458,7 +460,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) * One of the bios was finished. Check for completion of * the whole request and correctly clean up the buffer. */ -static void dec_pending(struct dm_crypt_io *io, int error) +static void crypt_dec_pending(struct dm_crypt_io *io, int error) { struct crypt_config *cc = (struct crypt_config *) io->target->private; @@ -474,18 +476,36 @@ static void dec_pending(struct dm_crypt_io *io, int error) } /* - * kcryptd: + * kcryptd/kcryptd_io: * * Needed because it would be very unwise to do decryption in an * interrupt context. + * + * kcryptd performs the actual encryption or decryption. + * + * kcryptd_io performs the IO submission. + * + * They must be separated as otherwise the final stages could be + * starved by new requests which can block in the first stages due + * to memory allocation. */ -static struct workqueue_struct *_kcryptd_workqueue; static void kcryptd_do_work(struct work_struct *work); +static void kcryptd_do_crypt(struct work_struct *work); static void kcryptd_queue_io(struct dm_crypt_io *io) { + struct crypt_config *cc = io->target->private; + INIT_WORK(&io->work, kcryptd_do_work); - queue_work(_kcryptd_workqueue, &io->work); + queue_work(cc->io_queue, &io->work); +} + +static void kcryptd_queue_crypt(struct dm_crypt_io *io) +{ + struct crypt_config *cc = io->target->private; + + INIT_WORK(&io->work, kcryptd_do_crypt); + queue_work(cc->crypt_queue, &io->work); } static void crypt_endio(struct bio *clone, int error) @@ -508,13 +528,12 @@ static void crypt_endio(struct bio *clone, int error) } bio_put(clone); - io->post_process = 1; - kcryptd_queue_io(io); + kcryptd_queue_crypt(io); return; out: bio_put(clone); - dec_pending(io, error); + crypt_dec_pending(io, error); } static void clone_init(struct dm_crypt_io *io, struct bio *clone) @@ -544,7 +563,7 @@ static void process_read(struct dm_crypt_io *io) */ clone = bio_alloc_bioset(GFP_NOIO, bio_segments(base_bio), cc->bs); if (unlikely(!clone)) { - dec_pending(io, -ENOMEM); + crypt_dec_pending(io, -ENOMEM); return; } @@ -579,7 +598,7 @@ static void process_write(struct dm_crypt_io *io) while (remaining) { clone = crypt_alloc_buffer(io, remaining); if (unlikely(!clone)) { - dec_pending(io, -ENOMEM); + crypt_dec_pending(io, -ENOMEM); return; } @@ -589,7 +608,7 @@ static void process_write(struct dm_crypt_io *io) if (unlikely(crypt_convert(cc, &ctx) < 0)) { crypt_free_buffer_pages(cc, clone); bio_put(clone); - dec_pending(io, -EIO); + crypt_dec_pending(io, -EIO); return; } @@ -624,17 +643,23 @@ static void process_read_endio(struct dm_crypt_io *io) crypt_convert_init(cc, &ctx, io->base_bio, io->base_bio, io->base_bio->bi_sector - io->target->begin, 0); - dec_pending(io, crypt_convert(cc, &ctx)); + crypt_dec_pending(io, crypt_convert(cc, &ctx)); } static void kcryptd_do_work(struct work_struct *work) { struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); - if (io->post_process) - process_read_endio(io); - else if (bio_data_dir(io->base_bio) == READ) + if (bio_data_dir(io->base_bio) == READ) process_read(io); +} + +static void kcryptd_do_crypt(struct work_struct *work) +{ + struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); + + if (bio_data_dir(io->base_bio) == READ) + process_read_endio(io); else process_write(io); } @@ -690,7 +715,7 @@ static int crypt_set_key(struct crypt_config *cc, char *key) cc->key_size = key_size; /* initial settings */ if ((!key_size && strcmp(key, "-")) || - (key_size && crypt_decode_key(cc->key, key, key_size) < 0)) + (key_size && crypt_decode_key(cc->key, key, key_size) < 0)) return -EINVAL; set_bit(DM_CRYPT_KEY_VALID, &cc->flags); @@ -746,7 +771,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (crypt_set_key(cc, argv[1])) { ti->error = "Error decoding key"; - goto bad1; + goto bad_cipher; } /* Compatiblity mode for old dm-crypt cipher strings */ @@ -757,19 +782,19 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (strcmp(chainmode, "ecb") && !ivmode) { ti->error = "This chaining mode requires an IV mechanism"; - goto bad1; + goto bad_cipher; } - if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", chainmode, - cipher) >= CRYPTO_MAX_ALG_NAME) { + if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", + chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { ti->error = "Chain mode + cipher name is too long"; - goto bad1; + goto bad_cipher; } tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { ti->error = "Error allocating crypto tfm"; - goto bad1; + goto bad_cipher; } strcpy(cc->cipher, cipher); @@ -793,18 +818,18 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops = &crypt_iv_null_ops; else { ti->error = "Invalid IV mode"; - goto bad2; + goto bad_ivmode; } if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) - goto bad2; + goto bad_ivmode; cc->iv_size = crypto_blkcipher_ivsize(tfm); if (cc->iv_size) /* at least a 64 bit sector number should fit in our buffer */ cc->iv_size = max(cc->iv_size, - (unsigned int)(sizeof(u64) / sizeof(u8))); + (unsigned int)(sizeof(u64) / sizeof(u8))); else { if (cc->iv_gen_ops) { DMWARN("Selected cipher does not support IVs"); @@ -817,13 +842,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); if (!cc->io_pool) { ti->error = "Cannot allocate crypt io mempool"; - goto bad3; + goto bad_slab_pool; } cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); if (!cc->page_pool) { ti->error = "Cannot allocate page mempool"; - goto bad4; + goto bad_page_pool; } cc->bs = bioset_create(MIN_IOS, MIN_IOS); @@ -834,25 +859,25 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) { ti->error = "Error setting key"; - goto bad5; + goto bad_device; } if (sscanf(argv[2], "%llu", &tmpll) != 1) { ti->error = "Invalid iv_offset sector"; - goto bad5; + goto bad_device; } cc->iv_offset = tmpll; if (sscanf(argv[4], "%llu", &tmpll) != 1) { ti->error = "Invalid device sector"; - goto bad5; + goto bad_device; } cc->start = tmpll; if (dm_get_device(ti, argv[3], cc->start, ti->len, - dm_table_get_mode(ti->table), &cc->dev)) { + dm_table_get_mode(ti->table), &cc->dev)) { ti->error = "Device lookup failed"; - goto bad5; + goto bad_device; } if (ivmode && cc->iv_gen_ops) { @@ -861,27 +886,45 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); if (!cc->iv_mode) { ti->error = "Error kmallocing iv_mode string"; - goto bad5; + goto bad_ivmode_string; } strcpy(cc->iv_mode, ivmode); } else cc->iv_mode = NULL; + cc->io_queue = create_singlethread_workqueue("kcryptd_io"); + if (!cc->io_queue) { + ti->error = "Couldn't create kcryptd io queue"; + goto bad_io_queue; + } + + cc->crypt_queue = create_singlethread_workqueue("kcryptd"); + if (!cc->crypt_queue) { + ti->error = "Couldn't create kcryptd queue"; + goto bad_crypt_queue; + } + ti->private = cc; return 0; -bad5: +bad_crypt_queue: + destroy_workqueue(cc->io_queue); +bad_io_queue: + kfree(cc->iv_mode); +bad_ivmode_string: + dm_put_device(ti, cc->dev); +bad_device: bioset_free(cc->bs); bad_bs: mempool_destroy(cc->page_pool); -bad4: +bad_page_pool: mempool_destroy(cc->io_pool); -bad3: +bad_slab_pool: if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) cc->iv_gen_ops->dtr(cc); -bad2: +bad_ivmode: crypto_free_blkcipher(tfm); -bad1: +bad_cipher: /* Must zero key material before freeing */ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); kfree(cc); @@ -892,7 +935,8 @@ static void crypt_dtr(struct dm_target *ti) { struct crypt_config *cc = (struct crypt_config *) ti->private; - flush_workqueue(_kcryptd_workqueue); + destroy_workqueue(cc->io_queue); + destroy_workqueue(cc->crypt_queue); bioset_free(cc->bs); mempool_destroy(cc->page_pool); @@ -918,9 +962,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, io = mempool_alloc(cc->io_pool, GFP_NOIO); io->target = ti; io->base_bio = bio; - io->error = io->post_process = 0; + io->error = 0; atomic_set(&io->pending, 0); - kcryptd_queue_io(io); + + if (bio_data_dir(io->base_bio) == READ) + kcryptd_queue_io(io); + else + kcryptd_queue_crypt(io); return DM_MAPIO_SUBMITTED; } @@ -1037,25 +1085,12 @@ static int __init dm_crypt_init(void) if (!_crypt_io_pool) return -ENOMEM; - _kcryptd_workqueue = create_workqueue("kcryptd"); - if (!_kcryptd_workqueue) { - r = -ENOMEM; - DMERR("couldn't create kcryptd"); - goto bad1; - } - r = dm_register_target(&crypt_target); if (r < 0) { DMERR("register failed %d", r); - goto bad2; + kmem_cache_destroy(_crypt_io_pool); } - return 0; - -bad2: - destroy_workqueue(_kcryptd_workqueue); -bad1: - kmem_cache_destroy(_crypt_io_pool); return r; } @@ -1066,7 +1101,6 @@ static void __exit dm_crypt_exit(void) if (r < 0) DMERR("unregister failed %d", r); - destroy_workqueue(_kcryptd_workqueue); kmem_cache_destroy(_crypt_io_pool); } diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 6928c136d3c..bdd37f881c4 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -83,7 +83,7 @@ static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) struct dm_delay_info *delayed, *next; unsigned long next_expires = 0; int start_timer = 0; - BIO_LIST(flush_bios); + struct bio_list flush_bios = { }; mutex_lock(&delayed_bios_lock); list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { @@ -163,34 +163,32 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } - if (argc == 3) { - dc->dev_write = NULL; + dc->dev_write = NULL; + if (argc == 3) goto out; - } if (sscanf(argv[4], "%llu", &tmpll) != 1) { ti->error = "Invalid write device sector"; - goto bad; + goto bad_dev_read; } dc->start_write = tmpll; if (sscanf(argv[5], "%u", &dc->write_delay) != 1) { ti->error = "Invalid write delay"; - goto bad; + goto bad_dev_read; } if (dm_get_device(ti, argv[3], dc->start_write, ti->len, dm_table_get_mode(ti->table), &dc->dev_write)) { ti->error = "Write device lookup failed"; - dm_put_device(ti, dc->dev_read); - goto bad; + goto bad_dev_read; } out: dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache); if (!dc->delayed_pool) { DMERR("Couldn't create delayed bio pool."); - goto bad; + goto bad_dev_write; } setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); @@ -203,6 +201,11 @@ out: ti->private = dc; return 0; +bad_dev_write: + if (dc->dev_write) + dm_put_device(ti, dc->dev_write); +bad_dev_read: + dm_put_device(ti, dc->dev_read); bad: kfree(dc); return -EINVAL; @@ -305,7 +308,7 @@ static int delay_status(struct dm_target *ti, status_type_t type, (unsigned long long) dc->start_read, dc->read_delay); if (dc->dev_write) - DMEMIT("%s %llu %u", dc->dev_write->name, + DMEMIT(" %s %llu %u", dc->dev_write->name, (unsigned long long) dc->start_write, dc->write_delay); break; diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 342517261ec..6b91b9ab1d4 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -81,7 +81,7 @@ static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size) } if (bio_add_page(bio, page, data_size, 0) != data_size) { - DMERR("get_failover_bio: alloc_page() failed."); + DMERR("get_failover_bio: bio_add_page() failed."); __free_page(page); bio_put(bio); return NULL; @@ -211,12 +211,10 @@ fail_path: static struct emc_handler *alloc_emc_handler(void) { - struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL); + struct emc_handler *h = kzalloc(sizeof(*h), GFP_KERNEL); - if (h) { - memset(h, 0, sizeof(*h)); + if (h) spin_lock_init(&h->lock); - } return h; } diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c index baafaaba4d4..2ee84d8aa0b 100644 --- a/drivers/md/dm-hw-handler.c +++ b/drivers/md/dm-hw-handler.c @@ -91,12 +91,10 @@ void dm_put_hw_handler(struct hw_handler_type *hwht) static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht) { - struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL); + struct hwh_internal *hwhi = kzalloc(sizeof(*hwhi), GFP_KERNEL); - if (hwhi) { - memset(hwhi, 0, sizeof(*hwhi)); + if (hwhi) hwhi->hwht = *hwht; - } return hwhi; } diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h index e0832e6fcf3..46809dcb121 100644 --- a/drivers/md/dm-hw-handler.h +++ b/drivers/md/dm-hw-handler.h @@ -58,5 +58,6 @@ unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio); #define MP_FAIL_PATH 1 #define MP_BYPASS_PG 2 #define MP_ERROR_IO 4 /* Don't retry this I/O */ +#define MP_RETRY 8 #endif diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index b441d82c338..138200bf5e0 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -700,7 +700,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) int r; char *new_name = (char *) param + param->data_start; - if (new_name < (char *) (param + 1) || + if (new_name < (char *) param->data || invalid_str(new_name, (void *) param + param_size)) { DMWARN("Invalid new logical volume name supplied."); return -EINVAL; @@ -726,7 +726,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) if (!md) return -ENXIO; - if (geostr < (char *) (param + 1) || + if (geostr < (char *) param->data || invalid_str(geostr, (void *) param + param_size)) { DMWARN("Invalid geometry supplied."); goto out; @@ -1233,7 +1233,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size) if (r) goto out; - if (tmsg < (struct dm_target_msg *) (param + 1) || + if (tmsg < (struct dm_target_msg *) param->data || invalid_str(tmsg->message, (void *) param + param_size)) { DMWARN("Invalid target message parameters."); r = -EINVAL; @@ -1358,7 +1358,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) if (tmp.data_size < sizeof(tmp)) return -EINVAL; - dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); + dmi = vmalloc(tmp.data_size); if (!dmi) return -ENOMEM; @@ -1515,3 +1515,35 @@ void dm_interface_exit(void) dm_hash_exit(); } + +/** + * dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers + * @md: Pointer to mapped_device + * @name: Buffer (size DM_NAME_LEN) for name + * @uuid: Buffer (size DM_UUID_LEN) for uuid or empty string if uuid not defined + */ +int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid) +{ + int r = 0; + struct hash_cell *hc; + + if (!md) + return -ENXIO; + + dm_get(md); + down_read(&_hash_lock); + hc = dm_get_mdptr(md); + if (!hc || hc->md != md) { + r = -ENXIO; + goto out; + } + + strcpy(name, hc->name); + strcpy(uuid, hc->uuid ? : ""); + +out: + up_read(&_hash_lock); + dm_put(md); + + return r; +} diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index a66428d860f..072ee4353ea 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -696,7 +696,7 @@ static struct dirty_log_type _disk_type = { .module = THIS_MODULE, .ctr = disk_ctr, .dtr = disk_dtr, - .suspend = disk_flush, + .postsuspend = disk_flush, .resume = disk_resume, .get_region_size = core_get_region_size, .is_clean = core_is_clean, diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index 86a301c8daf..3fae87eb596 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h @@ -32,7 +32,8 @@ struct dirty_log_type { * There are times when we don't want the log to touch * the disk. */ - int (*suspend)(struct dirty_log *log); + int (*presuspend)(struct dirty_log *log); + int (*postsuspend)(struct dirty_log *log); int (*resume)(struct dirty_log *log); /* diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c new file mode 100644 index 00000000000..204bf42c944 --- /dev/null +++ b/drivers/md/dm-mpath-hp-sw.c @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2005 Mike Christie, All rights reserved. + * Copyright (C) 2007 Red Hat, Inc. All rights reserved. + * Authors: Mike Christie + * Dave Wysochanski + * + * This file is released under the GPL. + * + * This module implements the specific path activation code for + * HP StorageWorks and FSC FibreCat Asymmetric (Active/Passive) + * storage arrays. + * These storage arrays have controller-based failover, not + * LUN-based failover. However, LUN-based failover is the design + * of dm-multipath. Thus, this module is written for LUN-based failover. + */ +#include <linux/blkdev.h> +#include <linux/list.h> +#include <linux/types.h> +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_dbg.h> + +#include "dm.h" +#include "dm-hw-handler.h" + +#define DM_MSG_PREFIX "multipath hp-sw" +#define DM_HP_HWH_NAME "hp-sw" +#define DM_HP_HWH_VER "1.0.0" + +struct hp_sw_context { + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; +}; + +/* + * hp_sw_error_is_retryable - Is an HP-specific check condition retryable? + * @req: path activation request + * + * Examine error codes of request and determine whether the error is retryable. + * Some error codes are already retried by scsi-ml (see + * scsi_decide_disposition), but some HP specific codes are not. + * The intent of this routine is to supply the logic for the HP specific + * check conditions. + * + * Returns: + * 1 - command completed with retryable error + * 0 - command completed with non-retryable error + * + * Possible optimizations + * 1. More hardware-specific error codes + */ +static int hp_sw_error_is_retryable(struct request *req) +{ + /* + * NOT_READY is known to be retryable + * For now we just dump out the sense data and call it retryable + */ + if (status_byte(req->errors) == CHECK_CONDITION) + __scsi_print_sense(DM_HP_HWH_NAME, req->sense, req->sense_len); + + /* + * At this point we don't have complete information about all the error + * codes from this hardware, so we are just conservative and retry + * when in doubt. + */ + return 1; +} + +/* + * hp_sw_end_io - Completion handler for HP path activation. + * @req: path activation request + * @error: scsi-ml error + * + * Check sense data, free request structure, and notify dm that + * pg initialization has completed. + * + * Context: scsi-ml softirq + * + */ +static void hp_sw_end_io(struct request *req, int error) +{ + struct dm_path *path = req->end_io_data; + unsigned err_flags = 0; + + if (!error) { + DMDEBUG("%s path activation command - success", + path->dev->name); + goto out; + } + + if (hp_sw_error_is_retryable(req)) { + DMDEBUG("%s path activation command - retry", + path->dev->name); + err_flags = MP_RETRY; + goto out; + } + + DMWARN("%s path activation fail - error=0x%x", + path->dev->name, error); + err_flags = MP_FAIL_PATH; + +out: + req->end_io_data = NULL; + __blk_put_request(req->q, req); + dm_pg_init_complete(path, err_flags); +} + +/* + * hp_sw_get_request - Allocate an HP specific path activation request + * @path: path on which request will be sent (needed for request queue) + * + * The START command is used for path activation request. + * These arrays are controller-based failover, not LUN based. + * One START command issued to a single path will fail over all + * LUNs for the same controller. + * + * Possible optimizations + * 1. Make timeout configurable + * 2. Preallocate request + */ +static struct request *hp_sw_get_request(struct dm_path *path) +{ + struct request *req; + struct block_device *bdev = path->dev->bdev; + struct request_queue *q = bdev_get_queue(bdev); + struct hp_sw_context *h = path->hwhcontext; + + req = blk_get_request(q, WRITE, GFP_NOIO); + if (!req) + goto out; + + req->timeout = 60 * HZ; + + req->errors = 0; + req->cmd_type = REQ_TYPE_BLOCK_PC; + req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; + req->end_io_data = path; + req->sense = h->sense; + memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); + + memset(&req->cmd, 0, BLK_MAX_CDB); + req->cmd[0] = START_STOP; + req->cmd[4] = 1; + req->cmd_len = COMMAND_SIZE(req->cmd[0]); + +out: + return req; +} + +/* + * hp_sw_pg_init - HP path activation implementation. + * @hwh: hardware handler specific data + * @bypassed: unused; is the path group bypassed? (see dm-mpath.c) + * @path: path to send initialization command + * + * Send an HP-specific path activation command on 'path'. + * Do not try to optimize in any way, just send the activation command. + * More than one path activation command may be sent to the same controller. + * This seems to work fine for basic failover support. + * + * Possible optimizations + * 1. Detect an in-progress activation request and avoid submitting another one + * 2. Model the controller and only send a single activation request at a time + * 3. Determine the state of a path before sending an activation request + * + * Context: kmpathd (see process_queued_ios() in dm-mpath.c) + */ +static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed, + struct dm_path *path) +{ + struct request *req; + struct hp_sw_context *h; + + path->hwhcontext = hwh->context; + h = hwh->context; + + req = hp_sw_get_request(path); + if (!req) { + DMERR("%s path activation command - allocation fail", + path->dev->name); + goto retry; + } + + DMDEBUG("%s path activation command - sent", path->dev->name); + + blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io); + return; + +retry: + dm_pg_init_complete(path, MP_RETRY); +} + +static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv) +{ + struct hp_sw_context *h; + + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (!h) + return -ENOMEM; + + hwh->context = h; + + return 0; +} + +static void hp_sw_destroy(struct hw_handler *hwh) +{ + struct hp_sw_context *h = hwh->context; + + kfree(h); +} + +static struct hw_handler_type hp_sw_hwh = { + .name = DM_HP_HWH_NAME, + .module = THIS_MODULE, + .create = hp_sw_create, + .destroy = hp_sw_destroy, + .pg_init = hp_sw_pg_init, +}; + +static int __init hp_sw_init(void) +{ + int r; + + r = dm_register_hw_handler(&hp_sw_hwh); + if (r < 0) + DMERR("register failed %d", r); + else + DMINFO("version " DM_HP_HWH_VER " loaded"); + + return r; +} + +static void __exit hp_sw_exit(void) +{ + int r; + + r = dm_unregister_hw_handler(&hp_sw_hwh); + if (r < 0) + DMERR("unregister failed %d", r); +} + +module_init(hp_sw_init); +module_exit(hp_sw_exit); + +MODULE_DESCRIPTION("DM Multipath HP StorageWorks / FSC FibreCat (A/P) support"); +MODULE_AUTHOR("Mike Christie, Dave Wysochanski <dm-devel@redhat.com>"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DM_HP_HWH_VER); diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c index 16b16134577..e04eb5c697f 100644 --- a/drivers/md/dm-mpath-rdac.c +++ b/drivers/md/dm-mpath-rdac.c @@ -664,20 +664,21 @@ static struct hw_handler_type rdac_handler = { static int __init rdac_init(void) { - int r = dm_register_hw_handler(&rdac_handler); - - if (r < 0) { - DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r); - return r; - } + int r; rdac_wkqd = create_singlethread_workqueue("rdac_wkqd"); if (!rdac_wkqd) { DMERR("Failed to create workqueue rdac_wkqd."); - dm_unregister_hw_handler(&rdac_handler); return -ENOMEM; } + r = dm_register_hw_handler(&rdac_handler); + if (r < 0) { + DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r); + destroy_workqueue(rdac_wkqd); + return r; + } + DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER); return 0; } diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 31056abca89..24b2b1e32fa 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -10,6 +10,7 @@ #include "dm-hw-handler.h" #include "dm-bio-list.h" #include "dm-bio-record.h" +#include "dm-uevent.h" #include <linux/ctype.h> #include <linux/init.h> @@ -75,6 +76,8 @@ struct multipath { unsigned queue_io; /* Must we queue all I/O? */ unsigned queue_if_no_path; /* Queue I/O if last path fails? */ unsigned saved_queue_if_no_path;/* Saved state during suspension */ + unsigned pg_init_retries; /* Number of times to retry pg_init */ + unsigned pg_init_count; /* Number of times pg_init called */ struct work_struct process_queued_ios; struct bio_list queued_ios; @@ -225,6 +228,8 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) m->pg_init_required = 0; m->queue_io = 0; } + + m->pg_init_count = 0; } static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) @@ -424,6 +429,7 @@ static void process_queued_ios(struct work_struct *work) must_queue = 0; if (m->pg_init_required && !m->pg_init_in_progress) { + m->pg_init_count++; m->pg_init_required = 0; m->pg_init_in_progress = 1; init_required = 1; @@ -689,9 +695,11 @@ static int parse_features(struct arg_set *as, struct multipath *m) int r; unsigned argc; struct dm_target *ti = m->ti; + const char *param_name; static struct param _params[] = { - {0, 1, "invalid number of feature args"}, + {0, 3, "invalid number of feature args"}, + {1, 50, "pg_init_retries must be between 1 and 50"}, }; r = read_param(_params, shift(as), &argc, &ti->error); @@ -701,12 +709,28 @@ static int parse_features(struct arg_set *as, struct multipath *m) if (!argc) return 0; - if (!strnicmp(shift(as), MESG_STR("queue_if_no_path"))) - return queue_if_no_path(m, 1, 0); - else { + do { + param_name = shift(as); + argc--; + + if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) { + r = queue_if_no_path(m, 1, 0); + continue; + } + + if (!strnicmp(param_name, MESG_STR("pg_init_retries")) && + (argc >= 1)) { + r = read_param(_params + 1, shift(as), + &m->pg_init_retries, &ti->error); + argc--; + continue; + } + ti->error = "Unrecognised multipath feature request"; - return -EINVAL; - } + r = -EINVAL; + } while (argc && !r); + + return r; } static int multipath_ctr(struct dm_target *ti, unsigned int argc, @@ -834,6 +858,9 @@ static int fail_path(struct pgpath *pgpath) if (pgpath == m->current_pgpath) m->current_pgpath = NULL; + dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti, + pgpath->path.dev->name, m->nr_valid_paths); + queue_work(kmultipathd, &m->trigger_event); out: @@ -873,6 +900,9 @@ static int reinstate_path(struct pgpath *pgpath) if (!m->nr_valid_paths++ && m->queue_size) queue_work(kmultipathd, &m->process_queued_ios); + dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, + pgpath->path.dev->name, m->nr_valid_paths); + queue_work(kmultipathd, &m->trigger_event); out: @@ -976,6 +1006,26 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed) } /* + * Should we retry pg_init immediately? + */ +static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath) +{ + unsigned long flags; + int limit_reached = 0; + + spin_lock_irqsave(&m->lock, flags); + + if (m->pg_init_count <= m->pg_init_retries) + m->pg_init_required = 1; + else + limit_reached = 1; + + spin_unlock_irqrestore(&m->lock, flags); + + return limit_reached; +} + +/* * pg_init must call this when it has completed its initialisation */ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) @@ -985,8 +1035,14 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) struct multipath *m = pg->m; unsigned long flags; - /* We insist on failing the path if the PG is already bypassed. */ - if (err_flags && pg->bypassed) + /* + * If requested, retry pg_init until maximum number of retries exceeded. + * If retry not requested and PG already bypassed, always fail the path. + */ + if (err_flags & MP_RETRY) { + if (pg_init_limit_reached(m, pgpath)) + err_flags |= MP_FAIL_PATH; + } else if (err_flags && pg->bypassed) err_flags |= MP_FAIL_PATH; if (err_flags & MP_FAIL_PATH) @@ -996,7 +1052,7 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) bypass_pg(m, pg, 1); spin_lock_irqsave(&m->lock, flags); - if (err_flags) { + if (err_flags & ~MP_RETRY) { m->current_pgpath = NULL; m->current_pg = NULL; } else if (!m->pg_init_required) @@ -1148,11 +1204,15 @@ static int multipath_status(struct dm_target *ti, status_type_t type, /* Features */ if (type == STATUSTYPE_INFO) - DMEMIT("1 %u ", m->queue_size); - else if (m->queue_if_no_path) - DMEMIT("1 queue_if_no_path "); - else - DMEMIT("0 "); + DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count); + else { + DMEMIT("%u ", m->queue_if_no_path + + (m->pg_init_retries > 0) * 2); + if (m->queue_if_no_path) + DMEMIT("queue_if_no_path "); + if (m->pg_init_retries) + DMEMIT("pg_init_retries %u ", m->pg_init_retries); + } if (hwh->type && hwh->type->status) sz += hwh->type->status(hwh, type, result + sz, maxlen - sz); diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c index f10a0c89b3f..ca1bb636a3e 100644 --- a/drivers/md/dm-path-selector.c +++ b/drivers/md/dm-path-selector.c @@ -94,12 +94,10 @@ out: static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst) { - struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL); + struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL); - if (psi) { - memset(psi, 0, sizeof(*psi)); + if (psi) psi->pst = *pst; - } return psi; } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d09ff15490a..31123d4a6b9 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -19,6 +19,7 @@ #include <linux/time.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> +#include <linux/log2.h> #define DM_MSG_PREFIX "raid1" #define DM_IO_PAGES 64 @@ -113,6 +114,7 @@ struct region { * Mirror set structures. *---------------------------------------------------------------*/ struct mirror { + struct mirror_set *ms; atomic_t error_count; struct dm_dev *dev; sector_t offset; @@ -974,6 +976,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { ti->error = "Error creating dirty region hash"; + dm_io_client_destroy(ms->io_client); kfree(ms); return NULL; } @@ -994,7 +997,7 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, static inline int _check_region_size(struct dm_target *ti, uint32_t size) { - return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) || + return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) || size > ti->len); } @@ -1015,6 +1018,7 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, return -ENXIO; } + ms->mirror[mirror].ms = ms; ms->mirror[mirror].offset = offset; return 0; @@ -1163,16 +1167,14 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); if (!ms->kmirrord_wq) { DMERR("couldn't start kmirrord"); - free_context(ms, ti, m); - return -ENOMEM; + r = -ENOMEM; + goto err_free_context; } INIT_WORK(&ms->kmirrord_work, do_mirror); r = parse_features(ms, argc, argv, &args_used); - if (r) { - free_context(ms, ti, ms->nr_mirrors); - return r; - } + if (r) + goto err_destroy_wq; argv += args_used; argc -= args_used; @@ -1188,19 +1190,22 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (argc) { ti->error = "Too many mirror arguments"; - free_context(ms, ti, ms->nr_mirrors); - return -EINVAL; + r = -EINVAL; + goto err_destroy_wq; } r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); - if (r) { - destroy_workqueue(ms->kmirrord_wq); - free_context(ms, ti, ms->nr_mirrors); - return r; - } + if (r) + goto err_destroy_wq; wake(ms); return 0; + +err_destroy_wq: + destroy_workqueue(ms->kmirrord_wq); +err_free_context: + free_context(ms, ti, ms->nr_mirrors); + return r; } static void mirror_dtr(struct dm_target *ti) @@ -1302,7 +1307,7 @@ static void mirror_postsuspend(struct dm_target *ti) wait_event(_kmirrord_recovery_stopped, !atomic_read(&ms->rh.recovery_in_flight)); - if (log->type->suspend && log->type->suspend(log)) + if (log->type->postsuspend && log->type->postsuspend(log)) /* FIXME: need better error handling */ DMWARN("log suspend failed"); } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 98a633f3d6b..cee16fadd9e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/log2.h> #include "dm-snap.h" #include "dm-bio-list.h" @@ -415,7 +416,7 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg, chunk_size = round_up(chunk_size, PAGE_SIZE >> 9); /* Check chunk_size is a power of 2 */ - if (chunk_size & (chunk_size - 1)) { + if (!is_power_of_2(chunk_size)) { *error = "Chunk size is not a power of 2"; return -EINVAL; } diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 51f5e076001..969944a8aba 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -11,6 +11,7 @@ #include <linux/blkdev.h> #include <linux/bio.h> #include <linux/slab.h> +#include <linux/log2.h> #define DM_MSG_PREFIX "striped" @@ -99,7 +100,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) /* * chunk_size is a power of two */ - if (!chunk_size || (chunk_size & (chunk_size - 1)) || + if (!is_power_of_2(chunk_size) || (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { ti->error = "Invalid chunk size"; return -EINVAL; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index fbe477bb2c6..8939e610508 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -213,12 +213,11 @@ static int alloc_targets(struct dm_table *t, unsigned int num) int dm_table_create(struct dm_table **result, int mode, unsigned num_targets, struct mapped_device *md) { - struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); + struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; - memset(t, 0, sizeof(*t)); INIT_LIST_HEAD(&t->devices); atomic_set(&t->holders, 1); diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 477a041a41c..835cf95b857 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c @@ -88,12 +88,10 @@ void dm_put_target_type(struct target_type *t) static struct tt_internal *alloc_target(struct target_type *t) { - struct tt_internal *ti = kmalloc(sizeof(*ti), GFP_KERNEL); + struct tt_internal *ti = kzalloc(sizeof(*ti), GFP_KERNEL); - if (ti) { - memset(ti, 0, sizeof(*ti)); + if (ti) ti->tt = *t; - } return ti; } diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c new file mode 100644 index 00000000000..50377e5dc2a --- /dev/null +++ b/drivers/md/dm-uevent.c @@ -0,0 +1,222 @@ +/* + * Device Mapper Uevent Support (dm-uevent) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2007 + * Author: Mike Anderson <andmike@linux.vnet.ibm.com> + */ +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/kobject.h> +#include <linux/dm-ioctl.h> + +#include "dm.h" +#include "dm-uevent.h" + +#define DM_MSG_PREFIX "uevent" + +static const struct { + enum dm_uevent_type type; + enum kobject_action action; + char *name; +} _dm_uevent_type_names[] = { + {DM_UEVENT_PATH_FAILED, KOBJ_CHANGE, "PATH_FAILED"}, + {DM_UEVENT_PATH_REINSTATED, KOBJ_CHANGE, "PATH_REINSTATED"}, +}; + +static struct kmem_cache *_dm_event_cache; + +struct dm_uevent { + struct mapped_device *md; + enum kobject_action action; + struct kobj_uevent_env ku_env; + struct list_head elist; + char name[DM_NAME_LEN]; + char uuid[DM_UUID_LEN]; +}; + +static void dm_uevent_free(struct dm_uevent *event) +{ + kmem_cache_free(_dm_event_cache, event); +} + +static struct dm_uevent *dm_uevent_alloc(struct mapped_device *md) +{ + struct dm_uevent *event; + + event = kmem_cache_zalloc(_dm_event_cache, GFP_ATOMIC); + if (!event) + return NULL; + + INIT_LIST_HEAD(&event->elist); + event->md = md; + + return event; +} + +static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md, + struct dm_target *ti, + enum kobject_action action, + const char *dm_action, + const char *path, + unsigned nr_valid_paths) +{ + struct dm_uevent *event; + + event = dm_uevent_alloc(md); + if (!event) { + DMERR("%s: dm_uevent_alloc() failed", __FUNCTION__); + goto err_nomem; + } + + event->action = action; + + if (add_uevent_var(&event->ku_env, "DM_TARGET=%s", ti->type->name)) { + DMERR("%s: add_uevent_var() for DM_TARGET failed", + __FUNCTION__); + goto err_add; + } + + if (add_uevent_var(&event->ku_env, "DM_ACTION=%s", dm_action)) { + DMERR("%s: add_uevent_var() for DM_ACTION failed", + __FUNCTION__); + goto err_add; + } + + if (add_uevent_var(&event->ku_env, "DM_SEQNUM=%u", + dm_next_uevent_seq(md))) { + DMERR("%s: add_uevent_var() for DM_SEQNUM failed", + __FUNCTION__); + goto err_add; + } + + if (add_uevent_var(&event->ku_env, "DM_PATH=%s", path)) { + DMERR("%s: add_uevent_var() for DM_PATH failed", __FUNCTION__); + goto err_add; + } + + if (add_uevent_var(&event->ku_env, "DM_NR_VALID_PATHS=%d", + nr_valid_paths)) { + DMERR("%s: add_uevent_var() for DM_NR_VALID_PATHS failed", + __FUNCTION__); + goto err_add; + } + + return event; + +err_add: + dm_uevent_free(event); +err_nomem: + return ERR_PTR(-ENOMEM); +} + +/** + * dm_send_uevents - send uevents for given list + * + * @events: list of events to send + * @kobj: kobject generating event + * + */ +void dm_send_uevents(struct list_head *events, struct kobject *kobj) +{ + int r; + struct dm_uevent *event, *next; + + list_for_each_entry_safe(event, next, events, elist) { + list_del_init(&event->elist); + + /* + * Need to call dm_copy_name_and_uuid from here for now. + * Context of previous var adds and locking used for + * hash_cell not compatable. + */ + if (dm_copy_name_and_uuid(event->md, event->name, + event->uuid)) { + DMERR("%s: dm_copy_name_and_uuid() failed", + __FUNCTION__); + goto uevent_free; + } + + if (add_uevent_var(&event->ku_env, "DM_NAME=%s", event->name)) { + DMERR("%s: add_uevent_var() for DM_NAME failed", + __FUNCTION__); + goto uevent_free; + } + + if (add_uevent_var(&event->ku_env, "DM_UUID=%s", event->uuid)) { + DMERR("%s: add_uevent_var() for DM_UUID failed", + __FUNCTION__); + goto uevent_free; + } + + r = kobject_uevent_env(kobj, event->action, event->ku_env.envp); + if (r) + DMERR("%s: kobject_uevent_env failed", __FUNCTION__); +uevent_free: + dm_uevent_free(event); + } +} +EXPORT_SYMBOL_GPL(dm_send_uevents); + +/** + * dm_path_uevent - called to create a new path event and queue it + * + * @event_type: path event type enum + * @ti: pointer to a dm_target + * @path: string containing pathname + * @nr_valid_paths: number of valid paths remaining + * + */ +void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti, + const char *path, unsigned nr_valid_paths) +{ + struct mapped_device *md = dm_table_get_md(ti->table); + struct dm_uevent *event; + + if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) { + DMERR("%s: Invalid event_type %d", __FUNCTION__, event_type); + goto out; + } + + event = dm_build_path_uevent(md, ti, + _dm_uevent_type_names[event_type].action, + _dm_uevent_type_names[event_type].name, + path, nr_valid_paths); + if (IS_ERR(event)) + goto out; + + dm_uevent_add(md, &event->elist); + +out: + dm_put(md); +} +EXPORT_SYMBOL_GPL(dm_path_uevent); + +int dm_uevent_init(void) +{ + _dm_event_cache = KMEM_CACHE(dm_uevent, 0); + if (!_dm_event_cache) + return -ENOMEM; + + DMINFO("version 1.0.3"); + + return 0; +} + +void dm_uevent_exit(void) +{ + kmem_cache_destroy(_dm_event_cache); +} diff --git a/drivers/md/dm-uevent.h b/drivers/md/dm-uevent.h new file mode 100644 index 00000000000..2eccc8bd671 --- /dev/null +++ b/drivers/md/dm-uevent.h @@ -0,0 +1,59 @@ +/* + * Device Mapper Uevent Support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2007 + * Author: Mike Anderson <andmike@linux.vnet.ibm.com> + */ +#ifndef DM_UEVENT_H +#define DM_UEVENT_H + +enum dm_uevent_type { + DM_UEVENT_PATH_FAILED, + DM_UEVENT_PATH_REINSTATED, +}; + +#ifdef CONFIG_DM_UEVENT + +extern int dm_uevent_init(void); +extern void dm_uevent_exit(void); +extern void dm_send_uevents(struct list_head *events, struct kobject *kobj); +extern void dm_path_uevent(enum dm_uevent_type event_type, + struct dm_target *ti, const char *path, + unsigned nr_valid_paths); + +#else + +static inline int dm_uevent_init(void) +{ + return 0; +} +static inline void dm_uevent_exit(void) +{ +} +static inline void dm_send_uevents(struct list_head *events, + struct kobject *kobj) +{ +} +static inline void dm_path_uevent(enum dm_uevent_type event_type, + struct dm_target *ti, const char *path, + unsigned nr_valid_paths) +{ +} + +#endif /* CONFIG_DM_UEVENT */ + +#endif /* DM_UEVENT_H */ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d837d37f620..07cbbb8eb3e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -7,6 +7,7 @@ #include "dm.h" #include "dm-bio-list.h" +#include "dm-uevent.h" #include <linux/init.h> #include <linux/module.h> @@ -112,6 +113,9 @@ struct mapped_device { */ atomic_t event_nr; wait_queue_head_t eventq; + atomic_t uevent_seq; + struct list_head uevent_list; + spinlock_t uevent_lock; /* Protect access to uevent_list */ /* * freeze/thaw support require holding onto a super block @@ -143,11 +147,19 @@ static int __init local_init(void) return -ENOMEM; } + r = dm_uevent_init(); + if (r) { + kmem_cache_destroy(_tio_cache); + kmem_cache_destroy(_io_cache); + return r; + } + _major = major; r = register_blkdev(_major, _name); if (r < 0) { kmem_cache_destroy(_tio_cache); kmem_cache_destroy(_io_cache); + dm_uevent_exit(); return r; } @@ -162,6 +174,7 @@ static void local_exit(void) kmem_cache_destroy(_tio_cache); kmem_cache_destroy(_io_cache); unregister_blkdev(_major, _name); + dm_uevent_exit(); _major = 0; @@ -751,15 +764,13 @@ static void __clone_and_map(struct clone_info *ci) /* * Split the bio into several clones. */ -static void __split_bio(struct mapped_device *md, struct bio *bio) +static int __split_bio(struct mapped_device *md, struct bio *bio) { struct clone_info ci; ci.map = dm_get_table(md); - if (!ci.map) { - bio_io_error(bio); - return; - } + if (unlikely(!ci.map)) + return -EIO; ci.md = md; ci.bio = bio; @@ -779,6 +790,8 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) /* drop the extra reference count */ dec_pending(ci.io, 0); dm_table_put(ci.map); + + return 0; } /*----------------------------------------------------------------- * CRUD END @@ -790,7 +803,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) */ static int dm_request(struct request_queue *q, struct bio *bio) { - int r; + int r = -EIO; int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; @@ -815,18 +828,11 @@ static int dm_request(struct request_queue *q, struct bio *bio) while (test_bit(DMF_BLOCK_IO, &md->flags)) { up_read(&md->io_lock); - if (bio_rw(bio) == READA) { - bio_io_error(bio); - return 0; - } - - r = queue_io(md, bio); - if (r < 0) { - bio_io_error(bio); - return 0; + if (bio_rw(bio) != READA) + r = queue_io(md, bio); - } else if (r == 0) - return 0; /* deferred successfully */ + if (r <= 0) + goto out_req; /* * We're in a while loop, because someone could suspend @@ -835,8 +841,13 @@ static int dm_request(struct request_queue *q, struct bio *bio) down_read(&md->io_lock); } - __split_bio(md, bio); + r = __split_bio(md, bio); up_read(&md->io_lock); + +out_req: + if (r < 0) + bio_io_error(bio); + return 0; } @@ -977,6 +988,9 @@ static struct mapped_device *alloc_dev(int minor) atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); atomic_set(&md->event_nr, 0); + atomic_set(&md->uevent_seq, 0); + INIT_LIST_HEAD(&md->uevent_list); + spin_lock_init(&md->uevent_lock); md->queue = blk_alloc_queue(GFP_KERNEL); if (!md->queue) @@ -1044,12 +1058,14 @@ static struct mapped_device *alloc_dev(int minor) return NULL; } +static void unlock_fs(struct mapped_device *md); + static void free_dev(struct mapped_device *md) { int minor = md->disk->first_minor; if (md->suspended_bdev) { - thaw_bdev(md->suspended_bdev, NULL); + unlock_fs(md); bdput(md->suspended_bdev); } mempool_destroy(md->tio_pool); @@ -1073,8 +1089,16 @@ static void free_dev(struct mapped_device *md) */ static void event_callback(void *context) { + unsigned long flags; + LIST_HEAD(uevents); struct mapped_device *md = (struct mapped_device *) context; + spin_lock_irqsave(&md->uevent_lock, flags); + list_splice_init(&md->uevent_list, &uevents); + spin_unlock_irqrestore(&md->uevent_lock, flags); + + dm_send_uevents(&uevents, &md->disk->kobj); + atomic_inc(&md->event_nr); wake_up(&md->eventq); } @@ -1233,7 +1257,8 @@ static void __flush_deferred_io(struct mapped_device *md, struct bio *c) while (c) { n = c->bi_next; c->bi_next = NULL; - __split_bio(md, c); + if (__split_bio(md, c)) + bio_io_error(c); c = n; } } @@ -1491,6 +1516,11 @@ out: /*----------------------------------------------------------------- * Event notification. *---------------------------------------------------------------*/ +uint32_t dm_next_uevent_seq(struct mapped_device *md) +{ + return atomic_add_return(1, &md->uevent_seq); +} + uint32_t dm_get_event_nr(struct mapped_device *md) { return atomic_read(&md->event_nr); @@ -1502,6 +1532,15 @@ int dm_wait_event(struct mapped_device *md, int event_nr) (event_nr != atomic_read(&md->event_nr))); } +void dm_uevent_add(struct mapped_device *md, struct list_head *elist) +{ + unsigned long flags; + + spin_lock_irqsave(&md->uevent_lock, flags); + list_add(elist, &md->uevent_list); + spin_unlock_irqrestore(&md->uevent_lock, flags); +} + /* * The gendisk is only valid as long as you have a reference * count on 'md'. diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 7e052378c47..f3831f31223 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -198,7 +198,7 @@ struct kcopyd_job { * These fields are only used if the job has been split * into more manageable parts. */ - struct semaphore lock; + struct mutex lock; atomic_t sub_jobs; sector_t progress; }; @@ -456,7 +456,7 @@ static void segment_complete(int read_err, sector_t count = 0; struct kcopyd_job *job = (struct kcopyd_job *) context; - down(&job->lock); + mutex_lock(&job->lock); /* update the error */ if (read_err) @@ -480,7 +480,7 @@ static void segment_complete(int read_err, job->progress += count; } } - up(&job->lock); + mutex_unlock(&job->lock); if (count) { int i; @@ -562,7 +562,7 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, dispatch_job(job); else { - init_MUTEX(&job->lock); + mutex_init(&job->lock); job->progress = 0; split_job(job); } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index fd9e8405fd7..ce34b539bf3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1293,9 +1293,6 @@ config PCNET32_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config AMD8111_ETH @@ -1313,7 +1310,7 @@ config AMD8111_ETH will be called amd8111e. config AMD8111E_NAPI - bool "Enable NAPI support" + bool "Use RX polling (NAPI)" depends on AMD8111_ETH help NAPI is a new driver API designed to reduce CPU and interrupt load @@ -1324,9 +1321,6 @@ config AMD8111E_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config ADAPTEC_STARFIRE @@ -1355,9 +1349,6 @@ config ADAPTEC_STARFIRE_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config AC3200 @@ -1431,7 +1422,7 @@ config FORCEDETH called forcedeth. config FORCEDETH_NAPI - bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on FORCEDETH && EXPERIMENTAL help NAPI is a new driver API designed to reduce CPU and interrupt load @@ -1442,9 +1433,6 @@ config FORCEDETH_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config CS89x0 @@ -1756,9 +1744,6 @@ config VIA_RHINE_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - config LAN_SAA9730 bool "Philips SAA9730 Ethernet support" depends on NET_PCI && PCI && MIPS_ATLAS @@ -2003,9 +1988,6 @@ config E1000_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config E1000_DISABLE_PACKET_SPLIT @@ -2099,7 +2081,7 @@ config R8169 will be called r8169. This is recommended. config R8169_NAPI - bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on R8169 && EXPERIMENTAL help NAPI is a new driver API designed to reduce CPU and interrupt load @@ -2110,9 +2092,6 @@ config R8169_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config R8169_VLAN @@ -2364,7 +2343,7 @@ config GIANFAR and MPC86xx family of chips, and the FEC on the 8540. config GFAR_NAPI - bool "NAPI Support" + bool "Use Rx Polling (NAPI)" depends on GIANFAR config UCC_GETH @@ -2376,7 +2355,7 @@ config UCC_GETH which is available on some Freescale SOCs. config UGETH_NAPI - bool "NAPI Support" + bool "Use Rx Polling (NAPI)" depends on UCC_GETH config UGETH_MAGIC_PACKET @@ -2494,7 +2473,7 @@ config CHELSIO_T3 config EHEA tristate "eHEA Ethernet support" - depends on IBMEBUS + depends on IBMEBUS && INET select INET_LRO ---help--- This driver supports the IBM pSeries eHEA ethernet adapter. @@ -2559,9 +2538,6 @@ config IXGB_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config S2IO @@ -2584,14 +2560,11 @@ config S2IO_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config MYRI10GE tristate "Myricom Myri-10G Ethernet support" - depends on PCI + depends on PCI && INET select FW_LOADER select CRC32 select INET_LRO diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 27ac010900a..3286d2a0a87 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -542,7 +542,8 @@ dm9000_probe(struct platform_device *pdev) if (id_val != DM9000_ID) { printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val); - goto release; + ret = -ENODEV; + goto out; } /* from this point we assume that we have found a DM9000 */ @@ -602,8 +603,7 @@ dm9000_probe(struct platform_device *pdev) } return 0; - release: - out: +out: printk("%s: not found (%d).\n", CARDNAME, ret); dm9000_release_board(pdev, db); diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index 8cd243d92af..2747b1f89ff 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -185,3 +185,5 @@ void free_mdio_bitbang(struct mii_bus *bus) module_put(ctrl->ops->owner); kfree(bus); } + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index df10af7df7b..35d15e85007 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1629,7 +1629,7 @@ tsi108_init_one(struct platform_device *pdev) goto register_fail; } - printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n" + printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n", dev->name, print_mac(mac, dev->dev_addr)); #ifdef DEBUG data->msg_enable = DEBUG; diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 1c537d5a306..49d7a290dbb 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -67,7 +67,7 @@ config TULIP_MMIO If in doubt, say N. config TULIP_NAPI - bool "Use NAPI RX polling " + bool "Use RX polling (NAPI)" depends on TULIP help NAPI is a new driver API designed to reduce CPU and interrupt load @@ -78,18 +78,16 @@ config TULIP_NAPI deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. - See <file:Documentation/networking/NAPI_HOWTO.txt> for more - information. - If in doubt, say N. config TULIP_NAPI_HW_MITIGATION - bool "Use Interrupt Mitigation " + bool "Use Interrupt Mitigation" depends on TULIP_NAPI ---help--- - Use HW to reduce RX interrupts. Not strict necessary since NAPI reduces - RX interrupts but itself. Although this reduces RX interrupts even at - low levels traffic at the cost of a small latency. + Use HW to reduce RX interrupts. Not strictly necessary since NAPI + reduces RX interrupts by itself. Interrupt mitigation reduces RX + interrupts even at low levels of traffic at the cost of a small + latency. If in doubt, say Y. diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c141a264ac4..9d9ff76a9bc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -49,7 +49,6 @@ #include "pio.h" #include "sysfs.h" #include "xmit.h" -#include "sysfs.h" #include "lo.h" #include "pcmcia.h" @@ -3495,7 +3494,7 @@ static int b43_start(struct ieee80211_hw *hw) struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; int did_init = 0; - int err; + int err = 0; mutex_lock(&wl->mutex); @@ -3521,7 +3520,7 @@ static int b43_start(struct ieee80211_hw *hw) return err; } -void b43_stop(struct ieee80211_hw *hw) +static void b43_stop(struct ieee80211_hw *hw) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f0749510bcd..d09479e816c 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3306,7 +3306,7 @@ static int b43legacy_start(struct ieee80211_hw *hw) struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; int did_init = 0; - int err; + int err = 0; mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 92314c365af..a6c7904de28 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -2089,12 +2089,46 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); } +static void send_scan_event(void *data) +{ + struct ipw2100_priv *priv = data; + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); +} + +static void ipw2100_scan_event_later(struct work_struct *work) +{ + send_scan_event(container_of(work, struct ipw2100_priv, + scan_event_later.work)); +} + +static void ipw2100_scan_event_now(struct work_struct *work) +{ + send_scan_event(container_of(work, struct ipw2100_priv, + scan_event_now)); +} + static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) { IPW_DEBUG_SCAN("scan complete\n"); /* Age the scan results... */ priv->ieee->scans++; priv->status &= ~STATUS_SCANNING; + + /* Only userspace-requested scan completion events go out immediately */ + if (!priv->user_requested_scan) { + if (!delayed_work_pending(&priv->scan_event_later)) + queue_delayed_work(priv->workqueue, + &priv->scan_event_later, + round_jiffies(msecs_to_jiffies(4000))); + } else { + priv->user_requested_scan = 0; + cancel_delayed_work(&priv->scan_event_later); + queue_work(priv->workqueue, &priv->scan_event_now); + } } #ifdef CONFIG_IPW2100_DEBUG @@ -4349,6 +4383,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) cancel_delayed_work(&priv->wx_event_work); cancel_delayed_work(&priv->hang_check); cancel_delayed_work(&priv->rf_kill); + cancel_delayed_work(&priv->scan_event_later); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; } @@ -6092,6 +6127,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); + INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); + INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -7396,6 +7433,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev, } IPW_DEBUG_WX("Initiating scan...\n"); + + priv->user_requested_scan = 1; if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { IPW_DEBUG_WX("Start scan failed.\n"); diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 2b8be2418fa..bbf1ddcafba 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -586,6 +586,10 @@ struct ipw2100_priv { struct delayed_work wx_event_work; struct delayed_work hang_check; struct delayed_work rf_kill; + struct work_struct scan_event_now; + struct delayed_work scan_event_later; + + int user_requested_scan; u32 interrupts; int tx_interrupts; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index f4aabcf480e..262ab0b5582 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -37,9 +37,6 @@ #include <linux/workqueue.h> -#include <net/mac80211.h> -#include <linux/wireless.h> - #define IWL 3945 #include "../net/mac80211/ieee80211_rate.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index acb38750535..19bcb01e278 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -38,7 +38,6 @@ #include <net/mac80211.h> #include <linux/etherdevice.h> -#include <linux/delay.h> #define IWL 3945 diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 287c75705c4..8dc78c0bf1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -36,9 +36,6 @@ #include <linux/workqueue.h> -#include <net/mac80211.h> -#include <linux/wireless.h> - #define IWL 4965 #include "../net/mac80211/ieee80211_rate.h" @@ -2024,12 +2021,18 @@ static int open_file_generic(struct inode *inode, struct file *file) static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv, struct iwl_rate *mcs, int index) { - const u32 cck_rate = 0x820A; + u32 base_rate; + + if (rs_priv->phymode == (u8) MODE_IEEE80211A) + base_rate = 0x800D; + else + base_rate = 0x820A; + if (rs_priv->dbg_fixed.rate_n_flags) { if (index < 12) mcs->rate_n_flags = rs_priv->dbg_fixed.rate_n_flags; else - mcs->rate_n_flags = cck_rate; + mcs->rate_n_flags = base_rate; IWL_DEBUG_RATE("Fixed rate ON\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b50d20267c8..557deebca1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -35,9 +35,7 @@ #include <linux/netdevice.h> #include <linux/wireless.h> #include <net/mac80211.h> -#include <linux/netdevice.h> #include <linux/etherdevice.h> -#include <linux/delay.h> #define IWL 4965 diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 75e3b5c3f15..83019d1d7cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -48,8 +48,6 @@ #include <linux/netdevice.h> #include <linux/wireless.h> #include <linux/firmware.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/if_arp.h> @@ -1749,21 +1747,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv) * return : set the bit for each supported rate insert in ie */ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int max_count) + u16 basic_rate, int *left) { u16 ret_rates = 0, bit; int i; - u8 *rates; - - rates = &(ie[1]); + u8 *cnt = ie; + u8 *rates = ie + 1; for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { if (bit & supported_rate) { ret_rates |= bit; - rates[*ie] = iwl_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - *ie = *ie + 1; - if (*ie >= max_count) + rates[*cnt] = iwl_rates[i].ieee | + ((bit & basic_rate) ? 0x80 : 0x00); + (*cnt)++; + (*left)--; + if ((*left <= 0) || + (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) break; } } @@ -1780,7 +1779,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, { int len = 0; u8 *pos = NULL; - u16 ret_rates; + u16 active_rates, ret_rates, cck_rates; /* Make sure there is enough space for the probe request, * two mandatory IEs and the data */ @@ -1825,19 +1824,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, left -= 2; if (left < 0) return 0; + /* ... fill it in... */ *pos++ = WLAN_EID_SUPP_RATES; *pos = 0; - ret_rates = priv->active_rate = priv->rates_mask; + + priv->active_rate = priv->rates_mask; + active_rates = priv->active_rate; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - iwl_supported_rate_to_ie(pos, priv->active_rate, - priv->active_rate_basic, left); + cck_rates = IWL_CCK_RATES_MASK & active_rates; + ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, + priv->active_rate_basic, &left); + active_rates &= ~ret_rates; + + ret_rates = iwl_supported_rate_to_ie(pos, active_rates, + priv->active_rate_basic, &left); + active_rates &= ~ret_rates; + len += 2 + *pos; pos += (*pos) + 1; - ret_rates = ~ret_rates & priv->active_rate; - - if (ret_rates == 0) + if (active_rates == 0) goto fill_end; /* fill in supported extended rate */ @@ -1848,7 +1855,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, /* ... fill it in... */ *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos = 0; - iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left); + iwl_supported_rate_to_ie(pos, active_rates, + priv->active_rate_basic, &left); if (*pos > 0) len += 2 + *pos; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index b1a6e39f782..5e1279263b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -48,8 +48,6 @@ #include <linux/netdevice.h> #include <linux/wireless.h> #include <linux/firmware.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/if_arp.h> @@ -1802,21 +1800,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv) * return : set the bit for each supported rate insert in ie */ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int max_count) + u16 basic_rate, int *left) { u16 ret_rates = 0, bit; int i; - u8 *rates; - - rates = &(ie[1]); + u8 *cnt = ie; + u8 *rates = ie + 1; for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { if (bit & supported_rate) { ret_rates |= bit; - rates[*ie] = iwl_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - *ie = *ie + 1; - if (*ie >= max_count) + rates[*cnt] = iwl_rates[i].ieee | + ((bit & basic_rate) ? 0x80 : 0x00); + (*cnt)++; + (*left)--; + if ((*left <= 0) || + (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) break; } } @@ -1839,7 +1838,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, { int len = 0; u8 *pos = NULL; - u16 ret_rates; + u16 active_rates, ret_rates, cck_rates; /* Make sure there is enough space for the probe request, * two mandatory IEs and the data */ @@ -1884,19 +1883,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, left -= 2; if (left < 0) return 0; + /* ... fill it in... */ *pos++ = WLAN_EID_SUPP_RATES; *pos = 0; - ret_rates = priv->active_rate = priv->rates_mask; + + priv->active_rate = priv->rates_mask; + active_rates = priv->active_rate; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - iwl_supported_rate_to_ie(pos, priv->active_rate, - priv->active_rate_basic, left); + cck_rates = IWL_CCK_RATES_MASK & active_rates; + ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, + priv->active_rate_basic, &left); + active_rates &= ~ret_rates; + + ret_rates = iwl_supported_rate_to_ie(pos, active_rates, + priv->active_rate_basic, &left); + active_rates &= ~ret_rates; + len += 2 + *pos; pos += (*pos) + 1; - ret_rates = ~ret_rates & priv->active_rate; - - if (ret_rates == 0) + if (active_rates == 0) goto fill_end; /* fill in supported extended rate */ @@ -1907,7 +1914,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, /* ... fill it in... */ *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos = 0; - iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left); + iwl_supported_rate_to_ie(pos, active_rates, + priv->active_rate_basic, &left); if (*pos > 0) len += 2 + *pos; @@ -4494,13 +4502,13 @@ static u8 ratio2dB[100] = { * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ int iwl_calc_db_from_ratio(int sig_ratio) { - /* Anything above 1000:1 just report as 60 dB */ - if (sig_ratio > 1000) + /* 1000:1 or higher just report as 60 dB */ + if (sig_ratio >= 1000) return 60; - /* Above 100:1, divide by 10 and use table, + /* 100:1 or higher, divide by 10 and use table, * add 20 dB to make up for divide by 10 */ - if (sig_ratio > 100) + if (sig_ratio >= 100) return (20 + (int)ratio2dB[sig_ratio/10]); /* We shouldn't see this */ diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h index e0b97c34121..432ce887807 100644 --- a/drivers/net/wireless/iwlwifi/iwlwifi.h +++ b/drivers/net/wireless/iwlwifi/iwlwifi.h @@ -39,18 +39,13 @@ struct iwl_priv; /* Hardware specific file defines the PCI IDs table for that hardware module */ extern struct pci_device_id iwl_hw_card_ids[]; +#include "iwl-hw.h" #if IWL == 3945 - #define DRV_NAME "iwl3945" -#include "iwl-hw.h" #include "iwl-3945-hw.h" - #elif IWL == 4965 - #define DRV_NAME "iwl4965" -#include "iwl-hw.h" #include "iwl-4965-hw.h" - #endif #include "iwl-prph.h" diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 2c63cf0ad2c..1437db0cf4b 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -577,7 +577,7 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, struct p54_tx_control_filter *filter; hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) + - priv->tx_hdr_len, GFP_KERNEL); + priv->tx_hdr_len, GFP_ATOMIC); if (!hdr) return -ENOMEM; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index bb6f46cfbb9..ff399f8083e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -550,7 +550,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Check if we need to set the Length Extension */ - if (bitrate == 110 && residual <= 3) + if (bitrate == 110 && residual <= 30) desc.service |= 0x80; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 3e42759473c..46c8c0840a6 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2029,6 +2029,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, /* Billionton */ { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, /* Buffalo */ diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 0ef887dd286..de61c8fe649 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -131,7 +131,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, struct rtl8187_tx_hdr *hdr; struct rtl8187_tx_info *info; struct urb *urb; - u32 tmp; + __le16 rts_dur = 0; + u32 flags; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { @@ -139,24 +140,24 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, return 0; } - hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - tmp = skb->len - sizeof(*hdr); - tmp |= RTL8187_TX_FLAG_NO_ENCRYPT; - tmp |= control->rts_cts_rate << 19; - tmp |= control->tx_rate << 24; - if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb)) - tmp |= RTL8187_TX_FLAG_MORE_FRAG; + flags = skb->len; + flags |= RTL8187_TX_FLAG_NO_ENCRYPT; + flags |= control->rts_cts_rate << 19; + flags |= control->tx_rate << 24; + if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) + flags |= RTL8187_TX_FLAG_MORE_FRAG; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { - tmp |= RTL8187_TX_FLAG_RTS; - hdr->rts_duration = - ieee80211_rts_duration(dev, priv->if_id, skb->len, control); + flags |= RTL8187_TX_FLAG_RTS; + rts_dur = ieee80211_rts_duration(dev, priv->if_id, skb->len, control); } if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - tmp |= RTL8187_TX_FLAG_CTS; - hdr->flags = cpu_to_le32(tmp); + flags |= RTL8187_TX_FLAG_CTS; + + hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); hdr->len = 0; - tmp = control->retry_limit << 8; - hdr->retry = cpu_to_le32(tmp); + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(control->retry_limit << 8); info = (struct rtl8187_tx_info *)skb->cb; info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC); @@ -587,8 +588,6 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, *total_flags = 0; - if (changed_flags & FIF_PROMISC_IN_BSS) - priv->rx_conf ^= RTL818X_RX_CONF_NICMAC; if (changed_flags & FIF_ALLMULTI) priv->rx_conf ^= RTL818X_RX_CONF_MULTICAST; if (changed_flags & FIF_FCSFAIL) @@ -601,8 +600,6 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, if (mc_count > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; - if (priv->rx_conf & RTL818X_RX_CONF_NICMAC) - *total_flags |= FIF_PROMISC_IN_BSS; if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) *total_flags |= FIF_ALLMULTI; if (priv->rx_conf & RTL818X_RX_CONF_FCS) diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 935b144d9b5..d5c0c66188c 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -327,8 +327,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, 6), &data[datalen-8], 6); memcpy(skb_put(skb, 2), &data[datalen-24], 2); memcpy(skb_put(skb, len), data, len); - skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, zd->dev); + skb->dev->last_rx = jiffies; zd->stats.rx_packets++; zd->stats.rx_bytes += skb->len; netif_rx(skb); @@ -384,8 +384,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, 2), &data[6], 2); memcpy(skb_put(skb, len), data+8, len); } - skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, zd->dev); + skb->dev->last_rx = jiffies; zd->stats.rx_packets++; zd->stats.rx_bytes += skb->len; netif_rx(skb); diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index b0684f96576..c755b692381 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1044,14 +1044,17 @@ error: static void disconnect(struct usb_interface *intf) { struct net_device *netdev = zd_intf_to_netdev(intf); - struct zd_mac *mac = zd_netdev_mac(netdev); - struct zd_usb *usb = &mac->chip.usb; + struct zd_mac *mac; + struct zd_usb *usb; /* Either something really bad happened, or we're just dealing with * a DEVICE_INSTALLER. */ if (netdev == NULL) return; + mac = zd_netdev_mac(netdev); + usb = &mac->chip.usb; + dev_dbg_f(zd_usb_dev(usb), "\n"); zd_netdev_disconnect(netdev); diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index a2d08c9ba3c..ff999ff0b62 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -6643,7 +6643,8 @@ qeth_netdev_init(struct net_device *dev) dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid; dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid; #endif - dev->header_ops = &qeth_null_ops; + if (qeth_get_netdev_flags(card) & IFF_NOARP) + dev->header_ops = &qeth_null_ops; #ifdef CONFIG_QETH_IPV6 /*IPv6 address autoconfiguration stuff*/ diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index 7f3f18d0671..febf09c6349 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c @@ -127,7 +127,7 @@ static void gx_set_dclk_frequency(struct fb_info *info) int timeout = 1000; /* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */ - if (cpu_data->x86_mask == 1) { + if (cpu_data(0).x86_mask == 1) { pll_table = gx_pll_table_14MHz; pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz); } else { diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index af8b235d405..11833f4caea 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -168,7 +168,8 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct spin_unlock(&inode->i_lock); spin_unlock(&clp->cl_lock); - kfree(delegation); + if (delegation != NULL) + nfs_free_delegation(delegation); return status; } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8ec7fbd8240..35334539d94 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -562,6 +562,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) nfs_fattr_init(&fattr); desc->entry = &my_entry; + nfs_block_sillyrename(dentry); while(!desc->entry->eof) { res = readdir_search_pagecache(desc); @@ -592,6 +593,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) break; } } + nfs_unblock_sillyrename(dentry); unlock_kernel(); if (res > 0) res = 0; @@ -866,6 +868,7 @@ struct dentry_operations nfs_dentry_operations = { static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) { struct dentry *res; + struct dentry *parent; struct inode *inode = NULL; int error; struct nfs_fh fhandle; @@ -894,26 +897,31 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru goto out_unlock; } + parent = dentry->d_parent; + /* Protect against concurrent sillydeletes */ + nfs_block_sillyrename(parent); error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); if (error == -ENOENT) goto no_entry; if (error < 0) { res = ERR_PTR(error); - goto out_unlock; + goto out_unblock_sillyrename; } inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); res = (struct dentry *)inode; if (IS_ERR(res)) - goto out_unlock; + goto out_unblock_sillyrename; no_entry: res = d_materialise_unique(dentry, inode); if (res != NULL) { if (IS_ERR(res)) - goto out_unlock; + goto out_unblock_sillyrename; dentry = res; } nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); +out_unblock_sillyrename: + nfs_unblock_sillyrename(parent); out_unlock: unlock_kernel(); out: diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d29f90d00aa..b3bb89f7d5d 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp) { /* Ensure that dirty pages are flushed out with the right creds */ if (filp->f_mode & FMODE_WRITE) - filemap_fdatawrite(filp->f_mapping); + nfs_wb_all(filp->f_path.dentry->d_inode); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); return NFS_PROTO(inode)->file_release(inode, filp); } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6d2f2a3eccf..db5d96dc610 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -514,7 +514,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) return ctx; } -void put_nfs_open_context(struct nfs_open_context *ctx) +static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) { struct inode *inode = ctx->path.dentry->d_inode; @@ -522,8 +522,12 @@ void put_nfs_open_context(struct nfs_open_context *ctx) return; list_del(&ctx->list); spin_unlock(&inode->i_lock); - if (ctx->state != NULL) - nfs4_close_state(&ctx->path, ctx->state, ctx->mode); + if (ctx->state != NULL) { + if (wait) + nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); + else + nfs4_close_state(&ctx->path, ctx->state, ctx->mode); + } if (ctx->cred != NULL) put_rpccred(ctx->cred); dput(ctx->path.dentry); @@ -531,6 +535,16 @@ void put_nfs_open_context(struct nfs_open_context *ctx) kfree(ctx); } +void put_nfs_open_context(struct nfs_open_context *ctx) +{ + __put_nfs_open_context(ctx, 0); +} + +static void put_nfs_open_context_sync(struct nfs_open_context *ctx) +{ + __put_nfs_open_context(ctx, 1); +} + /* * Ensure that mmap has a recent RPC credential for use when writing out * shared pages @@ -577,7 +591,7 @@ static void nfs_file_clear_open_context(struct file *filp) spin_lock(&inode->i_lock); list_move_tail(&ctx->list, &NFS_I(inode)->open_files); spin_unlock(&inode->i_lock); - put_nfs_open_context(ctx); + put_nfs_open_context_sync(ctx); } } @@ -1169,6 +1183,9 @@ static void init_once(struct kmem_cache * cachep, void *foo) INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); nfsi->ncommit = 0; nfsi->npages = 0; + atomic_set(&nfsi->silly_count, 1); + INIT_HLIST_HEAD(&nfsi->silly_list); + init_waitqueue_head(&nfsi->waitqueue); nfs4_init_once(nfsi); } diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index d2802b1ca3b..b35069a2aa9 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -178,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); -extern int nfs4_do_close(struct path *path, struct nfs4_state *state); +extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait); extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); @@ -209,6 +209,7 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *); extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t); +extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); extern void nfs4_schedule_state_recovery(struct nfs_client *); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); @@ -235,6 +236,7 @@ extern struct svc_version nfs4_callback_version1; #else #define nfs4_close_state(a, b, c) do { } while (0) +#define nfs4_close_sync(a, b, c) do { } while (0) #endif /* CONFIG_NFS_V4 */ #endif /* __LINUX_FS_NFS_NFS4_FS.H */ diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cb99fd90a9a..f03d9d5f5ba 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1305,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = { * * NOTE: Caller must be holding the sp->so_owner semaphore! */ -int nfs4_do_close(struct path *path, struct nfs4_state *state) +int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) { struct nfs_server *server = NFS_SERVER(state->inode); struct nfs4_closedata *calldata; @@ -1333,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state) task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); if (IS_ERR(task)) return PTR_ERR(task); + status = 0; + if (wait) + status = rpc_wait_for_completion_task(task); rpc_put_task(task); - return 0; + return status; out_free_calldata: kfree(calldata); out: @@ -1365,13 +1368,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct } ret = PTR_ERR(filp); out_close: - nfs4_close_state(path, state, nd->intent.open.flags); + nfs4_close_sync(path, state, nd->intent.open.flags); return ret; } struct dentry * nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { + struct dentry *parent; struct path path = { .mnt = nd->mnt, .dentry = dentry, @@ -1394,6 +1398,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); if (IS_ERR(cred)) return (struct dentry *)cred; + parent = dentry->d_parent; + /* Protect against concurrent sillydeletes */ + nfs_block_sillyrename(parent); state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); put_rpccred(cred); if (IS_ERR(state)) { @@ -1401,12 +1408,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) d_add(dentry, NULL); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); } + nfs_unblock_sillyrename(parent); return (struct dentry *)state; } res = d_add_unique(dentry, igrab(state->inode)); if (res != NULL) path.dentry = res; nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); + nfs_unblock_sillyrename(parent); nfs4_intent_set_file(nd, &path, state); return res; } @@ -1444,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st nfs4_intent_set_file(nd, &path, state); return 1; } - nfs4_close_state(&path, state, openflags); + nfs4_close_sync(&path, state, openflags); out_drop: d_drop(dentry); return 0; @@ -1898,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) status = nfs4_intent_set_file(nd, &path, state); else - nfs4_close_state(&path, state, flags); + nfs4_close_sync(&path, state, flags); out: return status; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index bfb36261cec..23a9a36556b 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -425,7 +425,7 @@ void nfs4_put_open_state(struct nfs4_state *state) /* * Close the current file. */ -void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) +static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait) { struct nfs4_state_owner *owner = state->owner; int call_close = 0; @@ -466,7 +466,17 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) nfs4_put_open_state(state); nfs4_put_state_owner(owner); } else - nfs4_do_close(path, state); + nfs4_do_close(path, state, wait); +} + +void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) +{ + __nfs4_close(path, state, mode, 0); +} + +void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode) +{ + __nfs4_close(path, state, mode, 1); } /* diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 1aed850d18f..ce558c2e4d5 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -11,9 +11,11 @@ #include <linux/sunrpc/sched.h> #include <linux/sunrpc/clnt.h> #include <linux/nfs_fs.h> - +#include <linux/sched.h> +#include <linux/wait.h> struct nfs_unlinkdata { + struct hlist_node list; struct nfs_removeargs args; struct nfs_removeres res; struct inode *dir; @@ -52,6 +54,20 @@ static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) return 0; } +static void nfs_free_dname(struct nfs_unlinkdata *data) +{ + kfree(data->args.name.name); + data->args.name.name = NULL; + data->args.name.len = 0; +} + +static void nfs_dec_sillycount(struct inode *dir) +{ + struct nfs_inode *nfsi = NFS_I(dir); + if (atomic_dec_return(&nfsi->silly_count) == 1) + wake_up(&nfsi->waitqueue); +} + /** * nfs_async_unlink_init - Initialize the RPC info * task: rpc_task of the sillydelete @@ -95,6 +111,8 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) static void nfs_async_unlink_release(void *calldata) { struct nfs_unlinkdata *data = calldata; + + nfs_dec_sillycount(data->dir); nfs_free_unlinkdata(data); } @@ -104,33 +122,100 @@ static const struct rpc_call_ops nfs_unlink_ops = { .rpc_release = nfs_async_unlink_release, }; -static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) +static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) { struct rpc_task *task; + struct dentry *alias; + + alias = d_lookup(parent, &data->args.name); + if (alias != NULL) { + int ret = 0; + /* + * Hey, we raced with lookup... See if we need to transfer + * the sillyrename information to the aliased dentry. + */ + nfs_free_dname(data); + spin_lock(&alias->d_lock); + if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { + alias->d_fsdata = data; + alias->d_flags ^= DCACHE_NFSFS_RENAMED; + ret = 1; + } + spin_unlock(&alias->d_lock); + nfs_dec_sillycount(dir); + dput(alias); + return ret; + } + data->dir = igrab(dir); + if (!data->dir) { + nfs_dec_sillycount(dir); + return 0; + } + data->args.fh = NFS_FH(dir); + nfs_fattr_init(&data->res.dir_attr); + + task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); + if (!IS_ERR(task)) + rpc_put_task(task); + return 1; +} + +static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) +{ struct dentry *parent; struct inode *dir; + int ret = 0; - if (nfs_copy_dname(dentry, data) < 0) - goto out_free; parent = dget_parent(dentry); if (parent == NULL) goto out_free; - dir = igrab(parent->d_inode); + dir = parent->d_inode; + if (nfs_copy_dname(dentry, data) == 0) + goto out_dput; + /* Non-exclusive lock protects against concurrent lookup() calls */ + spin_lock(&dir->i_lock); + if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) { + /* Deferred delete */ + hlist_add_head(&data->list, &NFS_I(dir)->silly_list); + spin_unlock(&dir->i_lock); + ret = 1; + goto out_dput; + } + spin_unlock(&dir->i_lock); + ret = nfs_do_call_unlink(parent, dir, data); +out_dput: dput(parent); - if (dir == NULL) - goto out_free; +out_free: + return ret; +} - data->dir = dir; - data->args.fh = NFS_FH(dir); - nfs_fattr_init(&data->res.dir_attr); +void nfs_block_sillyrename(struct dentry *dentry) +{ + struct nfs_inode *nfsi = NFS_I(dentry->d_inode); - task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); - if (!IS_ERR(task)) - rpc_put_task(task); - return 1; -out_free: - return 0; + wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1); +} + +void nfs_unblock_sillyrename(struct dentry *dentry) +{ + struct inode *dir = dentry->d_inode; + struct nfs_inode *nfsi = NFS_I(dir); + struct nfs_unlinkdata *data; + + atomic_inc(&nfsi->silly_count); + spin_lock(&dir->i_lock); + while (!hlist_empty(&nfsi->silly_list)) { + if (!atomic_inc_not_zero(&nfsi->silly_count)) + break; + data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list); + hlist_del(&data->list); + spin_unlock(&dir->i_lock); + if (nfs_do_call_unlink(dentry, dir, data) == 0) + nfs_free_unlinkdata(data); + spin_lock(&dir->i_lock); + } + spin_unlock(&dir->i_lock); } /** diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0cf9d1cd9bd..89527a487ed 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -174,8 +174,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int return; if (count != nfs_page_length(page)) return; - if (count != PAGE_CACHE_SIZE) - zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0); SetPageUptodate(page); } @@ -627,7 +625,8 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, return ERR_PTR(error); } spin_unlock(&inode->i_lock); - return new; + req = new; + goto zero_page; } spin_unlock(&inode->i_lock); @@ -655,13 +654,23 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, if (offset < req->wb_offset) { req->wb_offset = offset; req->wb_pgbase = offset; - req->wb_bytes = rqend - req->wb_offset; + req->wb_bytes = max(end, rqend) - req->wb_offset; + goto zero_page; } if (end > rqend) req->wb_bytes = end - req->wb_offset; return req; +zero_page: + /* If this page might potentially be marked as up to date, + * then we need to zero any uninitalised data. */ + if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE + && !PageUptodate(req->wb_page)) + zero_user_page(req->wb_page, req->wb_bytes, + PAGE_CACHE_SIZE - req->wb_bytes, + KM_USER0); + return req; } int nfs_flush_incompatible(struct file *file, struct page *page) diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h index 2a5cc0b367a..b7bf68d0407 100644 --- a/include/asm-alpha/ide.h +++ b/include/asm-alpha/ide.h @@ -40,7 +40,6 @@ static inline unsigned long ide_default_io_base(int index) } } -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #ifdef CONFIG_PCI diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h index 4f68c8a5a19..f348fcf3150 100644 --- a/include/asm-arm/ide.h +++ b/include/asm-arm/ide.h @@ -18,7 +18,6 @@ #endif #if !defined(CONFIG_ARCH_L7200) -# define IDE_ARCH_OBSOLETE_INIT # ifdef CONFIG_ARCH_CLPS7500 # define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ # else diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h index 41b2db46a16..121e272581d 100644 --- a/include/asm-blackfin/ide.h +++ b/include/asm-blackfin/ide.h @@ -20,7 +20,6 @@ #define MAX_HWIFS 1 /* Legacy ... BLK_DEV_IDECS */ -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h index 6590f657500..11296170d05 100644 --- a/include/asm-cris/arch-v32/ide.h +++ b/include/asm-cris/arch-v32/ide.h @@ -54,7 +54,7 @@ static inline unsigned long ide_default_io_base(int index) #define SUPPORT_VLB_SYNC 0 #define IDE_ARCH_ACK_INTR -#define ide_ack_intr(hwif) (hwif)->hw.ack_intr(hwif) +#define ide_ack_intr(hwif) ((hwif)->ack_intr(hwif)) #endif /* __KERNEL__ */ diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h index e928675de35..1ccf2380932 100644 --- a/include/asm-ia64/ide.h +++ b/include/asm-ia64/ide.h @@ -46,7 +46,6 @@ static inline unsigned long ide_default_io_base(int index) } } -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #ifdef CONFIG_PCI diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h index 4672a49e876..5d2044e529a 100644 --- a/include/asm-m32r/ide.h +++ b/include/asm-m32r/ide.h @@ -65,7 +65,6 @@ static __inline__ unsigned long ide_default_io_base(int index) } } -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #ifdef CONFIG_BLK_DEV_IDEPCI diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h index f9ffb2cbbae..909c6dfd385 100644 --- a/include/asm-m68k/ide.h +++ b/include/asm-m68k/ide.h @@ -137,7 +137,7 @@ ide_get_lock(irq_handler_t handler, void *data) #endif /* CONFIG_BLK_DEV_FALCON_IDE */ #define IDE_ARCH_ACK_INTR -#define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1) +#define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1) #endif /* __KERNEL__ */ #endif /* _M68K_IDE_H */ diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h index a77128362a7..4ec2b930dfb 100644 --- a/include/asm-mips/mach-generic/ide.h +++ b/include/asm-mips/mach-generic/ide.h @@ -98,7 +98,6 @@ static __inline__ unsigned long ide_default_io_base(int index) } } -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #ifdef CONFIG_BLK_DEV_IDEPCI diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h index b27bf7aeb25..be8760fbc8e 100644 --- a/include/asm-parisc/ide.h +++ b/include/asm-parisc/ide.h @@ -17,7 +17,6 @@ #define MAX_HWIFS 2 #endif -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h index 1644e44c875..fd7f5a430f0 100644 --- a/include/asm-powerpc/ide.h +++ b/include/asm-powerpc/ide.h @@ -69,12 +69,11 @@ static __inline__ unsigned long ide_default_io_base(int index) #ifdef CONFIG_BLK_DEV_MPC8xx_IDE #define IDE_ARCH_ACK_INTR 1 -#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) +#define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1) #endif #endif /* __powerpc64__ */ -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #endif /* __KERNEL__ */ diff --git a/include/asm-sh64/ide.h b/include/asm-sh64/ide.h index c9d84d5f772..b6e31e8b941 100644 --- a/include/asm-sh64/ide.h +++ b/include/asm-sh64/ide.h @@ -19,7 +19,6 @@ /* Without this, the initialisation of PCI IDE cards end up calling * ide_init_hwif_ports, which won't work. */ #ifdef CONFIG_BLK_DEV_IDEPCI -#define IDE_ARCH_OBSOLETE_INIT 1 #define ide_default_io_ctl(base) (0) #endif diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h index a6d735a1310..404022765fc 100644 --- a/include/asm-sparc/ide.h +++ b/include/asm-sparc/ide.h @@ -18,7 +18,6 @@ #undef MAX_HWIFS #define MAX_HWIFS 2 -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #define __ide_insl(data_reg, buffer, wcount) \ diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h index 55149cf933c..ac7eb210b94 100644 --- a/include/asm-sparc64/ide.h +++ b/include/asm-sparc64/ide.h @@ -24,7 +24,6 @@ # endif #endif -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #define __ide_insl(data_reg, buffer, wcount) \ diff --git a/include/asm-x86/acpi_32.h b/include/asm-x86/acpi_32.h index 125179adf04..723493e6c85 100644 --- a/include/asm-x86/acpi_32.h +++ b/include/asm-x86/acpi_32.h @@ -81,11 +81,7 @@ int __acpi_release_global_lock(unsigned int *lock); :"=r"(n_hi), "=r"(n_lo) \ :"0"(n_hi), "1"(n_lo)) -#ifdef CONFIG_X86_IO_APIC -extern void check_acpi_pci(void); -#else -static inline void check_acpi_pci(void) { } -#endif +extern void early_quirks(void); #ifdef CONFIG_ACPI extern int acpi_lapic; diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h index 53cb96b68a6..66ba7987184 100644 --- a/include/asm-x86/compat.h +++ b/include/asm-x86/compat.h @@ -6,6 +6,7 @@ */ #include <linux/types.h> #include <linux/sched.h> +#include <asm/user32.h> #define COMPAT_USER_HZ 100 @@ -181,6 +182,11 @@ struct compat_shmid64_ds { }; /* + * The type of struct elf_prstatus.pr_reg in compatible core dumps. + */ +typedef struct user_regs_struct32 compat_elf_gregset_t; + +/* * A pointer passed in from user mode. This should not * be used for syscall parameters, just declare them * as pointers because the syscall entry code will have diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h index ac991b5ca0f..7d9c938e69f 100644 --- a/include/asm-x86/desc_64.h +++ b/include/asm-x86/desc_64.h @@ -20,6 +20,16 @@ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES]; #define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8)) #define clear_LDT() asm volatile("lldt %w0"::"r" (0)) +static inline unsigned long __store_tr(void) +{ + unsigned long tr; + + asm volatile ("str %w0":"=r" (tr)); + return tr; +} + +#define store_tr(tr) (tr) = __store_tr() + /* * This is the ldt that every process will get unless we need * something other than this. @@ -31,6 +41,16 @@ extern struct desc_ptr cpu_gdt_descr[]; /* the cpu gdt accessor */ #define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address) +static inline void load_gdt(const struct desc_ptr *ptr) +{ + asm volatile("lgdt %w0"::"m" (*ptr)); +} + +static inline void store_gdt(struct desc_ptr *ptr) +{ + asm("sgdt %w0":"=m" (*ptr)); +} + static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist) { struct gate_struct s; @@ -71,6 +91,16 @@ static inline void set_system_gate_ist(int nr, void *func, unsigned ist) _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist); } +static inline void load_idt(const struct desc_ptr *ptr) +{ + asm volatile("lidt %w0"::"m" (*ptr)); +} + +static inline void store_idt(struct desc_ptr *dtr) +{ + asm("sidt %w0":"=m" (*dtr)); +} + static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, unsigned size) { diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h index d94898831ba..771af336734 100644 --- a/include/asm-x86/geode.h +++ b/include/asm-x86/geode.h @@ -38,6 +38,8 @@ extern int geode_get_dev_base(unsigned int dev); #define MSR_LBAR_ACPI 0x5140000E #define MSR_LBAR_PMS 0x5140000F +#define MSR_DIVIL_SOFT_RESET 0x51400017 + #define MSR_PIC_YSEL_LOW 0x51400020 #define MSR_PIC_YSEL_HIGH 0x51400021 #define MSR_PIC_ZSEL_LOW 0x51400022 diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index f95d79250a4..b1f3c1ea55d 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h @@ -58,6 +58,7 @@ /* hpet memory map physical address */ extern unsigned long hpet_address; extern unsigned long force_hpet_address; +extern int hpet_force_user; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern unsigned long hpet_readl(unsigned long a); diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h index e7817a3d657..42130adf9c7 100644 --- a/include/asm-x86/ide.h +++ b/include/asm-x86/ide.h @@ -62,7 +62,6 @@ static __inline__ unsigned long ide_default_io_base(int index) } } -#define IDE_ARCH_OBSOLETE_INIT #define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ #ifdef CONFIG_BLK_DEV_IDEPCI diff --git a/include/asm-x86/io_apic_64.h b/include/asm-x86/io_apic_64.h index d9f2e54324d..e2c13675ee4 100644 --- a/include/asm-x86/io_apic_64.h +++ b/include/asm-x86/io_apic_64.h @@ -133,4 +133,6 @@ void enable_NMI_through_LVT0 (void * dummy); extern spinlock_t i8259A_lock; +extern int timer_over_8254; + #endif diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h index a7c75ea408a..6d011bd6067 100644 --- a/include/asm-x86/ipi.h +++ b/include/asm-x86/ipi.h @@ -119,7 +119,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) */ local_irq_save(flags); for_each_cpu_mask(query_cpu, mask) { - __send_IPI_dest_field(x86_cpu_to_apicid[query_cpu], + __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu), vector, APIC_DEST_PHYSICAL); } local_irq_restore(flags); diff --git a/include/asm-x86/irq_32.h b/include/asm-x86/irq_32.h index 36f310632c4..aca9c96e8e6 100644 --- a/include/asm-x86/irq_32.h +++ b/include/asm-x86/irq_32.h @@ -45,4 +45,7 @@ unsigned int do_IRQ(struct pt_regs *regs); void init_IRQ(void); void __init native_init_IRQ(void); +/* Interrupt vector management */ +extern DECLARE_BITMAP(used_vectors, NR_VECTORS); + #endif /* _ASM_IRQ_H */ diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h index a02eb299134..a4944732be0 100644 --- a/include/asm-x86/msr-index.h +++ b/include/asm-x86/msr-index.h @@ -73,8 +73,32 @@ #define MSR_P6_EVNTSEL0 0x00000186 #define MSR_P6_EVNTSEL1 0x00000187 -/* K7/K8 MSRs. Not complete. See the architecture manual for a more +/* AMD64 MSRs. Not complete. See the architecture manual for a more complete list. */ + +#define MSR_AMD64_IBSFETCHCTL 0xc0011030 +#define MSR_AMD64_IBSFETCHLINAD 0xc0011031 +#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032 +#define MSR_AMD64_IBSOPCTL 0xc0011033 +#define MSR_AMD64_IBSOPRIP 0xc0011034 +#define MSR_AMD64_IBSOPDATA 0xc0011035 +#define MSR_AMD64_IBSOPDATA2 0xc0011036 +#define MSR_AMD64_IBSOPDATA3 0xc0011037 +#define MSR_AMD64_IBSDCLINAD 0xc0011038 +#define MSR_AMD64_IBSDCPHYSAD 0xc0011039 +#define MSR_AMD64_IBSCTL 0xc001103a + +/* K8 MSRs */ +#define MSR_K8_TOP_MEM1 0xc001001a +#define MSR_K8_TOP_MEM2 0xc001001d +#define MSR_K8_SYSCFG 0xc0010010 +#define MSR_K8_HWCR 0xc0010015 +#define MSR_K8_ENABLE_C1E 0xc0010055 +#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */ +#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */ +#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */ + +/* K7 MSRs */ #define MSR_K7_EVNTSEL0 0xc0010000 #define MSR_K7_PERFCTR0 0xc0010004 #define MSR_K7_EVNTSEL1 0xc0010001 @@ -83,20 +107,10 @@ #define MSR_K7_PERFCTR2 0xc0010006 #define MSR_K7_EVNTSEL3 0xc0010003 #define MSR_K7_PERFCTR3 0xc0010007 -#define MSR_K8_TOP_MEM1 0xc001001a #define MSR_K7_CLK_CTL 0xc001001b -#define MSR_K8_TOP_MEM2 0xc001001d -#define MSR_K8_SYSCFG 0xc0010010 - -#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */ -#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */ -#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */ - #define MSR_K7_HWCR 0xc0010015 -#define MSR_K8_HWCR 0xc0010015 #define MSR_K7_FID_VID_CTL 0xc0010041 #define MSR_K7_FID_VID_STATUS 0xc0010042 -#define MSR_K8_ENABLE_C1E 0xc0010055 /* K6 MSRs */ #define MSR_K6_EFER 0xc0000080 diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h index 83800e7496e..13976b08683 100644 --- a/include/asm-x86/processor_32.h +++ b/include/asm-x86/processor_32.h @@ -79,6 +79,7 @@ struct cpuinfo_x86 { unsigned char booted_cores; /* number of cores as seen by OS */ __u8 phys_proc_id; /* Physical processor id. */ __u8 cpu_core_id; /* Core id */ + __u8 cpu_index; /* index into per_cpu list */ #endif } __attribute__((__aligned__(SMP_CACHE_BYTES))); @@ -103,14 +104,19 @@ extern struct tss_struct doublefault_tss; DECLARE_PER_CPU(struct tss_struct, init_tss); #ifdef CONFIG_SMP -extern struct cpuinfo_x86 cpu_data[]; -#define current_cpu_data cpu_data[smp_processor_id()] +DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info); +#define cpu_data(cpu) per_cpu(cpu_info, cpu) +#define current_cpu_data cpu_data(smp_processor_id()) #else -#define cpu_data (&boot_cpu_data) -#define current_cpu_data boot_cpu_data +#define cpu_data(cpu) boot_cpu_data +#define current_cpu_data boot_cpu_data #endif -extern int cpu_llc_id[NR_CPUS]; +/* + * the following now lives in the per cpu area: + * extern int cpu_llc_id[NR_CPUS]; + */ +DECLARE_PER_CPU(u8, cpu_llc_id); extern char ignore_fpu_irq; void __init cpu_detect(struct cpuinfo_x86 *c); diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h index f422becbddd..e4f19970a82 100644 --- a/include/asm-x86/processor_64.h +++ b/include/asm-x86/processor_64.h @@ -74,6 +74,7 @@ struct cpuinfo_x86 { __u8 booted_cores; /* number of cores as seen by OS */ __u8 phys_proc_id; /* Physical Processor id. */ __u8 cpu_core_id; /* Core id. */ + __u8 cpu_index; /* index into per_cpu list */ #endif } ____cacheline_aligned; @@ -88,11 +89,12 @@ struct cpuinfo_x86 { #define X86_VENDOR_UNKNOWN 0xff #ifdef CONFIG_SMP -extern struct cpuinfo_x86 cpu_data[]; -#define current_cpu_data cpu_data[smp_processor_id()] +DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info); +#define cpu_data(cpu) per_cpu(cpu_info, cpu) +#define current_cpu_data cpu_data(smp_processor_id()) #else -#define cpu_data (&boot_cpu_data) -#define current_cpu_data boot_cpu_data +#define cpu_data(cpu) boot_cpu_data +#define current_cpu_data boot_cpu_data #endif extern char ignore_irq13; @@ -390,12 +392,6 @@ static inline void sync_core(void) asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory"); } -#define ARCH_HAS_PREFETCH -static inline void prefetch(void *x) -{ - asm volatile("prefetcht0 (%0)" :: "r" (x)); -} - #define ARCH_HAS_PREFETCHW 1 static inline void prefetchw(void *x) { diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h index c44a3a93b5a..dabba55f7ed 100644 --- a/include/asm-x86/proto.h +++ b/include/asm-x86/proto.h @@ -83,8 +83,6 @@ extern unsigned tsc_khz; extern int reboot_force; extern int notsc_setup(char *); -extern int timer_over_8254; - extern int gsi_irq_sharing(int gsi); extern int force_mwait; diff --git a/include/asm-x86/ptrace_32.h b/include/asm-x86/ptrace_32.h index 6002597b9e1..78d063dabe0 100644 --- a/include/asm-x86/ptrace_32.h +++ b/include/asm-x86/ptrace_32.h @@ -55,6 +55,8 @@ static inline int v8086_mode(struct pt_regs *regs) } #define instruction_pointer(regs) ((regs)->eip) +#define frame_pointer(regs) ((regs)->ebp) +#define stack_pointer(regs) ((regs)->esp) #define regs_return_value(regs) ((regs)->eax) extern unsigned long profile_pc(struct pt_regs *regs); diff --git a/include/asm-x86/ptrace_64.h b/include/asm-x86/ptrace_64.h index 7f166ccb060..7bfe61e1b70 100644 --- a/include/asm-x86/ptrace_64.h +++ b/include/asm-x86/ptrace_64.h @@ -40,6 +40,8 @@ struct pt_regs { #define user_mode(regs) (!!((regs)->cs & 3)) #define user_mode_vm(regs) user_mode(regs) #define instruction_pointer(regs) ((regs)->rip) +#define frame_pointer(regs) ((regs)->rbp) +#define stack_pointer(regs) ((regs)->rsp) #define regs_return_value(regs) ((regs)->rax) extern unsigned long profile_pc(struct pt_regs *regs); diff --git a/include/asm-x86/smp_32.h b/include/asm-x86/smp_32.h index 1f576a93368..7056d868452 100644 --- a/include/asm-x86/smp_32.h +++ b/include/asm-x86/smp_32.h @@ -39,9 +39,11 @@ extern void lock_ipi_call_lock(void); extern void unlock_ipi_call_lock(void); #define MAX_APICID 256 -extern u8 x86_cpu_to_apicid[]; +extern u8 __initdata x86_cpu_to_apicid_init[]; +extern void *x86_cpu_to_apicid_ptr; +DECLARE_PER_CPU(u8, x86_cpu_to_apicid); -#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] +#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) extern void set_cpu_sibling_map(int cpu); diff --git a/include/asm-x86/smp_64.h b/include/asm-x86/smp_64.h index d30e9b684fd..6f0e0273b64 100644 --- a/include/asm-x86/smp_64.h +++ b/include/asm-x86/smp_64.h @@ -37,6 +37,8 @@ extern void lock_ipi_call_lock(void); extern void unlock_ipi_call_lock(void); extern int smp_num_siblings; extern void smp_send_reschedule(int cpu); +extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *), + void *info, int wait); /* * cpu_sibling_map and cpu_core_map now live @@ -47,7 +49,7 @@ extern void smp_send_reschedule(int cpu); */ DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); DECLARE_PER_CPU(cpumask_t, cpu_core_map); -extern u8 cpu_llc_id[NR_CPUS]; +DECLARE_PER_CPU(u8, cpu_llc_id); #define SMP_TRAMPOLINE_BASE 0x6000 @@ -84,7 +86,9 @@ static inline int hard_smp_processor_id(void) * Some lowlevel functions might want to know about * the real APIC ID <-> CPU # mapping. */ -extern u8 x86_cpu_to_apicid[NR_CPUS]; /* physical ID */ +extern u8 __initdata x86_cpu_to_apicid_init[]; +extern void *x86_cpu_to_apicid_ptr; +DECLARE_PER_CPU(u8, x86_cpu_to_apicid); /* physical ID */ extern u8 bios_cpu_apicid[]; static inline int cpu_present_to_apicid(int mps_cpu) @@ -115,8 +119,9 @@ static __inline int logical_smp_processor_id(void) } #ifdef CONFIG_SMP -#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] +#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) #else +extern unsigned int boot_cpu_id; #define cpu_physical_id(cpu) boot_cpu_id #endif /* !CONFIG_SMP */ #endif diff --git a/include/asm-x86/system_32.h b/include/asm-x86/system_32.h index db6283eb5e4..ef8468883ba 100644 --- a/include/asm-x86/system_32.h +++ b/include/asm-x86/system_32.h @@ -315,5 +315,6 @@ extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); +void __show_registers(struct pt_regs *, int all); #endif diff --git a/include/asm-x86/topology_32.h b/include/asm-x86/topology_32.h index ae1074603c4..9040f5a6127 100644 --- a/include/asm-x86/topology_32.h +++ b/include/asm-x86/topology_32.h @@ -28,8 +28,8 @@ #define _ASM_I386_TOPOLOGY_H #ifdef CONFIG_X86_HT -#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id) -#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id) +#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) +#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) #define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu)) #endif diff --git a/include/asm-x86/topology_64.h b/include/asm-x86/topology_64.h index c0c93d74467..a718dda037e 100644 --- a/include/asm-x86/topology_64.h +++ b/include/asm-x86/topology_64.h @@ -56,8 +56,8 @@ extern int __node_distance(int, int); #endif #ifdef CONFIG_SMP -#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id) -#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id) +#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) +#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) #define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu)) #define mc_capable() (boot_cpu_data.x86_max_cores > 1) diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 499f5373e21..37c66d1254b 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -183,11 +183,14 @@ int dm_resume(struct mapped_device *md); */ uint32_t dm_get_event_nr(struct mapped_device *md); int dm_wait_event(struct mapped_device *md, int event_nr); +uint32_t dm_next_uevent_seq(struct mapped_device *md); +void dm_uevent_add(struct mapped_device *md, struct list_head *elist); /* * Info functions. */ const char *dm_device_name(struct mapped_device *md); +int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); int dm_noflush_suspending(struct dm_target *ti); diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index b9348610782..523281c5b7f 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -131,6 +131,7 @@ struct dm_ioctl { char name[DM_NAME_LEN]; /* device name */ char uuid[DM_UUID_LEN]; /* unique identifier for * the block device */ + char data[7]; /* padding or data */ }; /* @@ -285,9 +286,9 @@ typedef char ioctl_struct[308]; #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 11 +#define DM_VERSION_MINOR 12 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2006-10-12)" +#define DM_VERSION_EXTRA "-ioctl (2007-10-02)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 19db0a4ae44..2e4b8dd03cf 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -192,22 +192,20 @@ typedef unsigned char byte; /* used everywhere */ struct hwif_s; typedef int (ide_ack_intr_t)(struct hwif_s *); -#ifndef NO_DMA -#define NO_DMA 255 -#endif - /* * hwif_chipset_t is used to keep track of the specific hardware * chipset used by each IDE interface, if known. */ -typedef enum { ide_unknown, ide_generic, ide_pci, +enum { ide_unknown, ide_generic, ide_pci, ide_cmd640, ide_dtc2278, ide_ali14xx, ide_qd65xx, ide_umc8672, ide_ht6560b, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, ide_pmac, ide_etrax100, ide_acorn, ide_au1xxx, ide_forced -} hwif_chipset_t; +}; + +typedef u8 hwif_chipset_t; /* * Structure to hold all information about the location of this port @@ -215,22 +213,16 @@ typedef enum { ide_unknown, ide_generic, ide_pci, typedef struct hw_regs_s { unsigned long io_ports[IDE_NR_PORTS]; /* task file registers */ int irq; /* our irq number */ - int dma; /* our dma entry */ ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ hwif_chipset_t chipset; struct device *dev; } hw_regs_t; -/* - * Register new hardware with ide - */ -int ide_register_hw(hw_regs_t *, int, struct hwif_s **); -int ide_register_hw_with_fixup(hw_regs_t *, int, struct hwif_s **, - void (*)(struct hwif_s *)); +struct hwif_s * ide_find_port(unsigned long); + +int ide_register_hw(hw_regs_t *, void (*)(struct hwif_s *), int, + struct hwif_s **); -/* - * Set up hw_regs_t structure before calling ide_register_hw (optional) - */ void ide_setup_ports( hw_regs_t *hw, unsigned long base, int *offsets, @@ -268,11 +260,7 @@ static inline void ide_std_init_ports(hw_regs_t *hw, # define ide_init_default_irq(base) (0) #endif -/* - * ide_init_hwif_ports() is OBSOLETE and will be removed in 2.7 series. - * New ports shouldn't define IDE_ARCH_OBSOLETE_INIT in <asm/ide.h>. - */ -#ifdef IDE_ARCH_OBSOLETE_INIT +#ifdef CONFIG_IDE_ARCH_OBSOLETE_INIT static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long io_addr, unsigned long ctl_addr, @@ -302,7 +290,7 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw, if (io_addr || ctl_addr) printk(KERN_WARNING "%s: must not be called\n", __FUNCTION__); } -#endif /* IDE_ARCH_OBSOLETE_INIT */ +#endif /* CONFIG_IDE_ARCH_OBSOLETE_INIT */ /* Currently only m68k, apus and m8xx need it */ #ifndef IDE_ARCH_ACK_INTR @@ -363,7 +351,6 @@ typedef union { * ATA DATA Register Special. * ATA NSECTOR Count Register(). * ATAPI Byte Count Register. - * Channel index ordering pairs. */ typedef union { unsigned all :16; @@ -378,7 +365,7 @@ typedef union { #error "Please fix <asm/byteorder.h>" #endif } b; -} ata_nsector_t, ata_data_t, atapi_bcount_t, ata_index_t; +} ata_nsector_t, ata_data_t, atapi_bcount_t; /* * ATA-IDE Select Register, aka Device-Head @@ -657,7 +644,7 @@ typedef struct ide_drive_s { ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx)) #define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1) -struct ide_pci_device_s; +struct ide_port_info; typedef struct hwif_s { struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ @@ -672,7 +659,6 @@ typedef struct hwif_s { unsigned long sata_scr[SATA_NR_PORTS]; unsigned long sata_misc[SATA_NR_PORTS]; - hw_regs_t hw; /* Hardware info */ ide_drive_t drives[MAX_DRIVES]; /* drive info */ u8 major; /* our major number */ @@ -694,7 +680,9 @@ typedef struct hwif_s { hwif_chipset_t chipset; /* sub-module for tuning.. */ struct pci_dev *pci_dev; /* for pci chipsets */ - struct ide_pci_device_s *cds; /* chipset device struct */ + const struct ide_port_info *cds; /* chipset device struct */ + + ide_ack_intr_t *ack_intr; void (*rw_disk)(ide_drive_t *, struct request *); @@ -725,6 +713,8 @@ typedef struct hwif_s { u8 (*mdma_filter)(ide_drive_t *); u8 (*udma_filter)(ide_drive_t *); + void (*fixup)(struct hwif_s *); + void (*ata_input_data)(ide_drive_t *, void *, u32); void (*ata_output_data)(ide_drive_t *, void *, u32); @@ -841,8 +831,6 @@ typedef struct hwgroup_s { /* for pci chipsets */ struct pci_dev *pci_dev; - /* chipset device struct */ - struct ide_pci_device_s *cds; /* current request */ struct request *rq; @@ -1030,36 +1018,16 @@ extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors); -/* - * This is used on exit from the driver to designate the next irq handler - * and also to start the safety timer. - */ extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry); -/* - * This is used on exit from the driver to designate the next irq handler - * and start the safety time safely and atomically from the IRQ handler - * with respect to the command issue (which it also does) - */ extern void ide_execute_command(ide_drive_t *, task_ioreg_t cmd, ide_handler_t *, unsigned int, ide_expiry_t *); ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8); -/* - * ide_error() takes action based on the error returned by the controller. - * The caller should return immediately after invoking this. - * - * (drive, msg, status) - */ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); ide_startstop_t __ide_abort(ide_drive_t *, struct request *); -/* - * Abort a running command on the controller triggering the abort - * from a host side, non error situation - * (drive, msg) - */ extern ide_startstop_t ide_abort(ide_drive_t *, const char *); extern void ide_fix_driveid(struct hd_driveid *); @@ -1075,15 +1043,8 @@ extern void ide_fixstring(u8 *, const int, const int); int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); -/* - * Start a reset operation for an IDE interface. - * The caller should return immediately after invoking this. - */ extern ide_startstop_t ide_do_reset (ide_drive_t *); -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ extern void ide_init_drive_cmd (struct request *rq); /* @@ -1098,13 +1059,6 @@ typedef enum { extern int ide_do_drive_cmd(ide_drive_t *, struct request *, ide_action_t); -/* - * Clean up after success/failure of an explicit drive cmd. - * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD). - * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASK_MASK). - * - * (ide_drive_t *drive, u8 stat, u8 err) - */ extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); /* @@ -1177,10 +1131,6 @@ extern int taskfile_lib_get_identify(ide_drive_t *drive, u8 *); extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout); -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern int ide_spin_wait_hwgroup(ide_drive_t *); @@ -1200,8 +1150,8 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o #define ide_pci_register_driver(d) pci_register_driver(d) #endif -void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); -extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); +void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *); +void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); extern void default_hwif_iops(ide_hwif_t *); extern void default_hwif_mmiops(ide_hwif_t *); @@ -1261,6 +1211,14 @@ enum { IDE_HFLAG_SERIALIZE = (1 << 20), /* use legacy IRQs */ IDE_HFLAG_LEGACY_IRQS = (1 << 21), + /* force use of legacy IRQs */ + IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22), + /* limit LBA48 requests to 256 sectors */ + IDE_HFLAG_RQSIZE_256 = (1 << 23), + /* use 32-bit I/O ops */ + IDE_HFLAG_IO_32BIT = (1 << 24), + /* unmask IRQs */ + IDE_HFLAG_UNMASK_IRQS = (1 << 25), }; #ifdef CONFIG_BLK_DEV_OFFBOARD @@ -1269,7 +1227,7 @@ enum { # define IDE_HFLAG_OFF_BOARD 0 #endif -typedef struct ide_pci_device_s { +struct ide_port_info { char *name; unsigned int (*init_chipset)(struct pci_dev *, const char *); void (*init_iops)(ide_hwif_t *); @@ -1277,17 +1235,17 @@ typedef struct ide_pci_device_s { void (*init_dma)(ide_hwif_t *, unsigned long); void (*fixup)(ide_hwif_t *); ide_pci_enablebit_t enablebits[2]; + hwif_chipset_t chipset; unsigned int extra; - struct ide_pci_device_s *next; u32 host_flags; u8 pio_mask; u8 swdma_mask; u8 mwdma_mask; u8 udma_mask; -} ide_pci_device_t; +}; -extern int ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); -extern int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); +int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *); +int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *); void ide_map_sg(ide_drive_t *, struct request *); void ide_init_sg_cmd(ide_drive_t *, struct request *); @@ -1370,8 +1328,7 @@ void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_hwif_t *); -int probe_hwif_init_with_fixup(ide_hwif_t *, void (*)(ide_hwif_t *)); -extern int probe_hwif_init(ide_hwif_t *); +int ide_device_add(u8 idx[4]); static inline void *ide_get_hwifdata (ide_hwif_t * hwif) { diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index c5164c257f7..e82a6ebc725 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -160,6 +160,12 @@ struct nfs_inode { /* Open contexts for shared mmap writes */ struct list_head open_files; + /* Number of in-flight sillydelete RPC calls */ + atomic_t silly_count; + /* List of deferred sillydelete requests */ + struct hlist_head silly_list; + wait_queue_head_t waitqueue; + #ifdef CONFIG_NFS_V4 struct nfs4_cached_acl *nfs4_acl; /* NFSv4 state */ @@ -394,6 +400,8 @@ extern void nfs_release_automount_timer(void); */ extern int nfs_async_unlink(struct inode *dir, struct dentry *dentry); extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); +extern void nfs_block_sillyrename(struct dentry *dentry); +extern void nfs_unblock_sillyrename(struct dentry *dentry); /* * linux/fs/nfs/write.c diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h index 1adfe668d03..af7c36a5a52 100644 --- a/include/linux/prefetch.h +++ b/include/linux/prefetch.h @@ -34,17 +34,12 @@ */ -/* - * These cannot be do{}while(0) macros. See the mental gymnastics in - * the loop macro. - */ - #ifndef ARCH_HAS_PREFETCH -static inline void prefetch(const void *x) {;} +#define prefetch(x) __builtin_prefetch(x) #endif #ifndef ARCH_HAS_PREFETCHW -static inline void prefetchw(const void *x) {;} +#define prefetchw(x) __builtin_prefetch(x,1) #endif #ifndef ARCH_HAS_SPINLOCK_PREFETCH diff --git a/kernel/Makefile b/kernel/Makefile index 05c3e6df859..79f017e09fb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,8 +9,9 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \ - utsname.o sysctl_check.o notifier.o + utsname.o notifier.o +obj-$(CONFIG_SYSCTL) += sysctl_check.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += time/ obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index de7bb284c61..b96ea8d6a5e 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -56,6 +56,17 @@ endef # gcc support functions # See documentation in Documentation/kbuild/makefiles.txt +# cc-cross-prefix +# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-) +# Return first prefix where a prefix$(CC) is found in PATH. +# If no $(CC) found in PATH with listed prefixes return nothing +cc-cross-prefix = \ + $(word 1, $(foreach c,$(1), \ + $(shell set -e; \ + if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \ + echo $(c); \ + fi))) + # output directory for tests below TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index e5c6ac7bde9..0e4bd5459df 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c @@ -66,12 +66,15 @@ FILELINE * entity_system; #define FUNCTION "-function" #define NOFUNCTION "-nofunction" +char *srctree; + void usage (void) { fprintf(stderr, "Usage: docproc {doc|depend} file\n"); fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); fprintf(stderr, "doc: frontend when generating kernel documentation\n"); fprintf(stderr, "depend: generate list of files referenced within file\n"); + fprintf(stderr, "Environment variable SRCTREE: absolute path to kernel source tree.\n"); } /* @@ -90,7 +93,7 @@ void exec_kernel_doc(char **svec) exit(1); case 0: memset(real_filename, 0, sizeof(real_filename)); - strncat(real_filename, getenv("SRCTREE"), PATH_MAX); + strncat(real_filename, srctree, PATH_MAX); strncat(real_filename, KERNELDOCPATH KERNELDOC, PATH_MAX - strlen(real_filename)); execvp(real_filename, svec); @@ -171,7 +174,7 @@ void find_export_symbols(char * filename) if (filename_exist(filename) == NULL) { char real_filename[PATH_MAX + 1]; memset(real_filename, 0, sizeof(real_filename)); - strncat(real_filename, getenv("SRCTREE"), PATH_MAX); + strncat(real_filename, srctree, PATH_MAX); strncat(real_filename, filename, PATH_MAX - strlen(real_filename)); sym = add_new_file(filename); @@ -338,6 +341,10 @@ void parse_file(FILE *infile) int main(int argc, char *argv[]) { FILE * infile; + + srctree = getenv("SRCTREE"); + if (!srctree) + srctree = getcwd(NULL, 0); if (argc != 3) { usage(); exit(1); diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index bb08069b04a..83c5e76414c 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -84,7 +84,7 @@ help: # lxdialog stuff check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh -# Use reursively expanded variables so we do not call gcc unless +# Use recursively expanded variables so we do not call gcc unless # we really need to do so. (Do not call gcc as part of make mrproper) HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2ef9a193fca..93ac52adb49 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -268,6 +268,9 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, "was in %s%s\n", mod->name, name, s->module->name, is_vmlinux(s->module->name) ?"":".ko"); + } else { + /* In case Modules.symvers was out of date */ + s->module = mod; } } s->preloaded = 0; diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 6edb29f2b4a..0f657b5f3bc 100644 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -83,6 +83,7 @@ Maintainer: $name Standards-Version: 3.6.1 Package: $packagename +Provides: kernel-image-$version, linux-image-$version Architecture: any Description: User Mode Linux kernel, version $version User-mode Linux is a port of the Linux kernel to its own system call @@ -104,6 +105,7 @@ Maintainer: $name Standards-Version: 3.6.1 Package: $packagename +Provides: kernel-image-$version, linux-image-$version Architecture: any Description: Linux kernel, version $version This package contains the Linux kernel, modules and corresponding other |