diff options
author | Len Brown <len.brown@intel.com> | 2004-08-07 14:26:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2004-08-07 14:26:00 -0400 |
commit | 98102e736027f674ba55c959ee47df3877a4aa86 (patch) | |
tree | 9a19bdc90b72bda67a3e319b031babbc3e926554 /arch | |
parent | 6a9233c91d790d19ab17993c88a13c035a58d2bc (diff) | |
parent | 915a29ec1c5e34283a6231af1036114e4d612cb0 (diff) | |
download | history-98102e736027f674ba55c959ee47df3877a4aa86.tar.gz |
Merge intel.com:/home/lenb/bk/linux-2.6.8
into intel.com:/home/lenb/src/linux-acpi-test-2.6.8
Diffstat (limited to 'arch')
50 files changed, 1554 insertions, 2105 deletions
diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S index fc4cc2fb1e1b12..df7bc7068d0fa0 100644 --- a/arch/arm/boot/bootp/init.S +++ b/arch/arm/boot/bootp/init.S @@ -20,8 +20,10 @@ .type _start, #function .globl _start -_start: adr r13, data +_start: add lr, pc, #-0x8 @ lr = current load addr + adr r13, data ldmia r13!, {r4-r6} @ r5 = dest, r6 = length + add r4, r4, lr @ r4 = initrd_start + load addr bl move @ move the initrd /* diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 052cef4937430a..797292aa0805de 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -11,7 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set -CONFIG_STANDALONE=y CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y @@ -20,17 +19,24 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # # Loadable module support @@ -44,58 +50,32 @@ CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ADIFCC is not set -# CONFIG_ARCH_ANAKIN is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set CONFIG_ARCH_S3C2410=y - -# -# CLPS711X/EP721X Implementations -# - -# -# Epxa10db -# - -# -# Footbridge Implementations -# - -# -# IOP3xx Implementation Options -# -# CONFIG_ARCH_IOP310 is not set -# CONFIG_ARCH_IOP321 is not set - -# -# IOP3xx Chipset Features -# - -# -# Intel PXA250/210 Implementations -# - -# -# SA11x0 Implementations -# +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE_PB is not set # # S3C2410 Implementations # CONFIG_ARCH_BAST=y CONFIG_ARCH_H1940=y +CONFIG_ARCH_SMDK2410=y +CONFIG_MACH_VR1000=y # # Processor Type @@ -120,9 +100,8 @@ CONFIG_CPU_TLB_V4WBI=y # General setup # # CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -# CONFIG_HOTPLUG is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 # # At least one math emulation must be selected @@ -130,6 +109,7 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_FPE_NWFPE=y CONFIG_FPE_NWFPE_XP=y # CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -137,6 +117,9 @@ CONFIG_BINFMT_AOUT=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # CONFIG_PM is not set # CONFIG_PREEMPT is not set # CONFIG_ARTHUR is not set @@ -149,7 +132,6 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_PARPORT=y CONFIG_PARPORT_PC=y CONFIG_PARPORT_PC_CML1=y -# CONFIG_PARPORT_SERIAL is not set CONFIG_PARPORT_PC_FIFO=y CONFIG_PARPORT_PC_SUPERIO=y # CONFIG_PARPORT_ARC is not set @@ -180,9 +162,20 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -200,6 +193,7 @@ CONFIG_MTD_CFI_INTELEXT=y # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -218,7 +212,6 @@ CONFIG_MTD_CFI_INTELEXT=y # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -259,23 +252,21 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -291,11 +282,17 @@ CONFIG_IPV6_SCTP__=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -316,40 +313,25 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set -# CONFIG_HOSTAP is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ATA/ATAPI/MFM/RLL support @@ -360,9 +342,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=m @@ -372,10 +354,10 @@ CONFIG_BLK_DEV_IDEFLOPPY=m # # IDE chipset support/bugfixes # -CONFIG_BLK_DEV_IDE_BAST=y +CONFIG_IDE_GENERIC=y +# CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_HD is not set # @@ -384,13 +366,22 @@ CONFIG_BLK_DEV_IDE_BAST=y # CONFIG_SCSI is not set # +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# # I2O device support # # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Input device support @@ -406,7 +397,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -427,12 +417,13 @@ CONFIG_SERIO_SERPORT=y CONFIG_INPUT_KEYBOARD=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_PS2_SYNAPTICS is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -451,8 +442,6 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_DIGI is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set @@ -480,15 +469,37 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_S3C2410=y CONFIG_SERIAL_S3C2410_CONSOLE=y CONFIG_SERIAL_BAST_SIO=y -# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=y # CONFIG_TIPAR is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # I2C support @@ -507,55 +518,46 @@ CONFIG_I2C_ALGOBIT=m # # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ISA is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_SCx200_ACB is not set # -# I2C Hardware Sensors Chip support +# Hardware Sensors Chip support # CONFIG_I2C_SENSOR=m # CONFIG_SENSORS_ADM1021 is not set -CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set CONFIG_SENSORS_LM78=m +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set CONFIG_SENSORS_LM85=m -# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set # -# L3 serial bus support -# -# CONFIG_L3 is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver +# Other I2C Chip support # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set +CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # # Multimedia devices @@ -568,11 +570,6 @@ CONFIG_RTC=y # CONFIG_DVB is not set # -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# # File systems # CONFIG_EXT2_FS=y @@ -611,8 +608,8 @@ CONFIG_VFAT_FS=y # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLBFS is not set @@ -625,14 +622,20 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set CONFIG_JFFS_FS=y CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS_PROC_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 # CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -652,12 +655,11 @@ CONFIG_ROOT_NFS=y CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -675,16 +677,15 @@ CONFIG_BSD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set @@ -709,6 +710,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # 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 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -725,6 +727,11 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_UTF8 is not set # +# Profiling support +# +# CONFIG_PROFILING is not set + +# # Graphics support # CONFIG_FB=y @@ -744,21 +751,20 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_LOGO is not set # -# Misc devices +# Sound # +# CONFIG_SOUND is not set # -# Multimedia Capabilities Port drivers +# Misc devices # -# CONFIG_MCP is not set # -# Console Switches +# USB support # -# CONFIG_SWITCHES is not set # -# USB support +# USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -776,7 +782,6 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_PRINTK=y # CONFIG_DEBUG_ICEDCC is not set CONFIG_DEBUG_S3C2410_PORT=y CONFIG_DEBUG_S3C2410_UART=0 @@ -794,6 +799,8 @@ CONFIG_DEBUG_S3C2410_UART=0 # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index b71f89e11a7350..40e78bc4460a19 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -23,9 +23,12 @@ config ARCH_SMDK2410 <http://www.fsforth.de> config MACH_VR1000 - bool "Simtec VR1000" + bool "Thorcom VR1000" help - Say Y here if you are using the Simtec VR1000 board. + Say Y here if you are using the Thorcom VR1000 board. + + This linux port is currently being maintained by Simtec, on behalf + of Thorcom. Any queries, please contact Thorcom first. endmenu diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index fb180732b8608b..bfadbd4254f831 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -101,7 +101,7 @@ void __init smdk2410_init_irq(void) void __init smdk2410_init_time(void) { - s3c2401_init_time(); + s3c2410_init_time(); } MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 2246a30cea545e..aae341c6908fef 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -11,6 +11,7 @@ * published by the Free Software Foundation. * * Modifications: + * 06-Aug-2004 BJD Fixed call to time initialisation * 12-Jul-2004 BJD Renamed machine * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL @@ -159,7 +160,7 @@ void __init vr1000_init_irq(void) void __init vr1000_init_time(void) { - s3c2401_init_time(); + s3c2410_init_time(); } MACHINE_START(VR1000, "Thorcom-VR1000") diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index a38a1ffecbeed3..29be1c018949b6 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -66,9 +66,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) /* We must not map this if we have highmem enabled */ pte = pte_offset_map(pmd, addr); printk(", *pte=%08lx", pte_val(*pte)); -#ifdef CONFIG_CPU_32 printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE])); -#endif pte_unmap(pte); #endif } while(0); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index db6ebc23672778..060fea2e10cb03 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -24,13 +24,7 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#ifdef CONFIG_CPU_32 -#define TABLE_OFFSET (PTRS_PER_PTE) -#else -#define TABLE_OFFSET 0 -#endif - -#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t)) +#define TABLE_SIZE (2 * PTRS_PER_PTE * sizeof(pte_t)) DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -289,14 +283,13 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot */ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext); -#ifdef CONFIG_CPU_32 /* * Reserve the page tables. These are already in use, * and can only be in node 0. */ reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); -#endif + /* * And don't forget to reserve the allocator bitmap, * which will be freed later. diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index bcb3e0c5a3ec75..afd36307070a8b 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -477,6 +477,9 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, goto out; if (pos < 0) goto out; + ret = -ESPIPE; + if (!(file->f_mode & FMODE_PREAD)) + goto out; ret = read(file, buf, count, &pos); if (ret > 0) dnotify_parent(file->f_dentry, DN_ACCESS); @@ -511,6 +514,10 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, if (pos < 0) goto out; + ret = -ESPIPE; + if (!(file->f_mode & FMODE_PWRITE)) + goto out; + ret = write(file, buf, count, &pos); if (ret > 0) dnotify_parent(file->f_dentry, DN_MODIFY); diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 032168b86a4991..cc4e6b9db7733f 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -825,39 +825,6 @@ config PROC_DEVICETREE an image of the device tree that the kernel copies from Open Firmware. If unsure, say Y here. -config PPC_RTAS - bool "Support for RTAS (RunTime Abstraction Services) in /proc" - depends on PPC_OF && PROC_FS - ---help--- - When you use this option, you will be able to use RTAS from - userspace. - - RTAS stands for RunTime Abstraction Services and should - provide a portable way to access and set system information. This is - commonly used on RS/6000 (pSeries) computers. - - You can access RTAS via the special proc file system entry rtas. - Don't confuse this rtas entry with the one in /proc/device-tree/rtas - which is readonly. - - If you don't know if you can use RTAS look into - /proc/device-tree/rtas. If there are some entries, it is very likely - that you will be able to use RTAS. - - You can do cool things with rtas. To print out information about - various sensors in the system, just do a - - $ cat /proc/rtas/sensors - - or if you power off your machine at night but want it running when - you enter your office at 7:45 am, do a - - # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron - - and shutdown. - - If unsure, say Y. - config PREP_RESIDUAL bool "Support for PReP Residual Data" depends on PPC_PREP diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index bf3d1a2bd55861..e15c6919a27fe8 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -22,28 +22,25 @@ endif LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic CPPFLAGS += -Iarch/$(ARCH) -aflags-y += -Iarch/$(ARCH) -cflags-y += -Iarch/$(ARCH) -msoft-float -pipe \ +AFLAGS += -Iarch/$(ARCH) +CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -Wno-uninitialized -mmultiple CPP = $(CC) -E $(CFLAGS) CHECK := $(CHECK) -D__powerpc__=1 ifndef CONFIG_E500 -cflags-y += -mstring +CFLAGS += -mstring endif -aflags-$(CONFIG_4xx) += -m405 -cflags-$(CONFIG_4xx) += -Wa,-m405 -aflags-$(CONFIG_6xx) += -maltivec -cflags-$(CONFIG_6xx) += -Wa,-maltivec -aflags-$(CONFIG_E500) += -me500 -cflags-$(CONFIG_E500) += -Wa,-me500 -aflags-$(CONFIG_PPC64BRIDGE) += -mppc64bridge -cflags-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge - -AFLAGS += $(aflags-y) -CFLAGS += $(cflags-y) +cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge +cpu-as-$(CONFIG_4xx) += -Wa,-m405 +cpu-as-$(CONFIG_6xx) += -Wa,-maltivec +cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec +cpu-as-$(CONFIG_E500) += -Wa,-me500 + +AFLAGS += $(cpu-as-y) +CFLAGS += $(cpu-as-y) head-y := arch/ppc/kernel/head.o head-$(CONFIG_8xx) := arch/ppc/kernel/head_8xx.o diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index c3b03b6188fc21..2531070a689ab8 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -2,16 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_4xx -EXTRA_AFLAGS := -Wa,-m405 -endif -ifdef CONFIG_E500 -EXTRA_AFLAGS := -Wa,-me500 -endif - extra-$(CONFIG_PPC_STD_MMU) := head.o extra-$(CONFIG_40x) := head_4xx.o extra-$(CONFIG_44x) := head_44x.o diff --git a/arch/ppc/kernel/pci-dma.c b/arch/ppc/kernel/pci-dma.c deleted file mode 100644 index 63354f6af1b074..00000000000000 --- a/arch/ppc/kernel/pci-dma.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> - * - * - * Dynamic DMA mapping support. - * - * swiped from i386 - * - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/pci.h> -#include <asm/io.h> - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - -#ifdef CONFIG_NOT_COHERENT_CACHE - ret = consistent_alloc(gfp, size, dma_handle); -#else - ret = (void *)__get_free_pages(gfp, get_order(size)); -#endif - - if (ret != NULL) { - memset(ret, 0, size); -#ifndef CONFIG_NOT_COHERENT_CACHE - *dma_handle = virt_to_bus(ret); -#endif - } - return ret; -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ -#ifdef CONFIG_NOT_COHERENT_CACHE - consistent_free(vaddr); -#else - free_pages((unsigned long)vaddr, get_order(size)); -#endif -} diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c index b970dd51dd95a3..1d79838d90acbd 100644 --- a/arch/ppc/mm/44x_mmu.c +++ b/arch/ppc/mm/44x_mmu.c @@ -93,10 +93,14 @@ ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys) } /* - * Configure PPC44x TLB for AS0 exception processing. + * MMU_init_hw does the chip-specific initialization of the MMU hardware. */ -static void __init -ppc44x_tlb_config(void) +void __init MMU_init_hw(void) +{ + flush_instruction_cache(); +} + +unsigned long __init mmu_mapin_ram(void) { unsigned int pinned_tlbs = 1; int i; @@ -124,39 +128,6 @@ ppc44x_tlb_config(void) unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE; ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr); } -} - -/* - * MMU_init_hw does the chip-specific initialization of the MMU hardware. - */ -void __init MMU_init_hw(void) -{ - flush_instruction_cache(); - - ppc44x_tlb_config(); -} - -/* TODO: Add large page lowmem mapping support */ -unsigned long __init mmu_mapin_ram(void) -{ - unsigned long v, s, f = _PAGE_GUARDED; - phys_addr_t p; - - v = KERNELBASE; - p = PPC_MEMSTART; - - for (s = 0; s < total_lowmem; s += PAGE_SIZE) { - if ((char *) v >= _stext && (char *) v < etext) - f |= _PAGE_RAM_TEXT; - else - f |= _PAGE_RAM; - map_page(v, p, f); - v += PAGE_SIZE; - p += PAGE_SIZE; - } - - if (ppc_md.progress) - ppc_md.progress("MMU:mmu_mapin_ram done", 0x401); - return s; + return total_lowmem; } diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile index 458e67106c6a2e..cd3eae147cf81b 100644 --- a/arch/ppc/mm/Makefile +++ b/arch/ppc/mm/Makefile @@ -2,10 +2,6 @@ # Makefile for the linux ppc-specific parts of the memory manager. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif - obj-y := fault.o init.o mem_pieces.o \ mmu_context.o pgtable.o diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index b439b155c7c545..578b0ac9cc0463 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -175,6 +175,15 @@ config IBM_OPENBIOS depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y +config PPC4xx_DMA + bool "PPC4xx DMA controller support" + depends on 4xx + +config PPC4xx_EDMA + bool + depends on !STB03xxx && PPC4xx_DMA + default y + config PM bool "Power Management support (EXPERIMENTAL)" depends on 4xx && EXPERIMENTAL diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index 749fff956fe6c4..c4352e6bb71af4 100755 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -64,7 +64,8 @@ #define UART0_IO_BASE (u8 *) 0xE0000200 #define UART1_IO_BASE (u8 *) 0xE0000300 -#define BASE_BAUD 33000000/3/16 +/* external Epson SG-615P */ +#define BASE_BAUD 691200 #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile index 334015b3cf2858..c59d4871d95094 100644 --- a/arch/ppc/platforms/Makefile +++ b/arch/ppc/platforms/Makefile @@ -2,13 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_40x -EXTRA_AFLAGS := -Wa,-m405 -endif - # Extra CFLAGS so we don't have to do relative includes CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm @@ -26,7 +19,6 @@ obj-$(CONFIG_NVRAM) += pmac_nvram.o obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o endif obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o -obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o obj-$(CONFIG_EST8260) += est8260_setup.o diff --git a/arch/ppc/platforms/error_log.c b/arch/ppc/platforms/error_log.c deleted file mode 100644 index 4a71e1885fd2b1..00000000000000 --- a/arch/ppc/platforms/error_log.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * arch/ppc/kernel/error_log.c - * - * Copyright (c) 2000 Tilmann Bitterberg - * (tilmann@bitterberg.de) - * - * Error processing of errors found by rtas even-scan routine - * which is done with every heartbeat. (chrp_setup.c) - */ - -#include <linux/sched.h> - -#include <asm/prom.h> - -#include "error_log.h" - -/* ****************************************************************** */ -/* - * EVENT-SCAN - * The whole stuff below here doesn't take any action when it found - * an error, it just prints as much information as possible and - * then its up to the user to decide what to do. - * - * Returns 0 if no errors were found - * Returns 1 if there may be more errors - */ -int ppc_rtas_errorlog_scan(void) -{ -const char *_errlog_severity[] = { -#ifdef VERBOSE_ERRORS - "No Error\n\t\ -Should require no further information", - "Event\n\t\ -This is not really an error, it is an event. I use events\n\t\ -to communicate with RTAS back and forth.", - "Warning\n\t\ -Indicates a non-state-losing error, either fully recovered\n\t\ -by RTAS or not needing recovery. Ignore it.", - "Error sync\n\t\ -May only be fatal to a certain program or thread. Recovery\n\t\ -and continuation is possible, if I only had a handler for\n\t\ -this. Less serious", - "Error\n\t\ -Less serious, but still causing a loss of data and state.\n\t\ -I can't tell you exactly what to do, You have to decide\n\t\ -with help from the target and initiator field, what kind\n\t\ -of further actions may take place.", - "Fatal\n\t\ -Represent a permanent hardware failure and I believe this\n\t\ -affects my overall performance and behaviour. I would not\n\t\ -attempt to continue normal operation." -#else - "No Error", - "Event", - "Warning", - "Error sync", - "Error", - "Fatal" -#endif /* VERBOSE_ERRORS */ -}; - -#if 0 /* unused?? */ -const char *_errlog_disposition[] = { -#ifdef VERBOSE_ERRORS - "Fully recovered\n\t\ -There was an error, but it is fully recovered by RTAS.", - "Limited recovery\n\t\ -RTAS was able to recover the state of the machine, but some\n\t\ -feature of the machine has been disabled or lost (for example\n\t\ -error checking) or performance may suffer.", - "Not recovered\n\t\ -Whether RTAS did not try to recover anything or recovery failed:\n\t\ -HOUSTON, WE HAVE A PROBLEM!" -#else - "Fully recovered", - "Limited recovery", - "Not recovered" -#endif /* VERBOSE_ERRORS */ -}; -#endif - -const char *_errlog_extended[] = { -#ifdef VERBOSE_ERRORS - "Not present\n\t\ -Sad, the RTAS call didn't return an extended error log.", - "Present\n\t\ -The extended log is present and hopefully it contains a lot of\n\t\ -useful information, which leads to the solution of the problem." -#else - "Not present", - "Present" -#endif /* VERBOSE_ERRORS */ -}; - -const char *_errlog_initiator[] = { - "Unknown or not applicable", - "CPU", - "PCI", - "ISA", - "Memory", - "Power management" -}; - -const char *_errlog_target[] = { - "Unknown or not applicable", - "CPU", - "PCI", - "ISA", - "Memory", - "Power management" -}; - rtas_error_log error_log; - char logdata[1024]; - int error; -#if 0 /* unused?? */ - int retries = 0; /* if HW error, try 10 times */ -#endif - - error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log, - INTERNAL_ERROR | EPOW_WARNING, - 0, __pa(logdata), 1024); - - if (error == 1) /* no errors found */ - return 0; - - if (error == -1) { - printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n"); - return 0; - } - if (error_log.version != 1) - printk(KERN_WARNING "Unknown version (%d), please implement me\n", - error_log.version); - - switch (error_log.disposition) { - case DISP_FULLY_RECOVERED: - /* there was an error, but everything is fine now */ - return 0; - case DISP_NOT_RECOVERED: - printk("We have a really serious Problem!\n"); - case DISP_LIMITED_RECOVERY: - printk("Error classification\n"); - printk("Severity : %s\n", - ppc_rtas_errorlog_check_severity (error_log)); - printk("Initiator : %s\n", - ppc_rtas_errorlog_check_initiator (error_log)); - printk("Target : %s\n", - ppc_rtas_errorlog_check_target (error_log)); - printk("Type : %s\n", - ppc_rtas_errorlog_check_type (error_log)); - printk("Ext. log : %s\n", - ppc_rtas_errorlog_check_extended (error_log)); - if (error_log.extended) - ppc_rtas_errorlog_disect_extended (logdata); - return 1; - default: - /* nothing */ - break; - } - return 0; -} -/* ****************************************************************** */ -const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log) -{ - const char *_errlog_type[] = { - "unknown type", - "too many tries failed", - "TCE error", - "RTAS device failed", - "target timed out", - "parity error on data", /* 5 */ - "parity error on address", - "parity error on external cache", - "access to invalid address", - "uncorrectable ECC error", - "corrected ECC error" /* 10 */ - }; - if (error_log.type == TYPE_EPOW) - return "EPOW"; - if (error_log.type >= TYPE_PMGM_POWER_SW_ON) - return "PowerMGM Event (not handled right now)"; - return _errlog_type[error_log.type]; -} - diff --git a/arch/ppc/platforms/error_log.h b/arch/ppc/platforms/error_log.h deleted file mode 100644 index b8226aef3d4aa7..00000000000000 --- a/arch/ppc/platforms/error_log.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef __ERROR_LOG_H__ -#define __ERROR_LOG_H__ - -#define VERBOSE_ERRORS 1 /* Maybe I enlarge the kernel too much */ -#undef VERBOSE_ERRORS - -/* Event classes */ -/* XXX: Endianess correct? NOW*/ -#define INTERNAL_ERROR 0x80000000 /* set bit 0 */ -#define EPOW_WARNING 0x40000000 /* set bit 1 */ -#define POWERMGM_EVENTS 0x20000000 /* set bit 2 */ - -/* event-scan returns */ -#define SEVERITY_FATAL 0x5 -#define SEVERITY_ERROR 0x4 -#define SEVERITY_ERROR_SYNC 0x3 -#define SEVERITY_WARNING 0x2 -#define SEVERITY_EVENT 0x1 -#define SEVERITY_NO_ERROR 0x0 -#define DISP_FULLY_RECOVERED 0x0 -#define DISP_LIMITED_RECOVERY 0x1 -#define DISP_NOT_RECOVERED 0x2 -#define PART_PRESENT 0x0 -#define PART_NOT_PRESENT 0x1 -#define INITIATOR_UNKNOWN 0x0 -#define INITIATOR_CPU 0x1 -#define INITIATOR_PCI 0x2 -#define INITIATOR_ISA 0x3 -#define INITIATOR_MEMORY 0x4 -#define INITIATOR_POWERMGM 0x5 -#define TARGET_UNKNOWN 0x0 -#define TARGET_CPU 0x1 -#define TARGET_PCI 0x2 -#define TARGET_ISA 0x3 -#define TARGET_MEMORY 0x4 -#define TARGET_POWERMGM 0x5 -#define TYPE_RETRY 0x01 -#define TYPE_TCE_ERR 0x02 -#define TYPE_INTERN_DEV_FAIL 0x03 -#define TYPE_TIMEOUT 0x04 -#define TYPE_DATA_PARITY 0x05 -#define TYPE_ADDR_PARITY 0x06 -#define TYPE_CACHE_PARITY 0x07 -#define TYPE_ADDR_INVALID 0x08 -#define TYPE_ECC_UNCORR 0x09 -#define TYPE_ECC_CORR 0x0a -#define TYPE_EPOW 0x40 -/* I don't add PowerMGM events right now, this is a different topic */ -#define TYPE_PMGM_POWER_SW_ON 0x60 -#define TYPE_PMGM_POWER_SW_OFF 0x61 -#define TYPE_PMGM_LID_OPEN 0x62 -#define TYPE_PMGM_LID_CLOSE 0x63 -#define TYPE_PMGM_SLEEP_BTN 0x64 -#define TYPE_PMGM_WAKE_BTN 0x65 -#define TYPE_PMGM_BATTERY_WARN 0x66 -#define TYPE_PMGM_BATTERY_CRIT 0x67 -#define TYPE_PMGM_SWITCH_TO_BAT 0x68 -#define TYPE_PMGM_SWITCH_TO_AC 0x69 -#define TYPE_PMGM_KBD_OR_MOUSE 0x6a -#define TYPE_PMGM_ENCLOS_OPEN 0x6b -#define TYPE_PMGM_ENCLOS_CLOSED 0x6c -#define TYPE_PMGM_RING_INDICATE 0x6d -#define TYPE_PMGM_LAN_ATTENTION 0x6e -#define TYPE_PMGM_TIME_ALARM 0x6f -#define TYPE_PMGM_CONFIG_CHANGE 0x70 -#define TYPE_PMGM_SERVICE_PROC 0x71 - -typedef struct _rtas_error_log { - unsigned long version:8; /* Architectural version */ - unsigned long severity:3; /* Severity level of error */ - unsigned long disposition:2; /* Degree of recovery */ - unsigned long extended:1; /* extended log present? */ - unsigned long /* reserved */ :2; /* Reserved for future use */ - unsigned long initiator:4; /* Initiator of event */ - unsigned long target:4; /* Target of failed operation */ - unsigned long type:8; /* General event or error*/ - unsigned long extended_log_length:32; /* length in bytes */ -} rtas_error_log; - -/* ****************************************************************** */ -#define ppc_rtas_errorlog_check_severity(x) \ - (_errlog_severity[x.severity]) -#define ppc_rtas_errorlog_check_target(x) \ - (_errlog_target[x.target]) -#define ppc_rtas_errorlog_check_initiator(x) \ - (_errlog_initiator[x.initiator]) -#define ppc_rtas_errorlog_check_extended(x) \ - (_errlog_extended[x.extended]) -#define ppc_rtas_errorlog_disect_extended(x) \ - do { /* implement me */ } while(0) -extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log); -extern int ppc_rtas_errorlog_scan(void); - - -#endif /* __ERROR_LOG_H__ */ diff --git a/arch/ppc/platforms/proc_rtas.c b/arch/ppc/platforms/proc_rtas.c deleted file mode 100644 index f24f39923916fd..00000000000000 --- a/arch/ppc/platforms/proc_rtas.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * arch/ppc/platforms/proc_rtas.c - * Copyright (C) 2000 Tilmann Bitterberg - * (tilmann@bitterberg.de) - * - * RTAS (Runtime Abstraction Services) stuff - * Intention is to provide a clean user interface - * to use the RTAS. - * - * TODO: - * Split off a header file and maybe move it to a different - * location. Write Documentation on what the /proc/rtas/ entries - * actually do. - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/ctype.h> -#include <linux/time.h> -#include <linux/string.h> -#include <linux/init.h> - -#include <asm/uaccess.h> -#include <asm/bitops.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/prom.h> -#include <asm/machdep.h> /* for ppc_md */ -#include <asm/time.h> - -/* Token for Sensors */ -#define KEY_SWITCH 0x0001 -#define ENCLOSURE_SWITCH 0x0002 -#define THERMAL_SENSOR 0x0003 -#define LID_STATUS 0x0004 -#define POWER_SOURCE 0x0005 -#define BATTERY_VOLTAGE 0x0006 -#define BATTERY_REMAINING 0x0007 -#define BATTERY_PERCENTAGE 0x0008 -#define EPOW_SENSOR 0x0009 -#define BATTERY_CYCLESTATE 0x000a -#define BATTERY_CHARGING 0x000b - -/* IBM specific sensors */ -#define IBM_SURVEILLANCE 0x2328 /* 9000 */ -#define IBM_FANRPM 0x2329 /* 9001 */ -#define IBM_VOLTAGE 0x232a /* 9002 */ -#define IBM_DRCONNECTOR 0x232b /* 9003 */ -#define IBM_POWERSUPPLY 0x232c /* 9004 */ -#define IBM_INTQUEUE 0x232d /* 9005 */ - -/* Status return values */ -#define SENSOR_CRITICAL_HIGH 13 -#define SENSOR_WARNING_HIGH 12 -#define SENSOR_NORMAL 11 -#define SENSOR_WARNING_LOW 10 -#define SENSOR_CRITICAL_LOW 9 -#define SENSOR_SUCCESS 0 -#define SENSOR_HW_ERROR -1 -#define SENSOR_BUSY -2 -#define SENSOR_NOT_EXIST -3 -#define SENSOR_DR_ENTITY -9000 - -/* Location Codes */ -#define LOC_SCSI_DEV_ADDR 'A' -#define LOC_SCSI_DEV_LOC 'B' -#define LOC_CPU 'C' -#define LOC_DISKETTE 'D' -#define LOC_ETHERNET 'E' -#define LOC_FAN 'F' -#define LOC_GRAPHICS 'G' -/* reserved / not used 'H' */ -#define LOC_IO_ADAPTER 'I' -/* reserved / not used 'J' */ -#define LOC_KEYBOARD 'K' -#define LOC_LCD 'L' -#define LOC_MEMORY 'M' -#define LOC_NV_MEMORY 'N' -#define LOC_MOUSE 'O' -#define LOC_PLANAR 'P' -#define LOC_OTHER_IO 'Q' -#define LOC_PARALLEL 'R' -#define LOC_SERIAL 'S' -#define LOC_DEAD_RING 'T' -#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */ -#define LOC_VOLTAGE 'V' -#define LOC_SWITCH_ADAPTER 'W' -#define LOC_OTHER 'X' -#define LOC_FIRMWARE 'Y' -#define LOC_SCSI 'Z' - -/* Tokens for indicators */ -#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/ -#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */ -#define SYSTEM_POWER_STATE 0x0003 -#define WARNING_LIGHT 0x0004 -#define DISK_ACTIVITY_LIGHT 0x0005 -#define HEX_DISPLAY_UNIT 0x0006 -#define BATTERY_WARNING_TIME 0x0007 -#define CONDITION_CYCLE_REQUEST 0x0008 -#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */ -#define DR_ACTION 0x2329 /* 9001 */ -#define DR_INDICATOR 0x232a /* 9002 */ -/* 9003 - 9004: Vendor specific */ -#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */ -/* 9006 - 9999: Vendor specific */ - -/* other */ -#define MAX_SENSORS 17 /* I only know of 17 sensors */ -#define MAX_LINELENGTH 256 -#define SENSOR_PREFIX "ibm,sensor-" -#define cel_to_fahr(x) ((x*9/5)+32) - - -/* Globals */ -static struct proc_dir_entry *proc_rtas; -static struct rtas_sensors sensors; -static struct device_node *rtas; -static unsigned long power_on_time = 0; /* Save the time the user set */ -static char progress_led[MAX_LINELENGTH]; - -static unsigned long rtas_tone_frequency = 1000; -static unsigned long rtas_tone_volume = 0; - -/* ****************STRUCTS******************************************* */ -struct individual_sensor { - unsigned int token; - unsigned int quant; -}; - -struct rtas_sensors { - struct individual_sensor sensor[MAX_SENSORS]; - unsigned int quant; -}; - -/* ****************************************************************** */ -/* Declarations */ -static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, - int count, int *eof, void *data); -static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); - -static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, - size_t count, loff_t *ppos); - -struct file_operations ppc_rtas_poweron_operations = { - .read = ppc_rtas_poweron_read, - .write = ppc_rtas_poweron_write -}; -struct file_operations ppc_rtas_progress_operations = { - .read = ppc_rtas_progress_read, - .write = ppc_rtas_progress_write -}; - -struct file_operations ppc_rtas_clock_operations = { - .read = ppc_rtas_clock_read, - .write = ppc_rtas_clock_write -}; - -struct file_operations ppc_rtas_tone_freq_operations = { - .read = ppc_rtas_tone_freq_read, - .write = ppc_rtas_tone_freq_write -}; -struct file_operations ppc_rtas_tone_volume_operations = { - .read = ppc_rtas_tone_volume_read, - .write = ppc_rtas_tone_volume_write -}; - -int ppc_rtas_find_all_sensors (void); -int ppc_rtas_process_sensor(struct individual_sensor s, int state, - int error, char * buf); -char * ppc_rtas_process_error(int error); -int get_location_code(struct individual_sensor s, char * buf); -int check_location_string (char *c, char * buf); -int check_location (char *c, int idx, char * buf); - -/* ****************************************************************** */ -/* MAIN */ -/* ****************************************************************** */ -static int __init proc_rtas_init(void) -{ - struct proc_dir_entry *entry; - - rtas = find_devices("rtas"); - if ((rtas == 0) || (_machine != _MACH_chrp)) { - return 1; - } - - proc_rtas = proc_mkdir("rtas", 0); - if (proc_rtas == 0) - return 1; - - /* /proc/rtas entries */ - - entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_progress_operations; - - entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_clock_operations; - - entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_poweron_operations; - - create_proc_read_entry("sensors", S_IRUGO, proc_rtas, - ppc_rtas_sensor_read, NULL); - - entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations; - - entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations; - - return 0; -} -__initcall(proc_rtas_init); - -/* ****************************************************************** */ -/* POWER-ON-TIME */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - char *dest; - int error; - - nowtime = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_poweron_write: Invalid time\n"); - return count; - } - power_on_time = nowtime; /* save the time */ - - to_tm(nowtime, &tm); - - error = call_rtas("set-time-for-power-on", 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); - if (error != 0) - printk(KERN_WARNING "error: setting poweron time returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - if (power_on_time == 0) - n = sprintf(buf, "Power on time not set\n"); - else - n = sprintf(buf, "%lu\n", power_on_time); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* PROGRESS */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long hex; - - strcpy(progress_led, buf); /* save the string */ - /* Lets see if the user passed hexdigits */ - hex = simple_strtoul(buf, NULL, 10); - - ppc_md.progress ((char *)buf, hex); - return count; - - /* clear the line */ /* ppc_md.progress(" ", 0xffff);*/ -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n = 0; - if (progress_led != NULL) - n = sprintf (buf, "%s\n", progress_led); - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* CLOCK */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - char *dest; - int error; - - nowtime = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_clock_write: Invalid time\n"); - return count; - } - - to_tm(nowtime, &tm); - error = call_rtas("set-time-of-day", 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0); - if (error != 0) - printk(KERN_WARNING "error: setting the clock returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - unsigned int year, mon, day, hour, min, sec; - unsigned long *ret = kmalloc(4*8, GFP_KERNEL); - int n, error; - - error = call_rtas("get-time-of-day", 0, 8, ret); - - year = ret[0]; mon = ret[1]; day = ret[2]; - hour = ret[3]; min = ret[4]; sec = ret[5]; - - if (error != 0){ - printk(KERN_WARNING "error: reading the clock returned: %s\n", - ppc_rtas_process_error(error)); - n = sprintf (buf, "0"); - } else { - n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec)); - } - kfree(ret); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* SENSOR STUFF */ -/* ****************************************************************** */ -static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, - int count, int *eof, void *data) -{ - int i,j,n; - unsigned long ret; - int state, error; - char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */ - - if (count < 0) - return -EINVAL; - - n = sprintf ( buffer , "RTAS (RunTime Abstraction Services) Sensor Information\n"); - n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n"); - n += sprintf ( buffer+n, "********************************************************\n"); - - if (ppc_rtas_find_all_sensors() != 0) { - n += sprintf ( buffer+n, "\nNo sensors are available\n"); - goto return_string; - } - - for (i=0; i<sensors.quant; i++) { - j = sensors.sensor[i].quant; - /* A sensor may have multiple instances */ - while (j >= 0) { - error = call_rtas("get-sensor-state", 2, 2, &ret, - sensors.sensor[i].token, sensors.sensor[i].quant-j); - state = (int) ret; - n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n ); - n += sprintf (buffer+n, "\n"); - j--; - } /* while */ - } /* for */ - -return_string: - if (off >= strlen(buffer)) { - *eof = 1; - return 0; - } - if (n > strlen(buffer) - off) - n = strlen(buffer) - off; - if (n > count) - n = count; - else - *eof = 1; - memcpy(buf, buffer + off, n); - *start = buf; - return n; -} - -/* ****************************************************************** */ - -int ppc_rtas_find_all_sensors (void) -{ - unsigned long *utmp; - int len, i, j; - - utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len); - if (utmp == NULL) { - printk (KERN_ERR "error: could not get rtas-sensors\n"); - return 1; - } - - sensors.quant = len / 8; /* int + int */ - - for (i=0, j=0; j<sensors.quant; i+=2, j++) { - sensors.sensor[j].token = utmp[i]; - sensors.sensor[j].quant = utmp[i+1]; - } - return 0; -} - -/* ****************************************************************** */ -/* - * Builds a string of what rtas returned - */ -char * ppc_rtas_process_error(int error) -{ - switch (error) { - case SENSOR_CRITICAL_HIGH: - return "(critical high)"; - case SENSOR_WARNING_HIGH: - return "(warning high)"; - case SENSOR_NORMAL: - return "(normal)"; - case SENSOR_WARNING_LOW: - return "(warning low)"; - case SENSOR_CRITICAL_LOW: - return "(critical low)"; - case SENSOR_SUCCESS: - return "(read ok)"; - case SENSOR_HW_ERROR: - return "(hardware error)"; - case SENSOR_BUSY: - return "(busy)"; - case SENSOR_NOT_EXIST: - return "(non existant)"; - case SENSOR_DR_ENTITY: - return "(dr entity removed)"; - default: - return "(UNKNOWN)"; - } -} - -/* ****************************************************************** */ -/* - * Builds a string out of what the sensor said - */ - -int ppc_rtas_process_sensor(struct individual_sensor s, int state, - int error, char * buf) -{ - /* Defined return vales */ - const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" }; - const char * enclosure_switch[] = { "Closed", "Open" }; - const char * lid_status[] = { " ", "Open", "Closed" }; - const char * power_source[] = { "AC\t", "Battery", "AC & Battery" }; - const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" }; - const char * epow_sensor[] = { - "EPOW Reset", "Cooling warning", "Power warning", - "System shutdown", "System halt", "EPOW main enclosure", - "EPOW power off" }; - const char * battery_cyclestate[] = { "None", "In progress", "Requested" }; - const char * battery_charging[] = { "Charging", "Discharching", "No current flow" }; - const char * ibm_drconnector[] = { "Empty", "Present" }; - const char * ibm_intqueue[] = { "Disabled", "Enabled" }; - - int have_strings = 0; - int temperature = 0; - int unknown = 0; - int n = 0; - - /* What kind of sensor do we have here? */ - switch (s.token) { - case KEY_SWITCH: - n += sprintf(buf+n, "Key switch:\t"); - n += sprintf(buf+n, "%s\t", key_switch[state]); - have_strings = 1; - break; - case ENCLOSURE_SWITCH: - n += sprintf(buf+n, "Enclosure switch:\t"); - n += sprintf(buf+n, "%s\t", enclosure_switch[state]); - have_strings = 1; - break; - case THERMAL_SENSOR: - n += sprintf(buf+n, "Temp. (°C/°F):\t"); - temperature = 1; - break; - case LID_STATUS: - n += sprintf(buf+n, "Lid status:\t"); - n += sprintf(buf+n, "%s\t", lid_status[state]); - have_strings = 1; - break; - case POWER_SOURCE: - n += sprintf(buf+n, "Power source:\t"); - n += sprintf(buf+n, "%s\t", power_source[state]); - have_strings = 1; - break; - case BATTERY_VOLTAGE: - n += sprintf(buf+n, "Battery voltage:\t"); - break; - case BATTERY_REMAINING: - n += sprintf(buf+n, "Battery remaining:\t"); - n += sprintf(buf+n, "%s\t", battery_remaining[state]); - have_strings = 1; - break; - case BATTERY_PERCENTAGE: - n += sprintf(buf+n, "Battery percentage:\t"); - break; - case EPOW_SENSOR: - n += sprintf(buf+n, "EPOW Sensor:\t"); - n += sprintf(buf+n, "%s\t", epow_sensor[state]); - have_strings = 1; - break; - case BATTERY_CYCLESTATE: - n += sprintf(buf+n, "Battery cyclestate:\t"); - n += sprintf(buf+n, "%s\t", battery_cyclestate[state]); - have_strings = 1; - break; - case BATTERY_CHARGING: - n += sprintf(buf+n, "Battery Charging:\t"); - n += sprintf(buf+n, "%s\t", battery_charging[state]); - have_strings = 1; - break; - case IBM_SURVEILLANCE: - n += sprintf(buf+n, "Surveillance:\t"); - break; - case IBM_FANRPM: - n += sprintf(buf+n, "Fan (rpm):\t"); - break; - case IBM_VOLTAGE: - n += sprintf(buf+n, "Voltage (mv):\t"); - break; - case IBM_DRCONNECTOR: - n += sprintf(buf+n, "DR connector:\t"); - n += sprintf(buf+n, "%s\t", ibm_drconnector[state]); - have_strings = 1; - break; - case IBM_POWERSUPPLY: - n += sprintf(buf+n, "Powersupply:\t"); - break; - case IBM_INTQUEUE: - n += sprintf(buf+n, "Interrupt queue:\t"); - n += sprintf(buf+n, "%s\t", ibm_intqueue[state]); - have_strings = 1; - break; - default: - n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", - s.token); - unknown = 1; - have_strings = 1; - break; - } - if (have_strings == 0) { - if (temperature) { - n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state)); - } else - n += sprintf(buf+n, "%10d\t", state); - } - if (unknown == 0) { - n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error)); - n += get_location_code(s, buf+n); - } - return n; -} - -/* ****************************************************************** */ - -int check_location (char *c, int idx, char * buf) -{ - int n = 0; - - switch (*(c+idx)) { - case LOC_PLANAR: - n += sprintf ( buf, "Planar #%c", *(c+idx+1)); - break; - case LOC_CPU: - n += sprintf ( buf, "CPU #%c", *(c+idx+1)); - break; - case LOC_FAN: - n += sprintf ( buf, "Fan #%c", *(c+idx+1)); - break; - case LOC_RACKMOUNTED: - n += sprintf ( buf, "Rack #%c", *(c+idx+1)); - break; - case LOC_VOLTAGE: - n += sprintf ( buf, "Voltage #%c", *(c+idx+1)); - break; - case LOC_LCD: - n += sprintf ( buf, "LCD #%c", *(c+idx+1)); - break; - case '.': - n += sprintf ( buf, "- %c", *(c+idx+1)); - default: - n += sprintf ( buf, "Unknown location"); - break; - } - return n; -} - - -/* ****************************************************************** */ -/* - * Format: - * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ] - * the '.' may be an abbrevation - */ -int check_location_string (char *c, char *buf) -{ - int n=0,i=0; - - while (c[i]) { - if (isalpha(c[i]) || c[i] == '.') { - n += check_location(c, i, buf+n); - } - else if (c[i] == '/' || c[i] == '-') - n += sprintf(buf+n, " at "); - i++; - } - return n; -} - - -/* ****************************************************************** */ - -int get_location_code(struct individual_sensor s, char * buffer) -{ - char rstr[512], tmp[10], tmp2[10]; - int n=0, i=0, llen, len; - /* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */ - char *ret; - - static int pos = 0; /* remember position where buffer was */ - - /* construct the sensor number like 0003 */ - /* fill with zeros */ - n = sprintf(tmp, "%d", s.token); - len = strlen(tmp); - while (strlen(tmp) < 4) - n += sprintf (tmp+n, "0"); - - /* invert the string */ - while (tmp[i]) { - if (i<len) - tmp2[4-len+i] = tmp[i]; - else - tmp2[3-i] = tmp[i]; - i++; - } - tmp2[4] = '\0'; - - sprintf (rstr, SENSOR_PREFIX"%s", tmp2); - - ret = (char *) get_property(rtas, rstr, &llen); - - n=0; - if (ret[0] == '\0') - n += sprintf ( buffer+n, "--- ");/* does not have a location */ - else { - char t[50]; - ret += pos; - - n += check_location_string(ret, buffer + n); - n += sprintf ( buffer+n, " "); - /* see how many characters we have printed */ - sprintf ( t, "%s ", ret); - - pos += strlen(t); - if (pos >= llen) pos=0; - } - return n; -} -/* ****************************************************************** */ -/* INDICATORS - Tone Frequency */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long freq; - char *dest; - int error; - freq = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n"); - return count; - } - if (freq < 0) freq = 0; - rtas_tone_frequency = freq; /* save it for later */ - error = call_rtas("set-indicator", 3, 1, NULL, - TONE_FREQUENCY, 0, freq); - if (error != 0) - printk(KERN_WARNING "error: setting tone frequency returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - n = sprintf(buf, "%lu\n", rtas_tone_frequency); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} -/* ****************************************************************** */ -/* INDICATORS - Tone Volume */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long volume; - char *dest; - int error; - volume = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_tone_volume_write: Invalid tone volume\n"); - return count; - } - if (volume < 0) volume = 0; - if (volume > 100) volume = 100; - - rtas_tone_volume = volume; /* save it for later */ - error = call_rtas("set-indicator", 3, 1, NULL, - TONE_VOLUME, 0, volume); - if (error != 0) - printk(KERN_WARNING "error: setting tone volume returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - n = sprintf(buf, "%lu\n", rtas_tone_volume); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 0939624fb66e47..4de92f49857e2f 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -2,16 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_4xx -EXTRA_AFLAGS := -Wa,-m405 -endif -ifdef CONFIG_E500 -EXTRA_AFLAGS := -Wa,-me500 -endif - CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC @@ -25,7 +15,8 @@ ifeq ($(CONFIG_4xx),y) obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_setup.o obj-$(CONFIG_GEN_RTC) += todc_time.o -obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o +obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o +obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index 050e12bc59fb7e..b2f3d850503cde 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -1,42 +1,427 @@ /* - * Author: Pete Popov <ppopov@mvista.com> or source@mvista.com + * arch/ppc/kernel/ppc4xx_dma.c * - * arch/ppc/kernel/ppc405_dma.c + * IBM PPC4xx DMA engine core library * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. + * Copyright 2000-2004 MontaVista Software Inc. * - * IBM 405 DMA Controller Functions + * Cleaned up and converted to new DCR access + * Matt Porter <mporter@kernel.crashing.org> + * + * Original code by Armin Kuster <akuster@mvista.com> + * and Pete Popov <ppopov@mvista.com> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/config.h> #include <linux/kernel.h> -#include <asm/system.h> -#include <asm/io.h> #include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/init.h> #include <linux/module.h> -#include <asm/ppc405_dma.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/ppc4xx_dma.h> + +ppc_dma_ch_t dma_channels[MAX_PPC4xx_DMA_CHANNELS]; + +int +ppc4xx_get_dma_status(void) +{ + return (mfdcr(DCRN_DMASR)); +} + +void +ppc4xx_set_src_addr(int dmanr, phys_addr_t src_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_src_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA64BIT + mtdcr(DCRN_DMASAH0 + dmanr*2, (u32)(src_addr >> 32)); +#else + mtdcr(DCRN_DMASA0 + dmanr*2, (u32)src_addr); +#endif +} + +void +ppc4xx_set_dst_addr(int dmanr, phys_addr_t dst_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_dst_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA64BIT + mtdcr(DCRN_DMADAH0 + dmanr*2, (u32)(dst_addr >> 32)); +#else + mtdcr(DCRN_DMADA0 + dmanr*2, (u32)dst_addr); +#endif +} + +void +ppc4xx_enable_dma(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + unsigned int status_bits[] = { DMA_CS0 | DMA_TS0 | DMA_CH0_ERR, + DMA_CS1 | DMA_TS1 | DMA_CH1_ERR, + DMA_CS2 | DMA_TS2 | DMA_CH2_ERR, + DMA_CS3 | DMA_TS3 | DMA_CH3_ERR}; + + if (p_dma_ch->in_use) { + printk("enable_dma: channel %d in use\n", dmanr); + return; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("enable_dma: bad channel: %d\n", dmanr); + return; + } + + if (p_dma_ch->mode == DMA_MODE_READ) { + /* peripheral to memory */ + ppc4xx_set_src_addr(dmanr, 0); + ppc4xx_set_dst_addr(dmanr, p_dma_ch->addr); + } else if (p_dma_ch->mode == DMA_MODE_WRITE) { + /* memory to peripheral */ + ppc4xx_set_src_addr(dmanr, p_dma_ch->addr); + ppc4xx_set_dst_addr(dmanr, 0); + } + + /* for other xfer modes, the addresses are already set */ + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + + control &= ~(DMA_TM_MASK | DMA_TD); /* clear all mode bits */ + if (p_dma_ch->mode == DMA_MODE_MM) { + /* software initiated memory to memory */ + control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE; + } + + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + /* + * Clear the CS, TS, RI bits for the channel from DMASR. This + * has been observed to happen correctly only after the mode and + * ETD/DCE bits in DMACRx are set above. Must do this before + * enabling the channel. + */ + + mtdcr(DCRN_DMASR, status_bits[dmanr]); + + /* + * For device-paced transfers, Terminal Count Enable apparently + * must be on, and this must be turned on after the mode, etc. + * bits are cleared above (at least on Redwood-6). + */ + + if ((p_dma_ch->mode == DMA_MODE_MM_DEVATDST) || + (p_dma_ch->mode == DMA_MODE_MM_DEVATSRC)) + control |= DMA_TCE_ENABLE; + + /* + * Now enable the channel. + */ + + control |= (p_dma_ch->mode | DMA_CE_ENABLE); + + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + p_dma_ch->in_use = 1; +} + +void +ppc4xx_disable_dma(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (!p_dma_ch->in_use) { + printk("disable_dma: channel %d not in use\n", dmanr); + return; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("disable_dma: bad channel: %d\n", dmanr); + return; + } + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control &= ~DMA_CE_ENABLE; + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + p_dma_ch->in_use = 0; +} + +/* + * Sets the dma mode for single DMA transfers only. + * For scatter/gather transfers, the mode is passed to the + * alloc_dma_handle() function as one of the parameters. + * + * The mode is simply saved and used later. This allows + * the driver to call set_dma_mode() and set_dma_addr() in + * any order. + * + * Valid mode values are: + * + * DMA_MODE_READ peripheral to memory + * DMA_MODE_WRITE memory to peripheral + * DMA_MODE_MM memory to memory + * DMA_MODE_MM_DEVATSRC device-paced memory to memory, device at src + * DMA_MODE_MM_DEVATDST device-paced memory to memory, device at dst + */ +int +ppc4xx_set_dma_mode(unsigned int dmanr, unsigned int mode) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_dma_mode: bad channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->mode = mode; + + return DMA_STATUS_GOOD; +} + +/* + * Sets the DMA Count register. Note that 'count' is in bytes. + * However, the DMA Count register counts the number of "transfers", + * where each transfer is equal to the bus width. Thus, count + * MUST be a multiple of the bus width. + */ +void +ppc4xx_set_dma_count(unsigned int dmanr, unsigned int count) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + +#ifdef DEBUG_4xxDMA + { + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (count & 0x1) + error = 1; + break; + case PW_32: + if (count & 0x3) + error = 1; + break; + case PW_64: + if (count & 0x7) + error = 1; + break; + default: + printk("set_dma_count: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk + ("Warning: set_dma_count count 0x%x bus width %d\n", + count, p_dma_ch->pwidth); + } +#endif + count = count >> p_dma_ch->shift; + + mtdcr(DCRN_DMACT0 + (dmanr * 0x8), count); +} /* - * Function prototypes + * Returns the number of bytes left to be transfered. + * After a DMA transfer, this should return zero. + * Reading this while a DMA transfer is still in progress will return + * unpredictable results. */ +int +ppc4xx_get_dma_residue(unsigned int dmanr) +{ + unsigned int count; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; -int hw_init_dma_channel(unsigned int, ppc_dma_ch_t *); -int init_dma_channel(unsigned int); -int get_channel_config(unsigned int, ppc_dma_ch_t *); -int set_channel_priority(unsigned int, unsigned int); -unsigned int get_peripheral_width(unsigned int); -int alloc_dma_handle(sgl_handle_t *, unsigned int, unsigned int); -void free_dma_handle(sgl_handle_t); + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_dma_residue: bad channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + count = mfdcr(DCRN_DMACT0 + (dmanr * 0x8)); -ppc_dma_ch_t dma_channels[MAX_405GP_DMA_CHANNELS]; + return (count << p_dma_ch->shift); +} + +/* + * Sets the DMA address for a memory to peripheral or peripheral + * to memory transfer. The address is just saved in the channel + * structure for now and used later in enable_dma(). + */ +void +ppc4xx_set_dma_addr(unsigned int dmanr, phys_addr_t addr) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_dma_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef DEBUG_4xxDMA + { + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if ((unsigned) addr & 0x1) + error = 1; + break; + case PW_32: + if ((unsigned) addr & 0x3) + error = 1; + break; + case PW_64: + if ((unsigned) addr & 0x7) + error = 1; + break; + default: + printk("ppc4xx_set_dma_addr: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk("Warning: ppc4xx_set_dma_addr addr 0x%x bus width %d\n", + addr, p_dma_ch->pwidth); + } +#endif + + /* save dma address and program it later after we know the xfer mode */ + p_dma_ch->addr = addr; +} + +/* + * Sets both DMA addresses for a memory to memory transfer. + * For memory to peripheral or peripheral to memory transfers + * the function set_dma_addr() should be used instead. + */ +void +ppc4xx_set_dma_addr2(unsigned int dmanr, phys_addr_t src_dma_addr, + phys_addr_t dst_dma_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_dma_addr2: bad channel: %d\n", dmanr); + return; + } + +#ifdef DEBUG_4xxDMA + { + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (((unsigned) src_dma_addr & 0x1) || + ((unsigned) dst_dma_addr & 0x1) + ) + error = 1; + break; + case PW_32: + if (((unsigned) src_dma_addr & 0x3) || + ((unsigned) dst_dma_addr & 0x3) + ) + error = 1; + break; + case PW_64: + if (((unsigned) src_dma_addr & 0x7) || + ((unsigned) dst_dma_addr & 0x7) + ) + error = 1; + break; + default: + printk("ppc4xx_set_dma_addr2: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk + ("Warning: ppc4xx_set_dma_addr2 src 0x%x dst 0x%x bus width %d\n", + src_dma_addr, dst_dma_addr, p_dma_ch->pwidth); + } +#endif + + ppc4xx_set_src_addr(dmanr, src_dma_addr); + ppc4xx_set_dst_addr(dmanr, dst_dma_addr); +} + +/* + * Enables the channel interrupt. + * + * If performing a scatter/gatter transfer, this function + * MUST be called before calling alloc_dma_handle() and building + * the sgl list. Otherwise, interrupts will not be enabled, if + * they were previously disabled. + */ +int +ppc4xx_enable_dma_interrupt(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_enable_dma_interrupt: bad channel: %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->int_enable = 1; + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control |= DMA_CIE_ENABLE; /* Channel Interrupt Enable */ + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + return DMA_STATUS_GOOD; +} + +/* + * Disables the channel interrupt. + * + * If performing a scatter/gatter transfer, this function + * MUST be called before calling alloc_dma_handle() and building + * the sgl list. Otherwise, interrupts will not be disabled, if + * they were previously enabled. + */ +int +ppc4xx_disable_dma_interrupt(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_disable_dma_interrupt: bad channel: %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->int_enable = 0; + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control &= ~DMA_CIE_ENABLE; /* Channel Interrupt Enable */ + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + return DMA_STATUS_GOOD; +} /* * Configures a DMA channel, including the peripheral bus width, if a @@ -47,166 +432,112 @@ ppc_dma_ch_t dma_channels[MAX_405GP_DMA_CHANNELS]; * called from platform specific init code. The driver should not need to * call this function. */ -int hw_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t *p_init) +int +ppc4xx_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t * p_init) { - unsigned int polarity; - uint32_t control = 0; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - -#ifdef DEBUG_405DMA - if (!p_init) { - printk("hw_init_dma_channel: NULL p_init\n"); - return DMA_STATUS_NULL_POINTER; - } - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("hw_init_dma_channel: bad channel %d\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif + unsigned int polarity; + uint32_t control = 0; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + DMA_MODE_READ = (unsigned long) DMA_TD; /* Peripheral to Memory */ + DMA_MODE_WRITE = 0; /* Memory to Peripheral */ + + if (!p_init) { + printk("ppc4xx_init_dma_channel: NULL p_init\n"); + return DMA_STATUS_NULL_POINTER; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_init_dma_channel: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } #if DCRN_POL > 0 - polarity = mfdcr(DCRN_POL); + polarity = mfdcr(DCRN_POL); #else - polarity = 0; + polarity = 0; #endif - /* Setup the control register based on the values passed to - * us in p_init. Then, over-write the control register with this - * new value. - */ - - control |= ( - SET_DMA_CIE_ENABLE(p_init->int_enable) | /* interrupt enable */ - SET_DMA_BEN(p_init->buffer_enable) | /* buffer enable */ - SET_DMA_ETD(p_init->etd_output) | /* end of transfer pin */ - SET_DMA_TCE(p_init->tce_enable) | /* terminal count enable */ - SET_DMA_PL(p_init->pl) | /* peripheral location */ - SET_DMA_DAI(p_init->dai) | /* dest addr increment */ - SET_DMA_SAI(p_init->sai) | /* src addr increment */ - SET_DMA_PRIORITY(p_init->cp) | /* channel priority */ - SET_DMA_PW(p_init->pwidth) | /* peripheral/bus width */ - SET_DMA_PSC(p_init->psc) | /* peripheral setup cycles */ - SET_DMA_PWC(p_init->pwc) | /* peripheral wait cycles */ - SET_DMA_PHC(p_init->phc) | /* peripheral hold cycles */ - SET_DMA_PREFETCH(p_init->pf) /* read prefetch */ - ); - - switch (dmanr) { - case 0: - /* clear all polarity signals and then "or" in new signal levels */ - polarity &= ~(DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR0, control); - break; - case 1: - polarity &= ~(DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR1, control); - break; - case 2: - polarity &= ~(DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR2, control); - break; - case 3: - polarity &= ~(DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow); - polarity |= p_dma_ch->polarity; + /* Setup the control register based on the values passed to + * us in p_init. Then, over-write the control register with this + * new value. + */ + control |= SET_DMA_CONTROL; + + /* clear all polarity signals and then "or" in new signal levels */ + polarity &= ~GET_DMA_POLARITY(dmanr); + polarity |= p_dma_ch->polarity; #if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); + mtdcr(DCRN_POL, polarity); #endif - mtdcr(DCRN_DMACR3, control); - break; - default: - return DMA_STATUS_BAD_CHANNEL; - } - - /* save these values in our dma channel structure */ - memcpy(p_dma_ch, p_init, sizeof(ppc_dma_ch_t)); - - /* - * The peripheral width values written in the control register are: - * PW_8 0 - * PW_16 1 - * PW_32 2 - * PW_64 3 - * - * Since the DMA count register takes the number of "transfers", - * we need to divide the count sent to us in certain - * functions by the appropriate number. It so happens that our - * right shift value is equal to the peripheral width value. - */ - p_dma_ch->shift = p_init->pwidth; - - /* - * Save the control word for easy access. - */ - p_dma_ch->control = control; - - mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */ - return DMA_STATUS_GOOD; + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + /* save these values in our dma channel structure */ + memcpy(p_dma_ch, p_init, sizeof (ppc_dma_ch_t)); + + /* + * The peripheral width values written in the control register are: + * PW_8 0 + * PW_16 1 + * PW_32 2 + * PW_64 3 + * + * Since the DMA count register takes the number of "transfers", + * we need to divide the count sent to us in certain + * functions by the appropriate number. It so happens that our + * right shift value is equal to the peripheral width value. + */ + p_dma_ch->shift = p_init->pwidth; + + /* + * Save the control word for easy access. + */ + p_dma_ch->control = control; + + mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */ + return DMA_STATUS_GOOD; } - - - /* * This function returns the channel configuration. */ -int get_channel_config(unsigned int dmanr, ppc_dma_ch_t *p_dma_ch) +int +ppc4xx_get_channel_config(unsigned int dmanr, ppc_dma_ch_t * p_dma_ch) { - unsigned int polarity; - unsigned int control; + unsigned int polarity; + unsigned int control; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_channel_config: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } #if DCRN_POL > 0 - polarity = mfdcr(DCRN_POL); + polarity = mfdcr(DCRN_POL); #else - polarity = 0; + polarity = 0; #endif - switch (dmanr) { - case 0: - p_dma_ch->polarity = - polarity & (DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow); - control = mfdcr(DCRN_DMACR0); - break; - case 1: - p_dma_ch->polarity = - polarity & (DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow); - control = mfdcr(DCRN_DMACR1); - break; - case 2: - p_dma_ch->polarity = - polarity & (DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow); - control = mfdcr(DCRN_DMACR2); - break; - case 3: - p_dma_ch->polarity = - polarity & (DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow); - control = mfdcr(DCRN_DMACR3); - break; - default: - return DMA_STATUS_BAD_CHANNEL; - } - - p_dma_ch->cp = GET_DMA_PRIORITY(control); - p_dma_ch->pwidth = GET_DMA_PW(control); - p_dma_ch->psc = GET_DMA_PSC(control); - p_dma_ch->pwc = GET_DMA_PWC(control); - p_dma_ch->phc = GET_DMA_PHC(control); - p_dma_ch->pf = GET_DMA_PREFETCH(control); - p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control); - p_dma_ch->shift = GET_DMA_PW(control); - - return DMA_STATUS_GOOD; + p_dma_ch->polarity = polarity & GET_DMA_POLARITY(dmanr); + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + + p_dma_ch->cp = GET_DMA_PRIORITY(control); + p_dma_ch->pwidth = GET_DMA_PW(control); + p_dma_ch->psc = GET_DMA_PSC(control); + p_dma_ch->pwc = GET_DMA_PWC(control); + p_dma_ch->phc = GET_DMA_PHC(control); + p_dma_ch->ce = GET_DMA_CE_ENABLE(control); + p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control); + p_dma_ch->shift = GET_DMA_PW(control); + +#ifdef CONFIG_PPC4xx_EDMA + p_dma_ch->pf = GET_DMA_PREFETCH(control); +#else + p_dma_ch->ch_enable = GET_DMA_CH(control); + p_dma_ch->ece_enable = GET_DMA_ECE(control); + p_dma_ch->tcd_disable = GET_DMA_TCD(control); +#endif + return DMA_STATUS_GOOD; } /* @@ -222,50 +553,28 @@ int get_channel_config(unsigned int dmanr, ppc_dma_ch_t *p_dma_ch) * PRIORITY_HIGH * */ -int set_channel_priority(unsigned int dmanr, unsigned int priority) +int +ppc4xx_set_channel_priority(unsigned int dmanr, unsigned int priority) { - unsigned int control; - -#ifdef DEBUG_405DMA - if ( (priority != PRIORITY_LOW) && - (priority != PRIORITY_MID_LOW) && - (priority != PRIORITY_MID_HIGH) && - (priority != PRIORITY_HIGH)) { - printk("set_channel_priority: bad priority: 0x%x\n", priority); - } -#endif + unsigned int control; - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR0, control); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR1, control); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR2, control); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR3, control); - break; - default: -#ifdef DEBUG_405DMA - printk("set_channel_priority: bad channel: %d\n", dmanr); -#endif - return DMA_STATUS_BAD_CHANNEL; - } - return DMA_STATUS_GOOD; -} + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_channel_priority: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if ((priority != PRIORITY_LOW) && + (priority != PRIORITY_MID_LOW) && + (priority != PRIORITY_MID_HIGH) && (priority != PRIORITY_HIGH)) { + printk("ppc4xx_set_channel_priority: bad priority: 0x%x\n", priority); + } + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control |= SET_DMA_PRIORITY(priority); + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + return DMA_STATUS_GOOD; +} /* * Returns the width of the peripheral attached to this channel. This assumes @@ -280,213 +589,36 @@ int set_channel_priority(unsigned int dmanr, unsigned int priority) * * The function returns 0 on error. */ -unsigned int get_peripheral_width(unsigned int dmanr) +unsigned int +ppc4xx_get_peripheral_width(unsigned int dmanr) { - unsigned int control; - - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - break; - default: -#ifdef DEBUG_405DMA - printk("get_peripheral_width: bad channel: %d\n", dmanr); -#endif - return 0; - } - return(GET_DMA_PW(control)); -} - - - - -/* - * Create a scatter/gather list handle. This is simply a structure which - * describes a scatter/gather list. - * - * A handle is returned in "handle" which the driver should save in order to - * be able to access this list later. A chunk of memory will be allocated - * to be used by the API for internal management purposes, including managing - * the sg list and allocating memory for the sgl descriptors. One page should - * be more than enough for that purpose. Perhaps it's a bit wasteful to use - * a whole page for a single sg list, but most likely there will be only one - * sg list per channel. - * - * Interrupt notes: - * Each sgl descriptor has a copy of the DMA control word which the DMA engine - * loads in the control register. The control word has a "global" interrupt - * enable bit for that channel. Interrupts are further qualified by a few bits - * in the sgl descriptor count register. In order to setup an sgl, we have to - * know ahead of time whether or not interrupts will be enabled at the completion - * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST - * be called before calling alloc_dma_handle(). If the interrupt mode will never - * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt() - * do not have to be called -- interrupts will be enabled or disabled based - * on how the channel was configured after powerup by the hw_init_dma_channel() - * function. Each sgl descriptor will be setup to interrupt if an error occurs; - * however, only the last descriptor will be setup to interrupt. Thus, an - * interrupt will occur (if interrupts are enabled) only after the complete - * sgl transfer is done. - */ -int alloc_dma_handle(sgl_handle_t *phandle, unsigned int mode, unsigned int dmanr) -{ - sgl_list_info_t *psgl; - dma_addr_t dma_addr; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - uint32_t sg_command; - void *ret; - -#ifdef DEBUG_405DMA - if (!phandle) { - printk("alloc_dma_handle: null handle pointer\n"); - return DMA_STATUS_NULL_POINTER; - } - switch (mode) { - case DMA_MODE_READ: - case DMA_MODE_WRITE: - case DMA_MODE_MM: - case DMA_MODE_MM_DEVATSRC: - case DMA_MODE_MM_DEVATDST: - break; - default: - printk("alloc_dma_handle: bad mode 0x%x\n", mode); - return DMA_STATUS_BAD_MODE; - } - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("alloc_dma_handle: invalid channel 0x%x\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif + unsigned int control; - /* Get a page of memory, which is zeroed out by pci_alloc_consistent() */ - -/* wrong not a pci device - armin */ - /* psgl = (sgl_list_info_t *) pci_alloc_consistent(NULL, SGL_LIST_SIZE, &dma_addr); -*/ - - ret = consistent_alloc(GFP_ATOMIC |GFP_DMA, SGL_LIST_SIZE, &dma_addr); - if (ret != NULL) { - memset(ret, 0,SGL_LIST_SIZE ); - psgl = (sgl_list_info_t *) ret; + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_peripheral_width: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; } + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); - if (psgl == NULL) { - *phandle = (sgl_handle_t)NULL; - return DMA_STATUS_OUT_OF_MEMORY; - } - - psgl->dma_addr = dma_addr; - psgl->dmanr = dmanr; - - /* - * Modify and save the control word. These word will get written to each sgl - * descriptor. The DMA engine then loads this control word into the control - * register every time it reads a new descriptor. - */ - psgl->control = p_dma_ch->control; - psgl->control &= ~(DMA_TM_MASK | DMA_TD); /* clear all "mode" bits first */ - psgl->control |= (mode | DMA_CH_ENABLE); /* save the control word along with the mode */ - - if (p_dma_ch->int_enable) { - psgl->control |= DMA_CIE_ENABLE; /* channel interrupt enabled */ - } - else { - psgl->control &= ~DMA_CIE_ENABLE; - } - -#if DCRN_ASGC > 0 - sg_command = mfdcr(DCRN_ASGC); - switch (dmanr) { - case 0: - sg_command |= SSG0_MASK_ENABLE; - break; - case 1: - sg_command |= SSG1_MASK_ENABLE; - break; - case 2: - sg_command |= SSG2_MASK_ENABLE; - break; - case 3: - sg_command |= SSG3_MASK_ENABLE; - break; - default: -#ifdef DEBUG_405DMA - printk("alloc_dma_handle: bad channel: %d\n", dmanr); -#endif - free_dma_handle((sgl_handle_t)psgl); - *phandle = (sgl_handle_t)NULL; - return DMA_STATUS_BAD_CHANNEL; - } - - mtdcr(DCRN_ASGC, sg_command); /* enable writing to this channel's sgl control bits */ -#else - (void)sg_command; -#endif - psgl->sgl_control = SG_ERI_ENABLE | SG_LINK; /* sgl descriptor control bits */ - - if (p_dma_ch->int_enable) { - if (p_dma_ch->tce_enable) - psgl->sgl_control |= SG_TCI_ENABLE; - else - psgl->sgl_control |= SG_ETI_ENABLE; - } - - *phandle = (sgl_handle_t)psgl; - return DMA_STATUS_GOOD; -} - - - -/* - * Destroy a scatter/gather list handle that was created by alloc_dma_handle(). - * The list must be empty (contain no elements). - */ -void free_dma_handle(sgl_handle_t handle) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - - if (!handle) { -#ifdef DEBUG_405DMA - printk("free_dma_handle: got NULL\n"); -#endif - return; - } - else if (psgl->phead) { -#ifdef DEBUG_405DMA - printk("free_dma_handle: list not empty\n"); -#endif - return; - } - else if (!psgl->dma_addr) { /* should never happen */ -#ifdef DEBUG_405DMA - printk("free_dma_handle: no dma address\n"); -#endif - return; - } - - /* wrong not a PCI device -armin */ - /* pci_free_consistent(NULL, SGL_LIST_SIZE, (void *)psgl, psgl->dma_addr); */ - // free_pages((unsigned long)psgl, get_order(SGL_LIST_SIZE)); - consistent_free((void *)psgl); - - + return (GET_DMA_PW(control)); } -EXPORT_SYMBOL(hw_init_dma_channel); -EXPORT_SYMBOL(get_channel_config); -EXPORT_SYMBOL(set_channel_priority); -EXPORT_SYMBOL(get_peripheral_width); -EXPORT_SYMBOL(alloc_dma_handle); -EXPORT_SYMBOL(free_dma_handle); +EXPORT_SYMBOL(ppc4xx_init_dma_channel); +EXPORT_SYMBOL(ppc4xx_get_channel_config); +EXPORT_SYMBOL(ppc4xx_set_channel_priority); +EXPORT_SYMBOL(ppc4xx_get_peripheral_width); EXPORT_SYMBOL(dma_channels); +EXPORT_SYMBOL(ppc4xx_set_src_addr); +EXPORT_SYMBOL(ppc4xx_set_dst_addr); +EXPORT_SYMBOL(ppc4xx_set_dma_addr); +EXPORT_SYMBOL(ppc4xx_set_dma_addr2); +EXPORT_SYMBOL(ppc4xx_enable_dma); +EXPORT_SYMBOL(ppc4xx_disable_dma); +EXPORT_SYMBOL(ppc4xx_set_dma_mode); +EXPORT_SYMBOL(ppc4xx_set_dma_count); +EXPORT_SYMBOL(ppc4xx_get_dma_residue); +EXPORT_SYMBOL(ppc4xx_enable_dma_interrupt); +EXPORT_SYMBOL(ppc4xx_disable_dma_interrupt); +EXPORT_SYMBOL(ppc4xx_get_dma_status); diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c new file mode 100644 index 00000000000000..49c6e9c61f38e3 --- /dev/null +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -0,0 +1,455 @@ +/* + * arch/ppc/kernel/ppc4xx_sgdma.c + * + * IBM PPC4xx DMA engine scatter/gather library + * + * Copyright 2002-2003 MontaVista Software Inc. + * + * Cleaned up and converted to new DCR access + * Matt Porter <mporter@kernel.crashing.org> + * + * Original code by Armin Kuster <akuster@mvista.com> + * and Pete Popov <ppopov@mvista.com> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/ppc4xx_dma.h> + +void +ppc4xx_set_sg_addr(int dmanr, phys_addr_t sg_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_sg_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA_64BIT + mtdcr(DCRN_ASGH0 + (dmanr * 0x8), (u32)(sg_addr >> 32)); +#endif + mtdcr(DCRN_ASG0 + (dmanr * 0x8), (u32)sg_addr); +} + +/* + * Add a new sgl descriptor to the end of a scatter/gather list + * which was created by alloc_dma_handle(). + * + * For a memory to memory transfer, both dma addresses must be + * valid. For a peripheral to memory transfer, one of the addresses + * must be set to NULL, depending on the direction of the transfer: + * memory to peripheral: set dst_addr to NULL, + * peripheral to memory: set src_addr to NULL. + */ +int +ppc4xx_add_dma_sgl(sgl_handle_t handle, phys_addr_t src_addr, phys_addr_t dst_addr, + unsigned int count) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + + if (!handle) { + printk("ppc4xx_add_dma_sgl: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } + + if (psgl->dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_add_dma_sgl: bad channel: %d\n", psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch = &dma_channels[psgl->dmanr]; + +#ifdef DEBUG_4xxDMA + { + int error = 0; + unsigned int aligned = + (unsigned) src_addr | (unsigned) dst_addr | count; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (aligned & 0x1) + error = 1; + break; + case PW_32: + if (aligned & 0x3) + error = 1; + break; + case PW_64: + if (aligned & 0x7) + error = 1; + break; + default: + printk("ppc4xx_add_dma_sgl: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return DMA_STATUS_GENERAL_ERROR; + } + if (error) + printk + ("Alignment warning: ppc4xx_add_dma_sgl src 0x%x dst 0x%x count 0x%x bus width var %d\n", + src_addr, dst_addr, count, p_dma_ch->pwidth); + + } +#endif + + if ((unsigned) (psgl->ptail + 1) >= ((unsigned) psgl + SGL_LIST_SIZE)) { + printk("sgl handle out of memory \n"); + return DMA_STATUS_OUT_OF_MEMORY; + } + + if (!psgl->ptail) { + psgl->phead = (ppc_sgl_t *) + ((unsigned) psgl + sizeof (sgl_list_info_t)); + psgl->phead_dma = psgl->dma_addr + sizeof(sgl_list_info_t); + psgl->ptail = psgl->phead; + psgl->ptail_dma = psgl->phead_dma; + } else { + psgl->ptail->next = psgl->ptail_dma + sizeof(ppc_sgl_t); + psgl->ptail++; + psgl->ptail_dma += sizeof(ppc_sgl_t); + } + + psgl->ptail->control = psgl->control; + psgl->ptail->src_addr = src_addr; + psgl->ptail->dst_addr = dst_addr; + psgl->ptail->control_count = (count >> p_dma_ch->shift) | + psgl->sgl_control; + psgl->ptail->next = (uint32_t) NULL; + + return DMA_STATUS_GOOD; +} + +/* + * Enable (start) the DMA described by the sgl handle. + */ +void +ppc4xx_enable_dma_sgl(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + uint32_t sg_command; + + if (!handle) { + printk("ppc4xx_enable_dma_sgl: null handle\n"); + return; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n", + psgl->dmanr); + return; + } else if (!psgl->phead) { + printk("ppc4xx_enable_dma_sgl: sg list empty\n"); + return; + } + + p_dma_ch = &dma_channels[psgl->dmanr]; + psgl->ptail->control_count &= ~SG_LINK; /* make this the last dscrptr */ + sg_command = mfdcr(DCRN_ASGC); + + ppc4xx_set_sg_addr(psgl->dmanr, psgl->phead_dma); + + sg_command |= SSG_ENABLE(psgl->dmanr); + + mtdcr(DCRN_ASGC, sg_command); /* start transfer */ +} + +/* + * Halt an active scatter/gather DMA operation. + */ +void +ppc4xx_disable_dma_sgl(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + uint32_t sg_command; + + if (!handle) { + printk("ppc4xx_enable_dma_sgl: null handle\n"); + return; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n", + psgl->dmanr); + return; + } + + sg_command = mfdcr(DCRN_ASGC); + sg_command &= ~SSG_ENABLE(psgl->dmanr); + mtdcr(DCRN_ASGC, sg_command); /* stop transfer */ +} + +/* + * Returns number of bytes left to be transferred from the entire sgl list. + * *src_addr and *dst_addr get set to the source/destination address of + * the sgl descriptor where the DMA stopped. + * + * An sgl transfer must NOT be active when this function is called. + */ +int +ppc4xx_get_dma_sgl_residue(sgl_handle_t handle, phys_addr_t * src_addr, + phys_addr_t * dst_addr) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + ppc_sgl_t *pnext, *sgl_addr; + uint32_t count_left; + + if (!handle) { + printk("ppc4xx_get_dma_sgl_residue: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_get_dma_sgl_residue: bad channel in handle %d\n", + psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + sgl_addr = (ppc_sgl_t *) __va(mfdcr(DCRN_ASG0 + (psgl->dmanr * 0x8))); + count_left = mfdcr(DCRN_DMACT0 + (psgl->dmanr * 0x8)); + + if (!sgl_addr) { + printk("ppc4xx_get_dma_sgl_residue: sgl addr register is null\n"); + goto error; + } + + pnext = psgl->phead; + while (pnext && + ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE) && + (pnext != sgl_addr)) + ) { + pnext++; + } + + if (pnext == sgl_addr) { /* found the sgl descriptor */ + + *src_addr = pnext->src_addr; + *dst_addr = pnext->dst_addr; + + /* + * Now search the remaining descriptors and add their count. + * We already have the remaining count from this descriptor in + * count_left. + */ + pnext++; + + while ((pnext != psgl->ptail) && + ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE)) + ) { + count_left += pnext->control_count & SG_COUNT_MASK; + } + + if (pnext != psgl->ptail) { /* should never happen */ + printk + ("ppc4xx_get_dma_sgl_residue error (1) psgl->ptail 0x%x handle 0x%x\n", + (unsigned int) psgl->ptail, (unsigned int) handle); + goto error; + } + + /* success */ + p_dma_ch = &dma_channels[psgl->dmanr]; + return (count_left << p_dma_ch->shift); /* count in bytes */ + + } else { + /* this shouldn't happen */ + printk + ("get_dma_sgl_residue, unable to match current address 0x%x, handle 0x%x\n", + (unsigned int) sgl_addr, (unsigned int) handle); + + } + + error: + *src_addr = (phys_addr_t) NULL; + *dst_addr = (phys_addr_t) NULL; + return 0; +} + +/* + * Returns the address(es) of the buffer(s) contained in the head element of + * the scatter/gather list. The element is removed from the scatter/gather + * list and the next element becomes the head. + * + * This function should only be called when the DMA is not active. + */ +int +ppc4xx_delete_dma_sgl_element(sgl_handle_t handle, phys_addr_t * src_dma_addr, + phys_addr_t * dst_dma_addr) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + + if (!handle) { + printk("ppc4xx_delete_sgl_element: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_delete_sgl_element: bad channel in handle %d\n", + psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if (!psgl->phead) { + printk("ppc4xx_delete_sgl_element: sgl list empty\n"); + *src_dma_addr = (phys_addr_t) NULL; + *dst_dma_addr = (phys_addr_t) NULL; + return DMA_STATUS_SGL_LIST_EMPTY; + } + + *src_dma_addr = (phys_addr_t) psgl->phead->src_addr; + *dst_dma_addr = (phys_addr_t) psgl->phead->dst_addr; + + if (psgl->phead == psgl->ptail) { + /* last descriptor on the list */ + psgl->phead = NULL; + psgl->ptail = NULL; + } else { + psgl->phead++; + psgl->phead_dma += sizeof(ppc_sgl_t); + } + + return DMA_STATUS_GOOD; +} + + +/* + * Create a scatter/gather list handle. This is simply a structure which + * describes a scatter/gather list. + * + * A handle is returned in "handle" which the driver should save in order to + * be able to access this list later. A chunk of memory will be allocated + * to be used by the API for internal management purposes, including managing + * the sg list and allocating memory for the sgl descriptors. One page should + * be more than enough for that purpose. Perhaps it's a bit wasteful to use + * a whole page for a single sg list, but most likely there will be only one + * sg list per channel. + * + * Interrupt notes: + * Each sgl descriptor has a copy of the DMA control word which the DMA engine + * loads in the control register. The control word has a "global" interrupt + * enable bit for that channel. Interrupts are further qualified by a few bits + * in the sgl descriptor count register. In order to setup an sgl, we have to + * know ahead of time whether or not interrupts will be enabled at the completion + * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST + * be called before calling alloc_dma_handle(). If the interrupt mode will never + * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt() + * do not have to be called -- interrupts will be enabled or disabled based + * on how the channel was configured after powerup by the hw_init_dma_channel() + * function. Each sgl descriptor will be setup to interrupt if an error occurs; + * however, only the last descriptor will be setup to interrupt. Thus, an + * interrupt will occur (if interrupts are enabled) only after the complete + * sgl transfer is done. + */ +int +ppc4xx_alloc_dma_handle(sgl_handle_t * phandle, unsigned int mode, unsigned int dmanr) +{ + sgl_list_info_t *psgl; + dma_addr_t dma_addr; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + uint32_t sg_command; + void *ret; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_alloc_dma_handle: invalid channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if (!phandle) { + printk("ppc4xx_alloc_dma_handle: null handle pointer\n"); + return DMA_STATUS_NULL_POINTER; + } + + /* Get a page of memory, which is zeroed out by consistent_alloc() */ + ret = dma_alloc_coherent(NULL, DMA_PPC4xx_SIZE, &dma_addr, GFP_KERNEL); + if (ret != NULL) { + memset(ret, 0, DMA_PPC4xx_SIZE); + psgl = (sgl_list_info_t *) ret; + } + + if (psgl == NULL) { + *phandle = (sgl_handle_t) NULL; + return DMA_STATUS_OUT_OF_MEMORY; + } + + psgl->dma_addr = dma_addr; + psgl->dmanr = dmanr; + + /* + * Modify and save the control word. These words will be + * written to each sgl descriptor. The DMA engine then + * loads this control word into the control register + * every time it reads a new descriptor. + */ + psgl->control = p_dma_ch->control; + /* Clear all mode bits */ + psgl->control &= ~(DMA_TM_MASK | DMA_TD); + /* Save control word and mode */ + psgl->control |= (mode | DMA_CE_ENABLE); + + /* In MM mode, we must set ETD/TCE */ + if (mode == DMA_MODE_MM) + psgl->control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE; + + if (p_dma_ch->int_enable) { + /* Enable channel interrupt */ + psgl->control |= DMA_CIE_ENABLE; + } else { + psgl->control &= ~DMA_CIE_ENABLE; + } + + sg_command = mfdcr(DCRN_ASGC); + sg_command |= SSG_MASK_ENABLE(dmanr); + + /* Enable SGL control access */ + mtdcr(DCRN_ASGC, sg_command); + psgl->sgl_control = SG_ERI_ENABLE | SG_LINK; + + if (p_dma_ch->int_enable) { + if (p_dma_ch->tce_enable) + psgl->sgl_control |= SG_TCI_ENABLE; + else + psgl->sgl_control |= SG_ETI_ENABLE; + } + + *phandle = (sgl_handle_t) psgl; + return DMA_STATUS_GOOD; +} + +/* + * Destroy a scatter/gather list handle that was created by alloc_dma_handle(). + * The list must be empty (contain no elements). + */ +void +ppc4xx_free_dma_handle(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + + if (!handle) { + printk("ppc4xx_free_dma_handle: got NULL\n"); + return; + } else if (psgl->phead) { + printk("ppc4xx_free_dma_handle: list not empty\n"); + return; + } else if (!psgl->dma_addr) { /* should never happen */ + printk("ppc4xx_free_dma_handle: no dma address\n"); + return; + } + + dma_free_coherent(NULL, DMA_PPC4xx_SIZE, (void *) psgl, 0); +} + +EXPORT_SYMBOL(ppc4xx_alloc_dma_handle); +EXPORT_SYMBOL(ppc4xx_free_dma_handle); +EXPORT_SYMBOL(ppc4xx_add_dma_sgl); +EXPORT_SYMBOL(ppc4xx_delete_dma_sgl_element); +EXPORT_SYMBOL(ppc4xx_enable_dma_sgl); +EXPORT_SYMBOL(ppc4xx_disable_dma_sgl); +EXPORT_SYMBOL(ppc4xx_get_dma_sgl_residue); diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 304181cd88aff9..5705ce63bfc770 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -424,8 +424,6 @@ config IRQSTACKS for handling hard and soft interrupts. This can help avoid overflowing the process kernel stacks. -endmenu - config SPINLINE bool "Inline spinlock code at each call site" depends on SMP && !PPC_SPLPAR && !PPC_ISERIES @@ -436,6 +434,8 @@ config SPINLINE If in doubt, say N. +endmenu + source "security/Kconfig" source "crypto/Kconfig" diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 9e665ed64d42a9..c5dd7e13b7c182 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -15,14 +15,11 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ obj-$(CONFIG_PPC_OF) += of_device.o -obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_iommu.o +pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ + iSeries_IoMmTable.o +pci-obj-$(CONFIG_PPC_PSERIES) += pci_dn.o pci_dma_direct.o -ifdef CONFIG_PPC_ISERIES -obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ - iSeries_IoMmTable.o -else -obj-$(CONFIG_PCI) += pci_dma_direct.o -endif +obj-$(CONFIG_PCI) += pci.o pci_iommu.o $(pci-obj-y) obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ diff --git a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c index bb8ca7fcfca7df..d2a7377add536e 100644 --- a/arch/ppc64/kernel/chrp_setup.c +++ b/arch/ppc64/kernel/chrp_setup.c @@ -298,8 +298,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, cur_cpu_spec->firmware_features); } -void -chrp_progress(char *s, unsigned short hex) +void chrp_progress(char *s, unsigned short hex) { struct device_node *root; int width, *p; @@ -313,60 +312,55 @@ chrp_progress(char *s, unsigned short hex) return; if (max_width == 0) { - if ( (root = find_path_device("/rtas")) && + if ((root = find_path_device("/rtas")) && (p = (unsigned int *)get_property(root, "ibm,display-line-length", - NULL)) ) + NULL))) max_width = *p; else max_width = 0x10; display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } - if (display_character == RTAS_UNKNOWN_SERVICE) { - /* use hex display */ - if (set_indicator == RTAS_UNKNOWN_SERVICE) - return; - rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); - return; - } - if(display_character == RTAS_UNKNOWN_SERVICE) { + if (display_character == RTAS_UNKNOWN_SERVICE) { /* use hex display if available */ - if(set_indicator != RTAS_UNKNOWN_SERVICE) + if (set_indicator != RTAS_UNKNOWN_SERVICE) rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); return; } spin_lock(&progress_lock); - /* Last write ended with newline, but we didn't print it since + /* + * Last write ended with newline, but we didn't print it since * it would just clear the bottom line of output. Print it now * instead. * * If no newline is pending, print a CR to start output at the * beginning of the line. */ - if(pending_newline) { + if (pending_newline) { rtas_call(display_character, 1, 1, NULL, '\r'); rtas_call(display_character, 1, 1, NULL, '\n'); pending_newline = 0; - } else + } else { rtas_call(display_character, 1, 1, NULL, '\r'); + } width = max_width; os = s; while (*os) { - if(*os == '\n' || *os == '\r') { + if (*os == '\n' || *os == '\r') { /* Blank to end of line. */ - while(width-- > 0) + while (width-- > 0) rtas_call(display_character, 1, 1, NULL, ' '); /* If newline is the last character, save it * until next call to avoid bumping up the * display output. */ - if(*os == '\n' && !os[1]) { + if (*os == '\n' && !os[1]) { pending_newline = 1; spin_unlock(&progress_lock); return; @@ -374,7 +368,7 @@ chrp_progress(char *s, unsigned short hex) /* RTAS wants CR-LF, not just LF */ - if(*os == '\n') { + if (*os == '\n') { rtas_call(display_character, 1, 1, NULL, '\r'); rtas_call(display_character, 1, 1, NULL, '\n'); } else { @@ -393,14 +387,14 @@ chrp_progress(char *s, unsigned short hex) os++; /* if we overwrite the screen length */ - if ( width <= 0 ) - while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) + if (width <= 0) + while ((*os != 0) && (*os != '\n') && (*os != '\r')) os++; } /* Blank to end of line. */ - while ( width-- > 0 ) - rtas_call(display_character, 1, 1, NULL, ' ' ); + while (width-- > 0) + rtas_call(display_character, 1, 1, NULL, ' '); spin_unlock(&progress_lock); } diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index aa66533f24b8b3..5fdcce2db45e4e 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -618,7 +618,7 @@ void __init eeh_init(void) info.buid_lo = BUID_LO(buid); info.buid_hi = BUID_HI(buid); - traverse_pci_devices(phb, early_enable_eeh, NULL, &info); + traverse_pci_devices(phb, early_enable_eeh, &info); } if (eeh_subsystem_enabled) { diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index 148bb78cedf4bf..2d48d24e7ab809 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S @@ -194,6 +194,7 @@ syscall_exit_trace_cont: mtspr SRR0,r7 mtspr SRR1,r8 rfid + b . /* prevent speculative execution */ syscall_enosys: li r3,-ENOSYS @@ -540,7 +541,7 @@ restore: ld r1,GPR1(r1) rfid - b . + b . /* prevent speculative execution */ /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: @@ -684,6 +685,7 @@ _GLOBAL(enter_rtas) mtspr SRR0,r5 mtspr SRR1,r6 rfid + b . /* prevent speculative execution */ _STATIC(rtas_return_loc) /* relocation is off at this point */ @@ -704,6 +706,7 @@ _STATIC(rtas_return_loc) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ _STATIC(rtas_restore_regs) /* relocation is on at this point */ diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index aefc7e6f00333b..a5d67f59951ddd 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -221,7 +221,8 @@ exception_marker: mtspr SRR0,r12; \ mfspr r12,SRR1; /* and SRR1 */ \ mtspr SRR1,r10; \ - rfid + rfid; \ + b . /* prevent speculative execution */ /* * This is the start of the interrupt handlers for iSeries @@ -302,12 +303,14 @@ exception_marker: . = n; \ .globl label##_Pseries; \ label##_Pseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_Iseries; \ label##_Iseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(area); \ EXCEPTION_PROLOG_ISERIES_2; \ @@ -316,6 +319,7 @@ label##_Iseries: \ #define MASKABLE_EXCEPTION_ISERIES(n, label) \ .globl label##_Iseries; \ label##_Iseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ lbz r10,PACAPROFENABLED(r13); \ @@ -409,12 +413,14 @@ __start_interrupts: . = 0x200 _MachineCheckPseries: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) . = 0x300 .globl DataAccess_Pseries DataAccess_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 BEGIN_FTR_SECTION mtspr SPRG2,r12 @@ -433,6 +439,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) . = 0x380 .globl DataAccessSLB_Pseries DataAccessSLB_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ @@ -453,12 +460,14 @@ DataAccessSLB_Pseries: mtspr SRR1,r10 mfspr r3,DAR rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0x400, InstructionAccess) . = 0x480 .globl InstructionAccessSLB_Pseries InstructionAccessSLB_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ @@ -479,6 +488,7 @@ InstructionAccessSLB_Pseries: mtspr SRR1,r10 mr r3,r11 /* SRR0 is faulting address */ rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt) STD_EXCEPTION_PSERIES(0x600, Alignment) @@ -491,6 +501,7 @@ InstructionAccessSLB_Pseries: . = 0xc00 .globl SystemCall_Pseries SystemCall_Pseries: + HMT_MEDIUM mr r9,r13 mfmsr r10 mfspr r13,SPRG3 @@ -503,6 +514,7 @@ SystemCall_Pseries: mfspr r12,SRR1 mtspr SRR1,r10 rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0xd00, SingleStep) STD_EXCEPTION_PSERIES(0xe00, Trap_0e) @@ -727,6 +739,7 @@ HardwareInterrupt_Iseries_masked: ld r12,PACA_EXGEN+EX_R12(r13) ld r13,PACA_EXGEN+EX_R13(r13) rfid + b . /* prevent speculative execution */ #endif /* @@ -742,10 +755,12 @@ fwnmi_data_area: . = 0x8000 .globl SystemReset_FWNMI SystemReset_FWNMI: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, SystemReset_common) .globl MachineCheck_FWNMI MachineCheck_FWNMI: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) @@ -867,6 +882,7 @@ fast_exception_return: REST_4GPRS(10, r1) ld r1,GPR1(r1) rfid + b . /* prevent speculative execution */ unrecov_fer: bl .save_nvgprs @@ -1146,6 +1162,7 @@ _GLOBAL(do_stab_bolted) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid + b . /* prevent speculative execution */ /* * r13 points to the PACA, r9 contains the saved CR, @@ -1190,6 +1207,7 @@ _GLOBAL(do_slb_miss) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid + b . /* prevent speculative execution */ unrecov_slb: EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) @@ -1295,6 +1313,7 @@ _STATIC(mmu_off) mtspr SRR1,r3 sync rfid + b . /* prevent speculative execution */ _GLOBAL(__start_initialization_pSeries) mr r31,r3 /* save parameters */ mr r30,r4 @@ -1777,6 +1796,7 @@ _GLOBAL(__secondary_start) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ /* * Running with relocation on at this point. All we want to do is @@ -1940,6 +1960,7 @@ _STATIC(start_here_pSeries) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ #endif /* CONFIG_PPC_PSERIES */ /* This is where all platforms converge execution */ diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 75da7df42b7bb0..8461687468643a 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -143,47 +143,6 @@ EXPORT_SYMBOL(synchronize_irq); #endif /* CONFIG_SMP */ -/* XXX Make this into free_irq() - Anton */ - -/* This could be promoted to a real free_irq() ... */ -static int -do_free_irq(int irq, void* dev_id) -{ - irq_desc_t *desc = get_irq_desc(irq); - struct irqaction **p; - unsigned long flags; - - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return 0; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - break; - } - return -ENOENT; -} - - int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) @@ -194,8 +153,7 @@ int request_irq(unsigned int irq, if (irq >= NR_IRQS) return -EINVAL; if (!handler) - /* We could implement really free_irq() instead of that... */ - return do_free_irq(irq, dev_id); + return -EINVAL; action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); @@ -222,7 +180,38 @@ EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { - request_irq(irq, NULL, 0, NULL, dev_id); + irq_desc_t *desc = get_irq_desc(irq); + struct irqaction **p; + unsigned long flags; + + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + mask_irq(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + /* Wait to make sure it's not being used on another CPU */ + synchronize_irq(irq); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + break; + } + return; } EXPORT_SYMBOL(free_irq); diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index a04037bba2200a..92bc868f31d9a6 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -600,8 +600,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) BUG(); /* No I/O resource for this PHB? */ if (request_resource(&ioport_resource, res)) - printk(KERN_ERR "Failed to request IO" - "on hose %d\n", 0 /* FIXME */); + printk(KERN_ERR "Failed to request IO on " + "PCI domain %d\n", pci_domain_nr(bus)); + for (i = 0; i < 3; ++i) { res = &hose->mem_resources[i]; @@ -609,8 +610,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) BUG(); /* No memory resource for this PHB? */ bus->resource[i+1] = res; if (res->flags && request_resource(&iomem_resource, res)) - printk(KERN_ERR "Failed to request MEM" - "on hose %d\n", 0 /* FIXME */); + printk(KERN_ERR "Failed to request MEM on " + "PCI domain %d\n", + pci_domain_nr(bus)); } } else if (pci_probe_only && (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index 50c3bf6a113307..2ca27ccc77957c 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -34,8 +34,8 @@ extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ *******************************************************************/ struct device_node; typedef void *(*traverse_func)(struct device_node *me, void *data); -void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data); -void *traverse_all_pci_devices(traverse_func pre); +void *traverse_pci_devices(struct device_node *start, traverse_func pre, + void *data); void pci_devs_phb_init(void); void pci_fix_bus_sysdata(void); diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 7f003be6e0625d..c771bdc644dfd3 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -19,8 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/delay.h> @@ -40,20 +38,20 @@ #include "pci.h" -/* Traverse_func that inits the PCI fields of the device node. +/* + * Traverse_func that inits the PCI fields of the device node. * NOTE: this *must* be done before read/write config to the device. */ -static void * __init -update_dn_pci_info(struct device_node *dn, void *data) +static void * __init update_dn_pci_info(struct device_node *dn, void *data) { -#ifdef CONFIG_PPC_PSERIES - struct pci_controller *phb = (struct pci_controller *)data; + struct pci_controller *phb = data; u32 *regs; char *device_type = get_property(dn, "device_type", NULL); char *model; dn->phb = phb; - if (device_type && strcmp(device_type, "pci") == 0 && get_property(dn, "class-code", NULL) == 0) { + if (device_type && (strcmp(device_type, "pci") == 0) && + (get_property(dn, "class-code", NULL) == 0)) { /* special case for PHB's. Sigh. */ regs = (u32 *)get_property(dn, "bus-range", NULL); dn->busno = regs[0]; @@ -72,57 +70,47 @@ update_dn_pci_info(struct device_node *dn, void *data) dn->devfn = (regs[0] >> 8) & 0xff; } } -#endif return NULL; } -/****************************************************************** +/* * Traverse a device tree stopping each PCI device in the tree. * This is done depth first. As each node is processed, a "pre" - * function is called, the children are processed recursively, and - * then a "post" function is called. + * function is called and the children are processed recursively. * - * The "pre" and "post" funcs return a value. If non-zero - * is returned from the "pre" func, the traversal stops and this - * value is returned. The return value from "post" is not used. - * This return value is useful when using traverse as - * a method of finding a device. + * The "pre" func returns a value. If non-zero is returned from + * the "pre" func, the traversal stops and this value is returned. + * This return value is useful when using traverse as a method of + * finding a device. * - * NOTE: we do not run the funcs for devices that do not appear to + * NOTE: we do not run the func for devices that do not appear to * be PCI except for the start node which we assume (this is good * because the start node is often a phb which may be missing PCI * properties). * We use the class-code as an indicator. If we run into * one of these nodes we also assume its siblings are non-pci for * performance. - * - ******************************************************************/ -void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data) + */ +void *traverse_pci_devices(struct device_node *start, traverse_func pre, + void *data) { struct device_node *dn, *nextdn; void *ret; - if (pre && (ret = pre(start, data)) != NULL) + if (pre && ((ret = pre(start, data)) != NULL)) return ret; for (dn = start->child; dn; dn = nextdn) { nextdn = NULL; -#ifdef CONFIG_PPC_PSERIES if (get_property(dn, "class-code", NULL)) { - if (pre && (ret = pre(dn, data)) != NULL) + if (pre && ((ret = pre(dn, data)) != NULL)) return ret; - if (dn->child) { + if (dn->child) /* Depth first...do children */ nextdn = dn->child; - } else if (dn->sibling) { + else if (dn->sibling) /* ok, try next sibling instead. */ nextdn = dn->sibling; - } else { - /* no more children or siblings...call "post" */ - if (post) - post(dn, data); - } } -#endif if (!nextdn) { /* Walk up to next valid sibling. */ do { @@ -136,31 +124,35 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, travers return NULL; } -/* Same as traverse_pci_devices except this does it for all phbs. +/* + * Same as traverse_pci_devices except this does it for all phbs. */ -void *traverse_all_pci_devices(traverse_func pre) +static void *traverse_all_pci_devices(traverse_func pre) { - struct pci_controller* phb; + struct pci_controller *phb; void *ret; - for (phb=hose_head;phb;phb=phb->next) - if ((ret = traverse_pci_devices((struct device_node *)phb->arch_data, pre, NULL, phb)) != NULL) + + for (phb = hose_head; phb; phb = phb->next) + if ((ret = traverse_pci_devices(phb->arch_data, pre, phb)) + != NULL) return ret; return NULL; } -/* Traversal func that looks for a <busno,devfcn> value. +/* + * Traversal func that looks for a <busno,devfcn> value. * If found, the device_node is returned (thus terminating the traversal). */ -static void * -is_devfn_node(struct device_node *dn, void *data) +static void *is_devfn_node(struct device_node *dn, void *data) { int busno = ((unsigned long)data >> 8) & 0xff; int devfn = ((unsigned long)data) & 0xff; - return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL; + return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL; } -/* This is the "slow" path for looking up a device_node from a +/* + * This is the "slow" path for looking up a device_node from a * pci_dev. It will hunt for the device under its parent's * phb and then update sysdata for a future fastpath. * @@ -174,14 +166,14 @@ is_devfn_node(struct device_node *dn, void *data) */ struct device_node *fetch_dev_dn(struct pci_dev *dev) { - struct device_node *orig_dn = (struct device_node *)dev->sysdata; + struct device_node *orig_dn = dev->sysdata; struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */ struct device_node *phb_dn; struct device_node *dn; unsigned long searchval = (dev->bus->number << 8) | dev->devfn; - phb_dn = (struct device_node *)(phb->arch_data); - dn = (struct device_node *)traverse_pci_devices(phb_dn, is_devfn_node, NULL, (void *)searchval); + phb_dn = phb->arch_data; + dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval); if (dn) { dev->sysdata = dn; /* ToDo: call some device init hook here */ @@ -191,25 +183,23 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev) EXPORT_SYMBOL(fetch_dev_dn); -/****************************************************************** +/* * Actually initialize the phbs. * The buswalk on this phb has not happened yet. - ******************************************************************/ -void __init -pci_devs_phb_init(void) + */ +void __init pci_devs_phb_init(void) { /* This must be done first so the device nodes have valid pci info! */ traverse_all_pci_devices(update_dn_pci_info); } -static void __init -pci_fixup_bus_sysdata_list(struct list_head *bus_list) +static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list) { struct list_head *ln; struct pci_bus *bus; - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + for (ln = bus_list->next; ln != bus_list; ln = ln->next) { bus = pci_bus_b(ln); if (bus->self) bus->sysdata = bus->self->sysdata; @@ -217,7 +207,7 @@ pci_fixup_bus_sysdata_list(struct list_head *bus_list) } } -/****************************************************************** +/* * Fixup the bus->sysdata ptrs to point to the bus' device_node. * This is done late in pcibios_init(). We do this mostly for * sanity, but pci_dma.c uses these at DMA time so they must be @@ -225,9 +215,8 @@ pci_fixup_bus_sysdata_list(struct list_head *bus_list) * To do this we recurse down the bus hierarchy. Note that PHB's * have bus->self == NULL, but fortunately bus->sysdata is already * correct in this case. - ******************************************************************/ -void __init -pci_fix_bus_sysdata(void) + */ +void __init pci_fix_bus_sysdata(void) { pci_fixup_bus_sysdata_list(&pci_root_buses); } diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index 3484e480422731..e0ab44dc1fc4db 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -404,7 +404,9 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) break; } - + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + break; default: ret = ptrace_request(child, request, addr, data); diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 057c1382ed83c9..41b34932f14ab5 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -208,8 +208,8 @@ static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ return sprintf(buf, "%lx\n", val); \ } \ -static ssize_t store_##NAME(struct sys_device *dev, const char *buf, \ - size_t count) \ +static ssize_t __attribute_used__ \ + store_##NAME(struct sys_device *dev, const char *buf, size_t count) \ { \ struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ unsigned long val; \ diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index a881d25f1f1393..c9f950c2cea37e 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -27,7 +27,6 @@ #include <asm/naca.h> #include <asm/rtas.h> #include <asm/xics.h> -#include <asm/ppcdebug.h> #include <asm/hvcall.h> #include <asm/machdep.h> @@ -239,13 +238,13 @@ static unsigned int real_irq_to_virt(unsigned int real_irq) #ifdef CONFIG_SMP static int get_irq_server(unsigned int irq) { - cpumask_t cpumask = irq_affinity[irq]; - cpumask_t tmp = CPU_MASK_NONE; unsigned int server; #ifdef CONFIG_IRQ_ALL_CPUS /* For the moment only implement delivery to all cpus or one cpu */ if (smp_threads_ready) { + cpumask_t cpumask = irq_affinity[irq]; + cpumask_t tmp = CPU_MASK_NONE; if (cpus_equal(cpumask, CPU_MASK_ALL)) { server = default_distrib_server; } else { @@ -286,7 +285,7 @@ static void xics_enable_irq(unsigned int virq) call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_set_xive " + printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive " "returned %x\n", irq, call_status); return; } @@ -294,7 +293,7 @@ static void xics_enable_irq(unsigned int virq) /* Now unmask the interrupt (often a no-op) */ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_int_on " + printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on " "returned %x\n", irq, call_status); return; } @@ -310,7 +309,7 @@ static void xics_disable_real_irq(unsigned int irq) call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_disable_real_irq: irq=%x: " + printk(KERN_ERR "xics_disable_real_irq: irq=%d: " "ibm_int_off returned %x\n", irq, call_status); return; } @@ -319,7 +318,7 @@ static void xics_disable_real_irq(unsigned int irq) /* Have to set XIVE to 0xff to be able to remove a slot */ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); if (call_status != 0) { - printk(KERN_ERR "xics_disable_irq: irq=%x: ibm_set_xive(0xff)" + printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)" " returned %x\n", irq, call_status); return; } @@ -356,8 +355,6 @@ static void xics_mask_and_ack_irq(unsigned int irq) } } -extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); - int xics_get_irq(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); @@ -384,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs) if (irq == NO_IRQ) irq = real_irq_to_virt_slowpath(vec); if (irq == NO_IRQ) { - printk(KERN_ERR "Interrupt 0x%x (real) is invalid," + printk(KERN_ERR "Interrupt %d (real) is invalid," " disabling it.\n", vec); xics_disable_real_irq(vec); } else @@ -395,8 +392,6 @@ int xics_get_irq(struct pt_regs *regs) #ifdef CONFIG_SMP -extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -469,11 +464,9 @@ void xics_init_IRQ(void) ibm_int_off = rtas_token("ibm,int-off"); np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); - if (!np) { - printk(KERN_WARNING "Can't find Interrupt Presentation\n"); - udbg_printf("Can't find Interrupt Presentation\n"); - while (1); - } + if (!np) + panic("xics_init_IRQ: can't find interrupt presentation"); + nextnode: ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); if (ireg) { @@ -484,11 +477,8 @@ nextnode: } ireg = (uint *)get_property(np, "reg", &ilen); - if (!ireg) { - printk(KERN_WARNING "Can't find Interrupt Reg Property\n"); - udbg_printf("Can't find Interrupt Reg Property\n"); - while (1); - } + if (!ireg) + panic("xics_init_IRQ: can't find interrupt reg property"); while (ilen) { inodes[indx].addr = (unsigned long long)*ireg++ << 32; @@ -528,16 +518,14 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA Interrupt Controller\n"); + printk(KERN_WARNING "xics: no ISA interrupt controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { ireg = (uint *) get_property(np, "interrupts", NULL); - if (!ireg) { - printk(KERN_WARNING "Can't find ISA Interrupts Property\n"); - udbg_printf("Can't find ISA Interrupts Property\n"); - while (1); - } + if (!ireg) + panic("xics_init_IRQ: can't find ISA interrupts property"); + xics_irq_8259_cascade_real = *ireg; xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); @@ -558,13 +546,8 @@ nextnode: xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ -#ifdef CONFIG_PPC_PSERIES - /* actually iSeries does not use any of xics...but it has link dependencies - * for now, except this new one... - */ } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; -#endif } xics_8259_pic.enable = i8259_pic.enable; @@ -590,7 +573,8 @@ static int __init xics_setup_i8259(void) xics_irq_8259_cascade != -1) { if (request_irq(irq_offset_up(xics_irq_8259_cascade), no_action, 0, "8259 cascade", NULL)) - printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); + printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " + "cascade\n"); i8259_init(); } return 0; @@ -643,7 +627,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) irq, newmask, xics_status[1]); if (status) { - printk(KERN_ERR "xics_set_affinity irq=%d ibm,set-xive " + printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive " "returns %d\n", irq, status); return; } @@ -723,7 +707,7 @@ void xics_migrate_irqs_away(void) status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, xics_status[0], xics_status[1]); if (status) - printk(KERN_ERR "migrate_irqs_away irq=%d " + printk(KERN_ERR "migrate_irqs_away: irq=%d " "ibm,set-xive returns %d\n", virq, status); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 5906668177f0b4..ce8cb18b90a4f3 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -181,6 +181,15 @@ config QDIO_PERF_STATS If unsure, say N. +config QDIO_DEBUG + bool "Extended debugging information" + depends on QDIO + help + Say Y here to get extended debugging output in /proc/s390dbf/qdio... + Warning: this option reduces the performance of the QDIO module. + + If unsure, say N. + comment "Misc" config PREEMPT diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index d957683d6165ae..1395840ba98f7d 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <asm/uaccess.h> #include <asm/io.h> +#include <asm/smp.h> #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/page-flags.h> diff --git a/arch/s390/defconfig b/arch/s390/defconfig index ec342423d0d9eb..84650d326864df 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -11,7 +11,6 @@ CONFIG_UID16=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup @@ -71,6 +70,7 @@ CONFIG_MATHEMU=y CONFIG_MACHCHK_WARNING=y CONFIG_QDIO=y # CONFIG_QDIO_PERF_STATS is not set +# CONFIG_QDIO_DEBUG is not set # # Misc @@ -93,6 +93,7 @@ CONFIG_NO_IDLE_HZ_INIT=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set @@ -511,7 +512,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_GENERIC is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index a0e6722b6981b3..48209a81ae9fbc 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -214,4 +214,7 @@ struct sigevent32 { } _sigev_un; }; +extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from); +extern int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from); + #endif /* _ASM_S390X_S390_H */ diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 70c83cb56c3e95..e8c8b2fe7af578 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -106,6 +106,53 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) return err; } +int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from) +{ + int err; + u32 tmp; + + if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) + return -EFAULT; + + err = __get_user(to->si_signo, &from->si_signo); + err |= __get_user(to->si_errno, &from->si_errno); + err |= __get_user(to->si_code, &from->si_code); + + if (from->si_code < 0) + err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); + else { + switch (from->si_code >> 16) { + case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ + case __SI_MESGQ >> 16: + err |= __get_user(to->si_int, &from->si_int); + /* fallthrough */ + case __SI_KILL >> 16: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + break; + case __SI_CHLD >> 16: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + err |= __get_user(to->si_utime, &from->si_utime); + err |= __get_user(to->si_stime, &from->si_stime); + err |= __get_user(to->si_status, &from->si_status); + break; + case __SI_FAULT >> 16: + err |= __get_user(tmp, &from->si_addr); + to->si_addr = (void *)(u64) (tmp & PSW32_ADDR_INSN); + break; + case __SI_POLL >> 16: + case __SI_TIMER >> 16: + err |= __get_user(to->si_band, &from->si_band); + err |= __get_user(to->si_fd, &from->si_fd); + break; + default: + break; + } + } + return err; +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index a0ddc4f7d9e506..26b89e55d9c1bd 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -553,6 +553,19 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned int); } return 0; + case PTRACE_GETEVENTMSG: + return put_user((__u32) child->ptrace_message, + (unsigned int __user *) data); + case PTRACE_GETSIGINFO: + if (child->last_siginfo == NULL) + return -EINVAL; + return copy_siginfo_to_user32((siginfo_t32 __user *) data, + child->last_siginfo); + case PTRACE_SETSIGINFO: + if (child->last_siginfo == NULL) + return -EINVAL; + return copy_siginfo_from_user32(child->last_siginfo, + (siginfo_t32 __user *) data); } return ptrace_request(child, request, addr, data); } diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 72d4f1e6ff7b70..170da71fa2ff3c 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -19,6 +19,7 @@ #include <asm/pgalloc.h> #include <asm/uaccess.h> +#include <asm/smp.h> #include "../../../drivers/s390/net/smsgiucv.h" diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 79d52a1dd356e7..7d0688aa6833d9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -83,6 +83,7 @@ config HW_CONSOLE config SMP bool "Symmetric multi-processing support (does not work on sun4/sun4c)" + depends on BROKEN ---help--- This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -221,6 +222,7 @@ config SUN_PM config SUN4 bool "Support for SUN4 machines (disables SUN4[CDM] support)" + depends on !SMP help Say Y here if, and only if, your machine is a sun4. Note that a kernel compiled with this option will run only on sun4. diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index fd065fb3e00c73..46591a15eb43bb 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -45,6 +45,7 @@ int smp_activated = 0; volatile int __cpu_number_map[NR_CPUS]; volatile int __cpu_logical_map[NR_CPUS]; cycles_t cacheflush_time = 0; /* XXX */ +unsigned long cache_decay_ticks = 100; cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; @@ -203,6 +204,11 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) } } +void smp_reschedule_irq(void) +{ + set_need_resched(); +} + void smp_flush_page_to_ram(unsigned long page) { /* Current theory is that those who call this are the one's diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index e5e13490357077..9f659c2f4196d6 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -43,7 +43,6 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); extern volatile int smp_processors_ready; -extern unsigned long cpu_present_map; extern int smp_num_cpus; static int smp_highest_cpu; extern int smp_threads_ready; @@ -100,8 +99,6 @@ void __init smp4d_callin(void) * the SMP initialization the master will be just allowed * to call the scheduler code. */ - init_idle(); - /* Get our local ticker going. */ smp_setup_percpu_timer(); @@ -152,7 +149,6 @@ void __init smp4d_callin(void) extern int cpu_idle(void *unused); extern void init_IRQ(void); extern void cpu_panic(void); -extern int start_secondary(void *unused); /* * Cycle through the processors asking the PROM to start each one. @@ -174,12 +170,12 @@ void __init smp4d_boot_cpus(void) current_set[0] = NULL; local_irq_enable(); - cpu_present_map = 0; + cpus_clear(cpu_present_map); /* XXX This whole thing has to go. See sparc64. */ for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - cpu_present_map |= (1<<mid); - SMP_PRINTK(("cpu_present_map %08lx\n", cpu_present_map)); + cpu_set(mid, cpu_present_map); + SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0])); for(i=0; i < NR_CPUS; i++) __cpu_number_map[i] = -1; for(i=0; i < NR_CPUS; i++) @@ -197,7 +193,7 @@ void __init smp4d_boot_cpus(void) if(i == boot_cpu_id) continue; - if(cpu_present_map & (1 << i)) { + if (cpu_isset(i, cpu_present_map)) { extern unsigned long sun4d_cpu_startup; unsigned long *entry = &sun4d_cpu_startup; struct task_struct *p; @@ -254,19 +250,19 @@ void __init smp4d_boot_cpus(void) } } if(!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); + cpu_clear(i, cpu_present_map); __cpu_number_map[i] = -1; } } local_flush_cache_all(); if(cpucount == 0) { printk("Error: only one Processor found.\n"); - cpu_present_map = (1 << hard_smp4d_processor_id()); + cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id()); } else { unsigned long bogosum = 0; for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) { + if (cpu_isset(i, cpu_present_map)) { bogosum += cpu_data(i).udelay_val; smp_highest_cpu = i; } @@ -346,12 +342,13 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, /* Init receive/complete mapping, plus fire the IPI's off. */ { - register unsigned long mask; + cpumask_t mask; register int i; - mask = (cpu_present_map & ~(1 << hard_smp4d_processor_id())); + mask = cpumask_of_cpu(hard_smp4d_processor_id()); + cpus_andnot(mask, cpu_present_map, mask); for(i = 0; i <= high; i++) { - if(mask & (1 << i)) { + if (cpu_isset(i, mask)) { ccall_info.processors_in[i] = 0; ccall_info.processors_out[i] = 0; sun4d_send_ipi(i, IRQ_CROSS_CALL); @@ -498,11 +495,11 @@ void __init sun4d_init_smp(void) t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); /* And set btfixup... */ - BTFIXUPSET_BLACKBOX(smp_processor_id, smp4d_blackbox_id); + BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); for (i = 0; i < NR_CPUS; i++) { ccall_info.processors_in[i] = 1; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 01587b1608195b..f2fc64edc773d6 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -95,8 +95,6 @@ void __init smp4m_callin(void) * the SMP initialization the master will be just allowed * to call the scheduler code. */ - init_idle(); - /* Allow master to continue. */ swap((unsigned long *)&cpu_callin_map[cpuid], 1); @@ -126,7 +124,6 @@ void __init smp4m_callin(void) extern int cpu_idle(void *unused); extern void init_IRQ(void); extern void cpu_panic(void); -extern int start_secondary(void *unused); /* * Cycle through the processors asking the PROM to start each one. @@ -460,9 +457,9 @@ void __init smp4m_blackbox_current(unsigned *addr) void __init sun4m_init_smp(void) { - BTFIXUPSET_BLACKBOX(smp_processor_id, smp4m_blackbox_id); + BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); } diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S index 1db353f4668ef6..2dcdaa1fd8cd9e 100644 --- a/arch/sparc/kernel/trampoline.S +++ b/arch/sparc/kernel/trampoline.S @@ -88,8 +88,6 @@ cpu3_startup: .align 4 smp_do_cpu_idle: - call init_idle - nop call cpu_idle mov 0, %o0 diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S index ed91f1e8c4c4ac..eb6a9e7595df81 100644 --- a/arch/sparc/lib/memcpy.S +++ b/arch/sparc/lib/memcpy.S @@ -42,124 +42,124 @@ x: #endif /* Both these macros have to start with exactly the same insn */ -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - st %t0, [%dst + offset + 0x00]; \ - st %t1, [%dst + offset + 0x04]; \ - st %t2, [%dst + offset + 0x08]; \ - st %t3, [%dst + offset + 0x0c]; \ - st %t4, [%dst + offset + 0x10]; \ - st %t5, [%dst + offset + 0x14]; \ - st %t6, [%dst + offset + 0x18]; \ - st %t7, [%dst + offset + 0x1c]; - -#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - std %t0, [%dst + offset + 0x00]; \ - std %t2, [%dst + offset + 0x08]; \ - std %t4, [%dst + offset + 0x10]; \ - std %t6, [%dst + offset + 0x18]; - -#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - st %t0, [%dst - offset - 0x10]; \ - st %t1, [%dst - offset - 0x0c]; \ - st %t2, [%dst - offset - 0x08]; \ - st %t3, [%dst - offset - 0x04]; - -#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - std %t0, [%dst - offset - 0x10]; \ - std %t2, [%dst - offset - 0x08]; - -#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src - offset - 0x02], %t0; \ - ldub [%src - offset - 0x01], %t1; \ - stb %t0, [%dst - offset - 0x02]; \ - stb %t1, [%dst - offset - 0x01]; +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + st %t0, [%dst + (offset) + 0x00]; \ + st %t1, [%dst + (offset) + 0x04]; \ + st %t2, [%dst + (offset) + 0x08]; \ + st %t3, [%dst + (offset) + 0x0c]; \ + st %t4, [%dst + (offset) + 0x10]; \ + st %t5, [%dst + (offset) + 0x14]; \ + st %t6, [%dst + (offset) + 0x18]; \ + st %t7, [%dst + (offset) + 0x1c]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + std %t0, [%dst + (offset) + 0x00]; \ + std %t2, [%dst + (offset) + 0x08]; \ + std %t4, [%dst + (offset) + 0x10]; \ + std %t6, [%dst + (offset) + 0x18]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - (offset) - 0x10], %t0; \ + ldd [%src - (offset) - 0x08], %t2; \ + st %t0, [%dst - (offset) - 0x10]; \ + st %t1, [%dst - (offset) - 0x0c]; \ + st %t2, [%dst - (offset) - 0x08]; \ + st %t3, [%dst - (offset) - 0x04]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - (offset) - 0x10], %t0; \ + ldd [%src - (offset) - 0x08], %t2; \ + std %t0, [%dst - (offset) - 0x10]; \ + std %t2, [%dst - (offset) - 0x08]; + +#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src - (offset) - 0x02], %t0; \ + ldub [%src - (offset) - 0x01], %t1; \ + stb %t0, [%dst - (offset) - 0x02]; \ + stb %t1, [%dst - (offset) - 0x01]; /* Both these macros have to start with exactly the same insn */ -#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src - offset - 0x20], %t0; \ - ldd [%src - offset - 0x18], %t2; \ - ldd [%src - offset - 0x10], %t4; \ - ldd [%src - offset - 0x08], %t6; \ - st %t0, [%dst - offset - 0x20]; \ - st %t1, [%dst - offset - 0x1c]; \ - st %t2, [%dst - offset - 0x18]; \ - st %t3, [%dst - offset - 0x14]; \ - st %t4, [%dst - offset - 0x10]; \ - st %t5, [%dst - offset - 0x0c]; \ - st %t6, [%dst - offset - 0x08]; \ - st %t7, [%dst - offset - 0x04]; - -#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src - offset - 0x20], %t0; \ - ldd [%src - offset - 0x18], %t2; \ - ldd [%src - offset - 0x10], %t4; \ - ldd [%src - offset - 0x08], %t6; \ - std %t0, [%dst - offset - 0x20]; \ - std %t2, [%dst - offset - 0x18]; \ - std %t4, [%dst - offset - 0x10]; \ - std %t6, [%dst - offset - 0x08]; - -#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - st %t0, [%dst + offset + 0x00]; \ - st %t1, [%dst + offset + 0x04]; \ - st %t2, [%dst + offset + 0x08]; \ - st %t3, [%dst + offset + 0x0c]; - -#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src + offset + 0x00], %t0; \ - ldub [%src + offset + 0x01], %t1; \ - stb %t0, [%dst + offset + 0x00]; \ - stb %t1, [%dst + offset + 0x01]; - -#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - srl %t0, shir, %t5; \ - srl %t1, shir, %t6; \ - sll %t0, shil, %t0; \ - or %t5, %prev, %t5; \ - sll %t1, shil, %prev; \ - or %t6, %t0, %t0; \ - srl %t2, shir, %t1; \ - srl %t3, shir, %t6; \ - sll %t2, shil, %t2; \ - or %t1, %prev, %t1; \ - std %t4, [%dst + offset + offset2 - 0x04]; \ - std %t0, [%dst + offset + offset2 + 0x04]; \ - sll %t3, shil, %prev; \ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - (offset) - 0x20], %t0; \ + ldd [%src - (offset) - 0x18], %t2; \ + ldd [%src - (offset) - 0x10], %t4; \ + ldd [%src - (offset) - 0x08], %t6; \ + st %t0, [%dst - (offset) - 0x20]; \ + st %t1, [%dst - (offset) - 0x1c]; \ + st %t2, [%dst - (offset) - 0x18]; \ + st %t3, [%dst - (offset) - 0x14]; \ + st %t4, [%dst - (offset) - 0x10]; \ + st %t5, [%dst - (offset) - 0x0c]; \ + st %t6, [%dst - (offset) - 0x08]; \ + st %t7, [%dst - (offset) - 0x04]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - (offset) - 0x20], %t0; \ + ldd [%src - (offset) - 0x18], %t2; \ + ldd [%src - (offset) - 0x10], %t4; \ + ldd [%src - (offset) - 0x08], %t6; \ + std %t0, [%dst - (offset) - 0x20]; \ + std %t2, [%dst - (offset) - 0x18]; \ + std %t4, [%dst - (offset) - 0x10]; \ + std %t6, [%dst - (offset) - 0x08]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + st %t0, [%dst + (offset) + 0x00]; \ + st %t1, [%dst + (offset) + 0x04]; \ + st %t2, [%dst + (offset) + 0x08]; \ + st %t3, [%dst + (offset) + 0x0c]; + +#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src + (offset) + 0x00], %t0; \ + ldub [%src + (offset) + 0x01], %t1; \ + stb %t0, [%dst + (offset) + 0x00]; \ + stb %t1, [%dst + (offset) + 0x01]; + +#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + srl %t0, shir, %t5; \ + srl %t1, shir, %t6; \ + sll %t0, shil, %t0; \ + or %t5, %prev, %t5; \ + sll %t1, shil, %prev; \ + or %t6, %t0, %t0; \ + srl %t2, shir, %t1; \ + srl %t3, shir, %t6; \ + sll %t2, shil, %t2; \ + or %t1, %prev, %t1; \ + std %t4, [%dst + (offset) + (offset2) - 0x04]; \ + std %t0, [%dst + (offset) + (offset2) + 0x04]; \ + sll %t3, shil, %prev; \ or %t6, %t2, %t4; -#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - srl %t0, shir, %t4; \ - srl %t1, shir, %t5; \ - sll %t0, shil, %t6; \ - or %t4, %prev, %t0; \ - sll %t1, shil, %prev; \ - or %t5, %t6, %t1; \ - srl %t2, shir, %t4; \ - srl %t3, shir, %t5; \ - sll %t2, shil, %t6; \ - or %t4, %prev, %t2; \ - sll %t3, shil, %prev; \ - or %t5, %t6, %t3; \ - std %t0, [%dst + offset + offset2 + 0x00]; \ - std %t2, [%dst + offset + offset2 + 0x08]; +#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + srl %t0, shir, %t4; \ + srl %t1, shir, %t5; \ + sll %t0, shil, %t6; \ + or %t4, %prev, %t0; \ + sll %t1, shil, %prev; \ + or %t5, %t6, %t1; \ + srl %t2, shir, %t4; \ + srl %t3, shir, %t5; \ + sll %t2, shil, %t6; \ + or %t4, %prev, %t2; \ + sll %t3, shil, %prev; \ + or %t5, %t6, %t3; \ + std %t0, [%dst + (offset) + (offset2) + 0x00]; \ + std %t2, [%dst + (offset) + (offset2) + 0x08]; .text .align 4 diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 45469d2f6e1c75..c18475eaaee18c 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1697,9 +1697,7 @@ static void turbosparc_flush_cache_mm(struct mm_struct *mm) static void turbosparc_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; - - FLUSH_BEGIN(mm) + FLUSH_BEGIN(vma->vm_mm) flush_user_windows(); turbosparc_idflash_clear(); FLUSH_END @@ -1750,9 +1748,7 @@ static void turbosparc_flush_tlb_mm(struct mm_struct *mm) static void turbosparc_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; - - FLUSH_BEGIN(mm) + FLUSH_BEGIN(vma->vm_mm) srmmu_flush_whole_tlb(); FLUSH_END } |