Commit c259bd94 authored by Richard Russon's avatar Richard Russon

Merge flatcap.org:/home/flatcap/backup/bk/ntfs-2.6

into flatcap.org:/home/flatcap/backup/bk/ntfs-2.6-devel
parents ef31474f f2ddba8c
......@@ -9,32 +9,33 @@ The architecture specific code typically provides gettimeofday and
settimeofday under Linux. The time interpolator provides both if an arch
defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick
operations and call the necessary functions to advance the clock.
With the time interpolator a standardized interface exists for time
interpolation between ticks which also allows the determination
of time in a hardware independent way. The provided logic is highly scalable
interpolation between ticks. The provided logic is highly scalable
and has been tested in SMP situations of up to 512 CPUs.
If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code
(or the device drivers - like HPET) must register time interpolators.
(or the device drivers - like HPET) may register time interpolators.
These are typically defined in the following way:
static struct time_interpolator my_interpolator;
static struct time_interpolator my_interpolator {
.frequency = MY_FREQUENCY,
.source = TIME_SOURCE_MMIO32,
.shift = 8, /* scaling for higher accuracy */
.drift = -1, /* Unknown drift */
.jitter = 0 /* time source is stable */
};
void time_init(void)
{
....
/* Initialization of the timer *.
my_interpolator.frequency = MY_FREQUENCY;
my_interpolator.source = TIME_SOURCE_MMIO32;
my_interpolator.address = &my_timer;
my_interpolator.shift = 32; /* increase accuracy of scaling */
my_interpolator.drift = -1; /* Unknown */
my_interpolator.jitter = 0; /* A stable time source */
register_time_interpolator(&my_interpolator);
....
}
For more details see include/linux/timex.h.
For more details see include/linux/timex.h and kernel/timer.c.
Christoph Lameter <christoph@lameter.com>, September 8, 2004
Christoph Lameter <christoph@lameter.com>, October 31, 2004
......@@ -217,6 +217,7 @@ void foo(void)
DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle));
DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter));
DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter));
DEFINE(IA64_TIME_INTERPOLATOR_MASK_OFFSET, offsetof (struct time_interpolator, mask));
DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
......
......@@ -19,10 +19,11 @@ void __init cyclone_setup(void)
struct time_interpolator cyclone_interpolator = {
.source = TIME_SOURCE_MMIO32,
.shift = 32,
.source = TIME_SOURCE_MMIO64,
.shift = 16,
.frequency = CYCLONE_TIMER_FREQ,
.drift = -100,
.mask = (1LL << 40) - 1
};
int __init init_cyclone_clock(void)
......
......@@ -177,7 +177,7 @@ ENTRY(fsys_gettimeofday)
// r11 = preserved: saved ar.pfs
// r12 = preserved: memory stack
// r13 = preserved: thread pointer
// r14 = debug pointer / usable
// r14 = address of mask / mask
// r15 = preserved: system call number
// r16 = preserved: current task pointer
// r17 = wall to monotonic use
......@@ -226,7 +226,6 @@ ENTRY(fsys_gettimeofday)
add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20
extr r3 = r21,32,32 // time_interpolator->nsec_per_cyc
extr r8 = r21,0,16 // time_interpolator->source
nop.i 123
cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled
(p6) br.cond.spnt.many fsys_fallback_syscall
;;
......@@ -257,17 +256,20 @@ ENTRY(fsys_gettimeofday)
add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20
(p15) ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET
ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET
nop.i 123
add r14 = IA64_TIME_INTERPOLATOR_MASK_OFFSET, r20
;;
ld8 r18 = [r24] // time_interpolator->offset
ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET // xtime.tv_nsec
(p13) sub r3 = r25,r2 // Diff needed before comparison (thanks davidm)
;;
ld8 r14 = [r14] // time_interpolator->mask
(p13) cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared
sub r10 = r2,r26 // current_counter - last_counter
;;
(p6) sub r10 = r25,r26 // time we got was less than last_cycle
(p7) mov ar.ccv = r25 // more than last_cycle. Prep for cmpxchg
;;
and r10 = r10,r14 // Apply mask
;;
setf.sig f8 = r10
nop.i 123
......
......@@ -45,7 +45,11 @@ EXPORT_SYMBOL(last_cli_ip);
#endif
static struct time_interpolator itc_interpolator;
static struct time_interpolator itc_interpolator = {
.shift = 16,
.mask = 0xffffffffffffffffLL,
.source = TIME_SOURCE_CPU
};
static irqreturn_t
timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
......@@ -206,9 +210,7 @@ ia64_init_itm (void)
if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
itc_interpolator.frequency = local_cpu_data->itc_freq;
itc_interpolator.shift = 16;
itc_interpolator.drift = itc_drift;
itc_interpolator.source = TIME_SOURCE_CPU;
#ifdef CONFIG_SMP
/* On IA64 in an SMP configuration ITCs are never accurately synchronized.
* Jitter compensation requires a cmpxchg which may limit
......@@ -222,7 +224,6 @@ ia64_init_itm (void)
*/
if (!nojitter) itc_interpolator.jitter = 1;
#endif
itc_interpolator.addr = NULL;
register_time_interpolator(&itc_interpolator);
}
......
......@@ -22,14 +22,16 @@
extern unsigned long sn_rtc_cycles_per_second;
static struct time_interpolator sn2_interpolator;
static struct time_interpolator sn2_interpolator = {
.drift = -1,
.shift = 10,
.mask = (1LL << 55) - 1,
.source = TIME_SOURCE_MMIO64,
.addr = RTC_COUNTER_ADDR
};
void __init sn_timer_init(void)
{
sn2_interpolator.frequency = sn_rtc_cycles_per_second;
sn2_interpolator.drift = -1; /* unknown */
sn2_interpolator.shift = 10; /* RTC is 54 bits maximum shift is 10 */
sn2_interpolator.addr = RTC_COUNTER_ADDR;
sn2_interpolator.source = TIME_SOURCE_MMIO64;
register_time_interpolator(&sn2_interpolator);
}
......@@ -52,7 +52,6 @@ cflags-$(CONFIG_PA7300LC) += -march=1.1 -mschedule=7300
cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000
head-y := arch/parisc/kernel/head.o
head-$(CONFIG_PARISC64) := arch/parisc/kernel/head64.o
CFLAGS += $(cflags-y)
......@@ -86,6 +85,12 @@ oldpalo: vmlinux
# Shorthands for known targets not supported by parisc, use palo as default
Image zImage bzImage: palo
kernel_install: vmlinux
sh $(src)/arch/parisc/install.sh \
$(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
install: kernel_install modules_install
prepare: include/asm-parisc/offsets.h
arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \
......@@ -100,4 +105,8 @@ MRPROPER_FILES += palo.conf
define archhelp
@echo '* vmlinux - Uncompressed kernel image (./vmlinux)'
@echo ' palo - Bootable image (./lifimage)'
@echo ' install - Install kernel using'
@echo ' (your) ~/bin/installkernel or'
@echo ' (distribution) /sbin/installkernel or'
@echo ' copy to $$(INSTALL_PATH)'
endef
......@@ -11,7 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
#
CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
# CONFIG_STANDALONE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
......@@ -31,6 +30,7 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
......@@ -48,6 +48,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
#
# Processor type and features
......@@ -61,9 +62,12 @@ CONFIG_PA20=y
CONFIG_PREFETCH=y
CONFIG_PARISC64=y
CONFIG_64BIT=y
# CONFIG_SMP is not set
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
# CONFIG_DISCONTIGMEM is not set
# CONFIG_PREEMPT is not set
CONFIG_COMPAT=y
CONFIG_NR_CPUS=4
#
# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
......@@ -86,6 +90,7 @@ CONFIG_PCMCIA=m
CONFIG_PCMCIA_DEBUG=y
CONFIG_YENTA=m
CONFIG_CARDBUS=y
# CONFIG_PD6729 is not set
# CONFIG_I82092 is not set
# CONFIG_TCIC is not set
......@@ -107,6 +112,8 @@ CONFIG_BINFMT_ELF=y
#
# Generic Driver Options
#
# CONFIG_STANDALONE is not set
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
CONFIG_DEBUG_DRIVER=y
......@@ -135,7 +142,7 @@ CONFIG_BLK_DEV_UMEM=m
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_CARMEL is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=6144
CONFIG_BLK_DEV_INITRD=y
......@@ -165,7 +172,6 @@ CONFIG_CHR_DEV_SG=y
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_REPORT_LUNS=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
......@@ -179,6 +185,7 @@ CONFIG_SCSI_FC_ATTRS=m
# SCSI low-level drivers
#
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
......@@ -353,6 +360,8 @@ CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_IP_NF_COMPAT_IPFWADM is not set
CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_RAW=m
# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
# CONFIG_IP_NF_MATCH_REALM is not set
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
......@@ -379,6 +388,7 @@ CONFIG_LLC2=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
......@@ -452,6 +462,7 @@ CONFIG_EPIC100=m
# CONFIG_SUNDANCE is not set
CONFIG_VIA_RHINE=m
CONFIG_VIA_RHINE_MMIO=y
# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
......@@ -501,7 +512,6 @@ CONFIG_PCMCIA_NETWAVE=m
#
# Wireless 802.11b ISA/PCI cards support
#
# CONFIG_AIRO is not set
CONFIG_HERMES=m
CONFIG_PLX_HERMES=m
CONFIG_TMD_HERMES=m
......@@ -644,7 +654,6 @@ CONFIG_GEN_RTC_X=y
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_DRM is not set
......@@ -660,6 +669,11 @@ CONFIG_MAX_RAW_DEVS=256
#
# CONFIG_I2C is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
#
# Misc devices
#
......@@ -734,6 +748,7 @@ CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
......@@ -741,6 +756,8 @@ CONFIG_UDF_FS=m
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
......@@ -795,6 +812,9 @@ CONFIG_SMB_FS=m
CONFIG_SMB_NLS_DEFAULT=y
CONFIG_SMB_NLS_REMOTE="cp437"
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
# CONFIG_CIFS_XATTR is not set
# CONFIG_CIFS_POSIX is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
......@@ -833,6 +853,7 @@ CONFIG_NLS_CODEPAGE_865=m
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
......@@ -860,6 +881,8 @@ CONFIG_OPROFILE=m
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_RWLOCK is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_DEBUG_INFO is not set
......@@ -886,7 +909,9 @@ CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_CRC32C=m
......@@ -895,6 +920,7 @@ CONFIG_CRYPTO_TEST=m
#
# Library routines
#
CONFIG_CRC_CCITT=m
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
......
#!/bin/sh
#
# arch/parisc/install.sh, derived from arch/i386/boot/install.sh
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1995 by Linus Torvalds
#
# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
#
# "make install" script for i386 architecture
#
# Arguments:
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
#
# User may have a custom install script
if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
# Default install
if [ -f $4/vmlinux ]; then
mv $4/vmlinux $4/vmlinux.old
fi
if [ -f $4/System.map ]; then
mv $4/System.map $4/System.old
fi
cat $2 > $4/vmlinux
cp $3 $4/System.map
......@@ -2,9 +2,7 @@
# Makefile for arch/parisc/kernel
#
head-y := head.o
head-$(CONFIG_PARISC64) := head64.o
extra-y := init_task.o $(head-y) vmlinux.lds
extra-y := init_task.o head.o vmlinux.lds
AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
......
......@@ -33,6 +33,17 @@ int dcache_stride;
int icache_stride;
EXPORT_SYMBOL(dcache_stride);
#if defined(CONFIG_SMP)
/* On some machines (e.g. ones with the Merced bus), there can be
* only a single PxTLB broadcast at a time; this must be guaranteed
* by software. We put a spinlock around all TLB flushes to
* ensure this.
*/
spinlock_t pa_tlb_lock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(pa_tlb_lock);
#endif
struct pdc_cache_info cache_info;
#ifndef CONFIG_PA20
static struct pdc_btlb_info btlb_info;
......@@ -306,3 +317,13 @@ EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
EXPORT_SYMBOL(flush_kernel_dcache_page);
EXPORT_SYMBOL(flush_data_cache_local);
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
void clear_user_page_asm(void *page, unsigned long vaddr)
{
/* This function is implemented in assembly in pacache.S */
extern void __clear_user_page_asm(void *page, unsigned long vaddr);
purge_tlb_start();
__clear_user_page_asm(page, vaddr);
purge_tlb_end();
}
......@@ -783,7 +783,7 @@ __kernel_thread:
#ifdef __LP64__
ldo -16(%r30),%r29 /* Reference param save area */
#endif
bl do_fork, %r2
BL do_fork, %r2
copy %r1, %r24 /* pt_regs */
/* Parent Returns here */
......@@ -836,7 +836,7 @@ __execve:
#ifdef __LP64__
ldo -16(%r30),%r29 /* Reference param save area */
#endif
bl sys_execve, %r2
BL sys_execve, %r2
copy %r16, %r26
cmpib,=,n 0,%r28,intr_return /* forward */
......@@ -1076,7 +1076,7 @@ intr_do_signal:
ldo -16(%r30),%r29 /* Reference param save area */
#endif
bl do_signal,%r2
BL do_signal,%r2
copy %r0, %r26 /* sigset_t *oldset = NULL */
b intr_restore
......@@ -1819,7 +1819,7 @@ sys_fork_wrapper:
LDREG PT_GR30(%r1),%r25
copy %r1,%r24
bl sys_clone,%r2
BL sys_clone,%r2
ldi SIGCHLD,%r26
LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
......@@ -1839,7 +1839,7 @@ wrapper_exit:
/* Set the return value for the child */
child_return:
bl schedule_tail, %r2
BL schedule_tail, %r2
nop
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
......@@ -1864,7 +1864,7 @@ sys_clone_wrapper:
STREG %r2,PT_GR19(%r1) /* save for child */
STREG %r30,PT_GR21(%r1)
bl sys_clone,%r2
BL sys_clone,%r2
copy %r1,%r24
b wrapper_exit
......@@ -1887,7 +1887,7 @@ sys_vfork_wrapper:
STREG %r2,PT_GR19(%r1) /* save for child */
STREG %r30,PT_GR21(%r1)
bl sys_vfork,%r2
BL sys_vfork,%r2
copy %r1,%r26
b wrapper_exit
......@@ -1950,10 +1950,10 @@ sys_rt_sigreturn_wrapper:
STREG %r2, -RP_OFFSET(%r30)
#ifdef __LP64__
ldo FRAME_SIZE(%r30), %r30
bl sys_rt_sigreturn,%r2
BL sys_rt_sigreturn,%r2
ldo -16(%r30),%r29 /* Reference param save area */
#else
bl sys_rt_sigreturn,%r2
BL sys_rt_sigreturn,%r2
ldo FRAME_SIZE(%r30), %r30
#endif
......@@ -1981,7 +1981,7 @@ sys_sigaltstack_wrapper:
STREG %r2, -RP_OFFSET(%r30)
#ifdef __LP64__
ldo FRAME_SIZE(%r30), %r30
bl do_sigaltstack,%r2
b,l do_sigaltstack,%r2
ldo -16(%r30),%r29 /* Reference param save area */
#else
bl do_sigaltstack,%r2
......@@ -2001,7 +2001,7 @@ sys32_sigaltstack_wrapper:
LDREG TASK_PT_GR30(%r24),%r24
STREG %r2, -RP_OFFSET(%r30)
ldo FRAME_SIZE(%r30), %r30
bl do_sigaltstack32,%r2
b,l do_sigaltstack32,%r2
ldo -16(%r30),%r29 /* Reference param save area */
ldo -FRAME_SIZE(%r30), %r30
......@@ -2019,7 +2019,7 @@ sys_rt_sigsuspend_wrapper:
STREG %r2, -RP_OFFSET(%r30)
#ifdef __LP64__
ldo FRAME_SIZE(%r30), %r30
bl sys_rt_sigsuspend,%r2
b,l sys_rt_sigsuspend,%r2
ldo -16(%r30),%r29 /* Reference param save area */
#else
bl sys_rt_sigsuspend,%r2
......@@ -2251,7 +2251,7 @@ syscall_do_softirq:
.import schedule,code
syscall_do_resched:
bl schedule,%r2
BL schedule,%r2
#ifdef __LP64__
ldo -16(%r30),%r29 /* Reference param save area */
#else
......@@ -2275,7 +2275,7 @@ syscall_do_signal:
#ifdef __LP64__
ldo -16(%r30),%r29 /* Reference param save area */
#endif
bl do_signal,%r2
BL do_signal,%r2
copy %r0, %r26 /* sigset_t *oldset = NULL */
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
......
This diff is collapsed.
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1999 by Helge Deller
* Copyright 1999 SuSE GmbH (Philipp Rumpf)
* Copyright 1999 Philipp Rumpf (prumpf@tux.org)
* Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
* Copyright (C) 2001 Grant Grundler (Hewlett Packard)
*
* Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
*/
#include <linux/autoconf.h> /* for CONFIG_SMP */
#include <asm/offsets.h>
#include <asm/psw.h>
#include <asm/assembly.h>
#include <asm/pgtable.h>
#include <asm/pdc.h> /* for PDC_PSW defines */
.level 2.0w
.data
.export boot_args
boot_args:
.word 0 /* arg0 */
.word 0 /* arg1 */
.word 0 /* arg2 */
.word 0 /* arg3 */
.text
.align 4
.export stext
.export _stext,data /* Kernel want it this way! */
_stext:
stext:
.proc
.callinfo
/* Make sure sr4-sr7 are set to zero for the kernel address space */
mtsp %r0,%sr4
mtsp %r0,%sr5
mtsp %r0,%sr6
mtsp %r0,%sr7
/* Clear BSS (shouldn't the boot loader do this?) */
.import __bss_start,data
.import __bss_stop,data
ldil L%PA(__bss_start),%r3
ldo R%PA(__bss_start)(%r3),%r3
ldil L%PA(__bss_stop),%r4
ldo R%PA(__bss_stop)(%r4),%r4
$bss_loop:
cmpb,<<,n %r3,%r4,$bss_loop
stb,ma %r0,1(%r3)
/* Save away the arguments the boot loader passed in (32 bit args) */
ldil L%PA(boot_args),%r1
ldo R%PA(boot_args)(%r1),%r1
stw,ma %arg0,4(%r1)
stw,ma %arg1,4(%r1)
stw,ma %arg2,4(%r1)
stw,ma %arg3,4(%r1)
/* Initialize startup VM. Just map first 8 MB of memory */
ldil L%PA(pg0),%r1
ldo R%PA(pg0)(%r1),%r1
ldil L%PA(pmd0),%r5
ldo R%PA(pmd0)(%r5),%r5
shrd %r5,PxD_VALUE_SHIFT,%r3
ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
ldil L%PA(swapper_pg_dir),%r4
ldo R%PA(swapper_pg_dir)(%r4),%r4
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
shrd %r1,PxD_VALUE_SHIFT,%r3
ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r5
ldi ASM_PT_INITIAL,%r1
1:
stw %r3,0(%r5)
ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
addib,> -1,%r1,1b
ldo ASM_PMD_ENTRY_SIZE(%r5),%r5
ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
ldil L%PA(pg0),%r1
ldo R%PA(pg0)(%r1),%r1
$pgt_fill_loop:
std,ma %r3,ASM_PTE_ENTRY_SIZE(%r1)
ldo ASM_PAGE_SIZE(%r3),%r3
bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
nop
/* And the RFI Target address too */
load32 start_kernel, %r11
/* And the stack pointer too */
load32 PA(init_thread_union+THREAD_SZ_ALGN),%sp
/* And the initial task pointer */
load32 init_thread_union,%r6
mtctl %r6,%cr30
/* And the interrupt stack */
load32 interrupt_stack,%r6
mtctl %r6,%cr31
/* Act like PDC just called us - that's how slave CPUs enter */
#define MEM_PDC_LO 0x388
#define MEM_PDC_HI 0x35C
ldw MEM_PDC_LO(%r0),%r3
ldw MEM_PDC_HI(%r0),%r6
depd %r6, 31, 32, %r3 /* move to upper word */
#ifdef CONFIG_SMP
/* Set the smp rendevous address into page zero.
** It would be safer to do this in init_smp_config() but
** it's just way easier to deal with here because
** of 64-bit function ptrs and the address is local to this file.
*/
ldil L%PA(smp_slave_stext),%r10
ldo R%PA(smp_slave_stext)(%r10),%r10
stw %r10,0x10(%r0) /* MEM_RENDEZ */
stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */
/* FALLTHROUGH */
.procend
/*
** Code Common to both Monarch and Slave processors.
** Entry:
** %r3 PDCE_PROC address
** %r11 RFI target address.
**
** Caller must init: SR4-7, %sp, %r10, %cr24/25,
*/
common_stext:
.proc
.callinfo
#else /* CONFIG_SMP */
/* Clear PDC's CPU handoff address - we won't use it */
stw %r0,0x10(%r0) /* MEM_RENDEZ */
stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */
#endif /* CONFIG_SMP */
/* Save the rfi target address */
ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
tophys_r1 %r10
std %r11, TASK_PT_GR11(%r10)
/* Switch to wide mode; Superdome doesn't support narrow PDC
** calls.
*/
1: mfia %rp /* clear upper part of pcoq */
ldo 2f-1b(%rp),%rp
depdi 0,31,32,%rp
bv (%rp)
ssm PSW_SM_W,%r0
2:
/* Set Wide mode as the "Default" (eg for traps)
** First trap occurs *right* after (or part of) rfi for slave CPUs.
** Someday, palo might not do this for the Monarch either.
*/
ldo PDC_PSW(%r0),%arg0 /* 21 */
ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */
load32 PA(stext_pdc_ret), %rp
bv (%r3)
copy %r0,%arg3
stext_pdc_ret:
/* restore rfi target address*/
ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10
tophys_r1 %r10
ldd TASK_PT_GR11(%r10), %r11
/* PARANOID: clear user scratch/user space SR's */
mtsp %r0,%sr0
mtsp %r0,%sr1
mtsp %r0,%sr2
mtsp %r0,%sr3
/* Initialize Protection Registers */
mtctl %r0,%cr8
mtctl %r0,%cr9
mtctl %r0,%cr12
mtctl %r0,%cr13
/* Prepare to RFI! Man all the cannons! */
tovirt_r1 %sp
/* Initialize the global data pointer */
load32 __gp,%dp
/* Set up our interrupt table. HPMCs might not work after this! */
ldil L%PA(fault_vector_20),%r10
ldo R%PA(fault_vector_20)(%r10),%r10
mtctl %r10,%cr14
b aligned_rfi
nop
/* the magic spell */
.align 256
aligned_rfi:
ssm 0,0
nop /* 1 */
nop /* 2 */
nop /* 3 */
nop /* 4 */
nop /* 5 */
nop /* 6 */
nop /* 7 */
nop /* 8 */
/* turn off troublesome PSW bits */
rsm PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R, %r0
/* kernel PSW:
* - no interruptions except HPMC and TOC (which are handled by PDC)
* - Q bit set (IODC / PDC interruptions)
* - big-endian
* - virtually mapped
*/
load32 KERNEL_PSW,%r10
mtctl %r10,%ipsw
/* Set the space pointers for the post-RFI world
** Clear the two-level IIA Space Queue, effectively setting
** Kernel space.
*/
mtctl %r0,%cr17 /* Clear IIASQ tail */
mtctl %r0,%cr17 /* Clear IIASQ head */
/* Load RFI target into PC queue */
mtctl %r11,%cr18 /* IIAOQ head */
ldo 4(%r11),%r11
mtctl %r11,%cr18 /* IIAOQ tail */
/* Jump to hyperspace */
rfi
nop
.procend
#ifdef CONFIG_SMP
.import smp_init_current_idle_task,data
.import smp_callin,code
/***************************************************************************
*
* smp_slave_stext is executed by all non-monarch Processors when the Monarch
* pokes the slave CPUs in smp.c:smp_boot_cpus().
*
* Once here, registers values are initialized in order to branch to virtual
* mode. Once all available/eligible CPUs are in virtual mode, all are
* released and start out by executing their own idle task.
*****************************************************************************/
smp_slave_stext:
.proc
.callinfo
/*
** Initialize Space registers
*/
mtsp %r0,%sr4
mtsp %r0,%sr5
mtsp %r0,%sr6
mtsp %r0,%sr7
/* Initialize the SP - monarch sets up smp_init_current_idle_task */
load32 PA(smp_init_current_idle_task),%sp
ldd 0(%sp),%sp /* load task address */
tophys_r1 %sp
ldd TASK_THREAD_INFO(%sp), %sp
mtctl %sp,%cr30 /* store in cr30 */
ldo THREAD_SZ_ALGN(%sp),%sp
tophys_r1 %sp
/* point CPU to kernel page tables */
load32 PA(swapper_pg_dir),%r4
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
/* Setup PDCE_PROC entry */
copy %arg0,%r3
/* Load RFI target address. */
load32 smp_callin, %r11
/* ok...common code can handle the rest */
b common_stext
nop
.procend
#endif /* CONFIG_SMP */
......@@ -475,9 +475,9 @@ copy_user_page_asm:
.procend
#endif
.export clear_user_page_asm,code
.export __clear_user_page_asm,code
clear_user_page_asm:
__clear_user_page_asm:
.proc
.callinfo NO_CALLS
.entry
......
......@@ -104,7 +104,9 @@ static inline int map_pte_uncached(pte_t * pte,
if (!pte_none(*pte))
printk(KERN_ERR "map_pte_uncached: page already exists\n");
set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
purge_tlb_start();
pdtlb_kernel(orig_vaddr);
purge_tlb_end();
vaddr += PAGE_SIZE;
orig_vaddr += PAGE_SIZE;
(*paddr_ptr) += PAGE_SIZE;
......@@ -179,7 +181,9 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
do {
pte_t page = *pte;
pte_clear(pte);
purge_tlb_start();
pdtlb_kernel(orig_vaddr);
purge_tlb_end();
vaddr += PAGE_SIZE;
orig_vaddr += PAGE_SIZE;
pte++;
......
......@@ -2,6 +2,7 @@
* Imagine for use with the Onyx (PCX-U) CPU interface
*
* Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
* Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
*
* 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
......
......@@ -494,11 +494,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/
static long
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, int in_syscall)
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs, int in_syscall)
{
struct k_sigaction *ka = &current->sighand->action[sig-1];
DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
sig, ka, info, oldset, regs);
......@@ -506,9 +504,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
return 0;
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
......@@ -535,7 +530,7 @@ asmlinkage int
do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
{
siginfo_t info;
struct k_sigaction *ka;
struct k_sigaction ka;
int signr;
DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
......@@ -553,10 +548,15 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
oldset->sig[0], oldset->sig[1]);
signr = get_signal_to_deliver(&info, regs, NULL);
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
/* May need to force signal if handle_signal failed to deliver */
while (1) {
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
if (signr > 0) {
if (signr <= 0)
break;
/* Restart a system call if necessary. */
if (in_syscall) {
/* Check the return code */
......@@ -569,8 +569,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
break;
case -ERESTARTSYS:
ka = &current->sighand->action[signr-1];
if (!(ka->sa.sa_flags & SA_RESTART)) {
if (!(ka.sa.sa_flags & SA_RESTART)) {
DBG(1,"ERESTARTSYS: putting -EINTR\n");
regs->gr[28] = -EINTR;
break;
......@@ -578,8 +577,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
/* fallthrough */
case -ERESTARTNOINTR:
/* A syscall is just a branch, so all
we have to do is fiddle the return
pointer. */
we have to do is fiddle the return pointer. */
regs->gr[31] -= 8; /* delayed branching */
/* Preserve original r28. */
regs->gr[28] = regs->orig_r28;
......@@ -589,12 +587,13 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
/* Whee! Actually deliver the signal. If the
delivery failed, we need to continue to iterate in
this loop so we can deliver the SIGSEGV... */
if (handle_signal(signr, &info, oldset, regs, in_syscall)) {
if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
return 1;
}
}
/* end of while(1) looping forever if we can't force a signal */
/* Did we come from a system call? */
if (in_syscall) {
......
......@@ -333,6 +333,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
struct smp_call_struct data;
unsigned long timeout;
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int retries = 0;
if (num_online_cpus() < 2)
return 0;
......@@ -365,21 +366,22 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
/* Send a message to all other CPUs and wait for them to respond */
send_IPI_allbutself(IPI_CALL_FUNC);
retry:
/* Wait for response */
timeout = jiffies + HZ;
while ( (atomic_read (&data.unstarted_count) > 0) &&
time_before (jiffies, timeout) )
barrier ();
if (atomic_read (&data.unstarted_count) > 0) {
printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n",
smp_processor_id(), ++retries);
goto retry;
}
/* We either got one or timed out. Release the lock */
mb();
smp_call_function_data = NULL;
if (atomic_read (&data.unstarted_count) > 0) {
printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n",
smp_processor_id());
return -ETIMEDOUT;
}
while (wait && atomic_read (&data.unfinished_count) > 0)
barrier ();
......
This diff is collapsed.
......@@ -135,32 +135,19 @@ void dump_stack(void)
EXPORT_SYMBOL(dump_stack);
void show_stack(struct task_struct *task, unsigned long *s)
static void do_show_stack(struct unwind_frame_info *info)
{
int i = 1;
struct unwind_frame_info info;
if (!task) {
unsigned long sp, ip, rp;
HERE:
asm volatile ("copy %%r30, %0" : "=r"(sp));
ip = (unsigned long)&&HERE;
rp = (unsigned long)__builtin_return_address(0);
unwind_frame_init(&info, current, sp, ip, rp);
} else {
unwind_frame_init_from_blocked_task(&info, task);
}
printk("Backtrace:\n");
while (i <= 16) {
if (unwind_once(&info) < 0 || info.ip == 0)
if (unwind_once(info) < 0 || info->ip == 0)
break;
if (__kernel_text_address(info.ip)) {
printk(" [<" RFMT ">] ", info.ip);
if (__kernel_text_address(info->ip)) {
printk(" [<" RFMT ">] ", info->ip);
#ifdef CONFIG_KALLSYMS
print_symbol("%s\n", info.ip);
print_symbol("%s\n", info->ip);
#else
if ((i & 0x03) == 0)
printk("\n");
......@@ -171,6 +158,25 @@ void show_stack(struct task_struct *task, unsigned long *s)
printk("\n");
}
void show_stack(struct task_struct *task, unsigned long *s)
{
struct unwind_frame_info info;
if (!task) {
unsigned long sp, ip, rp;
HERE:
asm volatile ("copy %%r30, %0" : "=r"(sp));
ip = (unsigned long)&&HERE;
rp = (unsigned long)__builtin_return_address(0);
unwind_frame_init(&info, current, sp, ip, rp);
} else {
unwind_frame_init_from_blocked_task(&info, task);
}
do_show_stack(&info);
}
void die_if_kernel(char *str, struct pt_regs *regs, long err)
{
if (user_mode(regs)) {
......@@ -407,7 +413,12 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
}
show_stack(NULL, (unsigned long *)regs->gr[30]);
{
/* show_stack(NULL, (unsigned long *)regs->gr[30]); */
struct unwind_frame_info info;
unwind_frame_init(&info, current, regs->gr[30], regs->iaoq[0], regs->gr[2]);
do_show_stack(&info);
}
printk("\n");
printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
......
......@@ -492,7 +492,6 @@ void handle_unaligned(struct pt_regs *regs)
show_regs(regs);
#endif
}
if (!unaligned_enabled)
goto force_sigbus;
}
......@@ -557,16 +556,6 @@ void handle_unaligned(struct pt_regs *regs)
break;
}
if (regs->isr != regs->sr[7])
{
printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n",
regs->isr, regs->sr[7]);
/* don't kill him though, since he has appropriate access to the page, or we
* would never have gotten here.
*/
}
/* TODO: make this cleaner... */
switch (regs->iir & OPCODE1_MASK)
{
......
......@@ -218,6 +218,40 @@ void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline)
}
}
int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
{
#if 0
void *inline_pc = __builtin_return_address(0);
int cpu = smp_processor_id();
#endif
if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */
pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
BUG();
}
/* Note: if interrupts are disabled (which is most likely), the printk
will never show on the console. We might need a polling method to flush
the dmesg buffer anyhow. */
_raw_spin_lock(&rw->lock);
if(rw->counter != 0) {
/* this basically never happens */
_raw_spin_unlock(&rw->lock);
return 0;
}
/* got it. now leave without unlocking */
rw->counter = -1; /* remember we are locked */
#if 0
pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
bfile, bline, current->comm, inline_pc, cpu);
#endif
}
void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
{
#if 0
......
......@@ -1046,6 +1046,7 @@ static struct notifier_block sparc64_cpufreq_notifier_block = {
static struct time_interpolator sparc64_cpu_interpolator = {
.source = TIME_SOURCE_CPU,
.shift = 16,
.mask = 0xffffffffffffffffLL
};
/* The quotient formula is taken from the IA64 port. */
......
......@@ -246,38 +246,40 @@ void device_bind_driver(struct device * dev)
list_add_tail(&dev->driver_list, &dev->driver->devices);
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
}
/**
* bus_match - check compatibility between device & driver.
* @dev: device.
* driver_probe_device - attempt to bind device & driver.
* @drv: driver.
* @dev: device.
*
* First, we call the bus's match function, which should compare
* the device IDs the driver supports with the device IDs of the
* device. Note we don't do this ourselves because we don't know
* the format of the ID structures, nor what is to be considered
* a match and what is not.
* First, we call the bus's match function, if one present, which
* should compare the device IDs the driver supports with the
* device IDs of the device. Note we don't do this ourselves
* because we don't know the format of the ID structures, nor what
* is to be considered a match and what is not.
*
* If we find a match, we call @drv->probe(@dev) if it exists, and
* call attach() above.
* call device_bind_driver() above.
*/
static int bus_match(struct device * dev, struct device_driver * drv)
{
int error = -ENODEV;
if (dev->bus->match(dev, drv)) {
dev->driver = drv;
if (drv->probe) {
if ((error = drv->probe(dev))) {
dev->driver = NULL;
return error;
}
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
if (drv->bus->match && !drv->bus->match(dev, drv))
return -ENODEV;
dev->driver = drv;
if (drv->probe) {
int error = drv->probe(dev);
if (error) {
dev->driver = NULL;
return error;
}
device_bind_driver(dev);
error = 0;
}
return error;
device_bind_driver(dev);
return 0;
}
......@@ -285,10 +287,11 @@ static int bus_match(struct device * dev, struct device_driver * drv)
* device_attach - try to attach device to a driver.
* @dev: device.
*
* Walk the list of drivers that the bus has and call bus_match()
* for each pair. If a compatible pair is found, break out and return.
* Walk the list of drivers that the bus has and call
* driver_probe_device() for each pair. If a compatible
* pair is found, break out and return.
*/
static int device_attach(struct device * dev)
int device_attach(struct device * dev)
{
struct bus_type * bus = dev->bus;
struct list_head * entry;
......@@ -302,7 +305,7 @@ static int device_attach(struct device * dev)
if (bus->match) {
list_for_each(entry, &bus->drivers.list) {
struct device_driver * drv = to_drv(entry);
error = bus_match(dev, drv);
error = driver_probe_device(drv, dev);
if (!error)
/* success, driver matched */
return 1;
......@@ -327,8 +330,8 @@ static int device_attach(struct device * dev)
* If bus_match() returns 0 and the @dev->driver is set, we've found
* a compatible pair.
*
* Note that we ignore the -ENODEV error from bus_match(), since it's
* perfectly valid for a driver not to bind to any devices.
* Note that we ignore the -ENODEV error from driver_probe_device(),
* since it's perfectly valid for a driver not to bind to any devices.
*/
void driver_attach(struct device_driver * drv)
{
......@@ -342,7 +345,7 @@ void driver_attach(struct device_driver * drv)
list_for_each(entry, &bus->devices.list) {
struct device * dev = container_of(entry, struct device, bus_list);
if (!dev->driver) {
error = bus_match(dev, drv);
error = driver_probe_device(drv, dev);
if (error && (error != -ENODEV))
/* driver matched but the probe failed */
printk(KERN_WARNING
......@@ -368,6 +371,7 @@ void device_release_driver(struct device * dev)
struct device_driver * drv = dev->driver;
if (drv) {
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
list_del_init(&dev->driver_list);
device_detach_shutdown(dev);
if (drv->remove)
......@@ -726,8 +730,11 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(driver_probe_device);
EXPORT_SYMBOL_GPL(device_bind_driver);
EXPORT_SYMBOL_GPL(device_release_driver);
EXPORT_SYMBOL_GPL(device_attach);
EXPORT_SYMBOL_GPL(driver_attach);
EXPORT_SYMBOL_GPL(bus_add_device);
EXPORT_SYMBOL_GPL(bus_remove_device);
......
......@@ -28,6 +28,7 @@ LIST_HEAD(dpm_off);
LIST_HEAD(dpm_off_irq);
DECLARE_MUTEX(dpm_sem);
DECLARE_MUTEX(dpm_list_sem);
/*
* PM Reference Counting.
......@@ -75,12 +76,12 @@ int device_pm_add(struct device * dev)
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
atomic_set(&dev->power.pm_users, 0);
down(&dpm_sem);
down(&dpm_list_sem);
list_add_tail(&dev->power.entry, &dpm_active);
device_pm_set_parent(dev, dev->parent);
if ((error = dpm_sysfs_add(dev)))
list_del(&dev->power.entry);
up(&dpm_sem);
up(&dpm_list_sem);
return error;
}
......@@ -88,11 +89,11 @@ void device_pm_remove(struct device * dev)
{
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
down(&dpm_sem);
down(&dpm_list_sem);
dpm_sysfs_remove(dev);
device_pm_release(dev->power.pm_parent);
list_del(&dev->power.entry);
up(&dpm_sem);
list_del_init(&dev->power.entry);
up(&dpm_list_sem);
}
......@@ -27,6 +27,11 @@ extern void device_shutdown(void);
*/
extern struct semaphore dpm_sem;
/*
* Used to serialize changes to the dpm_* lists.
*/
extern struct semaphore dpm_list_sem;
/*
* The PM lists.
*/
......
......@@ -31,16 +31,22 @@ int resume_device(struct device * dev)
void dpm_resume(void)
{
down(&dpm_list_sem);
while(!list_empty(&dpm_off)) {
struct list_head * entry = dpm_off.next;
struct device * dev = to_device(entry);
get_device(dev);
list_del_init(entry);
list_add_tail(entry, &dpm_active);
up(&dpm_list_sem);
if (!dev->power.prev_state)
resume_device(dev);
list_add_tail(entry, &dpm_active);
down(&dpm_list_sem);
put_device(dev);
}
up(&dpm_list_sem);
}
......@@ -76,9 +82,13 @@ void dpm_power_up(void)
{
while(!list_empty(&dpm_off_irq)) {
struct list_head * entry = dpm_off_irq.next;
struct device * dev = to_device(entry);
get_device(dev);
list_del_init(entry);
resume_device(to_device(entry));
list_add_tail(entry, &dpm_active);
resume_device(dev);
put_device(dev);
}
}
......
......@@ -63,11 +63,6 @@ int suspend_device(struct device * dev, u32 state)
* If we hit a failure with any of the devices, call device_resume()
* above to bring the suspended devices back to life.
*
* Note this function leaves dpm_sem held to
* a) block other devices from registering.
* b) prevent other PM operations from happening after we've begun.
* c) make sure we're exclusive when we disable interrupts.
*
*/
int device_suspend(u32 state)
......@@ -75,29 +70,40 @@ int device_suspend(u32 state)
int error = 0;
down(&dpm_sem);
while(!list_empty(&dpm_active)) {
down(&dpm_list_sem);
while (!list_empty(&dpm_active) && error == 0) {
struct list_head * entry = dpm_active.prev;
struct device * dev = to_device(entry);
get_device(dev);
up(&dpm_list_sem);
error = suspend_device(dev, state);
if (!error) {
list_del(&dev->power.entry);
list_add(&dev->power.entry, &dpm_off);
} else if (error == -EAGAIN) {
list_del(&dev->power.entry);
list_add(&dev->power.entry, &dpm_off_irq);
} else {
down(&dpm_list_sem);
/* Check if the device got removed */
if (!list_empty(&dev->power.entry)) {
/* Move it to the dpm_off or dpm_off_irq list */
if (!error) {
list_del(&dev->power.entry);
list_add(&dev->power.entry, &dpm_off);
} else if (error == -EAGAIN) {
list_del(&dev->power.entry);
list_add(&dev->power.entry, &dpm_off_irq);
error = 0;
}
}
if (error)
printk(KERN_ERR "Could not suspend device %s: "
"error %d\n", kobject_name(&dev->kobj), error);
goto Error;
}
put_device(dev);
}
Done:
up(&dpm_list_sem);
if (error)
dpm_resume();
up(&dpm_sem);
return error;
Error:
dpm_resume();
goto Done;
}
EXPORT_SYMBOL_GPL(device_suspend);
......
......@@ -664,7 +664,8 @@ int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
static struct time_interpolator hpet_interpolator = {
.source = TIME_SOURCE_MMIO64,
.shift = 10
.shift = 10,
.mask = 0xffffffffffffffffLL
};
#endif
......
......@@ -197,6 +197,11 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
#ifndef CONFIG_IDEDMA_ICS_AUTO
#warning CONFIG_IDEDMA_ICS_AUTO=n support is obsolete, and will be removed soon.
#endif
/*
* SG-DMA support.
*
......
......@@ -543,8 +543,6 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
return ide_stopped;
}
EXPORT_SYMBOL(ide_error);
/**
* ide_abort - abort pending IDE operatins
* @drive: drive the error occurred on
......@@ -585,8 +583,6 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
return ide_stopped;
}
EXPORT_SYMBOL(ide_abort);
/**
* ide_cmd - issue a simple drive command
* @drive: drive the command is for
......@@ -598,7 +594,8 @@ EXPORT_SYMBOL(ide_abort);
* The drive must be selected beforehand.
*/
void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
ide_handler_t *handler)
{
ide_hwif_t *hwif = HWIF(drive);
if (IDE_CONTROL_REG)
......@@ -608,8 +605,6 @@ void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
}
EXPORT_SYMBOL(ide_cmd);
/**
* drive_cmd_intr - drive command completion interrupt
* @drive: drive the completion interrupt occurred on
......@@ -620,7 +615,7 @@ EXPORT_SYMBOL(ide_cmd);
* the request
*/
ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
......@@ -645,8 +640,6 @@ ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
return ide_stopped;
}
EXPORT_SYMBOL(drive_cmd_intr);
/**
* do_special - issue some special commands
* @drive: drive the command is for
......@@ -656,7 +649,7 @@ EXPORT_SYMBOL(drive_cmd_intr);
* back.
*/
ide_startstop_t do_special (ide_drive_t *drive)
static ide_startstop_t do_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
......@@ -673,8 +666,6 @@ ide_startstop_t do_special (ide_drive_t *drive)
return DRIVER(drive)->special(drive);
}
EXPORT_SYMBOL(do_special);
void ide_map_sg(ide_drive_t *drive, struct request *rq)
{
ide_hwif_t *hwif = drive->hwif;
......@@ -715,7 +706,8 @@ EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
* all commands to finish. Don't do this as that is due to change
*/
ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
if (rq->flags & REQ_DRIVE_TASKFILE) {
......@@ -805,8 +797,6 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
EXPORT_SYMBOL(execute_drive_cmd);
/**
* start_request - start of I/O and command issuing for IDE
*
......@@ -818,7 +808,7 @@ EXPORT_SYMBOL(execute_drive_cmd);
* FIXME: this function needs a rename
*/
ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
sector_t block;
......@@ -909,8 +899,6 @@ ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
EXPORT_SYMBOL(start_request);
/**
* ide_stall_queue - pause an IDE device
* @drive: drive to stall
......@@ -1033,10 +1021,7 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
*/
/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
* into life on wakeup from machine sleep.
*/
void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
ide_hwif_t *hwif;
......@@ -1168,8 +1153,6 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
}
EXPORT_SYMBOL(ide_do_request);
/*
* Passes the stuff to ide_do_request
*/
......@@ -1334,8 +1317,6 @@ void ide_timer_expiry (unsigned long data)
spin_unlock_irqrestore(&ide_lock, flags);
}
EXPORT_SYMBOL(ide_timer_expiry);
/**
* unexpected_intr - handle an unexpected IDE interrupt
* @irq: interrupt line
......@@ -1533,8 +1514,6 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
EXPORT_SYMBOL(ide_intr);
/**
* ide_init_drive_cmd - initialize a drive command request
* @rq: request object
......
......@@ -673,8 +673,6 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
return 0;
}
EXPORT_SYMBOL(ide_ata66_check);
/*
* Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
* 1 : Safe to update drive->id DMA registers.
......@@ -693,9 +691,8 @@ int set_transfer (ide_drive_t *drive, ide_task_t *args)
return 0;
}
EXPORT_SYMBOL(set_transfer);
u8 ide_auto_reduce_xfer (ide_drive_t *drive)
#ifdef CONFIG_BLK_DEV_IDEDMA
static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
{
if (!drive->crc_count)
return drive->current_speed;
......@@ -719,8 +716,7 @@ u8 ide_auto_reduce_xfer (ide_drive_t *drive)
default: return XFER_PIO_4;
}
}
EXPORT_SYMBOL(ide_auto_reduce_xfer);
#endif /* CONFIG_BLK_DEV_IDEDMA */
/*
* Update the
......@@ -795,8 +791,6 @@ int ide_driveid_update (ide_drive_t *drive)
#endif
}
EXPORT_SYMBOL(ide_driveid_update);
/*
* Similar to ide_wait_stat(), except it never calls ide_error internally.
* This is a kludge to handle the new ide_config_drive_speed() function,
......@@ -936,7 +930,7 @@ EXPORT_SYMBOL(ide_config_drive_speed);
*
* See also ide_execute_command
*/
void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned int timeout, ide_expiry_t *expiry)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
......@@ -952,8 +946,6 @@ void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
add_timer(&hwgroup->timer);
}
EXPORT_SYMBOL(__ide_set_handler);
void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned int timeout, ide_expiry_t *expiry)
{
......
......@@ -421,8 +421,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
blk_queue_bounce_limit(drive->queue, addr);
}
EXPORT_SYMBOL(ide_toggle_bounce);
/**
* ide_set_xfer_rate - set transfer rate
* @drive: drive to set
......
......@@ -132,6 +132,9 @@ static int proc_ide_read_settings
char *out = page;
int len, rc, mul_factor, div_factor;
printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
"obsolete, and will be removed soon!\n");
down(&ide_setting_sem);
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
......@@ -168,6 +171,9 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
ide_settings_t *setting;
char *buf, *s;
printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
"obsolete, and will be removed soon!\n");
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
......
......@@ -419,7 +419,7 @@ EXPORT_SYMBOL(task_in_intr);
/*
* Handler for command with PIO data-out phase (Write/Write Multiple).
*/
ide_startstop_t task_out_intr (ide_drive_t *drive)
static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
......@@ -444,8 +444,6 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
return ide_started;
}
EXPORT_SYMBOL(task_out_intr);
ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
......
......@@ -1882,10 +1882,10 @@ int __init ide_setup (char *s)
goto do_serialize;
case -6: /* "autotune" */
drive->autotune = IDE_TUNE_AUTO;
goto done;
goto obsolete_option;
case -7: /* "noautotune" */
drive->autotune = IDE_TUNE_NOAUTO;
goto done;
goto obsolete_option;
case -9: /* "swapdata" */
case -10: /* "bswap" */
drive->bswap = 1;
......@@ -2017,30 +2017,30 @@ int __init ide_setup (char *s)
case -7: /* ata66 */
#ifdef CONFIG_BLK_DEV_IDEPCI
hwif->udma_four = 1;
goto done;
goto obsolete_option;
#else
goto bad_hwif;
#endif
case -6: /* dma */
hwif->autodma = 1;
goto done;
goto obsolete_option;
case -5: /* "reset" */
hwif->reset = 1;
goto done;
goto obsolete_option;
case -4: /* "noautotune" */
hwif->drives[0].autotune = IDE_TUNE_NOAUTO;
hwif->drives[1].autotune = IDE_TUNE_NOAUTO;
goto done;
goto obsolete_option;
case -3: /* "autotune" */
hwif->drives[0].autotune = IDE_TUNE_AUTO;
hwif->drives[1].autotune = IDE_TUNE_AUTO;
goto done;
goto obsolete_option;
case -2: /* "serialize" */
do_serialize:
hwif->mate = &ide_hwifs[hw^1];
hwif->mate->mate = hwif;
hwif->serialized = hwif->mate->serialized = 1;
goto done;
goto obsolete_option;
case -1: /* "noprobe" */
hwif->noprobe = 1;
......@@ -2057,7 +2057,7 @@ int __init ide_setup (char *s)
hwif->irq = vals[2];
hwif->noprobe = 0;
hwif->chipset = ide_forced;
goto done;
goto obsolete_option;
case 0: goto bad_option;
default:
......@@ -2068,6 +2068,9 @@ int __init ide_setup (char *s)
bad_option:
printk(" -- BAD OPTION\n");
return 1;
obsolete_option:
printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n");
return 1;
bad_hwif:
printk("-- NOT SUPPORTED ON ide%d", hw);
done:
......
......@@ -52,8 +52,6 @@
#include "ide-timing.h"
extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq);
#define IDE_PMAC_DEBUG
#define DMA_WAIT_TIMEOUT 50
......
......@@ -494,6 +494,11 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi
}
}
}
#ifndef CONFIG_IDEDMA_PCI_AUTO
#warning CONFIG_IDEDMA_PCI_AUTO=n support is obsolete, and will be removed soon.
#endif
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
/**
......
......@@ -19,7 +19,7 @@
#include <linux/major.h>
#include <linux/pm.h>
#include <linux/proc_fs.h>
#include <linux/kmod.h>
#include <linux/kobject_uevent.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
......
......@@ -246,11 +246,6 @@ static ssize_t serio_show_description(struct device *dev, char *buf)
return sprintf(buf, "%s\n", serio->name);
}
static ssize_t serio_show_driver(struct device *dev, char *buf)
{
return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
}
static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
......@@ -307,7 +302,7 @@ static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t c
static struct device_attribute serio_device_attrs[] = {
__ATTR(description, S_IRUGO, serio_show_description, NULL),
__ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver),
__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
__ATTR_NULL
};
......
......@@ -54,9 +54,9 @@
#ifdef DEBUG
# define DPRINTK(x) printk x
# define DPRINTK(x...) printk(x)
#else
# define DPRINTK(x) do { } while (0)
# define DPRINTK(x...)
#endif
......@@ -120,14 +120,14 @@ static int shutdown_timer;
static void process_shutdown(void)
{
if (shutdown_timer == 0)
DPRINTK((KERN_INFO "Shutdown requested...\n"));
DPRINTK(KERN_INFO "Shutdown requested...\n");
shutdown_timer++;
/* wait until the button was pressed for 1 second */
if (shutdown_timer == HZ) {
static char msg[] = "Shutting down...";
DPRINTK((KERN_INFO "%s\n", msg));
DPRINTK(KERN_INFO "%s\n", msg);
#ifdef CONFIG_CHASSIS_LCD_LED
lcd_print(msg);
#endif
......
/*
** System Bus Adapter (SBA) I/O MMU manager
**
** (c) Copyright 2000 Grant Grundler
** (c) Copyright 2000 Hewlett-Packard Company
** (c) Copyright 2000-2004 Grant Grundler <grundler @ parisc-linux x org>
** (c) Copyright 2004 Naresh Kumar Inna <knaresh at india x hp x com>
** (c) Copyright 2000-2004 Hewlett-Packard Company
**
** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
**
......
......@@ -56,7 +56,7 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/slab.h>
#include <linux/kmod.h>
#include <linux/kobject_uevent.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/dmi.h>
......
......@@ -33,6 +33,7 @@
#include <linux/ioctl32.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kobject_uevent.h>
#include <linux/proc_fs.h>
#include <linux/syscalls.h>
#include <linux/version.h>
......
......@@ -17,8 +17,8 @@
static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
struct bin_attribute * attr = dentry->d_fsdata;
struct kobject * kobj = dentry->d_parent->d_fsdata;
struct bin_attribute * attr = to_bin_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
return attr->read(kobj, buffer, off, count);
}
......@@ -60,8 +60,8 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
static int
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
struct bin_attribute *attr = dentry->d_fsdata;
struct kobject *kobj = dentry->d_parent->d_fsdata;
struct bin_attribute *attr = to_bin_attr(dentry);
struct kobject *kobj = to_kobj(dentry->d_parent);
return attr->write(kobj, buffer, offset, count);
}
......@@ -95,7 +95,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
static int open(struct inode * inode, struct file * file)
{
struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
struct bin_attribute * attr = file->f_dentry->d_fsdata;
struct bin_attribute * attr = to_bin_attr(file->f_dentry);
int error = -EINVAL;
if (!kobj || !attr)
......@@ -130,8 +130,8 @@ static int open(struct inode * inode, struct file * file)
static int release(struct inode * inode, struct file * file)
{
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
struct bin_attribute * attr = file->f_dentry->d_fsdata;
struct kobject * kobj = to_kobj(file->f_dentry->d_parent);
struct bin_attribute * attr = to_bin_attr(file->f_dentry);
u8 * buffer = file->private_data;
if (kobj)
......@@ -141,7 +141,7 @@ static int release(struct inode * inode, struct file * file)
return 0;
}
static struct file_operations bin_fops = {
struct file_operations bin_fops = {
.read = read,
.write = write,
.llseek = generic_file_llseek,
......@@ -158,31 +158,9 @@ static struct file_operations bin_fops = {
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
struct dentry * dentry;
struct dentry * parent;
int error = 0;
BUG_ON(!kobj || !kobj->dentry || !attr);
if (!kobj || !attr)
return -EINVAL;
parent = kobj->dentry;
down(&parent->d_inode->i_sem);
dentry = sysfs_get_dentry(parent,attr->attr.name);
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)attr;
error = sysfs_create(dentry,
(attr->attr.mode & S_IALLUGO) | S_IFREG,
NULL);
if (!error) {
dentry->d_inode->i_size = attr->size;
dentry->d_inode->i_fop = &bin_fops;
}
dput(dentry);
} else
error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem);
return error;
return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
}
......
This diff is collapsed.
......@@ -6,18 +6,10 @@
#include <linux/dnotify.h>
#include <linux/kobject.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include "sysfs.h"
static struct file_operations sysfs_file_operations;
static int init_file(struct inode * inode)
{
inode->i_size = PAGE_SIZE;
inode->i_fop = &sysfs_file_operations;
return 0;
}
#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
......@@ -62,12 +54,14 @@ struct sysfs_buffer {
loff_t pos;
char * page;
struct sysfs_ops * ops;
struct semaphore sem;
int needs_read_fill;
};
/**
* fill_read_buffer - allocate and fill buffer from object.
* @file: file pointer.
* @dentry: dentry pointer.
* @buffer: data buffer for file.
*
* Allocate @buffer->page, if it hasn't been already, then call the
......@@ -75,10 +69,10 @@ struct sysfs_buffer {
* data.
* This is called only once, on the file's first read.
*/
static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
{
struct attribute * attr = file->f_dentry->d_fsdata;
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
struct attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_ops * ops = buffer->ops;
int ret = 0;
ssize_t count;
......@@ -89,6 +83,7 @@ static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
return -ENOMEM;
count = ops->show(kobj,attr,buffer->page);
buffer->needs_read_fill = 0;
BUG_ON(count > (ssize_t)PAGE_SIZE);
if (count >= 0)
buffer->count = count;
......@@ -115,6 +110,9 @@ static int flush_read_buffer(struct sysfs_buffer * buffer, char __user * buf,
{
int error;
if (*ppos > buffer->count)
return 0;
if (count > (buffer->count - *ppos))
count = buffer->count - *ppos;
......@@ -149,13 +147,17 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct sysfs_buffer * buffer = file->private_data;
ssize_t retval = 0;
if (!*ppos) {
if ((retval = fill_read_buffer(file,buffer)))
return retval;
down(&buffer->sem);
if (buffer->needs_read_fill) {
if ((retval = fill_read_buffer(file->f_dentry,buffer)))
goto out;
}
pr_debug("%s: count = %d, ppos = %lld, buf = %s\n",
__FUNCTION__,count,*ppos,buffer->page);
return flush_read_buffer(buffer,buf,count,ppos);
retval = flush_read_buffer(buffer,buf,count,ppos);
out:
up(&buffer->sem);
return retval;
}
......@@ -182,6 +184,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
if (count >= PAGE_SIZE)
count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
return error ? -EFAULT : count;
}
......@@ -197,10 +200,10 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
*/
static int
flush_write_buffer(struct file * file, struct sysfs_buffer * buffer, size_t count)
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
{
struct attribute * attr = file->f_dentry->d_fsdata;
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
struct attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_ops * ops = buffer->ops;
return ops->store(kobj,attr,buffer->page,count);
......@@ -229,18 +232,20 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
{
struct sysfs_buffer * buffer = file->private_data;
down(&buffer->sem);
count = fill_write_buffer(buffer,buf,count);
if (count > 0)
count = flush_write_buffer(file,buffer,count);
count = flush_write_buffer(file->f_dentry,buffer,count);
if (count > 0)
*ppos += count;
up(&buffer->sem);
return count;
}
static int check_perm(struct inode * inode, struct file * file)
{
struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
struct attribute * attr = file->f_dentry->d_fsdata;
struct attribute * attr = to_attr(file->f_dentry);
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
int error = 0;
......@@ -296,6 +301,8 @@ static int check_perm(struct inode * inode, struct file * file)
buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
if (buffer) {
memset(buffer,0,sizeof(struct sysfs_buffer));
init_MUTEX(&buffer->sem);
buffer->needs_read_fill = 1;
buffer->ops = ops;
file->private_data = buffer;
} else
......@@ -321,8 +328,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
static int sysfs_release(struct inode * inode, struct file * filp)
{
struct kobject * kobj = filp->f_dentry->d_parent->d_fsdata;
struct attribute * attr = filp->f_dentry->d_fsdata;
struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
struct attribute * attr = to_attr(filp->f_dentry);
struct sysfs_buffer * buffer = filp->private_data;
if (kobj)
......@@ -337,7 +344,7 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0;
}
static struct file_operations sysfs_file_operations = {
struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
......@@ -346,23 +353,16 @@ static struct file_operations sysfs_file_operations = {
};
int sysfs_add_file(struct dentry * dir, const struct attribute * attr)
int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
{
struct dentry * dentry;
int error;
struct sysfs_dirent * parent_sd = dir->d_fsdata;
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
int error = 0;
down(&dir->d_inode->i_sem);
dentry = sysfs_get_dentry(dir,attr->name);
if (!IS_ERR(dentry)) {
error = sysfs_create(dentry,
(attr->mode & S_IALLUGO) | S_IFREG,
init_file);
if (!error)
dentry->d_fsdata = (void *)attr;
dput(dentry);
} else
error = PTR_ERR(dentry);
error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
up(&dir->d_inode->i_sem);
return error;
}
......@@ -375,9 +375,10 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr)
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
{
if (kobj && attr)
return sysfs_add_file(kobj->dentry,attr);
return -EINVAL;
BUG_ON(!kobj || !kobj->dentry || !attr);
return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
}
......@@ -409,7 +410,8 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
*/
dput(victim);
res = 0;
}
} else
d_drop(victim);
/**
* Drop the reference acquired from sysfs_get_dentry() above.
......
......@@ -31,7 +31,7 @@ static int create_files(struct dentry * dir,
int error = 0;
for (attr = grp->attrs; *attr && !error; attr++) {
error = sysfs_add_file(dir,*attr);
error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
}
if (error)
remove_files(dir,grp);
......@@ -45,6 +45,8 @@ int sysfs_create_group(struct kobject * kobj,
struct dentry * dir;
int error;
BUG_ON(!kobj || !kobj->dentry);
if (grp->name) {
error = sysfs_create_subdir(kobj,grp->name,&dir);
if (error)
......
......@@ -11,6 +11,8 @@
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/backing-dev.h>
#include "sysfs.h"
extern struct super_block * sysfs_sb;
static struct address_space_operations sysfs_aops = {
......@@ -29,8 +31,8 @@ struct inode * sysfs_new_inode(mode_t mode)
struct inode * inode = new_inode(sysfs_sb);
if (inode) {
inode->i_mode = mode;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
......@@ -66,7 +68,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
error = init(inode);
if (!error) {
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
if (S_ISDIR(mode))
dget(dentry); /* pin only directory dentry in core */
} else
iput(inode);
Done:
......@@ -88,31 +91,74 @@ struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
return lookup_hash(&qstr,parent);
}
/*
* Get the name for corresponding element represented by the given sysfs_dirent
*/
const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
{
struct attribute * attr;
struct bin_attribute * bin_attr;
struct sysfs_symlink * sl;
if (!sd || !sd->s_element)
BUG();
switch (sd->s_type) {
case SYSFS_DIR:
/* Always have a dentry so use that */
return sd->s_dentry->d_name.name;
case SYSFS_KOBJ_ATTR:
attr = sd->s_element;
return attr->name;
case SYSFS_KOBJ_BIN_ATTR:
bin_attr = sd->s_element;
return bin_attr->attr.name;
case SYSFS_KOBJ_LINK:
sl = sd->s_element;
return sl->link_name;
}
return NULL;
}
/*
* Unhashes the dentry corresponding to given sysfs_dirent
* Called with parent inode's i_sem held.
*/
void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
{
struct dentry * dentry = sd->s_dentry;
if (dentry) {
spin_lock(&dcache_lock);
if (!(d_unhashed(dentry) && dentry->d_inode)) {
dget_locked(dentry);
__d_drop(dentry);
spin_unlock(&dcache_lock);
simple_unlink(parent->d_inode, dentry);
} else
spin_unlock(&dcache_lock);
}
}
void sysfs_hash_and_remove(struct dentry * dir, const char * name)
{
struct dentry * victim;
struct sysfs_dirent * sd;
struct sysfs_dirent * parent_sd = dir->d_fsdata;
down(&dir->d_inode->i_sem);
victim = sysfs_get_dentry(dir,name);
if (!IS_ERR(victim)) {
/* make sure dentry is really there */
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
pr_debug("sysfs: Removing %s (%d)\n", victim->d_name.name,
atomic_read(&victim->d_count));
d_drop(victim);
/* release the target kobject in case of
* a symlink
*/
if (S_ISLNK(victim->d_inode->i_mode))
kobject_put(victim->d_fsdata);
simple_unlink(dir->d_inode,victim);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)
continue;
if (!strcmp(sysfs_get_name(sd), name)) {
list_del_init(&sd->s_sibling);
sysfs_drop_dentry(sd, dir);
sysfs_put(sd);
break;
}
/*
* Drop reference from sysfs_get_dentry() above.
*/
dput(victim);
}
up(&dir->d_inode->i_sem);
}
......
......@@ -22,6 +22,13 @@ static struct super_operations sysfs_ops = {
.drop_inode = generic_delete_inode,
};
struct sysfs_dirent sysfs_root = {
.s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling),
.s_children = LIST_HEAD_INIT(sysfs_root.s_children),
.s_element = NULL,
.s_type = SYSFS_ROOT,
};
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode;
......@@ -35,8 +42,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
if (inode) {
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inode->i_nlink++;
} else {
......@@ -50,6 +57,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
iput(inode);
return -ENOMEM;
}
root->d_fsdata = &sysfs_root;
sb->s_root = root;
return 0;
}
......
......@@ -9,18 +9,12 @@
#include "sysfs.h"
static struct inode_operations sysfs_symlink_inode_operations = {
struct inode_operations sysfs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = sysfs_follow_link,
.put_link = sysfs_put_link,
};
static int init_symlink(struct inode * inode)
{
inode->i_op = &sysfs_symlink_inode_operations;
return 0;
}
static int object_depth(struct kobject * kobj)
{
struct kobject * p = kobj;
......@@ -55,6 +49,36 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
}
}
static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target)
{
struct sysfs_dirent * parent_sd = parent->d_fsdata;
struct sysfs_symlink * sl;
int error = 0;
error = -ENOMEM;
sl = kmalloc(sizeof(*sl), GFP_KERNEL);
if (!sl)
goto exit1;
sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
if (!sl->link_name)
goto exit2;
strcpy(sl->link_name, name);
sl->target_kobj = kobject_get(target);
error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
SYSFS_KOBJ_LINK);
if (!error)
return 0;
kfree(sl->link_name);
exit2:
kfree(sl);
exit1:
return error;
}
/**
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
......@@ -64,21 +88,12 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
{
struct dentry * dentry = kobj->dentry;
struct dentry * d;
int error = 0;
BUG_ON(!kobj || !kobj->dentry || !name);
down(&dentry->d_inode->i_sem);
d = sysfs_get_dentry(dentry,name);
if (!IS_ERR(d)) {
error = sysfs_create(d, S_IFLNK|S_IRWXUGO, init_symlink);
if (!error)
/*
* associate the link dentry with the target kobject
*/
d->d_fsdata = kobject_get(target);
dput(d);
} else
error = PTR_ERR(d);
error = sysfs_add_link(dentry, name, target);
up(&dentry->d_inode->i_sem);
return error;
}
......
......@@ -4,26 +4,93 @@ extern struct vfsmount * sysfs_mount;
extern struct inode * sysfs_new_inode(mode_t mode);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
umode_t, int);
extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
extern int sysfs_add_file(struct dentry * dir, const struct attribute * attr);
extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_follow_link(struct dentry *, struct nameidata *);
extern void sysfs_put_link(struct dentry *, struct nameidata *);
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
extern struct file_operations sysfs_dir_operations;
extern struct file_operations sysfs_file_operations;
extern struct file_operations bin_fops;
extern struct inode_operations sysfs_dir_inode_operations;
extern struct inode_operations sysfs_symlink_inode_operations;
struct sysfs_symlink {
char * link_name;
struct kobject * target_kobj;
};
static inline struct kobject * to_kobj(struct dentry * dentry)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct kobject *) sd->s_element);
}
static inline struct attribute * to_attr(struct dentry * dentry)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct attribute *) sd->s_element);
}
static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
return ((struct bin_attribute *) sd->s_element);
}
static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
{
struct kobject * kobj = NULL;
spin_lock(&dcache_lock);
if (!d_unhashed(dentry))
kobj = kobject_get(dentry->d_fsdata);
if (!d_unhashed(dentry)) {
struct sysfs_dirent * sd = dentry->d_fsdata;
if (sd->s_type & SYSFS_KOBJ_LINK) {
struct sysfs_symlink * sl = sd->s_element;
kobj = kobject_get(sl->target_kobj);
} else
kobj = kobject_get(sd->s_element);
}
spin_unlock(&dcache_lock);
return kobj;
}
static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
{
if (sd->s_type & SYSFS_KOBJ_LINK) {
struct sysfs_symlink * sl = sd->s_element;
kfree(sl->link_name);
kobject_put(sl->target_kobj);
kfree(sl);
}
kfree(sd);
}
static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
{
if (sd) {
WARN_ON(!atomic_read(&sd->s_count));
atomic_inc(&sd->s_count);
}
return sd;
}
static inline void sysfs_put(struct sysfs_dirent * sd)
{
if (atomic_dec_and_test(&sd->s_count))
release_sysfs_dirent(sd);
}
......@@ -27,6 +27,7 @@
#define LDREGX ldd,s
#define LDREGM ldd,mb
#define STREGM std,ma
#define SHRREG shrd
#define RP_OFFSET 16
#define FRAME_SIZE 128
#define CALLEE_SAVE_FRAME_SIZE 144
......@@ -43,8 +44,14 @@
#ifdef CONFIG_PA20
#define BL b,l
# ifdef CONFIG_PARISC64
# define LEVEL 2.0w
# else
# define LEVEL 2.0
# endif
#else
#define BL bl
#define LEVEL 1.1
#endif
#ifdef __ASSEMBLY__
......
......@@ -46,7 +46,8 @@ struct pt_regs {
#ifdef __KERNEL__
/* XXX should we use iaoq[1] or iaoq[0] ? */
#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0)
#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0)
#define user_space(regs) (((regs)->iasq[0] != 0) ? 1 : 0)
#define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs *);
......
......@@ -222,6 +222,26 @@ static __inline__ void _raw_write_unlock(rwlock_t *rw)
_raw_spin_unlock(&rw->lock);
}
#ifdef CONFIG_DEBUG_RWLOCK
extern void _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
#define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
#else
static __inline__ int _raw_write_trylock(rwlock_t *rw)
{
_raw_spin_lock(&rw->lock);
if (rw->counter != 0) {
/* this basically never happens */
_raw_spin_unlock(&rw->lock);
return 0;
}
/* got it. now leave without unlocking */
rw->counter = -1; /* remember we are locked */
return 1;
}
#endif /* CONFIG_DEBUG_RWLOCK */
static __inline__ int is_read_locked(rwlock_t *rw)
{
return rw->counter > 0;
......
......@@ -184,4 +184,22 @@ typedef struct {
#define KERNEL_START (0x10100000 - 0x1000)
/* This is for the serialisation of PxTLB broadcasts. At least on the
* N class systems, only one PxTLB inter processor broadcast can be
* active at any one time on the Merced bus. This tlb purge
* synchronisation is fairly lightweight and harmless so we activate
* it on all SMP systems not just the N class. */
#ifdef CONFIG_SMP
extern spinlock_t pa_tlb_lock;
#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
#else
#define purge_tlb_start(x) do { } while(0)
#define purge_tlb_end(x) do { } while (0)
#endif
#endif
......@@ -18,12 +18,15 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
exec_domain: &default_exec_domain, \
flags: 0, \
cpu: 0, \
addr_limit: KERNEL_DS, \
preempt_count: 0, \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.addr_limit = KERNEL_DS, \
.preempt_count = 0, \
.restart_block = { \
.fn = do_no_restart_syscall \
} \
}
#define init_thread_info (init_thread_union.thread_info)
......
......@@ -51,9 +51,12 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
{
/* For one page, it's not worth testing the split_tlb variable */
mb();
mtsp(vma->vm_mm->context,1);
purge_tlb_start();
pdtlb(addr);
pitlb(addr);
purge_tlb_end();
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
......@@ -61,6 +64,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
{
unsigned long npages;
npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
if (npages >= 512) /* XXX arbitrary, should be tuned */
flush_tlb_all();
......@@ -68,16 +72,20 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
mtsp(vma->vm_mm->context,1);
if (split_tlb) {
purge_tlb_start();
while (npages--) {
pdtlb(start);
pitlb(start);
start += PAGE_SIZE;
}
purge_tlb_end();
} else {
purge_tlb_start();
while (npages--) {
pdtlb(start);
start += PAGE_SIZE;
}
purge_tlb_end();
}
}
}
......
......@@ -8,6 +8,7 @@
#include <asm/page.h>
#include <asm/system.h>
#include <asm/cache.h>
#include <asm-generic/uaccess.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
......
......@@ -752,14 +752,10 @@
#ifdef PIC
/* WARNING: CANNOT BE USED IN A NOP! */
# define K_STW_PIC stw %r19, -32(%sr0, %sp) ASM_LINE_SEP
# define K_LDW_PIC ldw -32(%sr0, %sp), %r19 ASM_LINE_SEP
# define K_STW_ASM_PIC " copy %%r19, %%r4\n"
# define K_LDW_ASM_PIC " copy %%r4, %%r19\n"
# define K_USING_GR4 "%r4",
#else
# define K_STW_PIC ASM_LINE_SEP
# define K_LDW_PIC ASM_LINE_SEP
# define K_STW_ASM_PIC " \n"
# define K_LDW_ASM_PIC " \n"
# define K_USING_GR4
......
......@@ -322,11 +322,13 @@ extern int device_for_each_child(struct device *, void *,
int (*fn)(struct device *, void *));
/*
* Manual binding of a device to driver. See drivers/base/bus.c
* Manual binding of a device to driver. See drivers/base/bus.c
* for information on use.
*/
extern int driver_probe_device(struct device_driver * drv, struct device * dev);
extern void device_bind_driver(struct device * dev);
extern void device_release_driver(struct device * dev);
extern int device_attach(struct device * dev);
extern void driver_attach(struct device_driver * drv);
......
......@@ -1194,14 +1194,6 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
*/
extern ide_startstop_t ide_abort(ide_drive_t *, const char *);
/*
* Issue a simple drive command
* The drive must be selected beforehand.
*
* (drive, command, nsector, handler)
*/
extern void ide_cmd(ide_drive_t *, u8, u8, ide_handler_t *);
extern void ide_fix_driveid(struct hd_driveid *);
/*
* ide_fixstring() cleans up and (optionally) byte-swaps a text string,
......@@ -1366,7 +1358,6 @@ extern ide_startstop_t recal_intr(ide_drive_t *);
extern ide_startstop_t task_no_data_intr(ide_drive_t *);
extern ide_startstop_t task_in_intr(ide_drive_t *);
extern ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
extern ide_startstop_t task_out_intr(ide_drive_t *);
extern int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *);
......@@ -1376,7 +1367,6 @@ int ide_task_ioctl(ide_drive_t *, unsigned int, unsigned long);
extern int system_bus_clock(void);
extern u8 ide_auto_reduce_xfer(ide_drive_t *);
extern int ide_driveid_update(ide_drive_t *);
extern int ide_ata66_check(ide_drive_t *, ide_task_t *);
extern int ide_config_drive_speed(ide_drive_t *, u8);
......
......@@ -37,8 +37,4 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; }
extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
extern void usermodehelper_init(void);
#ifdef CONFIG_HOTPLUG
extern char hotplug_path [];
#endif
#endif /* __LINUX_KMOD_H__ */
......@@ -11,6 +11,11 @@
#ifndef _KOBJECT_EVENT_H_
#define _KOBJECT_EVENT_H_
#define HOTPLUG_PATH_LEN 256
/* path to the hotplug userspace helper executed on an event */
extern char hotplug_path[];
/*
* If you add an action here, you must also add the proper string to the
* lib/kobject_uevent.c file.
......
......@@ -9,6 +9,8 @@
#ifndef _SYSFS_H_
#define _SYSFS_H_
#include <asm/atomic.h>
struct kobject;
struct module;
......@@ -57,6 +59,23 @@ struct sysfs_ops {
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
struct sysfs_dirent {
atomic_t s_count;
struct list_head s_sibling;
struct list_head s_children;
void * s_element;
int s_type;
umode_t s_mode;
struct dentry * s_dentry;
};
#define SYSFS_ROOT 0x0001
#define SYSFS_DIR 0x0002
#define SYSFS_KOBJ_ATTR 0x0004
#define SYSFS_KOBJ_BIN_ATTR 0x0008
#define SYSFS_KOBJ_LINK 0x0020
#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
#ifdef CONFIG_SYSFS
extern int
......
......@@ -285,20 +285,18 @@ extern long pps_stbcnt; /* stability limit exceeded */
* for the compensation is that the timer routines are not as scalable anymore.
*/
#define INTERPOLATOR_ADJUST 65536
#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
struct time_interpolator {
unsigned short source; /* time source flags */
unsigned char shift; /* increases accuracy of multiply by shifting. */
/* Note that bits may be lost if shift is set too high */
unsigned char jitter; /* if set compensate for fluctuations */
unsigned nsec_per_cyc; /* set by register_time_interpolator() */
u16 source; /* time source flags */
u8 shift; /* increases accuracy of multiply by shifting. */
/* Note that bits may be lost if shift is set too high */
u8 jitter; /* if set compensate for fluctuations */
u32 nsec_per_cyc; /* set by register_time_interpolator() */
void *addr; /* address of counter or function */
u64 mask; /* mask the valid bits of the counter */
unsigned long offset; /* nsec offset at last update of interpolator */
unsigned long last_counter; /* counter value in units of the counter at last update */
unsigned long last_cycle; /* Last timer value if TIME_SOURCE_JITTER is set */
unsigned long frequency; /* frequency in counts/second */
u64 last_counter; /* counter value in units of the counter at last update */
u64 last_cycle; /* Last timer value if TIME_SOURCE_JITTER is set */
u64 frequency; /* frequency in counts/second */
long drift; /* drift in parts-per-million (or -1) */
unsigned long skips; /* skips forward */
unsigned long ns_skipped; /* nanoseconds skipped */
......@@ -308,7 +306,6 @@ struct time_interpolator {
extern void register_time_interpolator(struct time_interpolator *);
extern void unregister_time_interpolator(struct time_interpolator *);
extern void time_interpolator_reset(void);
extern unsigned long time_interpolator_resolution(void);
extern unsigned long time_interpolator_get_offset(void);
#else /* !CONFIG_TIME_INTERPOLATION */
......
......@@ -11,7 +11,6 @@
#include <linux/unistd.h>
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/kmod.h> /* for hotplug_path */
#include <linux/kthread.h>
#include <linux/stop_machine.h>
#include <asm/semaphore.h>
......
......@@ -115,29 +115,6 @@ int request_module(const char *fmt, ...)
EXPORT_SYMBOL(request_module);
#endif /* CONFIG_KMOD */
#ifdef CONFIG_HOTPLUG
/*
hotplug path is set via /proc/sys
invoked by hotplug-aware bus drivers,
with call_usermodehelper
argv [0] = hotplug_path;
argv [1] = "usb", "scsi", "pci", "network", etc;
... plus optional type-specific parameters
argv [n] = 0;
envp [*] = HOME, PATH; optional type-specific parameters
a hotplug bus should invoke this for device add/remove
events. the command is expected to load drivers when
necessary, and may perform additional system setup.
*/
char hotplug_path[KMOD_PATH_LEN] = "/sbin/hotplug";
EXPORT_SYMBOL(hotplug_path);
#endif /* CONFIG_HOTPLUG */
struct subprocess_info {
struct completion *complete;
char *path;
......
......@@ -394,7 +394,7 @@ static ctl_table kern_table[] = {
.ctl_name = KERN_HOTPLUG,
.procname = "hotplug",
.data = &hotplug_path,
.maxlen = KMOD_PATH_LEN,
.maxlen = HOTPLUG_PATH_LEN,
.mode = 0644,
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
......
......@@ -1438,7 +1438,7 @@ struct time_interpolator *time_interpolator;
static struct time_interpolator *time_interpolator_list;
static spinlock_t time_interpolator_lock = SPIN_LOCK_UNLOCKED;
static inline unsigned long time_interpolator_get_cycles(unsigned int src)
static inline u64 time_interpolator_get_cycles(unsigned int src)
{
unsigned long (*x)(void);
......@@ -1453,23 +1453,25 @@ static inline unsigned long time_interpolator_get_cycles(unsigned int src)
case TIME_SOURCE_MMIO32 :
return readl(time_interpolator->addr);
default: return get_cycles();
}
}
static inline unsigned long time_interpolator_get_counter(void)
static inline u64 time_interpolator_get_counter(void)
{
unsigned int src = time_interpolator->source;
if (time_interpolator->jitter)
{
unsigned long lcycle;
unsigned long now;
u64 lcycle;
u64 now;
do {
lcycle = time_interpolator->last_cycle;
now = time_interpolator_get_cycles(src);
if (lcycle && time_after(lcycle, now)) return lcycle;
if (lcycle && time_after(lcycle, now))
return lcycle;
/* Keep track of the last timer value returned. The use of cmpxchg here
* will cause contention in an SMP environment.
*/
......@@ -1486,26 +1488,29 @@ void time_interpolator_reset(void)
time_interpolator->last_counter = time_interpolator_get_counter();
}
unsigned long time_interpolator_resolution(void)
{
if (time_interpolator->frequency < NSEC_PER_SEC)
return NSEC_PER_SEC / time_interpolator->frequency;
else
return 1;
}
#define GET_TI_NSECS(count,i) ((((count) - i->last_counter) * i->nsec_per_cyc) >> i->shift)
#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
unsigned long time_interpolator_get_offset(void)
{
/* If we do not have a time interpolator set up then just return zero */
if (!time_interpolator)
return 0;
return time_interpolator->offset +
GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
}
#define INTERPOLATOR_ADJUST 65536
#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
static void time_interpolator_update(long delta_nsec)
{
unsigned long counter = time_interpolator_get_counter();
unsigned long offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
u64 counter;
unsigned long offset;
/* If there is no time interpolator set up then do nothing */
if (!time_interpolator)
return;
/* The interpolator compensates for late ticks by accumulating
* the late time in time_interpolator->offset. A tick earlier than
......@@ -1515,6 +1520,9 @@ static void time_interpolator_update(long delta_nsec)
* and the tuning logic insures that.
*/
counter = time_interpolator_get_counter();
offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
time_interpolator->offset = offset - delta_nsec;
else {
......@@ -1553,7 +1561,11 @@ register_time_interpolator(struct time_interpolator *ti)
{
unsigned long flags;
ti->nsec_per_cyc = (NSEC_PER_SEC << ti->shift) / ti->frequency;
/* Sanity check */
if (ti->frequency == 0 || ti->mask == 0)
BUG();
ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
spin_lock(&time_interpolator_lock);
write_seqlock_irqsave(&xtime_lock, flags);
if (is_better_time_interpolator(ti)) {
......
......@@ -50,7 +50,7 @@ config DEBUG_SLAB
config DEBUG_SPINLOCK
bool "Spinlock debugging"
depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64 || USERMODE)
depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PARISC || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64)
help
Say Y here and build SMP to catch missing spinlock initialization
and certain other kinds of spinlock errors commonly made. This is
......@@ -110,7 +110,7 @@ config DEBUG_INFO
if !X86_64
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on X86 || CRIS || M68KNOMMU || PARISC
depends on X86 || CRIS || M68KNOMMU
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
......
......@@ -23,6 +23,9 @@
#include <linux/kobject.h>
#include <net/sock.h>
#define BUFFER_SIZE 1024 /* buffer for the hotplug env */
#define NUM_ENVP 32 /* number of env pointers */
#if defined(CONFIG_KOBJECT_UEVENT) || defined(CONFIG_HOTPLUG)
static char *action_to_string(enum kobject_action action)
{
......@@ -53,12 +56,11 @@ static struct sock *uevent_sock;
*
* @signal: signal name
* @obj: object path (kobject)
* @buf: buffer used to pass auxiliary data like the hotplug environment
* @buflen:
* gfp_mask:
* @envp: possible hotplug environment to pass with the message
* @gfp_mask:
*/
static int send_uevent(const char *signal, const char *obj, const void *buf,
int buflen, int gfp_mask)
static int send_uevent(const char *signal, const char *obj,
char **envp, int gfp_mask)
{
struct sk_buff *skb;
char *pos;
......@@ -69,16 +71,25 @@ static int send_uevent(const char *signal, const char *obj, const void *buf,
len = strlen(signal) + 1;
len += strlen(obj) + 1;
len += buflen;
skb = alloc_skb(len, gfp_mask);
/* allocate buffer with the maximum possible message size */
skb = alloc_skb(len + BUFFER_SIZE, gfp_mask);
if (!skb)
return -ENOMEM;
pos = skb_put(skb, len);
sprintf(pos, "%s@%s", signal, obj);
/* copy the environment key by key to our continuous buffer */
if (envp) {
int i;
pos += sprintf(pos, "%s@%s", signal, obj) + 1;
memcpy(pos, buf, buflen);
for (i = 2; envp[i]; i++) {
len = strlen(envp[i]) + 1;
pos = skb_put(skb, len);
strcpy(pos, envp[i]);
}
}
return netlink_broadcast(uevent_sock, skb, 0, 1, gfp_mask);
}
......@@ -107,10 +118,10 @@ static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
if (!attrpath)
goto exit;
sprintf(attrpath, "%s/%s", path, attr->name);
rc = send_uevent(signal, attrpath, NULL, 0, gfp_mask);
rc = send_uevent(signal, attrpath, NULL, gfp_mask);
kfree(attrpath);
} else {
rc = send_uevent(signal, path, NULL, 0, gfp_mask);
rc = send_uevent(signal, path, NULL, gfp_mask);
}
exit:
......@@ -166,11 +177,10 @@ static inline int send_uevent(const char *signal, const char *obj,
#ifdef CONFIG_HOTPLUG
char hotplug_path[HOTPLUG_PATH_LEN] = "/sbin/hotplug";
u64 hotplug_seqnum;
static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
#define BUFFER_SIZE 1024 /* should be enough memory for the env */
#define NUM_ENVP 32 /* number of env pointers */
/**
* kobject_hotplug - notify userspace by executing /sbin/hotplug
*
......@@ -182,6 +192,7 @@ void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
char *argv [3];
char **envp = NULL;
char *buffer = NULL;
char *seq_buff;
char *scratch;
int i = 0;
int retval;
......@@ -258,6 +269,11 @@ void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
/* reserve space for the sequence,
* put the real one in after the hotplug call */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
if (hotplug_ops->hotplug) {
/* have the kset specific function add its stuff */
retval = hotplug_ops->hotplug (kset, kobj,
......@@ -273,15 +289,13 @@ void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
spin_lock(&sequence_lock);
seq = ++hotplug_seqnum;
spin_unlock(&sequence_lock);
envp [i++] = scratch;
scratch += sprintf(scratch, "SEQNUM=%lld", (long long)seq) + 1;
sprintf(seq_buff, "SEQNUM=%lld", (long long)seq);
pr_debug ("%s: %s %s seq=%lld %s %s %s %s %s\n",
__FUNCTION__, argv[0], argv[1], (long long)seq,
envp[0], envp[1], envp[2], envp[3], envp[4]);
send_uevent(action_string, kobj_path, buffer, scratch - buffer, GFP_KERNEL);
send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
if (!hotplug_path[0])
goto exit;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment